Jump to content

detecting a character in a string.


mamanybono

Recommended Posts

Hi everybody, I am trying to write a code which record a CIDR (5.2.80.0/21 5.11.128.0/17) format ip list into mysql database. I have a problem at one part of my code. Code is the below. With this code I am trying to find every third "." character's place and every "/" character's place and every " " characters place. After finding the places the code record the places in to an array which name is $reference_points. The problem is that for exaple if I apply this code on this 5.2.80.0/21 5.11.128.0/17 string. The result should be $reference_points.[1]=7 $reference_points.[2]=9 $reference_points.[3]=12 but it shows $reference_points.[1]=7 $reference_points.[2]=9 $reference_points.[3]=23. And the full list of CIDR ip is attached. By the way I use a form on php page to take this list. The code part is which start fith FOR loop. Thak you very much.

<div align="center"><form action="add_new_country.php" method="post"><table><tr><td>Country name:</td> <td><input type="text" maxlength="50" name="new_country_name" id="new_country_name" size="38" /></td></br></br></tr><tr><td>Country Ip Ranges:</td> <td><textarea rows="10" cols="30"  name="country_ip_ranges" id="country_ip_ranges"> </textarea></td></br></br></tr><tr><td><input type="submit"  name="submit" value="Add New Country" /></td><td></td></tr></table></form></div>   <div align="center"><?phpif(isset($_POST["new_country_name"]) && isset($_POST["country_ip_ranges"]) && !empty($_POST["new_country_name"]) &&             !empty($_POST["country_ip_ranges"])){$country_name=@$_POST['new_country_name'];$country_ip_range=@$_POST['country_ip_ranges']; $sql=mysql_query("SELECT id FROM countries WHERE  country_name='$country_name' LIMIT 1");$exist_count=mysql_num_rows($sql); if($exist_count==1){echo "The name of the country which you try to add is already exist in the system, please try to add different name.";}else{mysql_query("INSERT INTO countries (id,country_name) VALUES ('','$country_name')" );mkdir("$country_name");$dot=0;$reference_points=array();$reference_points_index=1; for($i=1;$i<=strlen(trim($country_ip_range));$i++){if(substr(trim($country_ip_range),$i-1,1)=='.' && $dot<3){$dot=$dot+1; if($dot==3){$reference_points[$reference_points_index]=$i;$dot=0;$reference_points_index=$reference_points_index+1;} }elseif(substr(trim($country_ip_range),$i-1,1)=='/'){$reference_points[$reference_points_index]=$i;$reference_points_index=$reference_points_index+1; }elseif(substr(trim($country_ip_range),$i-1,1)==' '){$reference_points[$reference_points_index]=$i;$reference_points_index=$reference_points_index+1;}}echo $reference_points[1].'<br/>';echo $reference_points[2].'<br/>';echo $reference_points[3].'<br/>';echo $reference_points[4].'<br/>';echo $reference_points[5].'<br/>';echo $reference_points[6].'<br/>';echo $reference_points[7].'<br/>';echo $reference_points[8].'<br/>';}}?></div>

TR_cidr.txt

Link to comment
Share on other sites

What's the idea here? I mean... you said the expected output is 7,9,12... but what does that represent?

Link to comment
Share on other sites

7,9,12 are the places of third "." and place of "/" and place of " " in this string 5.2.80.0/21 5.11.128.0/17. Actually I am trying to split this string at every third "." and every "/" and every " ". While ı am searchigt at web I found preg_splite function, right now I am working on it.

Link to comment
Share on other sites

Wait... so your end goal is to get the network addresses?You shoudn't rely on the final ".", since that is only true for "/24".How about:

$networkAddresses = array();foreach (explode($_POST['country_ip_ranges'], ' ') as $range) {    list ($ip, $mask) = explode($range, '/');    $networkAddresses[] = long2ip(sprintf('%u', ip2long($ip) & (pow(2, (int) $mask) - 1)));}

If you're then trying to compute stuff with those network addresses later on, it might be better if you keep the integer representations (resulting from ip2long), since they allow you to make bitwise operations, such as the one above.

  • Like 1
Link to comment
Share on other sites

Thank you boen_robot for your answer. I just tried to split this numbers because I want to record them into database in different colums so when I got a guest ip I able to compare it with my database. I am doing this because I need to learn guest's country but just country I don't care about city or state. One of my friend advice to me using preg_match_all function and this solved my problem. But until I understand the structure of preg_ functions and regex I studied around 4 hours. I can't concentrate on your code but I made a short research ip2long. I couldn't understant but you mean keep this ip adresses in IPv4 Internet network addres format(1320350348) instead of standard format (78.178.242.140). But if I don't understant this CIDR format 5.2.80.0/21 there is 21 ip adresses. And I got 1440 CIDR ip range for Turkey so approximately 1440*21=30240 numbers and think about I have Bulgaria's ip addresses too, İt's dublicate 2*30240=60480 numbers have to be checked. İnstead of that, I am going to sperate this 5.2.80.0/21 into 5 part like this 5 2 80 0 21 and sql query going to compare guest's first three part with my database if there is a matched, İt is going to check that, is the guest's fourth part number between my forth part number and fifth part number.

Edited by mamanybono
Link to comment
Share on other sites

CIDR is an alternative notation for a subnet mask. It specifies....(take a deep breath, focus and read slowly... it's impossible to avoid heavy use of terminology...)The number of bits from the IP address (left to right...) that indicate the network for an address. If another IP address starts with those same bits, it is considered to be part of the same network (a.k.a. "subnet"). An IP that after those bits has only 0s is considered "the network address", and is intended to be stored by applications that need to do network computations, such as what you're trying to do.For example78.178.242.140can be represented as the binary number01001110101100101111001010001100(which in decimal is 1320350348)A CIDR "21" would indicate that the first 21 bits are the network, so the network prefix is010011101011001011110(the network address is therefore 01001110101100101111000000000000 - 78.178.240.0)An IP address is always 32 bits, so whatever 11 bits follow those 21, they are part of that network. The IP with all 1s is also reserved => There are 2046 addresses within this subnet, and any subnet with the CIDR "21". They range from01001110101100101111000000000001 (78.178.240.1)to01001110101100101111011111111110 (78.178.247.254)Using ip2long(), you get the number, which you can then work with using bitwise operators (the "&" above is a "bitwise and"). You can check if an IP is within a network by doing a "bitwise and" between them, and checking if the result is the same as the network address, i.e.

if ((ip2long($_SERVER['REMOTE_ADDR']) & $networkAddress) == $networkAddress) {//Is in the network} else {//Is not in the network}

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...