Page 1 of 1

Array search with wildcard

Posted: Sun Jan 04, 2009 3:10 pm
by MichaelR
Because I want to cut down on database use, both to reduce storage space required and the number of queries performed, I needed to find a way to see if a user's IP address has been banned. I figured the easiest way for this to work is if each banned IP addresses is placed in an array. However, I ran into the problem of not being able to use a wildcard, as I could have in a database. So, I wrote this script. Keeping in line with my simplistic approach to coding, it's very short. Any criticism of it would be appreciated.

Code: Select all

 
 function ban($address) {
 
  $ban = array(
 
   0 => '255.255.255.255',
   1 => '250.250.250'
    
  );
 
  for ($i = 0; $i < sizeof($ban); $i++) {
 
   if (eregi('^'.$ban[$i], $address)) {
    return true; break;
   } 
 
  }
 
 }
 
Before writing this code myself, I tried searching the internet for it and found that others have this same problem. They, though, seek to compare a string with an array, whereas I am doing the opposite. So, for those people, I wrote this:

Code: Select all

 
 function search_array($search, $array, $type) {
 
  switch ($type) {
 
   case (1): // Wildcard at both ends of the string
    $one = '';
    $two = '';
   break;
   case (2): // Wildcard at the end of the string
    $one = '^';
    $two = '';
   break;
   case (3): // Wildcard at the start of the string
    $one = '';
    $two = '$';
   break;
   default: // No wildcard (if wrong type specified)
    $one = '^';
    $two = '$';
   break;
 
  }
 
  for ($i = 0; $i < sizeof($array); $i++) {
 
   if (eregi($one.$search.$two, $array[$i])) {
    return true; break;
   } 
 
  }
 
 }
 

Re: Array search with wildcard

Posted: Mon Jan 05, 2009 4:40 am
by VladSun
I was going to say that "I think that for resourse expensive array operations it's better to use PHP array functions instead of user defined loops. I would use array_walk() in your case."

Then... I decided to test it first ;)

Code: Select all

function microtime_float() 
{ 
    list($usec, $sec) = explode(" ", microtime()); 
    return ((float)$usec + (float)$sec); 
} 
 
function walker($value, $key)
{
    $b = $value;
}
 
$a = array();
 
for($i=0; $i< 10000; $i++)
    $a[] = $i;
 
$time_start = microtime_float();
for($j=0; $j<count($a); $j++) $b = $a[$j];
$time_end = microtime_float();
$time = $time_end - $time_start;
echo 'Loop with count(): '.$time.'<br />';
 
$c = count($a);
$time_start = microtime_float();
for($j=0; $j<$c; $j++) $b = $a[$j];
$time_end = microtime_float();
$time = $time_end - $time_start;
echo 'Loop with precalculated count(): '.$time.'<br />';
 
$time_start = microtime_float();
array_walk($a, 'walker');
$time_end = microtime_float();
$time = $time_end - $time_start;
echo 'Array_walk: '.$time.'<br />';
Results:
Loop with count(): 0.0048961639404297
Loop with precalculated count(): 0.0018329620361328
Array_walk: 0.011137008666992
:mrgreen:

Re: Array search with wildcard

Posted: Mon Jan 05, 2009 4:45 am
by VladSun
If search speed is a critical requirement then I will use a prefix tree - http://en.wikipedia.org/wiki/Trie, because you are matching prefixes indeed :)

Re: Array search with wildcard

Posted: Sat Jan 10, 2009 10:54 am
by jason.carter
I think is a better solution to ban based on the apache .htaccess file

simple as follows
order allow,deny
deny from xxx.xx.x.x
deny from xxx.xx.x.x
deny from xxx.xx.x.x
allow from all

Using this can also ban the IP accessing any resource on the web server (like images, pdf etc).

You just need to have a quick way to update the .htaccess file and keep it updated.