WordPress.org

Make WordPress Core


Ignore:
Timestamp:
05/02/2018 12:48:23 AM (17 months ago)
Author:
SergeyBiryukov
Message:

Privacy: add helper function for anonymizing data in a standardized way.

Props jesperher, allendav, iandunn, birgire, azaozz, joemcgill.
Merges [42971] and [43081] to the 4.9 branch.
Fixes #43545.

Location:
branches/4.9
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.9

  • branches/4.9/src/wp-includes/functions.php

    r42811 r43082  
    58175817    ), $email_change_email['message'], $email_change_email['headers'] );
    58185818}
     5819
     5820/**
     5821 * Return an anonymized IPv4 or IPv6 address.
     5822 *
     5823 * @since 4.9.6 Abstracted from `WP_Community_Events::get_unsafe_client_ip()`.
     5824 *
     5825 * @param  string $ip_addr        The IPv4 or IPv6 address to be anonymized.
     5826 * @param  bool   $ipv6_fallback  Optional. Whether to return the original IPv6 address if the needed functions
     5827 *                                to anonymize it are not present. Default false, return `::` (unspecified address).
     5828 * @return string  The anonymized IP address.
     5829 */
     5830function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
     5831    // Detect what kind of IP address this is.
     5832    $ip_prefix = '';
     5833    $is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
     5834    $is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
     5835
     5836    if ( $is_ipv6 && $is_ipv4 ) {
     5837        // IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
     5838        $ip_prefix = '::ffff:';
     5839        $ip_addr   = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $ip_addr );
     5840        $ip_addr   = str_replace( ']', '', $ip_addr );
     5841        $is_ipv6   = false;
     5842    }
     5843
     5844    if ( $is_ipv6 ) {
     5845        // IPv6 addresses will always be enclosed in [] if there's a port.
     5846        $left_bracket  = strpos( $ip_addr, '[' );
     5847        $right_bracket = strpos( $ip_addr, ']' );
     5848        $percent       = strpos( $ip_addr, '%' );
     5849        $netmask       = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
     5850
     5851        // Strip the port (and [] from IPv6 addresses), if they exist.
     5852        if ( false !== $left_bracket && false !== $right_bracket ) {
     5853            $ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 );
     5854        } elseif ( false !== $left_bracket || false !== $right_bracket ) {
     5855            // The IP has one bracket, but not both, so it's malformed.
     5856            return '::';
     5857        }
     5858
     5859        // Strip the reachability scope.
     5860        if ( false !== $percent ) {
     5861            $ip_addr = substr( $ip_addr, 0, $percent );
     5862        }
     5863
     5864        // No invalid characters should be left.
     5865        if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) {
     5866            return '::';
     5867        }
     5868
     5869        // Partially anonymize the IP by reducing it to the corresponding network ID.
     5870        if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
     5871            $ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
     5872            if ( false === $ip_addr) {
     5873                return '::';
     5874            }
     5875        } elseif ( ! $ipv6_fallback ) {
     5876            return '::';
     5877        }
     5878    } elseif ( $is_ipv4 ) {
     5879        // Strip any port and partially anonymize the IP.
     5880        $last_octet_position = strrpos( $ip_addr, '.' );
     5881        $ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
     5882    } else {
     5883        return '0.0.0.0';
     5884    }
     5885
     5886    // Restore the IPv6 prefix to compatibility mode addresses.
     5887    return $ip_prefix . $ip_addr;
     5888}
     5889
     5890/**
     5891 * Return uniform "anonymous" data by type.
     5892 *
     5893 * @since 4.9.6
     5894 *
     5895 * @param  string $type The type of data to be anonymized.
     5896 * @param  string $data Optional The data to be anonymized.
     5897 * @return string The anonymous data for the requested type.
     5898 */
     5899function wp_privacy_anonymize_data( $type, $data = '' ) {
     5900
     5901    switch ( $type ) {
     5902        case 'email':
     5903            $anonymous = 'deleted@site.invalid';
     5904            break;
     5905        case 'url':
     5906            $anonymous = 'https://site.invalid';
     5907            break;
     5908        case 'ip':
     5909            $anonymous = wp_privacy_anonymize_ip( $data );
     5910            break;
     5911        case 'date':
     5912            $anonymous = '0000-00-00 00:00:00';
     5913            break;
     5914        case 'text':
     5915            /* translators: deleted text */
     5916            $anonymous = __( '[deleted]' );
     5917            break;
     5918        case 'longtext':
     5919            /* translators: deleted long text */
     5920            $anonymous = __( 'This content was deleted by the author.' );
     5921            break;
     5922        default:
     5923            $anonymous = '';
     5924    }
     5925
     5926    /**
     5927     * Filters the anonymous data for each type.
     5928     *
     5929     * @since 4.9.6
     5930     *
     5931     * @param string $anonymous Anonymized data.
     5932     * @param string $type      Type of the data.
     5933     * @param string $data      Original data.
     5934     */
     5935    return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data );
     5936}
Note: See TracChangeset for help on using the changeset viewer.