block ip's help needed

Discussion in 'PHP' started by andre75, Jan 14, 2007.

  1. #1
    I am trying to block a certain range of ips and i want to do it in php rather than .htaccess. I am using this:
    <?php
    	$ip = $_SERVER['REMOTE_ADDR'];
    	$sparray = file ("iplist.txt");
    	//$sparray[0]="127.0.0.1"; 
    	//$sparray[1]="111.11.11.1";
    	for ($j=0;$j<count($sparray);$j++){
    		$sparray[$i]=trim($sparray[$i]);
    	}
    	if (in_array($ip, $sparray)) {
    		$block=1;
    	}
    	else{
    		$block=0;
    	}
    
    	echo $block."<br>";
            print_r($sparray);  //check the array
    ?>
    PHP:
    But it doesn't work. The value of $block is 0.
    When I comment out this line $sparray = file ("iplist.txt"); and instead remove the comments from the other two lines its working. The text file only contains the two ips for testing, but ultimately I will put all offenders there and fetch it from a server for all my sites (hence php instead of .htaccess).
    I am testing on my local machine 127.0.0.1.
    What am I missing? I have been banging my head forever on this.

    Andre
     
    andre75, Jan 14, 2007 IP
  2. maiahost

    maiahost Guest

    Messages:
    664
    Likes Received:
    35
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Why don't you put some error checking like :
    
    if (!($sparray = file ("iplist.txt"))
    {
    echo 'error opening file';
    }
    else {....}
    
    
    PHP:
     
    maiahost, Jan 14, 2007 IP
  3. andre75

    andre75 Peon

    Messages:
    1,203
    Likes Received:
    45
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Thanks for the answer, but that doesn't solve the problem.
    The output of the script is:
    (the first line is generated by the echo statement and the last one by the print_r statement). Hence the file is opened correctly.
    I still don't get why $block is 0.

    Anyone knows the answer?
     
    andre75, Jan 14, 2007 IP
  4. krakjoe

    krakjoe Well-Known Member

    Messages:
    1,795
    Likes Received:
    141
    Best Answers:
    0
    Trophy Points:
    135
    #4
    because you only set block to true if the ip that you're visiting from is an ip in the array ... I'm guessing it's not ...
     
    krakjoe, Jan 14, 2007 IP
  5. andre75

    andre75 Peon

    Messages:
    1,203
    Likes Received:
    45
    Best Answers:
    0
    Trophy Points:
    0
    #5
    But it is
    
    	echo $block."<br>";
    	echo $ip."<br>";
    	print_r($sparray);
    	echo "<br>";
    
    PHP:
    If I put this in my code I get:
    0
    127.0.0.1
    Array ( [0] => 127.0.0.1 [1] => 111.11.11.1 [] => )
    So clearly my ip (localhost) is detected right and is contained in the array.
    If I change the code to include iplist.php which looks like this:
    
    <?php
    $sparray = array(
    '111.11.11.1',
    '127.0.0.1', 
    );
    ?>
    
    PHP:
    Then the detection works right.
    That doesn't make any sense to me.
     
    andre75, Jan 14, 2007 IP
  6. krakjoe

    krakjoe Well-Known Member

    Messages:
    1,795
    Likes Received:
    141
    Best Answers:
    0
    Trophy Points:
    135
    #6
    ok, use this instead ....

    
    <?
    $iparray = split("\r\n", file_get_contents("ips.txt"));
    if(in_array($_SERVER['REMOTE_ADDR'], $iparray))
    {
    	die("BANNED");
    }
    ?>
    
    PHP:
    OR

    
    <?
    $iparray = split("\n", file_get_contents("ips.txt"));
    foreach( $iparray as $banned )
    {
        if( $_SERVER['REMOTE_ADDR'] == trim($banned) )
        {
            die("BANNED");
        }
    }
    ?>
    
    PHP:
    Both of the above code examples function with a ips.txt looking like

    
    127.0.0.1
    172.6.0.1
    192.168.0.1
    
    Code (markup):
    and both code examples work, theres only one explanation for this :

    I think that file() splits a file by newline characters ("\n"), however files authored inside windows will have carriage return and a newline character ("\r\n"), I have also discovered that php has the ability to detect line endings when it uses fopen wrappers ( near on everthing with file in the function name ), however this by default isn't set in an attempt to keep php multi-OS

    Hope that helps .....

    In addition :

    I read in your post you wish to block certain ip ranges, the above code will not do that .... however

    
    <?
    $iparray = split("\n", file_get_contents("ips.txt"));
    
    foreach ($iparray as $ip )
    {
    	$regex[] = str_replace( array(".", "*"), array("\.", "([0-9]+)"), $ip );
    }
    foreach( $regex as $banned )
    {
    	if(preg_match("/".trim($banned)."/", $_SERVER['REMOTE_ADDR']))
    	{
    		die("BANNED");	
    	}
    }
    
    ?>
    
    PHP:
    Will do exaclty that, the above code example works with a ips.txt that looks like

    
    127.0.0.*
    172.6.0.1
    192.168.0.1
    
    Code (markup):
    * is the wildcard character......

    Thats gotta help right ?
     
    krakjoe, Jan 16, 2007 IP
    andre75 likes this.
  7. andre75

    andre75 Peon

    Messages:
    1,203
    Likes Received:
    45
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Yeah, pretty cool. Thanks a bunch. I ran accross the ip range thing myself and my solution was to explode the string into an array with the . as delimiter and then check from the beginning on (this way I don't need a wildcard and my ranges look like this: 127.0.0 ).
    I will give it a try when I get home, just wanted to say thanks for spending the time on this.
     
    andre75, Jan 16, 2007 IP
  8. solidphp

    solidphp Peon

    Messages:
    46
    Likes Received:
    2
    Best Answers:
    0
    Trophy Points:
    0
    #8
    Just wanted to add to this thread, you could save yourself some trouble by changing this:


    $iparray = split("\n", file_get_contents("ips.txt"));
    PHP:
    To this:

    $iparray=file('ips.txt');
    PHP:
    file() returns an array split on \n
     
    solidphp, Jan 16, 2007 IP
  9. andre75

    andre75 Peon

    Messages:
    1,203
    Likes Received:
    45
    Best Answers:
    0
    Trophy Points:
    0
    #9
    and how is this different from my original script?
     
    andre75, Jan 16, 2007 IP
  10. solidphp

    solidphp Peon

    Messages:
    46
    Likes Received:
    2
    Best Answers:
    0
    Trophy Points:
    0
    #10
    In the end result there is no difference. I was just giving you a tip for future reference. Using file() saves you the trouble of reading in a file and then splitting that into an array based on a string value. This could make a big difference in resource usage depending on the size of the text file.

    So it was just something I picked up along the way and wanted to pass on to you and the community. Just ignore my reply if it confuses the situation.
     
    solidphp, Jan 16, 2007 IP
  11. krakjoe

    krakjoe Well-Known Member

    Messages:
    1,795
    Likes Received:
    141
    Best Answers:
    0
    Trophy Points:
    135
    #11
    There is a difference, if the file being parsed for ips is authored inside windows, then numbers will not match becuase the variable will contain the ip and an invisible \r so unless you get to trim the variable then using in_array and file will fail in these circumstances, it looks for an exact match and it doesn't have one, so its one or the other .....
     
    krakjoe, Jan 17, 2007 IP
  12. solidphp

    solidphp Peon

    Messages:
    46
    Likes Received:
    2
    Best Answers:
    0
    Trophy Points:
    0
    #12
    That's right Joe, it's not an issue with file() though. That's another reason it's better to go with file() instead of the other way.
     
    solidphp, Jan 17, 2007 IP
  13. krakjoe

    krakjoe Well-Known Member

    Messages:
    1,795
    Likes Received:
    141
    Best Answers:
    0
    Trophy Points:
    135
    #13
    it is an issue with file() like you said it splits files by \n chars and not \r\n so any variables will have \r on the end of them meaning if you cannot trim it you will not get a numerical match.
     
    krakjoe, Jan 17, 2007 IP
  14. solidphp

    solidphp Peon

    Messages:
    46
    Likes Received:
    2
    Best Answers:
    0
    Trophy Points:
    0
    #14
    file() only looks for a line ending, if that's \n or \r\n it doesn't matter. Create a test case and you'll see what I mean.

    Yes, this will fail with \r only:

    $iparray = split("\n", file_get_contents("ips.txt"));
    PHP:

    This will work everytime:

    $iparray=file('ips.txt');
    PHP:
    See this entry for more information: http://us2.php.net/file
     
    solidphp, Jan 17, 2007 IP
  15. andre75

    andre75 Peon

    Messages:
    1,203
    Likes Received:
    45
    Best Answers:
    0
    Trophy Points:
    0
    #15
    Hm. I appreciate your thoughts, but my original code doesn't work and it's doing exactly that
     
    andre75, Jan 17, 2007 IP