Make WordPress Core


Ignore:
Timestamp:
04/12/2018 09:19:24 PM (6 years ago)
Author:
azaozz
Message:

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

Props jesperher, allendav, iandunn, birgire, azaozz.
Fixes #43545.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/functions.php

    r42876 r42971  
    61286128    );
    61296129}
     6130
     6131/**
     6132 * Return an anonymized IPv4 or IPv6 address.
     6133 *
     6134 * @since 5.0.0 Abstracted from `WP_Community_Events::get_unsafe_client_ip()`.
     6135 *
     6136 * @param  string $ip_addr        The IPv4 or IPv6 address to be anonymized.
     6137 * @param  bool   $ipv6_fallback  Optional. Whether to return the original IPv6 address if the needed functions
     6138 *                                to anonymize it are not present. Default false, return `::` (unspecified address).
     6139 * @return string  The anonymized IP address.
     6140 */
     6141function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
     6142    // Detect what kind of IP address this is.
     6143    $ip_prefix = '';
     6144    $is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
     6145    $is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
     6146
     6147    if ( $is_ipv6 && $is_ipv4 ) {
     6148        // IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
     6149        $ip_prefix = '::ffff:';
     6150        $ip_addr   = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $ip_addr );
     6151        $ip_addr   = str_replace( ']', '', $ip_addr );
     6152        $is_ipv6   = false;
     6153    }
     6154
     6155    if ( $is_ipv6 ) {
     6156        // IPv6 addresses will always be enclosed in [] if there's a port.
     6157        $left_bracket  = strpos( $ip_addr, '[' );
     6158        $right_bracket = strpos( $ip_addr, ']' );
     6159        $percent       = strpos( $ip_addr, '%' );
     6160        $netmask       = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
     6161
     6162        // Strip the port (and [] from IPv6 addresses), if they exist.
     6163        if ( false !== $left_bracket && false !== $right_bracket ) {
     6164            $ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 );
     6165        } elseif ( false !== $left_bracket || false !== $right_bracket ) {
     6166            // The IP has one bracket, but not both, so it's malformed.
     6167            return '::';
     6168        }
     6169
     6170        // Strip the reachability scope.
     6171        if ( false !== $percent ) {
     6172            $ip_addr = substr( $ip_addr, 0, $percent );
     6173        }
     6174
     6175        // No invalid characters should be left.
     6176        if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) {
     6177            return '::';
     6178        }
     6179
     6180        // Partially anonymize the IP by reducing it to the corresponding network ID.
     6181        if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
     6182            $ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
     6183            if ( false === $ip_addr) {
     6184                return '::';
     6185            }
     6186        } elseif ( ! $ipv6_fallback ) {
     6187            return '::';
     6188        }
     6189    } elseif ( $is_ipv4 ) {
     6190        // Strip any port and partially anonymize the IP.
     6191        $last_octet_position = strrpos( $ip_addr, '.' );
     6192        $ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
     6193    } else {
     6194        return '0.0.0.0';
     6195    }
     6196
     6197    // Restore the IPv6 prefix to compatibility mode addresses.
     6198    return $ip_prefix . $ip_addr;
     6199}
     6200
     6201/**
     6202 * Return uniform "anonymous" data by type.
     6203 *
     6204 * @since 5.0.0
     6205 *
     6206 * @param  string $type The type of data to be anonymized.
     6207 * @param  string $data Optional The data to be anonymized.
     6208 * @return string The anonymous data for the requested type.
     6209 */
     6210function wp_privacy_anonymize_data( $type, $data = '' ) {
     6211
     6212    switch ( $type ) {
     6213        case 'email':
     6214            $anonymous = 'deleted@site.invalid';
     6215            break;
     6216        case 'url':
     6217            $anonymous = 'https://site.invalid';
     6218            break;
     6219        case 'ip':
     6220            $anonymous = wp_privacy_anonymize_ip( $data );
     6221            break;
     6222        case 'date':
     6223            $anonymous = '0000-00-00 00:00:00';
     6224            break;
     6225        case 'text':
     6226            /* translators: deleted text */
     6227            $anonymous = __( '[deleted]' );
     6228            break;
     6229        case 'longtext':
     6230            /* translators: deleted long text */
     6231            $anonymous = __( 'This content was deleted by the author.' );
     6232            break;
     6233        default:
     6234            $anonymous = '';
     6235    }
     6236
     6237    /**
     6238     * Filters the anonymous data for each type.
     6239     *
     6240     * @since 5.0.0
     6241     *
     6242     * @param string $anonymous Anonymized data.
     6243     * @param string $type      Type of the data.
     6244     * @param string $data      Original data.
     6245     */
     6246    return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data );
     6247}
Note: See TracChangeset for help on using the changeset viewer.