| 7638 | |
| 7639 | /** |
| 7640 | * Determines the user's actual IP address and attempts to partially |
| 7641 | * anonymize an IP address by converting it to a network ID. |
| 7642 | * |
| 7643 | * Geolocating the network ID usually returns a similar location as the |
| 7644 | * actual IP, but provides some privacy for the user. |
| 7645 | * |
| 7646 | * $_SERVER['REMOTE_ADDR'] cannot be used in all cases, such as when the user |
| 7647 | * is making their request through a proxy, or when the web server is behind |
| 7648 | * a proxy. In those cases, $_SERVER['REMOTE_ADDR'] is set to the proxy address rather |
| 7649 | * than the user's actual address. |
| 7650 | * |
| 7651 | * Modified from https://stackoverflow.com/a/2031935/450127, MIT license. |
| 7652 | * Modified from https://github.com/geertw/php-ip-anonymizer, MIT license. |
| 7653 | * |
| 7654 | * SECURITY WARNING: This function is _NOT_ intended to be used in |
| 7655 | * circumstances where the authenticity of the IP address matters. This does |
| 7656 | * _NOT_ guarantee that the returned address is valid or accurate, and it can |
| 7657 | * be easily spoofed. |
| 7658 | * |
| 7659 | * @since 5.6.0 |
| 7660 | * |
| 7661 | * @return string|false The anonymized address on success; or false on failure. |
| 7662 | */ |
| 7663 | function wp_get_unsafe_client_ip() { |
| 7664 | $client_ip = false; |
| 7665 | |
| 7666 | // In order of preference, with the best ones for this purpose first. |
| 7667 | $address_headers = array( |
| 7668 | 'HTTP_CLIENT_IP', |
| 7669 | 'HTTP_X_FORWARDED_FOR', |
| 7670 | 'HTTP_X_FORWARDED', |
| 7671 | 'HTTP_X_CLUSTER_CLIENT_IP', |
| 7672 | 'HTTP_FORWARDED_FOR', |
| 7673 | 'HTTP_FORWARDED', |
| 7674 | 'REMOTE_ADDR', |
| 7675 | ); |
| 7676 | |
| 7677 | foreach ( $address_headers as $header ) { |
| 7678 | if ( array_key_exists( $header, $_SERVER ) ) { |
| 7679 | /* |
| 7680 | * HTTP_X_FORWARDED_FOR can contain a chain of comma-separated |
| 7681 | * addresses. The first one is the original client. It can't be |
| 7682 | * trusted for authenticity, but we don't need to for this purpose. |
| 7683 | */ |
| 7684 | $address_chain = explode( ',', $_SERVER[ $header ] ); |
| 7685 | $client_ip = trim( $address_chain[0] ); |
| 7686 | |
| 7687 | break; |
| 7688 | } |
| 7689 | } |
| 7690 | |
| 7691 | if ( ! $client_ip ) { |
| 7692 | return false; |
| 7693 | } |
| 7694 | |
| 7695 | $anon_ip = wp_privacy_anonymize_ip( $client_ip, true ); |
| 7696 | |
| 7697 | if ( '0.0.0.0' === $anon_ip || '::' === $anon_ip ) { |
| 7698 | return false; |
| 7699 | } |
| 7700 | |
| 7701 | return $anon_ip; |
| 7702 | } |