Search code examples
phparraysforeachpreg-matchpreg-match-all

How do I extract deny from IP from htaccess PHP?


I am trying to list IPs that are listed in my htaccess to be denied. I do not want to see the deny from all or allow from.

Sample IP list:

<files .htaccess>
order allow,deny
deny from all
</files>

allow from 10.10.190.187
deny from 10.10.76.194
deny from 10.10.85.70
deny from 10.10.63.174
deny from 10.10.56.77
deny from 10.10.15.196

Desired output:

deny from 10.10.76.194
deny from 10.10.85.70
deny from 10.10.63.174
deny from 10.10.56.77
deny from 10.10.15.196

Note allow from 10.10.190.187 and deny from all are excluded from desired output.

My current code:

$htaccess = $_SERVER["DOCUMENT_ROOT"]."/.htaccess";
$file = $htaccess;
$contents = file_get_contents($file);
$lines = explode("\n", $contents); // this is your array of words
foreach($lines as $line) {
   if (preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $line, $ip_match)) {
   $ip =  $ip_match[0];
}
$pattern = "/deny from $ip/";
   if (preg_match_all($pattern, $line, $ip_denymatch)) {
      foreach($ip_denymatch[0] as $ipL){
         echo $ipL . "<br>"; 
   }
  }  
}

The current output sample is:

deny from
deny from 10.10.76.194
deny from 10.10.85.70
deny from 10.10.63.174
deny from 10.10.56.77
deny from 10.10.15.196

The output includes the deny from all.


Solution

  • When you're reading line: deny from all, the first preg_match return false and $ip is empty.

    Then when you call preg_match_all with $pattern = "/deny from $ip/";, the line is matched.

    You should use a single preg_match like:

    foreach($lines as $line) {
        if (preg_match('/^deny from \d{1,3}(?:\.\d{1,3}){3}$/', $line)) {
            echo $line,"\n";
        }
    }