2024 年 PHP Conference Japan

網路函式

目錄

新增註解

使用者貢獻的註解 10 則註解

claudiu at cnixs dot com
17 年前
一個簡單且非常快速的函式,用於檢查 CIDR。

您先前的範例太複雜,並且涉及許多函式呼叫。

這裡是它(僅使用算術運算子並僅呼叫 ip2long () 和 split())
<?php
函式 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,CIDR:192.168.101.144/24

<?php
函式 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
函數 cidrconv($net) {
$start = strtok($net,"/");
$n = 3 - substr_count($net, ".");
如果 ($n > 0)
{
對於 ($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 = "";
對於 ($i = 0; $i < 32; $i++)
{
如果 ($bits1[$i] == $bits2[$i]) $final .= $bits1[$i];
如果 ($bits1[$i] == 1 $bits2[$i] == 0) $final .= $bits1[$i];
如果 ($bits1[$i] == 0 $bits2[$i] == 1) $final .= $bits2[$i];
}
返回 array($start, long2ip(bindec($final)));
}
?>
David GASTALDIN
17 年前
這是一個我寫的 IP 範圍轉 CIDR 格式的函式,目的是用 ripe-ncc 的數據填充我的 Postfix client.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
函式 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 函式 - 更易於理解

函式 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(),它在整個網站中用於確保使用者已登入。
希望這個有幫助!
To Top