I need a very simplified script (no extras, no html parsers, no
multi-functioned scripting, etc) with ONE function that I can use to
check whether an IP (in standard form, aka 192.168.1.105) is in a
special "filter" list which contains numerious entries, in form of
single IPs, IP ranges specified as 192.168.1.*, IP ranges specified as
192.168.1.??, and IP ranges specified as 192.168.1.0-100. If the
looked up IP belongs to any of the single IP entries, or is within a
range of any, then it should return a $TRUE, otherwise a $FALSE.
For example, if your function is named chkiplist() and I do :
$ipchk1 = chkiplist(24.25.26.27);
$ipchk2 = chkiplist(24.26.27.28);
$ipchk3 = chkiplist(25.28.27.28);
$ipchk3 = chkiplist(26.27.28.29);
And the block list is:
24.25.26.27
24.26.*.*
25.26.??.2?
26.27.0-50.0-225
ALL of them should return $TRUE, because each of the entries in the
block list corresponds to the IPs looked up, respectively.
Also, I would like to be able to place 'comments' in the block list, in form of a :
# Comment Here
// Another Comment hEre
/ Another Comment here
/* Another Comment here */
; Another comment here
Or you can simply just have the script check whether the line contains
an IP/Range, and if it does not, then the line is a comment.
Overview:
1) Single working function, not a full script, the simpler, the better
2) Uses a txt filter list, one IP/Range per line
3) IP/Range Format:
- 192.168.1.105 (Single IP)
- 192.168.1.* (IP Range with *)
- 192.168.1.100-110 (IP range with -)
- 192.168.?.* (IP range with ?)
4) Script should be able to ignore comments (text) within the block
.txt list and skip the comments, but check the IP/Range entries.
5) Script should return a simple $TRUE if the looked up IP matches any
of the entries, and a $FALSE if it does not.
6) Script must be clean, but also very short and simple.
7) If possible, have it UNIX/win32 reverse compatible
Please let me know if you need me to include any specifications. Thank you. |
Hello theboistard
Thank-you for your question. I have pasted the solution you require below.
I have commented the script so that you can see what it is doing at
each stage - these can be removed once you are happy that you
understand this.
The script returns true (or "1") if a match is not found, if it is not
it returns false (or "").
If you have any questions regarding this function please ask for
clarification and I will do my best to help further.
<?
function chkiplist($ip) {
# read in the ip address file
$lines = file("ipaddresses.txt");
# set a variable as false
$found = false;
# loop through the ip address file
foreach ($lines as $line) {
# remove line feeds from the line
$line = chop($line);
# replace * with a 3 digit number
$line = str_replace("*","\d{1,3}",$line);
# replace ? with a single digit
$line = str_replace("?","\d",$line);
# if it contains a - character
if ( strpos($line,"-",0) <> "" ) {
# split the line and number you are checking into parts
$line_chunks = split(".",$line);
$ip_chunks = split("-",$ip);
# set a variable to count things
$valid = 0;
# for each number in the ip address
for ( $i=0;$i<4; $i++ ) {
# if the chunk contains a -
if ( strpos($line_chunks[$i],"-",0) <> "" ) {
# if the line chunk is the same as the ip chunk then increment the
# counter
if ( $line_chunks[$i] == $ip_chunks[$i] ) { $valid++; };
}
else { # if no - in the line chunk
$splitit = split("-",$line_chunks[$i]);
# increment the counter if the chunk is in the range
if ( ($splitit[0] >= $ip_chunks[$i]) && ($splitit[1] <=
$ip_chunks[$i]) ) { $valid++; };
}
};
# if all the parts match then return a match
if ( $valid == 4 ) { $found = true; };
}
else { # if the line does not contain a -
# if the line matches the ip address then return a match
if ( preg_match ("|$line|",$ip) ) { $found = true; };
}
}
return $found;
}; # end function
?> |
Request for Answer Clarification by
theboistard-ga
on
26 Jul 2004 13:12 PDT
Hello palitoy,
I think your preg_match string is wrong.
I implemented your function and it seems to return a 1 no matter what
parameters I specify, even if I leave a "// Comment". I debugged it to
be because of this line (by changing the return value):
if ( preg_match ("|$line|",$ip) ) { $found = true; };
Let me know if you have an idea why this may happen
|
Clarification of Answer by
palitoy-ga
on
27 Jul 2004 01:31 PDT
I am having trouble replicating the problem on my PC as it works as it
should on my PC.
Can you please supply the following to me via Google Answers:
1) The PHP script (or lines) you are using to call the function
(including the IP addresses you are using to test the match).
2) A copy of the ipaddresses.txt file that you are using with the comments.
The preg_match line you indicated simply takes the line direct from
the ipaddresses.txt file and if this regular expression matches the ip
address passed to the function it returns true (1).
|
Clarification of Answer by
palitoy-ga
on
27 Jul 2004 01:39 PDT
I have just had an idea! Your ipaddresses.txt file also includes
blank lines doesn't it?!
In the script I sent to you replace:
# remove line feeds from the line
$line = chop($line);
With:
# remove line feeds from the line
$line = chop($line);
if ( $line == "" ) { continue; };
|
Request for Answer Clarification by
theboistard-ga
on
27 Jul 2004 10:27 PDT
hello palitoy,
I got it to work, thank you very much, but I have an additional
request that I would like to add to the main question, and I am
willing to tip you an additional $65.00 if you make the code changes.
You will understand why the tip is so high. I need the following
features, mostly format changes:
1) The filter list will contain an entry such as :
192.168.1.100 - 192.168.1.105
2) The filter list should also work with CLASS B/C ranges :
192.168.* - 192.169.*
3) The filter list should allow comments to be placed AFTER the IP entries:
192.168.* - 192.169.* Here goes my comment
4) The filter list should also work with the following:
192.168.3.x (similar to *)
5) The filter list should also differentiate whether a range is given
or its a comment:
192.168.* - 192.169.*
(The above is a range)
192.168.0.* - My Home Network IPs
(The above is a comment)
I am so very sorry for not including these requests in the main
question. Its just that I received filter lists which contain such
entries, and the list itself is very large for me to reformat the IPs
to the format that the script can recognize.
I am ready to rate you with 5 stars, but if you wish to receive the
additional tip, please include the above features to which I would be
very thankful for.
Thanks
|
Clarification of Answer by
palitoy-ga
on
27 Jul 2004 10:39 PDT
I will work on these additions for you and post it as soon as I can...
|
Request for Answer Clarification by
theboistard-ga
on
27 Jul 2004 10:50 PDT
Thank you very much, I will wait patiently.
|
Clarification of Answer by
palitoy-ga
on
27 Jul 2004 11:13 PDT
I need a little more clarification on the latest additions to the question...
If a line has a comment and an IP address on it what should the
function do? Point 3) above suggests it should process the IP, point
5) suggests it should not, obviously only one can be right!
|
Request for Answer Clarification by
theboistard-ga
on
27 Jul 2004 13:09 PDT
hello palitoy,
im sorry for not making it clear enough, look below for clarification:
I'd say it would be good if the script checks whether the line
contains an IP/RAnge entry or a combination of an IP/RAnge + comment.
Here are some entries:
127.0.0.1 Localhost
10.68.* - 10.69.*
24.19.14.12 - 24.20.*.* Added on July 24, 2004
14.* - CyberLink Range
192.168.24.* - 192.168.29.* First Floor Network
192.168.1.* - Local Network
68.24.51.* My local ISP
68.95.*.* : Sys Admin's Range
69.10.1?.* -- Linkage Servers
69.12.44.19 - Linkage Servers 2
I'd say the script has to be very "smart" to know whether the part
after the "-" is a comment (like "Local Network") or a part of a
specified range, and it would be very nice if it can even allow
comments on every line, no matter if its an IP, IP Range (in form of
*, -, ?, etc) or whatever.
Please let me know if this is not clear.
|
Clarification of Answer by
palitoy-ga
on
28 Jul 2004 02:58 PDT
This took quite a lot of working out but I think I have it now ;-)
I have taken a completely different approach to the problem this time
which is why it took so long. The function now converts the IP
addresses to a 13-digit number which can then be compared. This was
necessary for the range checking part.
If you have any queries, let me know!
function chkiplist($ip) {
# read in the ip address file
$lines = file("ipaddresses.txt");
# set a variable as false
$found = false;
# convert ip address into a number
$split_it = split("\.",$ip);
$ip = "1" . sprintf("%03d",$split_it[0]) .
sprintf("%03d",$split_it[1]) . sprintf("%03d",$split_it[2]) .
sprintf("%03d",$split_it[3]);
# loop through the ip address file
foreach ($lines as $line) {
# remove line feeds from the line
$line = chop($line);
# replace x with a *
$line = str_replace("x","*",$line);
# remove comments
$line = preg_replace("|[A-Za-z#/]|","",$line);
# set a maximum and minimum value
$max = $line;
$min = $line;
# replace * with a 3 digit number
if ( strpos($line,"*",0) <> "" ) {
$max = str_replace("*","999",$line);
$min = str_replace("*","000",$line);
}
# replace ? with a single digit
if ( strpos($line,"?",0) <> "" ) {
$max = str_replace("?","9",$line);
$min = str_replace("?","0",$line);
}
# if the line is invalid go to the next line
if ( $max == "" ) { continue; };
# check for a range
if ( strpos($max," - ",0) <> "" ) {
$split_it = split(" - ",$max);
# if the second part does not match an ip address
if ( !preg_match("|\d{1,3}\.|",$split_it[1]) ) {
$max = $split_it[0];
}
else {
$max = $split_it[1];
};
}
if ( strpos($min," - ",0) <> "" ) {
$split_it = split(" - ",$min);
$min = $split_it[0];
}
# make $max into a number
$split_it = split("\.",$max);
for ( $i=0;$i<4;$i++ ) {
if ( $i == 0 ) { $max = 1; };
if ( strpos($split_it[$i],"-",0) <> "" ) {
$another_split = split("-",$split_it[$i]);
$split_it[$i] = $another_split[1];
}
$max .= sprintf("%03d",$split_it[$i]);
}
# make $min into a number
$split_it = split("\.",$min);
for ( $i=0;$i<4;$i++ ) {
if ( $i == 0 ) { $min = 1; };
if ( strpos($split_it[$i],"-",0) <> "" ) {
$another_split = split("-",$split_it[$i]);
$split_it[$i] = $another_split[0];
}
$min .= sprintf("%03d",$split_it[$i]);
}
# check for a match
if ( ($ip <= $max) && ($ip >= $min) ) {
$found = true;
break;
};
}
return $found;
}; # end function
|
Request for Answer Clarification by
theboistard-ga
on
28 Jul 2004 10:02 PDT
Neatly done, thank you so very much.
I am going to rate this question, and then if I have any problems, I
will post them as a comment. Please check back every once in awhile
for a few days just incase, thank you.
|
Clarification of Answer by
palitoy-ga
on
28 Jul 2004 10:49 PDT
Thank-you for the 5-star rating, tip and generous comments they are
all much appreciated. If you need any more help regarding this please
just ask for clarification as you have been doing and I will do my
best to help (if you do it this way it is flagged up as something for
me to clarify whereas just a comment I may miss).
Thanks again.
|