Update HTACCESS file using PHP

ellandrd
ellandrd used Ask the Experts™
on
I want to update my .htaccess file using PHP.

I have a section with comments and rules which I would like to read, update and then write back to the htaccess

So far I get read the contents, but all the contents get read.

How can i start reading the file contents at my comment, update the comment and write back to the htaccess?

My code so far:

$htaccess = $_SERVER['DOCUMENT_ROOT'].'/.htaccess';
             
       $content = file_get_contents($htaccess);
              
                $start = '# Restrict START #';
                  
                  $end = '# Restrict END #';
      
                  preg_match('/$start(.*)$end/s',$content,$matches);
                  
                  echo '<pre>';
                  print_r($matches);
                  echo '</pre>';
          

My .htaccess file contents:


# Restrict START #
order deny,allow
deny from all
allow from 127.0.0.1 # Localhost
# Restrict END #


My matches array is empty though
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2011
Top Expert 2016

Commented:
You can use explode(PHP_EOL, file_get_contents($htaccess)); to create an array of the lines in the file, then iterate over the array.

Author

Commented:
Will this still be a good solution if the htaccess has other rules.  currently it has 346 lines of rules.

Author

Commented:
I've tried using explode(PHP_EOL, file_get_contents($htaccess)); but my array stops after 143 lines.

Most Valuable Expert 2011
Top Expert 2016

Commented:
http://www.laprbass.com/RAY_temp_ellandrd.php

Now tell us what sort of thing you want to change in the .htaccess file and I'll show you how to incorporate the changes and write it back.

Best, ~Ray
<?php // RAY_temp_ellandrd.php
error_reporting(E_ALL);
echo "<pre>";

// THIS STRING SIMULATES READING THE HTACCESS FILE
$htaccess = <<<HTACCESS
# Restrict START #
order deny,allow
deny from all
allow from 127.0.0.1 # Localhost
# Restrict END #
HTACCESS;

// SHOW THE STRING
echo htmlentities($htaccess);

// MAKE IT INTO AN ARRAY
$arr = explode(PHP_EOL, $htaccess);

// SHOW THE ARRAY
print_r($arr);

Open in new window

Most Valuable Expert 2011
Top Expert 2016

Commented:
my array stops

What's the URL of your .htaccess file?  Or can you copy it and paste it into the code snippet?  I'd like to work with the real data.  Thanks, ~Ray

Author

Commented:
>>Now tell us what sort of thing you want to change in the .htaccess file and I'll show you how to incorporate the changes and write it back.

I'm trying to update the:

allow from x.x.x.x #comment

I have a DB table containing IP addresses and comments.  I want to remove the .htaccess rules between # Restrict START # and # Restrict END # and insert new ones.

Author

Commented:
I've attached my htaccess file (renamed it .txt)


htaccess.txt
Most Valuable Expert 2011
Top Expert 2016

Commented:
to remove the .htaccess rules between # Restrict START # and # Restrict END # and insert new ones.
That seems to be fairly easy if I understand it correctly.  Back in a moment...
Most Valuable Expert 2011
Top Expert 2016

Commented:
stops after 143 lines?

What is this thing about at line 142 in the file?

#   <script src="application.js?20100608">

Author

Commented:
Thats a comment in the expire headers/cache section of the htaccess file.
Most Valuable Expert 2011
Top Expert 2016
Commented:
This seems to handle the replacement correctly.  If your script has the right permissions, you can probably use file_put_contents() to write the .htaccess file back after the changes.  You might want to consider file locking.  Just a thought, ~Ray
<?php // RAY_temp_ellandrd.php
error_reporting(E_ALL);
echo "<pre>";

// THIS STRING SIMULATES READING THE HTACCESS FILE
$htaccess = <<<HTACCESS
# Secure .htaccess file
<Files .htaccess>
order allow,deny
deny from all
</Files>


# LOTS OF STUFF REMOVED HERE


# Your server does not allow PHP directives to be set via .htaccess. In that
# case you must make this change in your php.ini file instead. If you are
# using a commercial web host, contact the administrators for assistance in
# doing this. Not all servers allow local php.ini files, and they should
# include all PHP configurations (not just this one), or you will effectively
# reset everything to PHP defaults. Consult www.php.net for more detailed
# information about setting PHP directives.

# php_flag register_globals Off
php_value memory_limit "512M"


# Restrict START #
order deny,allow
deny from all
allow from 127.0.0.1 # Localhost
# Restrict END #
HTACCESS;

// SHOW THE STRING
// echo htmlentities($htaccess);

// MAKE IT INTO AN ARRAY
$arr = explode(PHP_EOL, $htaccess);

// TRIM THE LINES TO REMOVE EXTRANEOUS EOL CHARACTERS
foreach ($arr as $key => $line)
{
    $arr[$key]=trim($line);
}

// SHOW THE ARRAY
// var_dump($arr);

// CREATE SOME NEW STUFF TO INSERT INTO THE SPECIAL PLACE
$newtext = <<<NEWTEXT
# HERE IS THE NEW STUFF, BELOW
# HELLO WORLD
# HERE IS THE NEW STUFF, ABOVE
NEWTEXT;

$new = explode(PHP_EOL, $newtext);

// SHOW THE NEW PART OF THE ARRAY
// print_r($new);

// COMBINE THE ARRAYS USING THE SIGNAL STRINGS
$signal_alpha = '# Restrict START #';
$signal_omega = '# Restrict END #';

// FIND THE SIGNAL STRINGS AND COPY THE PARTS OF THE ARRAY
$top = array_slice($arr, 0, array_search($signal_alpha, $arr)+1);
$end = array_slice($arr, array_search($signal_omega, $arr));
$out = array_merge($top, $new, $end);

// REBUILD THE STRING
$str = implode(PHP_EOL, $out);
echo htmlentities($str);

Open in new window

Most Valuable Expert 2011
Top Expert 2016

Commented:
Sidebar note - I think that <script> tag, which is unclosed, is why you think that file_get_contents() cuts off.  It does not actually cut off, but your browser will have trouble rendering the string.  You can use view source to get a better picture of what is really going on.  HTH, ~Ray
Sandeep KothariProject Lead

Commented:
@ellandrd :

the code you posted is perfect the only mistake was in preg_match you put php variables directly...

the only change needed is this line... replace the preg match line with this one and all is fine...

                  preg_match('/'.$start.'(.*)'.$end.'/s',$content,$matches);

Open in new window

Most Valuable Expert 2011
Top Expert 2016

Commented:
preg_match('/'.$start.'(.*)'.$end.'/s',$content,$matches);

or maybe...

preg_match("/$start(.*)$end/s",$content,$matches);

Either way it might be useful to use preg_quote()
Sandeep KothariProject Lead

Commented:
Ray.... you are reposting the same thing...  this is say 3rd time you are doing it !... anyways!
Most Valuable Expert 2011
Top Expert 2016

Commented:
@kshna: The point of my post is that if ellandrd actually used single quotes around the PHP variables in the regular expression, a change to double quotes might do the job.  There are usually many ways to achieve the same objective, which in this case is variable substitution.  The reason I mentioned preg_quote() is given here.
http://www.php.net/manual/en/function.preg-quote.php

To quote, "useful if you have a run-time string that you need to match" and it looks to me that ellandrd may one day have a run-time string instead of a single variable assignment.

Best to all, over and out, ~Ray
Terry WoodsIT Guru
Most Valuable Expert 2011

Commented:
Altering Ray's code (which is the same as kshna's) to include the preg_quote (very important), and to suggest some supporting code:
$start = '# Restrict START #';
$end = '# Restrict END #';
preg_match('/^(.*'.preg_quote($start,'/').')(.*?)('.preg_quote($end,'/').'.*)$/s',$content,$matches);

$htaccess_part1 = $matches[1];
$htaccess_part2 = $matches[2];  #This is the part you want to update
$htaccess_part3 = $matches[3];

<update $htaccess_part2>

file_put_contents($htaccess, $htaccess_part1.$htaccess_part2.$htaccess_part3);

Open in new window

Author

Commented:
Thanks for all the input guys.

I couldn't get preg_quot or preg_match working?  Not sure if it was my htaccess comments or other rules like you suggested, that was causing issues?

Anyways, I did get it working using this solution by Ray.

BIG THANK YOU DUDE!

Ellandrd
Most Valuable Expert 2011
Top Expert 2016

Commented:
Thanks for the points.  You might want to consider using this:
http://php.net/manual/en/function.flock.php

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial