Ticket #43545: 43545.4.diff
File 43545.4.diff, 8.8 KB (added by , 7 years ago) |
---|
-
src/wp-admin/includes/class-wp-community-events.php
265 265 return false; 266 266 } 267 267 268 // Detect what kind of IP address this is. 269 $is_ipv6 = substr_count( $client_ip, ':' ) > 1; 270 $is_ipv4 = ( 3 === substr_count( $client_ip, '.' ) ); 268 $anon_ip = wp_privacy_anonymize_ip( $client_ip, true ); 271 269 272 if ( $is_ipv6 && $is_ipv4 ) { 273 // IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4. 274 $ip_prefix = '::ffff:'; 275 $client_ip = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $client_ip ); 276 $client_ip = str_replace( ']', '', $client_ip ); 277 $is_ipv6 = false; 278 } 279 280 if ( $is_ipv6 ) { 281 // IPv6 addresses will always be enclosed in [] if there's a port. 282 $left_bracket = strpos( $client_ip, '[' ); 283 $right_bracket = strpos( $client_ip, ']' ); 284 $percent = strpos( $client_ip, '%' ); 285 $netmask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; 286 287 // Strip the port (and [] from IPv6 addresses), if they exist. 288 if ( false !== $left_bracket && false !== $right_bracket ) { 289 $client_ip = substr( $client_ip, $left_bracket + 1, $right_bracket - $left_bracket - 1 ); 290 } elseif ( false !== $left_bracket || false !== $right_bracket ) { 291 // The IP has one bracket, but not both, so it's malformed. 292 return false; 293 } 294 295 // Strip the reachability scope. 296 if ( false !== $percent ) { 297 $client_ip = substr( $client_ip, 0, $percent ); 298 } 299 300 // No invalid characters should be left. 301 if ( preg_match( '/[^0-9a-f:]/i', $client_ip ) ) { 302 return false; 303 } 304 305 // Partially anonymize the IP by reducing it to the corresponding network ID. 306 if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) { 307 $client_ip = inet_ntop( inet_pton( $client_ip ) & inet_pton( $netmask ) ); 308 } 309 } elseif ( $is_ipv4 ) { 310 // Strip any port and partially anonymize the IP. 311 $last_octet_position = strrpos( $client_ip, '.' ); 312 $client_ip = substr( $client_ip, 0, $last_octet_position ) . '.0'; 313 } else { 270 if ( '0.0.0.0' === $anon_ip || '::' === $anon_ip ) { 314 271 return false; 315 272 } 316 273 317 // Restore the IPv6 prefix to compatibility mode addresses. 318 return $ip_prefix . $client_ip; 274 return $anon_ip; 319 275 } 320 276 321 277 /** -
src/wp-includes/functions.php
6127 6127 ), $email_change_email['message'], $email_change_email['headers'] 6128 6128 ); 6129 6129 } 6130 6131 /** 6132 * Return an anonymized IPV4 or IPV6 address. 6133 * 6134 * @since 5.0.0 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 */ 6141 function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) { 6142 // Detect what kind of IP address this is. 6143 $is_ipv6 = substr_count( $ip_addr, ':' ) > 1; 6144 $is_ipv4 = ( 3 === substr_count( $ip_addr, '.' ) ); 6145 6146 if ( $is_ipv6 && $is_ipv4 ) { 6147 // IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4. 6148 $ip_prefix = '::ffff:'; 6149 $ip_addr = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $ip_addr ); 6150 $ip_addr = str_replace( ']', '', $ip_addr ); 6151 $is_ipv6 = false; 6152 } 6153 6154 if ( $is_ipv6 ) { 6155 // IPv6 addresses will always be enclosed in [] if there's a port. 6156 $left_bracket = strpos( $ip_addr, '[' ); 6157 $right_bracket = strpos( $ip_addr, ']' ); 6158 $percent = strpos( $ip_addr, '%' ); 6159 $netmask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; 6160 6161 // Strip the port (and [] from IPv6 addresses), if they exist. 6162 if ( false !== $left_bracket && false !== $right_bracket ) { 6163 $ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 ); 6164 } elseif ( false !== $left_bracket || false !== $right_bracket ) { 6165 // The IP has one bracket, but not both, so it's malformed. 6166 return '::'; 6167 } 6168 6169 // Strip the reachability scope. 6170 if ( false !== $percent ) { 6171 $ip_addr = substr( $ip_addr, 0, $percent ); 6172 } 6173 6174 // No invalid characters should be left. 6175 if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) { 6176 return '::'; 6177 } 6178 6179 // Partially anonymize the IP by reducing it to the corresponding network ID. 6180 if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) { 6181 $ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) ); 6182 } elseif ( ! $ipv6_fallback ) { 6183 return '::'; 6184 } 6185 } elseif ( $is_ipv4 ) { 6186 // Strip any port and partially anonymize the IP. 6187 $last_octet_position = strrpos( $ip_addr, '.' ); 6188 $ip_addr = substr( $ip_addr, 0, $last_octet_position ) . '.0'; 6189 } else { 6190 return '0.0.0.0'; 6191 } 6192 6193 // Restore the IPv6 prefix to compatibility mode addresses. 6194 return $ip_prefix . $ip_addr; 6195 } 6196 6197 /** 6198 * Return uniform "anonymous" data by type. 6199 * 6200 * @since 5.0.0 6201 * 6202 * @param string $type The type of data to be anonymized. 6203 * @param string $data Optional The data to be anonymized. 6204 * @return string The anonymous data for the requested type. 6205 */ 6206 function wp_privacy_anonymize_data( $type, $data = '' ) { 6207 6208 switch ( $type ) { 6209 case 'email': 6210 $anonymous = 'deleted@site.invalid'; 6211 break; 6212 case 'url': 6213 $anonymous = 'https://site.invalid'; 6214 break; 6215 case 'ip': 6216 $anonymous = wp_privacy_anonymize_ip( $data ); 6217 break; 6218 case 'date': 6219 $anonymous = '0000-00-00 00:00:00'; 6220 break; 6221 case 'text': 6222 /* translators: deleted text */ 6223 $anonymous = __( '[deleted]' ); 6224 break; 6225 case 'longtext': 6226 /* translators: deleted long text */ 6227 $anonymous = __( 'This content was deleted by the author.' ); 6228 break; 6229 default: 6230 $anonymous = ''; 6231 } 6232 6233 /** 6234 * Filters the anonymous data for each type. 6235 * 6236 * @since 5.0.0 6237 * 6238 * @param string $anonymous Anonymized data. 6239 * @param string $type Type of the data. 6240 * @param string $data Original data. 6241 */ 6242 return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data ); 6243 } -
tests/phpunit/tests/functions/anonymization.php
1 <?php 2 3 /** 4 * @group functions.php 5 * @group privacy 6 */ 7 class Tests_Functions_Anonymization extends WP_UnitTestCase { 8 function test_anonymize_invalid_ip() { 9 $ip_addrs = array( '', 'invalid', '0.0.0.0.0' ); 10 11 foreach ( (array) $ip_addrs as $ip_addr ) { 12 $this->assertEquals( '0.0.0.0', wp_privacy_anonymize_data( $ip_addr, 'ip' ) ); 13 } 14 } 15 16 function test_anonymize_ipv4() { 17 $ip_addrs = array( 18 '198.143.164.252' => '198.143.164.0', 19 '127.0.0.1' => '127.0.0.0', 20 ); 21 22 foreach ( (array) $ip_addrs as $ip_addr => $anonymized_ip_addr ) { 23 $this->assertEquals( $anonymized_ip_addr, wp_privacy_anonymize_data( $ip_addr, 'ip' ) ); 24 } 25 } 26 27 function test_anonymize_ipv6() { 28 $ip_addrs = array( 29 '2001:0db8:0a0b:12f0:0000:0000:0000:0001' => '2001:db8:a0b:12f0::', 30 '2001:db8:a0b:12f0::1' => '2001:db8:a0b:12f0::', 31 '2001:db8::1' => '2001:db8::', 32 '::ffff:10.0.0.3' => '::ffff:10.0.0.0', 33 '[2001:db8:a0b:12f0::1]' => '2001:db8:a0b:12f0::', 34 '[2001:db8:a0b:12f0::1]:21' => '2001:db8:a0b:12f0::', 35 '::1' => '::', 36 ); 37 38 foreach ( (array) $ip_addrs as $ip_addr => $anonymized_ip_addr ) { 39 $this->assertEquals( $anonymized_ip_addr, wp_privacy_anonymize_data( $ip_addr, 'ip' ) ); 40 } 41 } 42 43 function test_anonymize_email() { 44 $this->assertEquals( 'deleted@site.invalid', wp_privacy_anonymize_data( 'bar@example.com', 'email' ) ); 45 } 46 47 function test_anonymize_url() { 48 $this->assertEquals( 'https://site.invalid', wp_privacy_anonymize_data( 'https://example.com/author/username', 'url' ) ); 49 } 50 51 function test_anonymize_date() { 52 $this->assertEquals( '0000-00-00 00:00:00', wp_privacy_anonymize_data( '2003-12-25 12:34:56', 'date' ) ); 53 } 54 55 function test_anonymize_text() { 56 $text = __( 'Four score and seven years ago' ); 57 $this->assertNotEquals( $text, wp_privacy_anonymize_data( $text, 'text' ) ); 58 } 59 60 function test_anonymize_long_text() { 61 $text = __( 'Four score and seven years ago' ); 62 $this->assertNotEquals( $text, wp_privacy_anonymize_data( $text, 'longtext' ) ); 63 } 64 }