函数文档

wp_privacy_anonymize_ip()

💡 云策文档标注

概述

wp_privacy_anonymize_ip() 函数用于对 IPv4 或 IPv6 地址进行匿名化处理,以保护用户隐私。它通过部分掩码或网络 ID 转换来减少 IP 地址的识别性。

关键要点

  • 函数接受两个参数:$ip_addr(必需,要匿名化的 IP 地址字符串)和 $ipv6_fallback(可选,布尔值,控制 IPv6 匿名化失败时的回退行为,默认为 false)。
  • 返回匿名化后的 IP 地址字符串,对于无效输入或处理失败,可能返回 '0.0.0.0' 或 '::'。
  • 支持 IPv4 和 IPv6 地址,包括 IPv6 兼容模式,并处理端口和范围等附加信息。
  • 内部使用 inet_pton 和 inet_ntop 函数进行 IPv6 网络掩码操作,若不可用且 $ipv6_fallback 为 false,则返回 '::'。

代码示例

function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
    if ( empty( $ip_addr ) ) {
        return '0.0.0.0';
    }

    // Detect what kind of IP address this is.
    $ip_prefix = '';
    $is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
    $is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );

    if ( $is_ipv6 && $is_ipv4 ) {
        // IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
        $ip_prefix = '::ffff:';
        $ip_addr   = preg_replace( '/^[?[0-9a-f:]*:/i', '', $ip_addr );
        $ip_addr   = str_replace( ']', '', $ip_addr );
        $is_ipv6   = false;
    }

    if ( $is_ipv6 ) {
        // IPv6 addresses will always be enclosed in [] if there's a port.
        $left_bracket  = strpos( $ip_addr, '[' );
        $right_bracket = strpos( $ip_addr, ']' );
        $percent       = strpos( $ip_addr, '%' );
        $netmask       = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';

        // Strip the port (and [] from IPv6 addresses), if they exist.
        if ( false !== $left_bracket && false !== $right_bracket ) {
            $ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 );
        } elseif ( false !== $left_bracket || false !== $right_bracket ) {
            // The IP has one bracket, but not both, so it's malformed.
            return '::';
        }

        // Strip the reachability scope.
        if ( false !== $percent ) {
            $ip_addr = substr( $ip_addr, 0, $percent );
        }

        // No invalid characters should be left.
        if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) {
            return '::';
        }

        // Partially anonymize the IP by reducing it to the corresponding network ID.
        if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
            $ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
            if ( false === $ip_addr ) {
                return '::';
            }
        } elseif ( ! $ipv6_fallback ) {
            return '::';
        }
    } elseif ( $is_ipv4 ) {
        // Strip any port and partially anonymize the IP.
        $last_octet_position = strrpos( $ip_addr, '.' );
        $ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
    } else {
        return '0.0.0.0';
    }

    // Restore the IPv6 prefix to compatibility mode addresses.
    return $ip_prefix . $ip_addr;
}

注意事项

  • 该函数从 WordPress 4.9.6 版本引入,主要用于隐私保护相关功能。
  • 在 IPv6 处理中,依赖 inet_pton 和 inet_ntop 函数,若系统不支持且 $ipv6_fallback 为 false,会返回 '::' 作为匿名地址。
  • 函数会清理 IP 地址中的端口、括号和范围标识符,确保输入格式正确。

📄 原文内容

Returns an anonymized IPv4 or IPv6 address.

Parameters

$ip_addrstringrequired
The IPv4 or IPv6 address to be anonymized.
$ipv6_fallbackbooloptional
Whether to return the original IPv6 address if the needed functions to anonymize it are not present. Default false, return :: (unspecified address).

Default:false

Return

string The anonymized IP address.

Source

function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
	if ( empty( $ip_addr ) ) {
		return '0.0.0.0';
	}

	// Detect what kind of IP address this is.
	$ip_prefix = '';
	$is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
	$is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );

	if ( $is_ipv6 && $is_ipv4 ) {
		// IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
		$ip_prefix = '::ffff:';
		$ip_addr   = preg_replace( '/^[?[0-9a-f:]*:/i', '', $ip_addr );
		$ip_addr   = str_replace( ']', '', $ip_addr );
		$is_ipv6   = false;
	}

	if ( $is_ipv6 ) {
		// IPv6 addresses will always be enclosed in [] if there's a port.
		$left_bracket  = strpos( $ip_addr, '[' );
		$right_bracket = strpos( $ip_addr, ']' );
		$percent       = strpos( $ip_addr, '%' );
		$netmask       = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';

		// Strip the port (and [] from IPv6 addresses), if they exist.
		if ( false !== $left_bracket && false !== $right_bracket ) {
			$ip_addr = substr( $ip_addr, $left_bracket + 1, $right_bracket - $left_bracket - 1 );
		} elseif ( false !== $left_bracket || false !== $right_bracket ) {
			// The IP has one bracket, but not both, so it's malformed.
			return '::';
		}

		// Strip the reachability scope.
		if ( false !== $percent ) {
			$ip_addr = substr( $ip_addr, 0, $percent );
		}

		// No invalid characters should be left.
		if ( preg_match( '/[^0-9a-f:]/i', $ip_addr ) ) {
			return '::';
		}

		// Partially anonymize the IP by reducing it to the corresponding network ID.
		if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
			$ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
			if ( false === $ip_addr ) {
				return '::';
			}
		} elseif ( ! $ipv6_fallback ) {
			return '::';
		}
	} elseif ( $is_ipv4 ) {
		// Strip any port and partially anonymize the IP.
		$last_octet_position = strrpos( $ip_addr, '.' );
		$ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
	} else {
		return '0.0.0.0';
	}

	// Restore the IPv6 prefix to compatibility mode addresses.
	return $ip_prefix . $ip_addr;
}

Changelog

Version Description
4.9.6 Introduced.