0

I want to check if a line exists in a file so that I avoid the same line repetition. I have put a dev restriction to the site to only allow myself to view it, others are redirected to "unavailable.php" page
But I want to allow people to view site if they request a permission
In my case, I have a .htaccess file

Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REMOTE_HOST} !^34\.120\.121\.20 #this a random ip
RewriteCond %{REQUEST_URI} !path/to/first/exception\.php$ #first exception is 'unavailable.php'
RewriteCond %{REQUEST_URI} !path/to/another/exception\.php$ #the second exception is 'request_permission.php'
RewriteRule \.php$ /redirect/to/first/exception/ [L]

and in request_permission.php, I have the following code:

<?php
    $ip = $_SERVER['REMOTE_ADDR'];
    $data = file('.htaccess');
    $parts = explode(' ', $data[2]);
    $parts_end = end($parts);
    $parts_substred = substr($parts_end, 2); 
    $ip_addr = str_replace('\\', '', $parts_substred); 
    if ($ip_addr != $ip){
        $new_ip = str_replace('.', '\\.', $_SERVER['REMOTE_ADDR']);
        $new_string = str_replace($parts_end, "", $data[2]) . "!^".$new_ip;
        $string = $data[0].$data[1].$data[2].$new_string.PHP_EOL.$data[3].$data[4].$data[5];
        //file_put_contents(".htaccess", $string);
    }
?>

Now everytime I visit request_permission.php a new line, like this is being created: RewriteCond %{REMOTE_HOST} !^56\.80\.1\.15 (let's say this is my ip).

I want to check if the line with my IP address exists in htaccess, do that I won't duplicate it again.


I tried to use strpos() but it doesn't find my IP address even if that exists.

How should I do this?

  • Something like this? http://stackoverflow.com/questions/19760564/php-find-a-string-in-file-then-show-its-line-number – bloodyKnuckles Mar 15 '15 at 14:25
  • 2
    You use the wrong approach. Do not modify an `.htaccess` style file for this. Instead take a look at the documentation: there are means to access a database in background for this. Much more convenient, less error prone, easier. – arkascha Mar 15 '15 at 14:25
  • humm, then how can I allow that IP if I don't modify the `.htaccess` file? – Cristian Alexandru Mar 15 '15 at 14:29
  • In your code you are explicitly requiring that duplicate to be in the 3rd line (`$data[2]`) and if it exists somewhere else then you ignore it (thus perhaps duplicating it). Can I assume this is NOT what you are wanting to do? – Peter Bowers Mar 15 '15 at 14:32
  • Christian, I recommend you to not use .htaccess for this. Another approach, is rely on a database, where you may persist the IP data of the authorized person. (to check this, you just may create an include file that will check the remote address (in $_SERVER) and match against the data in your database. If there`s no match, means it has no access to that place. – Thiago Elias Mar 15 '15 at 14:34
  • @PeterBowers you may assume this – Cristian Alexandru Mar 15 '15 at 14:34
  • Was this question a reply to my comment? "then how can I allow that IP if I don't modify the .htaccess file?" Well, didn't I say so? " – arkascha Mar 15 '15 at 14:35
  • @ThiagoElias `.htaccess` style file is perfectly fine, if you combine it with a database. :-) – arkascha Mar 15 '15 at 14:36
  • @arkascha: yes, it was | I use it together with a database in the real project, to track the expiration time.. in fact I only allow permission for 7 hours/day – Cristian Alexandru Mar 15 '15 at 14:38
  • Ok, but what is that meant to tell us? – arkascha Mar 15 '15 at 14:38
  • I agree with you @arkascha =D (my concern is just about rely only in .htaccess) bigger .htaccess file will result in performance loss.. I had to deal with some awful .htaccess file in my old job haha.. I don't even like to remember.. They looked like an horror movie.. hahah – Thiago Elias Mar 15 '15 at 14:39
  • @ThiagoElias OK, I just mentioned that because in your comment above you suggest a php based database access which is something totally different. – arkascha Mar 15 '15 at 14:40

1 Answers1

2

I would just look for any REMOTE_HOST line using a regex in preg_match() and then append the needed line if it's not found:

Do note that I fully agree with the opinions of others that this is not really a GOOD solution. I am answering the question but recommending at the same time that you look for some alternate way...

My original (now deleted) had some problems - this one works, albeit still doing something I don't think you should do (I'm just copying in the whole test script for ease - you'll need to go back to reading the file):

<?php

$ip = '34.120.121.29';
$ip_pat = str_replace('.', '\\\\\\.', $ip);
# Note that I'm using $data as a straight string, not an array - use file_get_contents() to read it
$data = <<<EOF
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REMOTE_HOST} !^34\.120\.121\.20 #this a random ip
RewriteCond %{REQUEST_URI} !path/to/first/exception\.php$ #first exception is 'unavailable.php'
RewriteCond %{REQUEST_URI} !path/to/another/exception\.php$ #the second exception is 'request_permission.php'
RewriteRule \.php$ /redirect/to/first/exception/ [L]
EOF;
$pat = '^RewriteCond *%{REMOTE_HOST} *';
if (!preg_match("/$pat.*$ip_pat/m", $data)) {
    #echo "NO MATCH<br />\n";
    $new_ip = str_replace('.', '\\.', $ip);
    $new_string = preg_replace("/$pat/m", "RewriteCond %{REMOTE_HOST} !^$new_ip".PHP_EOL."$0", $data);
    #$data .= $new_string.PHP_EOL;
    echo nl2br("$new_string");
}

Note the use of the limit parameter in the call to preg_replace() to only replace the first occurrence. If you don't do that then your 3rd addition will be doubled and your 4th addition will be quadrupled and so on.

Peter Bowers
  • 3,063
  • 1
  • 10
  • 18
  • @arkascha, please re-read my evaluative paragraph. I said I agree with others that it is *not* (emphasis added) a good idea and that the OP look for some *alternate* way. – Peter Bowers Mar 15 '15 at 15:01
  • the snippet gives me an error, that `preg match requests at least 2 parameters, 1 given`, where did you search that: `/RewriteCond *%\{REMOTE_HOST\} *!^'.$ip_pat.'/'`? – Cristian Alexandru Mar 15 '15 at 15:04
  • Look at the part below where I edited it. Adding the extra argument into the preg_match was just one needed change... – Peter Bowers Mar 15 '15 at 15:05
  • It doesn't do what I expect to. Here is the rendered result: `NO MATCH | Options +FollowSymlinks | RewriteEngine On | RewriteCond %{REMOTE_HOST} !^34\.120\.121\.29 !^34\.120\.121\.20 #this a random ip | RewriteCond %{REQUEST_URI} !path/to/first/exception\.php$ #first exception is 'unavailable.php' | RewriteCond %{REQUEST_URI} !path/to/another/exception\.php$ #the second exception is 'request_permission.php' | RewriteRule \.php$ /redirect/to/first/exception/ [L]` – Cristian Alexandru Mar 15 '15 at 15:16
  • Since it's a comment I'm not sure if the issue is newlines or if you don't like the placement of the new IP address. Please be specific about what you are expecting. – Peter Bowers Mar 15 '15 at 15:21
  • The problem is here: `RewriteCond %{REMOTE_HOST} !^34\.120\.121\.29 !^34\.120\.121\.20`, notice there are 2 IPs separated by a space, what I need is that each IP to be on a new line, with `RewriteCond %{REMOTE_HOST}` before the second one as well. – Cristian Alexandru Mar 15 '15 at 15:25
  • Looks from this link http://stackoverflow.com/questions/8602399/allow-multiple-ips-to-access-wordpress-site-admin-via-htaccess that your proposed solution isn't going to work. You will need to put all the IPs on the same line, but in a slightly different syntax. – Peter Bowers Mar 15 '15 at 15:50
  • Your last edited answer has been accepted, as it did what I wanted! Thank you so much – Cristian Alexandru Mar 15 '15 at 16:54
  • The `m` pattern modifier has no impact on the pattern because the pattern does not contain any starting or ending anchors in it (`^` or `$`). – mickmackusa Jan 16 '23 at 00:58