From bb02906b6897c69ca4950ba735a72c273444d888 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 12:42:13 +0530 Subject: [PATCH 01/15] fix: strengthen API user token generation --- app/main/controllers/api/RTMediaJsonApiFunctions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/main/controllers/api/RTMediaJsonApiFunctions.php b/app/main/controllers/api/RTMediaJsonApiFunctions.php index 14d683343..3810d95d3 100644 --- a/app/main/controllers/api/RTMediaJsonApiFunctions.php +++ b/app/main/controllers/api/RTMediaJsonApiFunctions.php @@ -28,9 +28,9 @@ public function rtmedia_api_get_user_token( $user_id, $user_login ) { if ( empty( $user_id ) || empty( $user_login ) ) { return false; } - $string = '08~' . $user_id . '~' . $user_login . '~kumar'; - return sha1( $string . current_time( 'timestamp' ) . wp_rand( 1, 9 ) ); + // Generate an opaque 64 character long token for user login. + return wp_generate_password( 64, false, false ); } /** From 56369a31e591fb7d8bd929981241ed6a1a6f9786 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 13:25:53 +0530 Subject: [PATCH 02/15] fix: expire and validate API tokens --- .../api/RTMediaJsonApiFunctions.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/app/main/controllers/api/RTMediaJsonApiFunctions.php b/app/main/controllers/api/RTMediaJsonApiFunctions.php index 3810d95d3..e88067f68 100644 --- a/app/main/controllers/api/RTMediaJsonApiFunctions.php +++ b/app/main/controllers/api/RTMediaJsonApiFunctions.php @@ -11,6 +11,13 @@ */ class RTMediaJsonApiFunctions { + /** + * Token lifetime in seconds. + * + * @var int + */ + public $token_lifetime = 2592000; // 30 days. + /** * RTMediaJsonApiFunctions constructor. */ @@ -33,6 +40,17 @@ public function rtmedia_api_get_user_token( $user_id, $user_login ) { return wp_generate_password( 64, false, false ); } + /** + * Get the absolute API token lifetime in seconds. + * + * @return int + */ + public function rtmedia_api_get_token_lifetime() { + $token_lifetime = (int) apply_filters( 'rtmedia_api_token_lifetime', $this->token_lifetime ); + + return max( MINUTE_IN_SECONDS, $token_lifetime ); + } + /** * User data from user id * @@ -96,6 +114,11 @@ public function rtmedia_api_validate_token( $token ) { return false; } + // Revoke predictable 40-character SHA-1 tokens issued by affected versions. + if ( 1 !== preg_match( '/^[A-Za-z0-9]{64}$/D', $token ) ) { + return false; + } + if ( class_exists( 'RTMediaApiLogin' ) ) { $rtmediaapilogin = new RTMediaApiLogin(); $columns = array( @@ -106,6 +129,15 @@ public function rtmedia_api_validate_token( $token ) { return false; } + $issued_at = isset( $token_data[0]->token_time ) ? (int) $token_data[0]->token_time : 0; + $expires_at = $issued_at + $this->rtmedia_api_get_token_lifetime(); + + if ( $issued_at <= 0 || time() >= $expires_at ) { + $rtmediaapilogin->update( array( 'status' => 'FALSE' ), array( 'id' => $token_data[0]->id ) ); + + return false; + } + return $token_data; } else { return false; @@ -124,6 +156,9 @@ public function rtmedia_api_get_user_id_from_token( $token ) { return false; } $token_data = $this->rtmedia_api_validate_token( $token ); + if ( empty( $token_data ) ) { + return false; + } return $token_data[0]->user_id; } From d8b84fb82658eaa50c46b924aa255b892b03a9a0 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 14:51:00 +0530 Subject: [PATCH 03/15] fix: parse API token issue time correctly --- app/main/controllers/api/RTMediaJsonApi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/controllers/api/RTMediaJsonApi.php b/app/main/controllers/api/RTMediaJsonApi.php index 769dd1453..44d2072bd 100644 --- a/app/main/controllers/api/RTMediaJsonApi.php +++ b/app/main/controllers/api/RTMediaJsonApi.php @@ -347,7 +347,7 @@ public function rtmedia_api_process_wp_login_request() { 'user_id' => intval( $user_login->ID ), 'ip' => $remote_addr, 'token' => sanitize_text_field( $access_token ), - 'token_time' => date( 'Y-m-d H:i:s' ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date + 'token_time' => time(), ); $rtmapilogin->insert( $login_details ); wp_send_json( $this->rtmedia_api_response_object( 'TRUE', $ec_login_success, $msg_login_success, $data ) ); From c64c08f6551de797dbb40197e3e784d80df7c758 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 13:38:37 +0530 Subject: [PATCH 04/15] fix: add rate limiting for API authentication --- .../controllers/api/RTMediaApiRateLimiter.php | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 app/main/controllers/api/RTMediaApiRateLimiter.php diff --git a/app/main/controllers/api/RTMediaApiRateLimiter.php b/app/main/controllers/api/RTMediaApiRateLimiter.php new file mode 100644 index 000000000..1afff6390 --- /dev/null +++ b/app/main/controllers/api/RTMediaApiRateLimiter.php @@ -0,0 +1,240 @@ +get_attempts( $this->get_key( 'login_ip', $this->get_client_ip() ) ) >= $this->get_login_ip_limit() + || $this->get_attempts( $this->get_key( 'login_id', $this->normalize_identifier( $identifier ) ) ) >= $this->get_login_identifier_limit(); + } + + /** + * Record a failed login attempt. + * + * @param string $identifier Username or email address supplied for login. + */ + public function record_login_failure( $identifier ) { + $this->increment( $this->get_key( 'login_ip', $this->get_client_ip() ) ); + $this->increment( $this->get_key( 'login_id', $this->normalize_identifier( $identifier ) ) ); + } + + /** + * Clear the identifier bucket after a successful login. + * + * The IP bucket is deliberately retained so an attacker cannot reset it by + * successfully authenticating an account they control. + * + * @param string $identifier Username or email address supplied for login. + */ + public function clear_login_identifier( $identifier ) { + $this->delete( $this->get_key( 'login_id', $this->normalize_identifier( $identifier ) ) ); + } + + /** + * Check whether invalid token submissions should be blocked for this client. + * + * @return bool + */ + public function is_token_validation_blocked() { + return $this->get_attempts( $this->get_key( 'token_ip', $this->get_client_ip() ) ) >= $this->get_token_limit(); + } + + /** + * Record an invalid token submission. + */ + public function record_token_failure() { + $this->increment( $this->get_key( 'token_ip', $this->get_client_ip() ) ); + } + + /** + * Return the rate-limit window in seconds. + * + * @return int + */ + public function get_window() { + $window = (int) apply_filters( 'rtmedia_api_rate_limit_window', 5 * MINUTE_IN_SECONDS ); + + return max( MINUTE_IN_SECONDS, $window ); + } + + /** + * Increment a rate-limit bucket and return the new count. + * + * When a persistent object cache is active (Redis, Memcached, etc.), the + * increment is atomic: wp_cache_add() seeds the key exactly once and + * wp_cache_incr() is a single atomic operation on the cache backend, so + * concurrent requests cannot race on a read-modify-write cycle. + * + * Without a persistent object cache, this falls back to a transient + * (stored in wp_options). That fallback is NOT atomic: two concurrent + * requests can both read the same count and both write count+1, silently + * losing an increment. + * + * @param string $key Bucket key. + * + * @return int + */ + private function increment( $key ) { + $window = $this->get_window(); + + if ( wp_using_ext_object_cache() ) { + // Seed the key only if absent; wp_cache_add() itself is atomic + // (no-op if the key already exists), so this never clobbers an + // in-flight counter from a concurrent request. + wp_cache_add( $key, 0, self::CACHE_GROUP, $window ); + + $count = wp_cache_incr( $key, 1, self::CACHE_GROUP ); + + // wp_cache_incr() can return false if the key expired between + // the add() above and the incr() call. Reseed at 1 in that case. + if ( false === $count ) { + wp_cache_set( $key, 1, self::CACHE_GROUP, $window ); + $count = 1; + } + + return (int) $count; + } + + // Transient fallback — see race-condition note in the docblock above. + $count = $this->get_attempts( $key ) + 1; + set_transient( $key, $count, $window ); + + return $count; + } + + /** + * Get the number of attempts in a bucket. + * + * @param string $key Bucket key. + * + * @return int + */ + private function get_attempts( $key ) { + if ( wp_using_ext_object_cache() ) { + $count = wp_cache_get( $key, self::CACHE_GROUP ); + + return false === $count ? 0 : (int) $count; + } + + return (int) get_transient( $key ); + } + + /** + * Delete a bucket, regardless of backend. + * + * @param string $key Bucket key. + */ + private function delete( $key ) { + if ( wp_using_ext_object_cache() ) { + wp_cache_delete( $key, self::CACHE_GROUP ); + + return; + } + + delete_transient( $key ); + } + + /** + * Create a bounded, non-reversible bucket key. + * + * @param string $scope Rate-limit scope. + * @param string $identifier Client or login identifier. + * + * @return string + */ + private function get_key( $scope, $identifier ) { + return 'rtm_api_rl_' . $scope . '_' . substr( wp_hash( (string) $identifier, 'auth' ), 0, 32 ); + } + + /** + * Get the client IP address to key rate limits on. + * + * By default only REMOTE_ADDR is trusted. Proxy headers such as + * X-Forwarded-For or CF-Connecting-IP are never read here because they + * can be forged by the client unless a specific, known reverse proxy + * strips and rewrites them first — and this plugin has no way to know + * whether that's true for any given install. + * + * @return string + */ + private function get_client_ip() { + $remote_addr = rtm_get_server_var( 'REMOTE_ADDR', 'FILTER_VALIDATE_IP' ); + $remote_addr = $remote_addr ? $remote_addr : 'unknown'; + + /** + * Filters the client IP address used for API rate limiting. + * + * @param string $remote_addr The address read from REMOTE_ADDR. + */ + $client_ip = apply_filters( 'rtmedia_api_client_ip', $remote_addr ); + + $client_ip = is_string( $client_ip ) ? trim( $client_ip ) : ''; + + // Validate whatever the filter returned; never trust it blindly, + // since a badly written filter could hand back attacker-controlled + // input straight from an unvalidated header. + return filter_var( $client_ip, FILTER_VALIDATE_IP ) ? $client_ip : 'unknown'; + } + + /** + * Normalize a login identifier before deriving its rate-limit key. + * + * @param string $identifier Username or email address. + * + * @return string + */ + private function normalize_identifier( $identifier ) { + return strtolower( trim( (string) $identifier ) ); + } + + /** + * Get the maximum login failures allowed per IP address. + * + * @return int + */ + private function get_login_ip_limit() { + return max( 1, (int) apply_filters( 'rtmedia_api_login_ip_limit', 20 ) ); + } + + /** + * Get the maximum login failures allowed per identifier. + * + * @return int + */ + private function get_login_identifier_limit() { + return max( 1, (int) apply_filters( 'rtmedia_api_login_identifier_limit', 5 ) ); + } + + /** + * Get the maximum invalid token submissions allowed per IP address. + * + * @return int + */ + private function get_token_limit() { + return max( 1, (int) apply_filters( 'rtmedia_api_token_attempt_limit', 20 ) ); + } +} From c94b231cab33d239c6471a2bc36f5b9217ebf280 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 13:58:07 +0530 Subject: [PATCH 05/15] fix: add rate limiting and generic API login errors --- app/main/controllers/api/RTMediaJsonApi.php | 48 ++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/app/main/controllers/api/RTMediaJsonApi.php b/app/main/controllers/api/RTMediaJsonApi.php index 44d2072bd..051a9a9b3 100644 --- a/app/main/controllers/api/RTMediaJsonApi.php +++ b/app/main/controllers/api/RTMediaJsonApi.php @@ -137,6 +137,20 @@ class RTMediaJsonApi { */ public $msg_api_disabled = 'API disabled by site administrator'; + /** + * Error code for rate-limited API requests. + * + * @var int + */ + public $ec_rate_limit_exceeded = 600010; + + /** + * Error message for rate-limited API requests. + * + * @var string + */ + public $msg_rate_limit_exceeded = 'too many requests; please try again later'; + /** * Object of RTMediaJsonApiFunctions class to handle api requests. * @@ -306,33 +320,37 @@ public function rtmedia_api_process_wp_login_request() { $ec_user_pass_missing = 200001; $msg_user_pass_missing = esc_html__( 'username/password empty', 'buddypress-media' ); - $ec_incorrect_username = 200002; - $msg_incorrect_username = esc_html__( 'incorrect username', 'buddypress-media' ); + $ec_invalid_credentials = 200003; + $msg_invalid_credentials = esc_html__( 'invalid username or password', 'buddypress-media' ); - $ec_incorrect_pass = 200003; - $msg_incorrect_pass = esc_html__( 'incorrect password', 'buddypress-media' ); + $ec_login_rate_limited = 200005; + $msg_login_rate_limited = esc_html__( 'too many login attempts; please try again later', 'buddypress-media' ); $ec_login_success = 200004; $msg_login_success = esc_html__( 'login success', 'buddypress-media' ); - $username = sanitize_text_field( filter_input( INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); - $password = sanitize_text_field( filter_input( INPUT_POST, 'password', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); + $username = filter_input( INPUT_POST, 'username', FILTER_UNSAFE_RAW ); + $password = filter_input( INPUT_POST, 'password', FILTER_UNSAFE_RAW ); + $username = is_string( $username ) ? sanitize_text_field( $username ) : ''; + $password = is_string( $password ) ? $password : ''; if ( empty( $username ) || empty( $password ) ) { wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_user_pass_missing, $msg_user_pass_missing ) ); } else { - $user_login = wp_authenticate( trim( $username ), trim( $password ) ); + $rate_limiter = new RTMediaApiRateLimiter(); - if ( is_wp_error( $user_login ) ) { + if ( $rate_limiter->is_login_blocked( $username ) ) { + header( 'Retry-After: ' . $rate_limiter->get_window() ); + status_header( 429 ); + wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_login_rate_limited, $msg_login_rate_limited ) ); + } - $incorrect_password = ! empty( $user_login->errors['incorrect_password'] ) ? true : false; - $incorrect_username = ! empty( $user_login->errors['invalid_username'] ) ? true : false; + $user_login = wp_authenticate( trim( $username ), $password ); - if ( $incorrect_password ) { - wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_incorrect_pass, $msg_incorrect_pass ) ); - } elseif ( $incorrect_username ) { - wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_incorrect_username, $msg_incorrect_username ) ); - } + if ( is_wp_error( $user_login ) ) { + $rate_limiter->record_login_failure( $username ); + wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_invalid_credentials, $msg_invalid_credentials ) ); } else { + $rate_limiter->clear_login_identifier( $username ); $access_token = $this->rtmediajsonapifunction->rtmedia_api_get_user_token( $user_login->ID, $user_login->data->user_login ); $data = array( From 4d87a5fb06115fdb1b2ae15dab1cd782b007f0c4 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 13:58:29 +0530 Subject: [PATCH 06/15] fix: enforce rate limits during API token validation --- .../controllers/api/RTMediaJsonApiFunctions.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/main/controllers/api/RTMediaJsonApiFunctions.php b/app/main/controllers/api/RTMediaJsonApiFunctions.php index e88067f68..a114ddbbb 100644 --- a/app/main/controllers/api/RTMediaJsonApiFunctions.php +++ b/app/main/controllers/api/RTMediaJsonApiFunctions.php @@ -157,7 +157,7 @@ public function rtmedia_api_get_user_id_from_token( $token ) { } $token_data = $this->rtmedia_api_validate_token( $token ); if ( empty( $token_data ) ) { - return false; + return false; } return $token_data[0]->user_id; @@ -167,17 +167,25 @@ public function rtmedia_api_get_user_id_from_token( $token ) { * Token processing for all data fetch/post requests */ public function rtmedia_api_verfiy_token() { - $rtmjsonapi = new RTMediaJsonApi(); - $token = sanitize_text_field( filter_input( INPUT_POST, 'token', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); + $rtmjsonapi = new RTMediaJsonApi(); + $rate_limiter = new RTMediaApiRateLimiter(); + $token = sanitize_text_field( filter_input( INPUT_POST, 'token', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); if ( empty( $token ) ) { wp_send_json( $rtmjsonapi->rtmedia_api_response_object( 'FALSE', $rtmjsonapi->ec_token_missing, $rtmjsonapi->msg_token_missing ) ); } + if ( $rate_limiter->is_token_validation_blocked() ) { + header( 'Retry-After: ' . $rate_limiter->get_window() ); + status_header( 429 ); + wp_send_json( $rtmjsonapi->rtmedia_api_response_object( 'FALSE', $rtmjsonapi->ec_rate_limit_exceeded, $rtmjsonapi->msg_rate_limit_exceeded ) ); + } + // Validate token. $token_valid = $this->rtmedia_api_validate_token( $token ); if ( ! $token_valid ) { + $rate_limiter->record_token_failure(); wp_send_json( $rtmjsonapi->rtmedia_api_response_object( 'FALSE', $rtmjsonapi->ec_token_invalid, $rtmjsonapi->msg_token_invalid ) ); } } From 72fa3521deae0a97b1f30a381a5ab8a5f18b7554 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 17:21:00 +0530 Subject: [PATCH 07/15] fix: use unique error code for login rate limiting --- app/main/controllers/api/RTMediaJsonApi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/controllers/api/RTMediaJsonApi.php b/app/main/controllers/api/RTMediaJsonApi.php index 051a9a9b3..7df2cb31e 100644 --- a/app/main/controllers/api/RTMediaJsonApi.php +++ b/app/main/controllers/api/RTMediaJsonApi.php @@ -323,7 +323,7 @@ public function rtmedia_api_process_wp_login_request() { $ec_invalid_credentials = 200003; $msg_invalid_credentials = esc_html__( 'invalid username or password', 'buddypress-media' ); - $ec_login_rate_limited = 200005; + $ec_login_rate_limited = 200006; $msg_login_rate_limited = esc_html__( 'too many login attempts; please try again later', 'buddypress-media' ); $ec_login_success = 200004; From e0dafec56d0af25df893111fa0fdafd6a21d0159 Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 17:24:05 +0530 Subject: [PATCH 08/15] refactor: define constants for rate limit defaults --- .../controllers/api/RTMediaApiRateLimiter.php | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/app/main/controllers/api/RTMediaApiRateLimiter.php b/app/main/controllers/api/RTMediaApiRateLimiter.php index 1afff6390..5b739c3c6 100644 --- a/app/main/controllers/api/RTMediaApiRateLimiter.php +++ b/app/main/controllers/api/RTMediaApiRateLimiter.php @@ -20,6 +20,34 @@ class RTMediaApiRateLimiter { */ const CACHE_GROUP = 'rtmedia_api_rate_limit'; + /** + * Default rate-limit window in seconds. + * + * @var int + */ + const DEFAULT_WINDOW = 300; + + /** + * Default maximum login failures per IP address. + * + * @var int + */ + const DEFAULT_LOGIN_IP_LIMIT = 20; + + /** + * Default maximum login failures per identifier. + * + * @var int + */ + const DEFAULT_LOGIN_IDENTIFIER_LIMIT = 5; + + /** + * Default maximum invalid token submissions per IP address. + * + * @var int + */ + const DEFAULT_TOKEN_ATTEMPT_LIMIT = 20; + /** * Check whether a login attempt should be blocked. * @@ -76,7 +104,7 @@ public function record_token_failure() { * @return int */ public function get_window() { - $window = (int) apply_filters( 'rtmedia_api_rate_limit_window', 5 * MINUTE_IN_SECONDS ); + $window = (int) apply_filters( 'rtmedia_api_rate_limit_window', self::DEFAULT_WINDOW ); return max( MINUTE_IN_SECONDS, $window ); } @@ -217,7 +245,7 @@ private function normalize_identifier( $identifier ) { * @return int */ private function get_login_ip_limit() { - return max( 1, (int) apply_filters( 'rtmedia_api_login_ip_limit', 20 ) ); + return max( 1, (int) apply_filters( 'rtmedia_api_login_ip_limit', self::DEFAULT_LOGIN_IP_LIMIT ) ); } /** @@ -226,7 +254,7 @@ private function get_login_ip_limit() { * @return int */ private function get_login_identifier_limit() { - return max( 1, (int) apply_filters( 'rtmedia_api_login_identifier_limit', 5 ) ); + return max( 1, (int) apply_filters( 'rtmedia_api_login_identifier_limit', self::DEFAULT_LOGIN_IDENTIFIER_LIMIT ) ); } /** @@ -235,6 +263,6 @@ private function get_login_identifier_limit() { * @return int */ private function get_token_limit() { - return max( 1, (int) apply_filters( 'rtmedia_api_token_attempt_limit', 20 ) ); + return max( 1, (int) apply_filters( 'rtmedia_api_token_attempt_limit', self::DEFAULT_TOKEN_ATTEMPT_LIMIT ) ); } } From 9fdca44c03a51ac7ef67b2eea0ec6f33b22c37ce Mon Sep 17 00:00:00 2001 From: elphizu Date: Wed, 26 Aug 2026 20:10:17 +0530 Subject: [PATCH 09/15] fix: preserve rate-limit transient expiry window --- .../controllers/api/RTMediaApiRateLimiter.php | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/app/main/controllers/api/RTMediaApiRateLimiter.php b/app/main/controllers/api/RTMediaApiRateLimiter.php index 5b739c3c6..a79106cbd 100644 --- a/app/main/controllers/api/RTMediaApiRateLimiter.php +++ b/app/main/controllers/api/RTMediaApiRateLimiter.php @@ -148,8 +148,26 @@ private function increment( $key ) { } // Transient fallback — see race-condition note in the docblock above. - $count = $this->get_attempts( $key ) + 1; - set_transient( $key, $count, $window ); + $now = time(); + $bucket = get_transient( $key ); + + if ( + ! is_array( $bucket ) + || ! isset( $bucket['count'], $bucket['expires_at'] ) + || ! is_numeric( $bucket['count'] ) + || ! is_numeric( $bucket['expires_at'] ) + || (int) $bucket['expires_at'] <= $now + ) { + $bucket = array( + 'count' => 0, + 'expires_at' => $now + $window, + ); + } + + $count = (int) $bucket['count'] + 1; + $bucket['count'] = $count; + $remaining = max( 1, (int) $bucket['expires_at'] - time() ); + set_transient( $key, $bucket, $remaining ); return $count; } @@ -168,7 +186,19 @@ private function get_attempts( $key ) { return false === $count ? 0 : (int) $count; } - return (int) get_transient( $key ); + $bucket = get_transient( $key ); + + if ( + ! is_array( $bucket ) + || ! isset( $bucket['count'], $bucket['expires_at'] ) + || ! is_numeric( $bucket['count'] ) + || ! is_numeric( $bucket['expires_at'] ) + || (int) $bucket['expires_at'] <= time() + ) { + return 0; + } + + return (int) $bucket['count']; } /** From 1f8b1109e5c67d8c5922403fefa2b10b12732402 Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 11:38:22 +0530 Subject: [PATCH 10/15] fix: return accurate rate-limit retry-after TTL --- .../controllers/api/RTMediaApiRateLimiter.php | 112 +++++++++++++++++- app/main/controllers/api/RTMediaJsonApi.php | 5 +- .../api/RTMediaJsonApiFunctions.php | 6 +- 3 files changed, 115 insertions(+), 8 deletions(-) diff --git a/app/main/controllers/api/RTMediaApiRateLimiter.php b/app/main/controllers/api/RTMediaApiRateLimiter.php index a79106cbd..5d2aba521 100644 --- a/app/main/controllers/api/RTMediaApiRateLimiter.php +++ b/app/main/controllers/api/RTMediaApiRateLimiter.php @@ -20,6 +20,13 @@ class RTMediaApiRateLimiter { */ const CACHE_GROUP = 'rtmedia_api_rate_limit'; + /** + * Suffix used for object-cache bucket expiry metadata. + * + * @var string + */ + const EXPIRY_KEY_SUFFIX = '_expires_at'; + /** * Default rate-limit window in seconds. * @@ -56,8 +63,33 @@ class RTMediaApiRateLimiter { * @return bool */ public function is_login_blocked( $identifier ) { - return $this->get_attempts( $this->get_key( 'login_ip', $this->get_client_ip() ) ) >= $this->get_login_ip_limit() - || $this->get_attempts( $this->get_key( 'login_id', $this->normalize_identifier( $identifier ) ) ) >= $this->get_login_identifier_limit(); + return 0 < $this->get_login_retry_after( $identifier ); + } + + /** + * Get the remaining time for blocked login buckets. + * + * When both the client IP and identifier buckets are blocking, the client + * must wait until both have expired, so return the longer remaining TTL. + * + * @param string $identifier Username or email address supplied for login. + * + * @return int Remaining seconds, or zero when the login is not blocked. + */ + public function get_login_retry_after( $identifier ) { + $ip_key = $this->get_key( 'login_ip', $this->get_client_ip() ); + $identifier_key = $this->get_key( 'login_id', $this->normalize_identifier( $identifier ) ); + $retry_after = 0; + + if ( $this->get_attempts( $ip_key ) >= $this->get_login_ip_limit() ) { + $retry_after = max( 1, $this->get_remaining_ttl( $ip_key ) ); + } + + if ( $this->get_attempts( $identifier_key ) >= $this->get_login_identifier_limit() ) { + $retry_after = max( $retry_after, 1, $this->get_remaining_ttl( $identifier_key ) ); + } + + return $retry_after; } /** @@ -88,7 +120,22 @@ public function clear_login_identifier( $identifier ) { * @return bool */ public function is_token_validation_blocked() { - return $this->get_attempts( $this->get_key( 'token_ip', $this->get_client_ip() ) ) >= $this->get_token_limit(); + return 0 < $this->get_token_retry_after(); + } + + /** + * Get the remaining time for a blocked token-validation bucket. + * + * @return int Remaining seconds, or zero when token validation is not blocked. + */ + public function get_token_retry_after() { + $key = $this->get_key( 'token_ip', $this->get_client_ip() ); + + if ( $this->get_attempts( $key ) < $this->get_token_limit() ) { + return 0; + } + + return max( 1, $this->get_remaining_ttl( $key ) ); } /** @@ -130,10 +177,21 @@ private function increment( $key ) { $window = $this->get_window(); if ( wp_using_ext_object_cache() ) { + $now = time(); + $expiry_key = $this->get_expiry_key( $key ); + // Seed the key only if absent; wp_cache_add() itself is atomic // (no-op if the key already exists), so this never clobbers an // in-flight counter from a concurrent request. - wp_cache_add( $key, 0, self::CACHE_GROUP, $window ); + $counter_added = wp_cache_add( $key, 0, self::CACHE_GROUP, $window ); + + // WordPress does not expose a cached key's remaining TTL. Store + // the absolute expiry separately so Retry-After can be accurate. + if ( $counter_added ) { + wp_cache_set( $expiry_key, $now + $window, self::CACHE_GROUP, $window ); + } else { + wp_cache_add( $expiry_key, $now + $window, self::CACHE_GROUP, $window ); + } $count = wp_cache_incr( $key, 1, self::CACHE_GROUP ); @@ -141,6 +199,7 @@ private function increment( $key ) { // the add() above and the incr() call. Reseed at 1 in that case. if ( false === $count ) { wp_cache_set( $key, 1, self::CACHE_GROUP, $window ); + wp_cache_set( $expiry_key, $now + $window, self::CACHE_GROUP, $window ); $count = 1; } @@ -201,6 +260,39 @@ private function get_attempts( $key ) { return (int) $bucket['count']; } + /** + * Get the remaining lifetime of a bucket. + * + * @param string $key Bucket key. + * + * @return int Remaining seconds, or zero when no valid expiry is available. + */ + private function get_remaining_ttl( $key ) { + if ( wp_using_ext_object_cache() ) { + $expires_at = wp_cache_get( $this->get_expiry_key( $key ), self::CACHE_GROUP ); + + // Counters created before expiry metadata was introduced may remain + // active for one window. Use the full window as a safe fallback. + if ( false === $expires_at || ! is_numeric( $expires_at ) ) { + return $this->get_window(); + } + + return max( 0, (int) $expires_at - time() ); + } + + $bucket = get_transient( $key ); + + if ( + ! is_array( $bucket ) + || ! isset( $bucket['expires_at'] ) + || ! is_numeric( $bucket['expires_at'] ) + ) { + return 0; + } + + return max( 0, (int) $bucket['expires_at'] - time() ); + } + /** * Delete a bucket, regardless of backend. * @@ -209,6 +301,7 @@ private function get_attempts( $key ) { private function delete( $key ) { if ( wp_using_ext_object_cache() ) { wp_cache_delete( $key, self::CACHE_GROUP ); + wp_cache_delete( $this->get_expiry_key( $key ), self::CACHE_GROUP ); return; } @@ -228,6 +321,17 @@ private function get_key( $scope, $identifier ) { return 'rtm_api_rl_' . $scope . '_' . substr( wp_hash( (string) $identifier, 'auth' ), 0, 32 ); } + /** + * Get the companion object-cache key for a bucket's absolute expiry. + * + * @param string $key Bucket key. + * + * @return string + */ + private function get_expiry_key( $key ) { + return $key . self::EXPIRY_KEY_SUFFIX; + } + /** * Get the client IP address to key rate limits on. * diff --git a/app/main/controllers/api/RTMediaJsonApi.php b/app/main/controllers/api/RTMediaJsonApi.php index 7df2cb31e..c7ea38509 100644 --- a/app/main/controllers/api/RTMediaJsonApi.php +++ b/app/main/controllers/api/RTMediaJsonApi.php @@ -337,9 +337,10 @@ public function rtmedia_api_process_wp_login_request() { wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_user_pass_missing, $msg_user_pass_missing ) ); } else { $rate_limiter = new RTMediaApiRateLimiter(); + $retry_after = $rate_limiter->get_login_retry_after( $username ); - if ( $rate_limiter->is_login_blocked( $username ) ) { - header( 'Retry-After: ' . $rate_limiter->get_window() ); + if ( 0 < $retry_after ) { + header( 'Retry-After: ' . $retry_after ); status_header( 429 ); wp_send_json( $this->rtmedia_api_response_object( 'FALSE', $ec_login_rate_limited, $msg_login_rate_limited ) ); } diff --git a/app/main/controllers/api/RTMediaJsonApiFunctions.php b/app/main/controllers/api/RTMediaJsonApiFunctions.php index a114ddbbb..152816258 100644 --- a/app/main/controllers/api/RTMediaJsonApiFunctions.php +++ b/app/main/controllers/api/RTMediaJsonApiFunctions.php @@ -175,8 +175,10 @@ public function rtmedia_api_verfiy_token() { wp_send_json( $rtmjsonapi->rtmedia_api_response_object( 'FALSE', $rtmjsonapi->ec_token_missing, $rtmjsonapi->msg_token_missing ) ); } - if ( $rate_limiter->is_token_validation_blocked() ) { - header( 'Retry-After: ' . $rate_limiter->get_window() ); + $retry_after = $rate_limiter->get_token_retry_after(); + + if ( 0 < $retry_after ) { + header( 'Retry-After: ' . $retry_after ); status_header( 429 ); wp_send_json( $rtmjsonapi->rtmedia_api_response_object( 'FALSE', $rtmjsonapi->ec_rate_limit_exceeded, $rtmjsonapi->msg_rate_limit_exceeded ) ); } From d42bc334c8e39e0fdba21ca99a186ecdcd8a235a Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 15:46:47 +0530 Subject: [PATCH 11/15] chore: force trigger ci From 23e3f69d44fbd1264ecf5b3dd04593bd2247673e Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 16:56:05 +0530 Subject: [PATCH 12/15] Version update v4.7.13 --- README.md | 11 +++- changelog.txt | 8 +++ index.php | 4 +- languages/buddpress-media.pot | 116 ++++++++++++++++----------------- languages/buddypress-media.pot | 116 ++++++++++++++++----------------- readme.txt | 14 +++- 6 files changed, 147 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 512d483c0..dae98ff5f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Add albums, photo, audio/video upload, privacy, sharing, front-end uploads & mor ![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=MU1JamdmRnppK0hhQy9QMU8wdDJ2MUEyb1ZuS0ljVFQvSHZ6anFvNzUxTT0tLXhUNnliTnZGcE5CcW93N0I1eXdnM3c9PQ==--8c124e667dd0c317618efde1bed2b260000916b6) -* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/) +* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/), [suryakantupadhyay](https://profiles.wordpress.org/suryakantupadhyay/) * **License:** [GPL v2 or later]( http://www.gnu.org/licenses/gpl-2.0.html) @@ -147,6 +147,13 @@ https://www.youtube.com/watch?v=dJrykKQGDcs ## Changelog ## +### 4.7.13 + +* FIXED + * Fixed insecure API token generation, validation and expiration. + * Fixed insufficient brute-force protection for API authentication and token validation. + * Fixed username enumeration through API login error responses. + ### 4.7.12 * FIXED * Fixed authorization checks for media, albums, comments and activity privacy so actions are limited to permitted users. @@ -1049,4 +1056,4 @@ rtMedia uses the following projects/sources for some functionality * [Magnific Popup](http://dimsemenov.com/plugins/magnific-popup/) for responsive lightbox * [getID3](http://getid3.sourceforge.net/) gets us some ID tags for the media * [Foundation](http://foundation.zurb.com/) for the media grid and layout -* [Backbone.js](http://backbonejs.org/) for an MVC architecture for the frontend +* [Backbone.js](http://backbonejs.org/) for an MVC architecture for the frontend \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index d1d0ccbbf..3bc0adb40 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,13 @@ == Changelog == += 4.7.13 [August 27, 2026] = + +* FIXED + * Fixed insecure API token generation, validation and expiration. + * Fixed insufficient brute-force protection for API authentication and token validation. + * Fixed username enumeration through API login error responses. + + = 4.7.12 [August 18, 2026] = * FIXED diff --git a/index.php b/index.php index f85316e0f..1ac75c42c 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ * Plugin Name: rtMedia for WordPress, BuddyPress and bbPress * Plugin URI: https://rtmedia.io/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media * Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously! - * Version: 4.7.12 + * Version: 4.7.13 * Requires at least: 4.9.6 * Text Domain: buddypress-media * Author: rtCamp @@ -26,7 +26,7 @@ /** * The version of the plugin */ - define( 'RTMEDIA_VERSION', '4.7.12' ); + define( 'RTMEDIA_VERSION', '4.7.13' ); } if ( ! defined( 'RTMEDIA_PATH' ) ) { diff --git a/languages/buddpress-media.pot b/languages/buddpress-media.pot index 099730dca..91eb52c51 100644 --- a/languages/buddpress-media.pot +++ b/languages/buddpress-media.pot @@ -2,14 +2,14 @@ # This file is distributed under the GPLv2 or later. msgid "" msgstr "" -"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.7.12\n" +"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.7.13\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/buddypress-media\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2026-08-17T13:32:53+00:00\n" +"POT-Creation-Date: 2026-08-27T11:14:49+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.12.0\n" "X-Domain: buddypress-media\n" @@ -2261,217 +2261,217 @@ msgstr "" msgid "%1$s commented on %2$s's %3$s" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:307 +#: app/main/controllers/api/RTMediaJsonApi.php:321 msgid "username/password empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:310 -msgid "incorrect username" +#: app/main/controllers/api/RTMediaJsonApi.php:324 +msgid "invalid username or password" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:313 -msgid "incorrect password" +#: app/main/controllers/api/RTMediaJsonApi.php:327 +msgid "too many login attempts; please try again later" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:316 +#: app/main/controllers/api/RTMediaJsonApi.php:330 msgid "login success" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:365 +#: app/main/controllers/api/RTMediaJsonApi.php:384 msgid "fields empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:368 +#: app/main/controllers/api/RTMediaJsonApi.php:387 msgid "invalid email" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:371 +#: app/main/controllers/api/RTMediaJsonApi.php:390 msgid "password do not match" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:374 +#: app/main/controllers/api/RTMediaJsonApi.php:393 msgid "username already registered" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:377 +#: app/main/controllers/api/RTMediaJsonApi.php:396 msgid "email already exists" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:380 +#: app/main/controllers/api/RTMediaJsonApi.php:399 msgid "new user created" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:383 +#: app/main/controllers/api/RTMediaJsonApi.php:402 msgid "user registration is not allowed" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:457 +#: app/main/controllers/api/RTMediaJsonApi.php:476 msgid "email empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:460 +#: app/main/controllers/api/RTMediaJsonApi.php:479 msgid "username/email not registered" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:463 +#: app/main/controllers/api/RTMediaJsonApi.php:482 msgid "reset link sent" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:497 +#: app/main/controllers/api/RTMediaJsonApi.php:516 msgid "Someone has asked to reset the password for the following site and username." msgstr "" #. translators: 1: Username. -#: app/main/controllers/api/RTMediaJsonApi.php:501 +#: app/main/controllers/api/RTMediaJsonApi.php:520 #, php-format msgid "Username: %s" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:502 +#: app/main/controllers/api/RTMediaJsonApi.php:521 msgid "To reset your password visit the following address, otherwise just ignore this email and nothing will happen." msgstr "" #. translators: 1: Blog name. -#: app/main/controllers/api/RTMediaJsonApi.php:507 +#: app/main/controllers/api/RTMediaJsonApi.php:526 #, php-format msgid "[%s] Password Reset" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:523 +#: app/main/controllers/api/RTMediaJsonApi.php:542 msgid "bp activities" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:526 +#: app/main/controllers/api/RTMediaJsonApi.php:545 msgid "user activities" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:535 +#: app/main/controllers/api/RTMediaJsonApi.php:554 msgid "no updates" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:558 +#: app/main/controllers/api/RTMediaJsonApi.php:577 msgid "comment content missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:561 +#: app/main/controllers/api/RTMediaJsonApi.php:580 msgid "comment posted" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:609 +#: app/main/controllers/api/RTMediaJsonApi.php:628 msgid "unliked media" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:612 +#: app/main/controllers/api/RTMediaJsonApi.php:631 msgid "liked media" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:704 +#: app/main/controllers/api/RTMediaJsonApi.php:723 msgid "no comments" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:707 +#: app/main/controllers/api/RTMediaJsonApi.php:726 msgid "media comments" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:771 +#: app/main/controllers/api/RTMediaJsonApi.php:790 msgid "no likes" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:774 +#: app/main/controllers/api/RTMediaJsonApi.php:793 msgid "media likes" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:835 +#: app/main/controllers/api/RTMediaJsonApi.php:854 msgid "invalid comment/media id" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:838 +#: app/main/controllers/api/RTMediaJsonApi.php:857 msgid "no comment id" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:841 +#: app/main/controllers/api/RTMediaJsonApi.php:860 msgid "comment deleted" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:945 +#: app/main/controllers/api/RTMediaJsonApi.php:964 msgid "no profile found" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:948 +#: app/main/controllers/api/RTMediaJsonApi.php:967 msgid "profile fields" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1050 +#: app/main/controllers/api/RTMediaJsonApi.php:1069 msgid "follow user id missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1053 +#: app/main/controllers/api/RTMediaJsonApi.php:1072 msgid "started following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1056 +#: app/main/controllers/api/RTMediaJsonApi.php:1075 msgid "already following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1089 +#: app/main/controllers/api/RTMediaJsonApi.php:1108 msgid "unfollow id missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1092 +#: app/main/controllers/api/RTMediaJsonApi.php:1111 msgid "stopped following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1095 +#: app/main/controllers/api/RTMediaJsonApi.php:1114 msgid "not following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1128 +#: app/main/controllers/api/RTMediaJsonApi.php:1147 msgid "name/location empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1131 +#: app/main/controllers/api/RTMediaJsonApi.php:1150 msgid "profile updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1160 -#: app/main/controllers/api/RTMediaJsonApi.php:1188 +#: app/main/controllers/api/RTMediaJsonApi.php:1179 +#: app/main/controllers/api/RTMediaJsonApi.php:1207 msgid "no file" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1163 -#: app/main/controllers/api/RTMediaJsonApi.php:1200 +#: app/main/controllers/api/RTMediaJsonApi.php:1182 +#: app/main/controllers/api/RTMediaJsonApi.php:1219 msgid "upload failed, check size and file type" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1166 +#: app/main/controllers/api/RTMediaJsonApi.php:1185 msgid "avatar updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1191 +#: app/main/controllers/api/RTMediaJsonApi.php:1210 msgid "invalid file type. jpeg and png are allowed." msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1194 +#: app/main/controllers/api/RTMediaJsonApi.php:1213 msgid "image type missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1197 +#: app/main/controllers/api/RTMediaJsonApi.php:1216 msgid "no title" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1203 +#: app/main/controllers/api/RTMediaJsonApi.php:1222 msgid "media updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1417 +#: app/main/controllers/api/RTMediaJsonApi.php:1436 msgid "media list" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1420 +#: app/main/controllers/api/RTMediaJsonApi.php:1439 msgid "no media found for requested media type" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1538 +#: app/main/controllers/api/RTMediaJsonApi.php:1557 msgid "single media" msgstr "" diff --git a/languages/buddypress-media.pot b/languages/buddypress-media.pot index 584709b10..4aa99a7b7 100644 --- a/languages/buddypress-media.pot +++ b/languages/buddypress-media.pot @@ -2,14 +2,14 @@ # This file is distributed under the GPLv2 or later. msgid "" msgstr "" -"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.7.12\n" +"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.7.13\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/buddypress-media\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2026-08-17T19:10:32+00:00\n" +"POT-Creation-Date: 2026-08-27T11:14:44+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.12.0\n" "X-Domain: buddypress-media\n" @@ -2261,217 +2261,217 @@ msgstr "" msgid "%1$s commented on %2$s's %3$s" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:307 +#: app/main/controllers/api/RTMediaJsonApi.php:321 msgid "username/password empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:310 -msgid "incorrect username" +#: app/main/controllers/api/RTMediaJsonApi.php:324 +msgid "invalid username or password" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:313 -msgid "incorrect password" +#: app/main/controllers/api/RTMediaJsonApi.php:327 +msgid "too many login attempts; please try again later" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:316 +#: app/main/controllers/api/RTMediaJsonApi.php:330 msgid "login success" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:365 +#: app/main/controllers/api/RTMediaJsonApi.php:384 msgid "fields empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:368 +#: app/main/controllers/api/RTMediaJsonApi.php:387 msgid "invalid email" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:371 +#: app/main/controllers/api/RTMediaJsonApi.php:390 msgid "password do not match" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:374 +#: app/main/controllers/api/RTMediaJsonApi.php:393 msgid "username already registered" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:377 +#: app/main/controllers/api/RTMediaJsonApi.php:396 msgid "email already exists" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:380 +#: app/main/controllers/api/RTMediaJsonApi.php:399 msgid "new user created" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:383 +#: app/main/controllers/api/RTMediaJsonApi.php:402 msgid "user registration is not allowed" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:457 +#: app/main/controllers/api/RTMediaJsonApi.php:476 msgid "email empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:460 +#: app/main/controllers/api/RTMediaJsonApi.php:479 msgid "username/email not registered" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:463 +#: app/main/controllers/api/RTMediaJsonApi.php:482 msgid "reset link sent" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:497 +#: app/main/controllers/api/RTMediaJsonApi.php:516 msgid "Someone has asked to reset the password for the following site and username." msgstr "" #. translators: 1: Username. -#: app/main/controllers/api/RTMediaJsonApi.php:501 +#: app/main/controllers/api/RTMediaJsonApi.php:520 #, php-format msgid "Username: %s" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:502 +#: app/main/controllers/api/RTMediaJsonApi.php:521 msgid "To reset your password visit the following address, otherwise just ignore this email and nothing will happen." msgstr "" #. translators: 1: Blog name. -#: app/main/controllers/api/RTMediaJsonApi.php:507 +#: app/main/controllers/api/RTMediaJsonApi.php:526 #, php-format msgid "[%s] Password Reset" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:523 +#: app/main/controllers/api/RTMediaJsonApi.php:542 msgid "bp activities" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:526 +#: app/main/controllers/api/RTMediaJsonApi.php:545 msgid "user activities" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:535 +#: app/main/controllers/api/RTMediaJsonApi.php:554 msgid "no updates" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:558 +#: app/main/controllers/api/RTMediaJsonApi.php:577 msgid "comment content missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:561 +#: app/main/controllers/api/RTMediaJsonApi.php:580 msgid "comment posted" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:609 +#: app/main/controllers/api/RTMediaJsonApi.php:628 msgid "unliked media" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:612 +#: app/main/controllers/api/RTMediaJsonApi.php:631 msgid "liked media" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:704 +#: app/main/controllers/api/RTMediaJsonApi.php:723 msgid "no comments" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:707 +#: app/main/controllers/api/RTMediaJsonApi.php:726 msgid "media comments" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:771 +#: app/main/controllers/api/RTMediaJsonApi.php:790 msgid "no likes" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:774 +#: app/main/controllers/api/RTMediaJsonApi.php:793 msgid "media likes" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:835 +#: app/main/controllers/api/RTMediaJsonApi.php:854 msgid "invalid comment/media id" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:838 +#: app/main/controllers/api/RTMediaJsonApi.php:857 msgid "no comment id" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:841 +#: app/main/controllers/api/RTMediaJsonApi.php:860 msgid "comment deleted" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:945 +#: app/main/controllers/api/RTMediaJsonApi.php:964 msgid "no profile found" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:948 +#: app/main/controllers/api/RTMediaJsonApi.php:967 msgid "profile fields" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1050 +#: app/main/controllers/api/RTMediaJsonApi.php:1069 msgid "follow user id missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1053 +#: app/main/controllers/api/RTMediaJsonApi.php:1072 msgid "started following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1056 +#: app/main/controllers/api/RTMediaJsonApi.php:1075 msgid "already following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1089 +#: app/main/controllers/api/RTMediaJsonApi.php:1108 msgid "unfollow id missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1092 +#: app/main/controllers/api/RTMediaJsonApi.php:1111 msgid "stopped following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1095 +#: app/main/controllers/api/RTMediaJsonApi.php:1114 msgid "not following" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1128 +#: app/main/controllers/api/RTMediaJsonApi.php:1147 msgid "name/location empty" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1131 +#: app/main/controllers/api/RTMediaJsonApi.php:1150 msgid "profile updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1160 -#: app/main/controllers/api/RTMediaJsonApi.php:1188 +#: app/main/controllers/api/RTMediaJsonApi.php:1179 +#: app/main/controllers/api/RTMediaJsonApi.php:1207 msgid "no file" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1163 -#: app/main/controllers/api/RTMediaJsonApi.php:1200 +#: app/main/controllers/api/RTMediaJsonApi.php:1182 +#: app/main/controllers/api/RTMediaJsonApi.php:1219 msgid "upload failed, check size and file type" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1166 +#: app/main/controllers/api/RTMediaJsonApi.php:1185 msgid "avatar updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1191 +#: app/main/controllers/api/RTMediaJsonApi.php:1210 msgid "invalid file type. jpeg and png are allowed." msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1194 +#: app/main/controllers/api/RTMediaJsonApi.php:1213 msgid "image type missing" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1197 +#: app/main/controllers/api/RTMediaJsonApi.php:1216 msgid "no title" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1203 +#: app/main/controllers/api/RTMediaJsonApi.php:1222 msgid "media updated" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1417 +#: app/main/controllers/api/RTMediaJsonApi.php:1436 msgid "media list" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1420 +#: app/main/controllers/api/RTMediaJsonApi.php:1439 msgid "no media found for requested media type" msgstr "" -#: app/main/controllers/api/RTMediaJsonApi.php:1538 +#: app/main/controllers/api/RTMediaJsonApi.php:1557 msgid "single media" msgstr "" diff --git a/readme.txt b/readme.txt index 6acad4f03..36e2e2405 100644 --- a/readme.txt +++ b/readme.txt @@ -1,11 +1,11 @@ === rtMedia for WordPress, BuddyPress and bbPress === -Contributors: rtcamp, mangeshp, sanket.parmar, pranalipatel, jignesh.nakrani, manishsongirkar36, kiranpotphode, yahil, 1naveengiri, bhargavbhandari90, raftaar1191, rittesh.patel, sagarjadhav, pushpak.pop, faishal, desaiuditd, rahul286, JoshuaAbenazer, gagan0123, saurabhshukla, nitun.lanjewar, umesh.nevase, suhasgirgaonkar, neerukoul, hrishiv90, kanakiyajay, jarretc, tobiaskluge, rafaelfunchal, UmeshSingla, mehulkaklotar, tannermirabel, kishores, chandrapatel, rahul3883, nomnom99, sayanchakraborty, milindmore22, thrijith, abhijitrakas, sid177, montu3366, jashwini, juhise, ravatparmar, dharmin16, malavvasita, pooja1210, krupajnanda, surajkumarsingh, kanumalivad, dishitpala, shobhit2412, vaishu.agola27, kapilpaul, opurockey, vkd007, pavanpatil1, pradeep1308, shardul200, sabbir1991, kamalahmed, ibnulk, harshbarach, Mukulsingh27, vishalkakadiya, elifvish, krupajnanda, utsavladani, krishana79, rohitmathur7, kuldipchaudhary, mchirag2002, vedantgandhi28, mohamedahamed, the-hercules +Contributors: rtcamp, mangeshp, sanket.parmar, pranalipatel, jignesh.nakrani, manishsongirkar36, kiranpotphode, yahil, 1naveengiri, bhargavbhandari90, raftaar1191, rittesh.patel, sagarjadhav, pushpak.pop, faishal, desaiuditd, rahul286, JoshuaAbenazer, gagan0123, saurabhshukla, nitun.lanjewar, umesh.nevase, suhasgirgaonkar, neerukoul, hrishiv90, kanakiyajay, jarretc, tobiaskluge, rafaelfunchal, UmeshSingla, mehulkaklotar, tannermirabel, kishores, chandrapatel, rahul3883, nomnom99, sayanchakraborty, milindmore22, thrijith, abhijitrakas, sid177, montu3366, jashwini, juhise, ravatparmar, dharmin16, malavvasita, pooja1210, krupajnanda, surajkumarsingh, kanumalivad, dishitpala, shobhit2412, vaishu.agola27, kapilpaul, opurockey, vkd007, pavanpatil1, pradeep1308, shardul200, sabbir1991, kamalahmed, ibnulk, harshbarach, Mukulsingh27, vishalkakadiya, elifvish, krupajnanda, utsavladani, krishana79, rohitmathur7, kuldipchaudhary, mchirag2002, vedantgandhi28, mohamedahamed, the-hercules, suryakantupadhyay Tags: BuddyPress, media, multimedia, album, audio, music, video, photo, upload, share, MediaElement.js, media-node, rtMedia, WordPress, bbPress, masonry License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Requires at least: 4.9.6 Tested up to: 7.0 -Stable tag: 4.7.12 +Stable tag: 4.7.13 Add albums, photo, audio/video upload, privacy, sharing, front-end uploads & more. All this works on mobile/tablets devices. @@ -128,6 +128,13 @@ http://www.youtube.com/watch?v=dJrykKQGDcs == Changelog == += 4.7.13 [August 27, 2026] = + +* FIXED + * Fixed insecure API token generation, validation and expiration. + * Fixed insufficient brute-force protection for API authentication and token validation. + * Fixed username enumeration through API login error responses. + = 4.7.12 [August 18, 2026] = * FIXED @@ -1017,6 +1024,9 @@ http://www.youtube.com/watch?v=dJrykKQGDcs == Upgrade Notice == += 4.7.13 = +This release includes important security improvements for API authentication and tokens. Existing API users must log in again to receive a new token. We strongly recommend upgrading. + = 4.7.12 = This release includes important security fixes and permission improvements. We strongly recommend upgrading. From c89196457cb6aa561843fb778e8d46e7d4ab9668 Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 17:24:47 +0530 Subject: [PATCH 13/15] add thehercules to contributors --- README.md | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dae98ff5f..ff19774fa 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Add albums, photo, audio/video upload, privacy, sharing, front-end uploads & mor ![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=MU1JamdmRnppK0hhQy9QMU8wdDJ2MUEyb1ZuS0ljVFQvSHZ6anFvNzUxTT0tLXhUNnliTnZGcE5CcW93N0I1eXdnM3c9PQ==--8c124e667dd0c317618efde1bed2b260000916b6) -* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/), [suryakantupadhyay](https://profiles.wordpress.org/suryakantupadhyay/) +* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/),[thehercules](https://profiles.wordpress.org/thehercules/) [suryakantupadhyay](https://profiles.wordpress.org/suryakantupadhyay/) * **License:** [GPL v2 or later]( http://www.gnu.org/licenses/gpl-2.0.html) diff --git a/readme.txt b/readme.txt index 36e2e2405..f62f0122e 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ === rtMedia for WordPress, BuddyPress and bbPress === -Contributors: rtcamp, mangeshp, sanket.parmar, pranalipatel, jignesh.nakrani, manishsongirkar36, kiranpotphode, yahil, 1naveengiri, bhargavbhandari90, raftaar1191, rittesh.patel, sagarjadhav, pushpak.pop, faishal, desaiuditd, rahul286, JoshuaAbenazer, gagan0123, saurabhshukla, nitun.lanjewar, umesh.nevase, suhasgirgaonkar, neerukoul, hrishiv90, kanakiyajay, jarretc, tobiaskluge, rafaelfunchal, UmeshSingla, mehulkaklotar, tannermirabel, kishores, chandrapatel, rahul3883, nomnom99, sayanchakraborty, milindmore22, thrijith, abhijitrakas, sid177, montu3366, jashwini, juhise, ravatparmar, dharmin16, malavvasita, pooja1210, krupajnanda, surajkumarsingh, kanumalivad, dishitpala, shobhit2412, vaishu.agola27, kapilpaul, opurockey, vkd007, pavanpatil1, pradeep1308, shardul200, sabbir1991, kamalahmed, ibnulk, harshbarach, Mukulsingh27, vishalkakadiya, elifvish, krupajnanda, utsavladani, krishana79, rohitmathur7, kuldipchaudhary, mchirag2002, vedantgandhi28, mohamedahamed, the-hercules, suryakantupadhyay +Contributors: rtcamp, mangeshp, sanket.parmar, pranalipatel, jignesh.nakrani, manishsongirkar36, kiranpotphode, yahil, 1naveengiri, bhargavbhandari90, raftaar1191, rittesh.patel, sagarjadhav, pushpak.pop, faishal, desaiuditd, rahul286, JoshuaAbenazer, gagan0123, saurabhshukla, nitun.lanjewar, umesh.nevase, suhasgirgaonkar, neerukoul, hrishiv90, kanakiyajay, jarretc, tobiaskluge, rafaelfunchal, UmeshSingla, mehulkaklotar, tannermirabel, kishores, chandrapatel, rahul3883, nomnom99, sayanchakraborty, milindmore22, thrijith, abhijitrakas, sid177, montu3366, jashwini, juhise, ravatparmar, dharmin16, malavvasita, pooja1210, krupajnanda, surajkumarsingh, kanumalivad, dishitpala, shobhit2412, vaishu.agola27, kapilpaul, opurockey, vkd007, pavanpatil1, pradeep1308, shardul200, sabbir1991, kamalahmed, ibnulk, harshbarach, Mukulsingh27, vishalkakadiya, elifvish, krupajnanda, utsavladani, krishana79, rohitmathur7, kuldipchaudhary, mchirag2002, vedantgandhi28, mohamedahamed, thehercules, suryakantupadhyay Tags: BuddyPress, media, multimedia, album, audio, music, video, photo, upload, share, MediaElement.js, media-node, rtMedia, WordPress, bbPress, masonry License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From 334aa980af4983242afd2b99d8cd97ba075f60c9 Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 17:26:51 +0530 Subject: [PATCH 14/15] docs: add missing contributors to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff19774fa..b1cd6edfd 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Add albums, photo, audio/video upload, privacy, sharing, front-end uploads & mor ![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=MU1JamdmRnppK0hhQy9QMU8wdDJ2MUEyb1ZuS0ljVFQvSHZ6anFvNzUxTT0tLXhUNnliTnZGcE5CcW93N0I1eXdnM3c9PQ==--8c124e667dd0c317618efde1bed2b260000916b6) -* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/),[thehercules](https://profiles.wordpress.org/thehercules/) [suryakantupadhyay](https://profiles.wordpress.org/suryakantupadhyay/) +* **Contributors:** [rtcamp](http://profiles.wordpress.org/rtcamp), [mangeshp](http://profiles.wordpress.org/mangeshp), [sanket.parmar](http://profiles.wordpress.org/sanket.parmar), [pranalipatel](http://profiles.wordpress.org/pranalipatel), [jignesh.nakrani](http://profiles.wordpress.org/jignesh.nakrani), [manishsongirkar36](http://profiles.wordpress.org/manishsongirkar36), [kiranpotphode](http://profiles.wordpress.org/kiranpotphode), [yahil](http://profiles.wordpress.org/yahil), [1naveengiri](http://profiles.wordpress.org/1naveengiri), [bhargavbhandari90](http://profiles.wordpress.org/bhargavbhandari90), [deepak1191](http://profiles.wordpress.org/deepak1191), [rittesh.patel](http://profiles.wordpress.org/rittesh.patel), [sagarjadhav](http://profiles.wordpress.org/sagarjadhav), [pushpak.pop](http://profiles.wordpress.org/pushpak.pop), [faishal](http://profiles.wordpress.org/faishal), [desaiuditd](http://profiles.wordpress.org/desaiuditd), [rahul286](http://profiles.wordpress.org/rahul286), [JoshuaAbenazer](http://profiles.wordpress.org/JoshuaAbenazer), [gagan0123](http://profiles.wordpress.org/gagan0123), [saurabhshukla](http://profiles.wordpress.org/saurabhshukla), [nitun.lanjewar](http://profiles.wordpress.org/nitun.lanjewar), [umesh.nevase](http://profiles.wordpress.org/umesh.nevase), [suhasgirgaonkar](http://profiles.wordpress.org/suhasgirgaonkar), [neerukoul](http://profiles.wordpress.org/neerukoul), [hrishiv90](http://profiles.wordpress.org/hrishiv90), [kanakiyajay](http://profiles.wordpress.org/kanakiyajay), [jarretc](http://profiles.wordpress.org/jarretc), [tobiaskluge](http://profiles.wordpress.org/tobiaskluge), [rafaelfunchal](http://profiles.wordpress.org/rafaelfunchal), [UmeshSingla](http://profiles.wordpress.org/UmeshSingla), [mehulkaklotar](http://profiles.wordpress.org/mehulkaklotar), [tannermirabel](http://profiles.wordpress.org/tannermirabel), [kishores](http://profiles.wordpress.org/kishores), [chandrapatel](http://profiles.wordpress.org/chandrapatel), [rahul3883](http://profiles.wordpress.org/rahul3883/), [nomnom99](http://profiles.wordpress.org/nomnom99), [sayanchakraborty](https://profiles.wordpress.org/sayanchakraborty), [milindmore22](https://profiles.wordpress.org/milindmore22), [thrijith](https://profiles.wordpress.org/thrijith), [abhijitrakas](https://profiles.wordpress.org/abhijitrakas), [sid177](https://profiles.wordpress.org/sid177), [montu3366](https://profiles.wordpress.org/montu3366), [jashwini](https://profiles.wordpress.org/jashwini), [juhise](https://profiles.wordpress.org/juhise), [ravatparmar](https://profiles.wordpress.org/ravatparmar), [dharmin16](https://profiles.wordpress.org/dharmin16), [malavvasita](https://profiles.wordpress.org/malavvasita), [pooja1210](https://profiles.wordpress.org/pooja1210), [krupajnanda](https://profiles.wordpress.org/krupajnanda), [kanumalivad](https://profiles.wordpress.org/kanumalivad), [surajkumarsingh](https://profiles.wordpress.org/surajkumarsingh), [dishitpala](https://profiles.wordpress.org/dishitpala), [shobhit2412](https://profiles.wordpress.org/shobhit2412/), [vkd007](https://profiles.wordpress.org/vkd007/), [vaishu.agola27](https://profiles.wordpress.org/vaishuagola27/), [kapilpaul](https://profiles.wordpress.org/kapilpaul/), [opurockey](https://profiles.wordpress.org/opurockey/), [pavanpatil1](https://profiles.wordpress.org/pavanpatil1/), [pradeep1308](https://profiles.wordpress.org/pradeep1308/), [shardul200](https://profiles.wordpress.org/shardul200/), [ibnulk](https://profiles.wordpress.org/ibnulk/), [sabbir1991](https://profiles.wordpress.org/sabbir1991/), [kamalahmed](https://profiles.wordpress.org/kamalahmed/), [harshbarach](https://profiles.wordpress.org/harshbarach/), [mukulsingh27](https://profiles.wordpress.org/mukulsingh27/), [vishalkakadiya](https://profiles.wordpress.org/vishalkakadiya/), [elifvish](https://profiles.wordpress.org/elifvish/), [krupajnanda](https://profiles.wordpress.org/krupajnanda/), [utsavladani](https://profiles.wordpress.org/utsavladani/),[krishana79](https://profiles.wordpress.org/krishana79/), [rohitmathur7](https://profiles.wordpress.org/rohitmathur7/), [kuldipchaudhary](https://profiles.wordpress.org/kuldipchaudhary/), [mchirag2002](https://profiles.wordpress.org/mchirag2002/), [vedantgandhi28](https://profiles.wordpress.org/vedantgandhi28/), [mohamedahamed](https://profiles.wordpress.org/mohamedahamed/),[thehercules](https://profiles.wordpress.org/thehercules/), [suryakantupadhyay](https://profiles.wordpress.org/suryakantupadhyay/) * **License:** [GPL v2 or later]( http://www.gnu.org/licenses/gpl-2.0.html) From 0bfb26bd99756d8e7e9b0eadf0902467505012b7 Mon Sep 17 00:00:00 2001 From: elphizu Date: Thu, 27 Aug 2026 17:30:48 +0530 Subject: [PATCH 15/15] chore: force trigger ci