PHP Conference Japan 2024

网络函数

目录

添加注释

用户贡献的注释 10 条注释

claudiu at cnixs dot com
17 年前
一个简单且非常快速的函数,用于检查 CIDR。

您之前的示例过于复杂,并且涉及大量函数调用。

这是它(仅使用算术运算符,并且仅调用 ip2long() 和 split())
<?php
function ipCIDRCheck ($IP, $CIDR) {
list (
$net, $mask) = split ("/", $CIDR);

$ip_net = ip2long ($net);
$ip_mask = ~((1 << (32 - $mask)) - 1);

$ip_ip = ip2long ($IP);

$ip_ip_net = $ip_ip & $ip_mask;

return (
$ip_ip_net == $ip_net);
}
?>
调用示例: <?php echo ipCheck ("192.168.1.23", "192.168.1.0/24"); ?>
Anton Avramov - lukav at lukav dot com
7 年前
claudiu at cnixs dot com 的改进版本,不使用 split 并且适用于以下情况
IP:192.168.101.123,CIRD:192.168.101.144/24

<?php
function ipCIDRCheck ($IP, $CIDR) {
list (
$net, $mask) = explode ('/', $CIDR);

$ip_net = ip2long ($net);
$ip_mask = ~((1 << (32 - $mask)) - 1);

$ip_ip = ip2long ($IP);

return ((
$ip_ip & $ip_mask) == ($ip_net & $ip_mask));
}
?>
匿名用户
8 年前
philippe-at-cyberabuse.org 的答案的改进版本

<?php
function cidrconv($net) {
$start = strtok($net,"/");
$n = 3 - substr_count($net, ".");
if (
$n > 0)
{
for (
$i = $n;$i > 0; $i--)
$start .= ".0";
}
$bits1 = str_pad(decbin(ip2long($start)), 32, "0", STR_PAD_LEFT);
$net = (1 << (32 - substr(strstr($net, "/"), 1))) - 1;
$bits2 = str_pad(decbin($net), 32, "0", STR_PAD_LEFT);
$final = "";
for (
$i = 0; $i < 32; $i++)
{
if (
$bits1[$i] == $bits2[$i]) $final .= $bits1[$i];
if (
$bits1[$i] == 1 and $bits2[$i] == 0) $final .= $bits1[$i];
if (
$bits1[$i] == 0 and $bits2[$i] == 1) $final .= $bits2[$i];
}
return array(
$start, long2ip(bindec($final)));
}
?>
David GASTALDIN
17 年前
这里有一个我为了填充我的 Postfix client.cidr 使用 ripe-ncc 数据来阻止来自无用国家的垃圾邮件而编写的 IP 范围到 CIDR 的函数。Strcmp 函数旨在解决愚蠢的 PHP 字符串比较问题,该问题不可避免地尝试在可能的情况下将字符串作为数字进行比较。我不会对这个事实发表任何评论……但我必须强忍住不说话。

function PlageVersCIDRs($ip_min, $ip_max) {
$cidrs = array();
$ip_min_bin = sprintf('%032b', $ip_min);
$ip_max_bin = sprintf('%032b', $ip_max);
$ip_cour_bin = $ip_min_bin;
while (strcmp($ip_cour_bin, $ip_max_bin) <= 0) {
$lng_reseau = 32;
$ip_reseau_bin = $ip_cour_bin;
while (($ip_cour_bin[$lng_reseau - 1] == '0') && (strcmp(substr_replace($ip_reseau_bin, '1', $lng_reseau - 1, 1), $ip_max_bin) <= 0)) {
$ip_reseau_bin[$lng_reseau - 1] = '1';
$lng_reseau--;
}
$cidrs[] = long2ip(bindec($ip_cour_bin)).'/'.$lng_reseau;
$ip_cour_bin = sprintf('%032b', bindec($ip_reseau_bin) + 1);
}
return $cidrs;
}
philippe-at-cyberabuse.org
22 年前
PHP 缺少 CIDR 函数。

这个函数将转换一个像这样的 CIDR
0.0.0.0/16 -> 0.0.0.0 - 0.0.255.255
127.0/16 -> 127.0.0.0 - 127.0.255.255
等等...

function cidrconv($net) {
$start=strtok($net,"/");
$n=3-substr_count($net, ".");
if ($n>0) { for ($i=$n;$i>0;$i--) $start.=".0"; }
$bits1=str_pad(decbin(ip2long($start)),32,"0","STR_PAD_LEFT");
$net=pow(2,(32-substr(strstr($net,"/"),1)))-1;
$bits2=str_pad(decbin($net),32,"0","STR_PAD_LEFT");
for ($i=0;$i<32;$i++) {
if ($bits1[$i]==$bits2[$i]) $final.=$bits1[$i];
if ($bits1[$i]==1 and $bits2[$i]==0) $final.=$bits1[$i];
if ($bits1[$i]==0 and $bits2[$i]==1) $final.=$bits2[$i];
}
return $start." - ".long2ip(bindec($final));
}
nexxer at rogers dot com
19 年前
在 Trevor Hemsley 对 perl range2cidr 函数的翻译中,

while ($end > $start)

条件应该是

while ($end >= $start)

否则它将无法处理 /32,例如,如果您向 range2cidr("1.2.3.4", "1.2.3.4") 提供数据。

-- nex
-dR
9 年前
这个小函数可能会派上用场

<?php
function cidr_range( $cidr, $chkip=null )
{
// 分配 IP / 掩码
list($ip,$mask) = explode("/",$cidr);

// 清理 IP
$ip1 = preg_replace( '_(\d+\.\d+\.\d+\.\d+).*$_', '$1', "$ip.0.0.0" );

// 计算范围
$ip2 = long2ip( ip2long( $ip1 ) - 1 + ( 1 << ( 32 - $mask) ) );

// 我们是否正在进行 CIDR 范围检查?
if ( $chkip != null && ! filter_var( $chkip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false )
{
return
ip2long( $ip1 ) <= ip2long( $chkip ) && ip2long( $ip2 ) >= ip2long( $chkip ) ? true : false;
} else {
return
"$ip1 - $ip2";
}
}

var_dump( cidr_range( "127.0/16", "127.0.0.1" ) ); // bool(true)
var_dump( cidr_range( "127.0/16", "192.168.0.1" ) ); // bool(false)
var_dump( cidr_range( "192.168.0.0/24" ) ); // string(27) "192.168.0.0 - 192.168.0.255"

?>
匿名
21 年前
cidr_conv 函数的替代方案 - 稍微容易理解一些

function cidr_conv($cidr_address) {
$first = substr($cidr_address, 0, strpos($cidr_address, "/"));
$netmask = substr(strstr($cidr_address, "/"), 1);

$first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT);
$netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT);

for ($i = 0; $i < 32; $i++) {
if ($netmask_bin[$i] == "1")
$last_bin .= $first_bin[$i];
else
$last_bin .= "1";
}

$last = long2ip(bindec($last_bin));

return "$first - $last";
}
samuele at norsam dot org
21 年前
要查找某个 IP 是否在一个网络/掩码中(非常快)
<?php
function isIPIn($ip,$net,$mask) {
$lnet=ip2long($net);
$lip=ip2long($ip);
$binnet=str_pad( decbin($lnet),32,"0","STR_PAD_LEFT" );
$firstpart=substr($binnet,0,$mask);
$binip=str_pad( decbin($lip),32,"0","STR_PAD_LEFT" );
$firstip=substr($binip,0,$mask);
return(
strcmp($firstpart,$firstip)==0);
}
?>

这个函数可以压缩,避免一些变量设置,但函数将不太易于阅读……
示例代码,用于制作一种基于网络的位置服务

<?php
$n
= array ( "192.168.0.0/16" => "托斯卡纳",
"192.168.1.0/24" => "- 佛罗伦萨",
"192.168.2.0/24" => "- 比萨",
"192.168.3.0/24" => "- 锡耶纳",
"192.168.64.0/21" => "- 托斯卡纳群岛",
"192.168.64.0/23" => "--- 埃尔巴岛",
"192.168.66.0/24" => "--- 卡普拉亚岛",
"192.168.67.0/24" => "--- 吉安努特里岛");

// 通常情况下,您应该使用以下代码行
$myip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
// 这是第一个示例:返回托斯卡纳/比萨
$myip = "192.168.2.33";
// 这是第二个示例:返回托斯卡纳/托斯卡纳群岛/埃尔巴岛
$myip = "192.168.65.34";

echo
"您的位置:<br />\n";
foreach (
$n as $k=>$v ) {
list(
$net,$mask)=split("/",$k);
if (
isIPIn($myip,$net,$mask)) {
echo
$n[$k]."<br />\n"; }
}
?>

等等...
dand at ddchosting.com
18年前
当我从事一个项目时,遇到了重定向的问题。我的解决方案如下:
header("Refresh: 5; url=../main/main.php?".session_id()."");

这允许我传递 session_id(),该 ID 在整个站点中使用,以确保用户已登录。
希望这有帮助!
To Top