Changeset 3778544
- Timestamp:
- 11/01/2026 08:51:37 PM (5 hours ago)
- Location:
- reactwoo-geocore
- Files:
-
- 12 edited
- 1 copied
-
tags/1.9.23 (copied) (copied from reactwoo-geocore/trunk )
-
tags/1.9.23/blocks/experience-slot/editor.asset.php (modified) (1 diff)
-
tags/1.9.23/blocks/geo-content/index.asset.php (modified) (1 diff)
-
tags/1.9.23/includes/class-rwgc-geoip.php (modified) (6 diffs)
-
tags/1.9.23/reactwoo-geocore.php (modified) (2 diffs)
-
tags/1.9.23/readme.txt (modified) (3 diffs)
-
tags/1.9.23/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/blocks/experience-slot/editor.asset.php (modified) (1 diff)
-
trunk/blocks/geo-content/index.asset.php (modified) (1 diff)
-
trunk/includes/class-rwgc-geoip.php (modified) (6 diffs)
-
trunk/reactwoo-geocore.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (3 diffs)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
reactwoo-geocore/tags/1.9.23/blocks/experience-slot/editor.asset.php
r3771487 r3778544 17 17 'wp-i18n', 18 18 ), 19 'version' => '1.9.2 2',19 'version' => '1.9.23', 20 20 ); -
reactwoo-geocore/tags/1.9.23/blocks/geo-content/index.asset.php
r3771487 r3778544 17 17 ), 18 18 'handle' => 'rwgc-geo-content-editor', 19 'version' => '1.9.2 2',19 'version' => '1.9.23', 20 20 ); -
reactwoo-geocore/tags/1.9.23/includes/class-rwgc-geoip.php
r3771487 r3778544 146 146 * is on. Private and loopback addresses are not trusted on their own. 147 147 * 148 * X-Forwarded-For, Forwarded, X-Real-IP, True-Client-IP, Client-IP, 149 * CF-Connecting-IP, and CF-IPCountry are ignored for every other peer. 150 * Behind a trusted proxy, X-Forwarded-For is walked from the right and 151 * trusted hops are skipped. The left-most value is never taken because it 152 * is first. CF-Connecting-IP is used only when Behind Cloudflare is on and 153 * REMOTE_ADDR is inside the bundled Cloudflare ranges. 148 * X-Forwarded-For, Forwarded, X-Forwarded, X-Real-IP, True-Client-IP, 149 * Client-IP, CF-Connecting-IP, and CF-IPCountry are ignored for every 150 * other peer. Behind a trusted proxy, X-Forwarded-For is walked from the 151 * right and trusted hops are skipped. The left-most value is never taken 152 * because it is first. X-Real-IP and True-Client-IP are used only when 153 * that walk has no public hop. Forwarded and X-Forwarded are used only 154 * when that walk found nothing and the proxy did not send X-Real-IP, 155 * True-Client-IP, or (while Behind Cloudflare is on) CF-Connecting-IP. 156 * A present proxy header blocks them even when its value is not a single 157 * public address, because nginx forwards a client Forwarded header unless 158 * it is cleared. CF-Connecting-IP is used only when Behind Cloudflare is 159 * on and REMOTE_ADDR is inside the bundled Cloudflare ranges. 154 160 * 155 161 * `rwgc_is_trusted_proxy` can force the trust decision. `rwgc_visitor_ip` … … 182 188 } 183 189 190 // Set when the proxy sent a client-address header. Forwarded and 191 // X-Forwarded stay client-controlled unless that proxy clears them, 192 // so they must not replace a header the proxy did send. 193 $proxy_set_client_header = false; 194 184 195 if ( self::cloudflare_headers_trusted( $remote ) ) { 185 $cf = self::first_public_ip( self::server_header( 'HTTP_CF_CONNECTING_IP' ) ); 186 if ( '' !== $cf && ! self::is_trusted_hop( $cf ) ) { 187 return $cf; 196 $cf_raw = self::server_header( 'HTTP_CF_CONNECTING_IP' ); 197 if ( '' !== $cf_raw ) { 198 $proxy_set_client_header = true; 199 $cf = self::first_public_ip( $cf_raw ); 200 if ( '' !== $cf && ! self::is_trusted_hop( $cf ) ) { 201 return $cf; 202 } 188 203 } 189 204 } … … 195 210 196 211 foreach ( array( 'HTTP_X_REAL_IP', 'HTTP_TRUE_CLIENT_IP' ) as $key ) { 197 $single = self::single_forwarded_ip( self::server_header( $key ) ); 212 $raw = self::server_header( $key ); 213 if ( '' === $raw ) { 214 continue; 215 } 216 $proxy_set_client_header = true; 217 $single = self::single_forwarded_ip( $raw ); 198 218 if ( '' !== $single && ! self::ips_equal( $single, $remote ) && ! self::is_trusted_hop( $single ) ) { 199 219 return $single; 220 } 221 } 222 223 if ( $proxy_set_client_header ) { 224 return $remote; 225 } 226 227 foreach ( array( 'HTTP_FORWARDED', 'HTTP_X_FORWARDED' ) as $key ) { 228 $from_forwarded = self::visitor_from_forwarding_header( self::server_header( $key ), $remote ); 229 if ( '' !== $from_forwarded ) { 230 return $from_forwarded; 200 231 } 201 232 } … … 275 306 $out = array(); 276 307 foreach ( explode( ',', (string) $header ) as $part ) { 277 $ip = trim( $part ); 278 if ( 0 === stripos( $ip, 'for=' ) ) { 279 $ip = trim( substr( $ip, 4 ), " \t\"[]" ); 280 } 281 $ip = trim( $ip, '[]' ); 308 $ip = self::ip_token_from_forwarded_part( $part ); 282 309 if ( self::is_public_ip( $ip ) ) { 283 310 $out[] = $ip; … … 285 312 } 286 313 return $out; 314 } 315 316 /** 317 * One address from an X-Forwarded-For hop or an RFC 7239 Forwarded element. 318 * 319 * `for=` may follow other parameters. A quoted value may be an IPv6 address 320 * in brackets. Parameters after the address are ignored. 321 * 322 * @param string $part Comma-separated element. 323 * @return string 324 */ 325 private static function ip_token_from_forwarded_part( $part ) { 326 $part = trim( (string) $part ); 327 if ( '' === $part ) { 328 return ''; 329 } 330 if ( false !== stripos( $part, 'for=' ) ) { 331 if ( ! preg_match( '/(?:^|;)\s*for=\s*("?)(\[[^\]]+\]|[^";,\s]+)\1/i', $part, $matches ) ) { 332 return ''; 333 } 334 return trim( $matches[2], " \t\"[]" ); 335 } 336 return trim( $part, '[]' ); 287 337 } 288 338 … … 710 760 711 761 /** 712 * Rightmost public forwarding hop that is not itself a trusted proxy. 713 * 714 * Reads X-Forwarded-For, then Forwarded, then X-Forwarded. When every public 715 * hop is a trusted proxy, the rightmost hop is kept. The left-most address 716 * is never chosen merely because it is first. 762 * Rightmost public X-Forwarded-For hop that is not itself a trusted proxy. 763 * 764 * When every public hop is a trusted proxy, the rightmost hop is kept. 765 * The left-most address is never chosen merely because it is first. 766 * Forwarded and X-Forwarded are not read here; a client can send those 767 * while the proxy overwrites X-Real-IP. 717 768 * 718 769 * @param string $remote REMOTE_ADDR. 719 * @return string Empty when the header s haveno public hop.770 * @return string Empty when the header has no public hop. 720 771 */ 721 772 private static function visitor_from_trusted_xff( $remote ) { 722 $ips = self::public_ips_from_header( self::server_header( 'HTTP_X_FORWARDED_FOR' ) ); 723 if ( empty( $ips ) ) { 724 $ips = self::public_ips_from_header( self::server_header( 'HTTP_FORWARDED' ) ); 725 } 726 if ( empty( $ips ) ) { 727 $ips = self::public_ips_from_header( self::server_header( 'HTTP_X_FORWARDED' ) ); 728 } 773 return self::visitor_from_forwarding_header( self::server_header( 'HTTP_X_FORWARDED_FOR' ), $remote ); 774 } 775 776 /** 777 * Rightmost public hop in one forwarding header that is not a trusted proxy. 778 * 779 * @param string $header Header value. 780 * @param string $remote REMOTE_ADDR. 781 * @return string Empty when the header has no public hop. 782 */ 783 private static function visitor_from_forwarding_header( $header, $remote ) { 784 $ips = self::public_ips_from_header( $header ); 729 785 $count = count( $ips ); 730 786 if ( 0 === $count ) { -
reactwoo-geocore/tags/1.9.23/reactwoo-geocore.php
r3771487 r3778544 4 4 * Plugin URI: https://reactwoo.com/geo-core/ 5 5 * Description: Country-targeted content for your website. MaxMind country detection, shortcodes, a Gutenberg block, REST, and country visibility rules. No ReactWoo product license is required for those features. 6 * Version: 1.9.2 26 * Version: 1.9.23 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 8.1 … … 20 20 // Core constants. 21 21 if ( ! defined( 'RWGC_VERSION' ) ) { 22 define( 'RWGC_VERSION', '1.9.2 2' );22 define( 'RWGC_VERSION', '1.9.23' ); 23 23 } 24 24 if ( ! defined( 'RWGC_FILE' ) ) { -
reactwoo-geocore/tags/1.9.23/readme.txt
r3771487 r3778544 5 5 Tested up to: 7.1 6 6 Requires PHP: 8.1 7 Stable tag: 1.9.2 27 Stable tag: 1.9.23 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 165 165 166 166 Recent releases are listed here. Older notes: https://github.com/reactwoo/reactwoo-geocore/blob/main/CHANGELOG.md and the history of this file on GitHub. 167 168 = 1.9.23 = 169 * A visitor can no longer choose a country by sending a Forwarded or X-Forwarded header when the proxy has set X-Real-IP or True-Client-IP. That stays true when the proxy header is present but is not a single public address. Cloudflare's CF-Connecting-IP is not replaced by those headers while Behind Cloudflare is on. 167 170 168 171 = 1.9.22 = … … 318 321 == Upgrade Notice == 319 322 323 = 1.9.23 = 324 A client Forwarded or X-Forwarded header no longer replaces the visitor address a trusted proxy set in X-Real-IP or True-Client-IP. Trusted proxies and Behind Cloudflare are unchanged from 1.9.22. 325 320 326 = 1.9.22 = 321 327 Visitor country is taken from the connection address unless you list a trusted proxy or turn on Behind Cloudflare. Sites that already use Cloudflare keep that behaviour until settings are saved. Review Settings → Detection after updating. -
reactwoo-geocore/tags/1.9.23/vendor/composer/installed.php
r3771487 r3778544 2 2 'root' => array( 3 3 'name' => 'reactwoo/reactwoo-geocore', 4 'pretty_version' => 'v1.9.2 2',5 'version' => '1.9.2 2.0',6 'reference' => ' 9f185d5845b72dd9904405ca456b8fa0a9a048c4',4 'pretty_version' => 'v1.9.23', 5 'version' => '1.9.23.0', 6 'reference' => 'c8b38ce5625d2ebf6131974846af8b92b2665400', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 48 48 ), 49 49 'reactwoo/reactwoo-geocore' => array( 50 'pretty_version' => 'v1.9.2 2',51 'version' => '1.9.2 2.0',52 'reference' => ' 9f185d5845b72dd9904405ca456b8fa0a9a048c4',50 'pretty_version' => 'v1.9.23', 51 'version' => '1.9.23.0', 52 'reference' => 'c8b38ce5625d2ebf6131974846af8b92b2665400', 53 53 'type' => 'wordpress-plugin', 54 54 'install_path' => __DIR__ . '/../../', -
reactwoo-geocore/trunk/blocks/experience-slot/editor.asset.php
r3771487 r3778544 17 17 'wp-i18n', 18 18 ), 19 'version' => '1.9.2 2',19 'version' => '1.9.23', 20 20 ); -
reactwoo-geocore/trunk/blocks/geo-content/index.asset.php
r3771487 r3778544 17 17 ), 18 18 'handle' => 'rwgc-geo-content-editor', 19 'version' => '1.9.2 2',19 'version' => '1.9.23', 20 20 ); -
reactwoo-geocore/trunk/includes/class-rwgc-geoip.php
r3771487 r3778544 146 146 * is on. Private and loopback addresses are not trusted on their own. 147 147 * 148 * X-Forwarded-For, Forwarded, X-Real-IP, True-Client-IP, Client-IP, 149 * CF-Connecting-IP, and CF-IPCountry are ignored for every other peer. 150 * Behind a trusted proxy, X-Forwarded-For is walked from the right and 151 * trusted hops are skipped. The left-most value is never taken because it 152 * is first. CF-Connecting-IP is used only when Behind Cloudflare is on and 153 * REMOTE_ADDR is inside the bundled Cloudflare ranges. 148 * X-Forwarded-For, Forwarded, X-Forwarded, X-Real-IP, True-Client-IP, 149 * Client-IP, CF-Connecting-IP, and CF-IPCountry are ignored for every 150 * other peer. Behind a trusted proxy, X-Forwarded-For is walked from the 151 * right and trusted hops are skipped. The left-most value is never taken 152 * because it is first. X-Real-IP and True-Client-IP are used only when 153 * that walk has no public hop. Forwarded and X-Forwarded are used only 154 * when that walk found nothing and the proxy did not send X-Real-IP, 155 * True-Client-IP, or (while Behind Cloudflare is on) CF-Connecting-IP. 156 * A present proxy header blocks them even when its value is not a single 157 * public address, because nginx forwards a client Forwarded header unless 158 * it is cleared. CF-Connecting-IP is used only when Behind Cloudflare is 159 * on and REMOTE_ADDR is inside the bundled Cloudflare ranges. 154 160 * 155 161 * `rwgc_is_trusted_proxy` can force the trust decision. `rwgc_visitor_ip` … … 182 188 } 183 189 190 // Set when the proxy sent a client-address header. Forwarded and 191 // X-Forwarded stay client-controlled unless that proxy clears them, 192 // so they must not replace a header the proxy did send. 193 $proxy_set_client_header = false; 194 184 195 if ( self::cloudflare_headers_trusted( $remote ) ) { 185 $cf = self::first_public_ip( self::server_header( 'HTTP_CF_CONNECTING_IP' ) ); 186 if ( '' !== $cf && ! self::is_trusted_hop( $cf ) ) { 187 return $cf; 196 $cf_raw = self::server_header( 'HTTP_CF_CONNECTING_IP' ); 197 if ( '' !== $cf_raw ) { 198 $proxy_set_client_header = true; 199 $cf = self::first_public_ip( $cf_raw ); 200 if ( '' !== $cf && ! self::is_trusted_hop( $cf ) ) { 201 return $cf; 202 } 188 203 } 189 204 } … … 195 210 196 211 foreach ( array( 'HTTP_X_REAL_IP', 'HTTP_TRUE_CLIENT_IP' ) as $key ) { 197 $single = self::single_forwarded_ip( self::server_header( $key ) ); 212 $raw = self::server_header( $key ); 213 if ( '' === $raw ) { 214 continue; 215 } 216 $proxy_set_client_header = true; 217 $single = self::single_forwarded_ip( $raw ); 198 218 if ( '' !== $single && ! self::ips_equal( $single, $remote ) && ! self::is_trusted_hop( $single ) ) { 199 219 return $single; 220 } 221 } 222 223 if ( $proxy_set_client_header ) { 224 return $remote; 225 } 226 227 foreach ( array( 'HTTP_FORWARDED', 'HTTP_X_FORWARDED' ) as $key ) { 228 $from_forwarded = self::visitor_from_forwarding_header( self::server_header( $key ), $remote ); 229 if ( '' !== $from_forwarded ) { 230 return $from_forwarded; 200 231 } 201 232 } … … 275 306 $out = array(); 276 307 foreach ( explode( ',', (string) $header ) as $part ) { 277 $ip = trim( $part ); 278 if ( 0 === stripos( $ip, 'for=' ) ) { 279 $ip = trim( substr( $ip, 4 ), " \t\"[]" ); 280 } 281 $ip = trim( $ip, '[]' ); 308 $ip = self::ip_token_from_forwarded_part( $part ); 282 309 if ( self::is_public_ip( $ip ) ) { 283 310 $out[] = $ip; … … 285 312 } 286 313 return $out; 314 } 315 316 /** 317 * One address from an X-Forwarded-For hop or an RFC 7239 Forwarded element. 318 * 319 * `for=` may follow other parameters. A quoted value may be an IPv6 address 320 * in brackets. Parameters after the address are ignored. 321 * 322 * @param string $part Comma-separated element. 323 * @return string 324 */ 325 private static function ip_token_from_forwarded_part( $part ) { 326 $part = trim( (string) $part ); 327 if ( '' === $part ) { 328 return ''; 329 } 330 if ( false !== stripos( $part, 'for=' ) ) { 331 if ( ! preg_match( '/(?:^|;)\s*for=\s*("?)(\[[^\]]+\]|[^";,\s]+)\1/i', $part, $matches ) ) { 332 return ''; 333 } 334 return trim( $matches[2], " \t\"[]" ); 335 } 336 return trim( $part, '[]' ); 287 337 } 288 338 … … 710 760 711 761 /** 712 * Rightmost public forwarding hop that is not itself a trusted proxy. 713 * 714 * Reads X-Forwarded-For, then Forwarded, then X-Forwarded. When every public 715 * hop is a trusted proxy, the rightmost hop is kept. The left-most address 716 * is never chosen merely because it is first. 762 * Rightmost public X-Forwarded-For hop that is not itself a trusted proxy. 763 * 764 * When every public hop is a trusted proxy, the rightmost hop is kept. 765 * The left-most address is never chosen merely because it is first. 766 * Forwarded and X-Forwarded are not read here; a client can send those 767 * while the proxy overwrites X-Real-IP. 717 768 * 718 769 * @param string $remote REMOTE_ADDR. 719 * @return string Empty when the header s haveno public hop.770 * @return string Empty when the header has no public hop. 720 771 */ 721 772 private static function visitor_from_trusted_xff( $remote ) { 722 $ips = self::public_ips_from_header( self::server_header( 'HTTP_X_FORWARDED_FOR' ) ); 723 if ( empty( $ips ) ) { 724 $ips = self::public_ips_from_header( self::server_header( 'HTTP_FORWARDED' ) ); 725 } 726 if ( empty( $ips ) ) { 727 $ips = self::public_ips_from_header( self::server_header( 'HTTP_X_FORWARDED' ) ); 728 } 773 return self::visitor_from_forwarding_header( self::server_header( 'HTTP_X_FORWARDED_FOR' ), $remote ); 774 } 775 776 /** 777 * Rightmost public hop in one forwarding header that is not a trusted proxy. 778 * 779 * @param string $header Header value. 780 * @param string $remote REMOTE_ADDR. 781 * @return string Empty when the header has no public hop. 782 */ 783 private static function visitor_from_forwarding_header( $header, $remote ) { 784 $ips = self::public_ips_from_header( $header ); 729 785 $count = count( $ips ); 730 786 if ( 0 === $count ) { -
reactwoo-geocore/trunk/reactwoo-geocore.php
r3771487 r3778544 4 4 * Plugin URI: https://reactwoo.com/geo-core/ 5 5 * Description: Country-targeted content for your website. MaxMind country detection, shortcodes, a Gutenberg block, REST, and country visibility rules. No ReactWoo product license is required for those features. 6 * Version: 1.9.2 26 * Version: 1.9.23 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 8.1 … … 20 20 // Core constants. 21 21 if ( ! defined( 'RWGC_VERSION' ) ) { 22 define( 'RWGC_VERSION', '1.9.2 2' );22 define( 'RWGC_VERSION', '1.9.23' ); 23 23 } 24 24 if ( ! defined( 'RWGC_FILE' ) ) { -
reactwoo-geocore/trunk/readme.txt
r3771487 r3778544 5 5 Tested up to: 7.1 6 6 Requires PHP: 8.1 7 Stable tag: 1.9.2 27 Stable tag: 1.9.23 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 165 165 166 166 Recent releases are listed here. Older notes: https://github.com/reactwoo/reactwoo-geocore/blob/main/CHANGELOG.md and the history of this file on GitHub. 167 168 = 1.9.23 = 169 * A visitor can no longer choose a country by sending a Forwarded or X-Forwarded header when the proxy has set X-Real-IP or True-Client-IP. That stays true when the proxy header is present but is not a single public address. Cloudflare's CF-Connecting-IP is not replaced by those headers while Behind Cloudflare is on. 167 170 168 171 = 1.9.22 = … … 318 321 == Upgrade Notice == 319 322 323 = 1.9.23 = 324 A client Forwarded or X-Forwarded header no longer replaces the visitor address a trusted proxy set in X-Real-IP or True-Client-IP. Trusted proxies and Behind Cloudflare are unchanged from 1.9.22. 325 320 326 = 1.9.22 = 321 327 Visitor country is taken from the connection address unless you list a trusted proxy or turn on Behind Cloudflare. Sites that already use Cloudflare keep that behaviour until settings are saved. Review Settings → Detection after updating. -
reactwoo-geocore/trunk/vendor/composer/installed.php
r3771487 r3778544 2 2 'root' => array( 3 3 'name' => 'reactwoo/reactwoo-geocore', 4 'pretty_version' => 'v1.9.2 2',5 'version' => '1.9.2 2.0',6 'reference' => ' 9f185d5845b72dd9904405ca456b8fa0a9a048c4',4 'pretty_version' => 'v1.9.23', 5 'version' => '1.9.23.0', 6 'reference' => 'c8b38ce5625d2ebf6131974846af8b92b2665400', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 48 48 ), 49 49 'reactwoo/reactwoo-geocore' => array( 50 'pretty_version' => 'v1.9.2 2',51 'version' => '1.9.2 2.0',52 'reference' => ' 9f185d5845b72dd9904405ca456b8fa0a9a048c4',50 'pretty_version' => 'v1.9.23', 51 'version' => '1.9.23.0', 52 'reference' => 'c8b38ce5625d2ebf6131974846af8b92b2665400', 53 53 'type' => 'wordpress-plugin', 54 54 'install_path' => __DIR__ . '/../../',
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)