0

I want to append new rules between two comments in an .htaccess file

Order deny,allow
Deny from All

# COMMENT_OPEN #
allow from 151.106.35.164
allow from 152.106.35.164
# COMMENT_CLOSE #

I want to append the new content between the comments, so it appears as the following:

allow from 151.106.35.164
allow from 152.106.35.164
allow from 153.106.35.164

but only if no duplicate is found.


This is the PHP code I tried:

<?php
$htaccess_content = file_get_contents('/path/to/.htaccess'); //open the .htaccess file

$new_rules = 'allow from 153.106.35.164';

$COMMENT_OPEN = "# COMMENT_OPEN #";
$COMMENT_CLOSE = "# COMMENT_CLOSE #";

$search = "/[^\$COMMENT_OPEN](.*)[^\$COMMENT_CLOSE]/";
$replace = "$COMMENT_OPEN \n$new_rules\n $COMMENT_CLOSE";
$remove = preg_replace($search, $replace, $htaccess_content);

$htaccess_content = preg_replace('/'.preg_quote($remove,'/').'/', $replace, $htaccess_content, 1);

file_put_contents($htaccess, $htaccess_content); //save to the .htaccess file
?>

I need suggestions on how to:

  1. Get the content between the comments (to manipulate it).
  2. Replace with the new content between the comments.

Update

Working Solution

//Function to get the content between two strings
function get_string_between($string, $start, $end){
    $string = ' ' . $string;
    $ini = strpos($string, $start);

    if ($ini == 0) return '';

    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;

    return substr($string, $ini, $len);
}

$htaccess_content = file_get_contents('/path/to/.htaccess'); //open the .htaccess file

$updated_rules = '';
$new_rules = 'allow from 153.106.35.164';

$COMMENT_OPEN = "# COMMENT_OPEN #";
$COMMENT_CLOSE = "# COMMENT_CLOSE #";

$current_rules = get_string_between($htaccess_content, $COMMENT_OPEN, $COMMENT_CLOSE);

//If rule not found
if( strpos( $htaccess_content, $new_rules ) === false ) {
    /* Add new rule */ 
    $updated_rules = trim($current_rules) ."\n". $new_rules;
    $pattern = '/'.preg_quote($COMMENT_OPEN).'[\s\S]+?'.preg_quote($COMMENT_CLOSE).'/';
    $replacement = $COMMENT_OPEN."\n\n".$updated_rules."\n\n".$COMMENT_CLOSE;
    $htaccess_content = preg_replace($pattern, $replacement, $htaccess_content);
}

file_put_contents('/path/to/.htaccess', $htaccess_content); //save to the .htaccess file
Amr
  • 574
  • 1
  • 11
  • 15
  • 1
    Allowing `.htaccess` to be edited via a web request can be a serious security hole – anubhava Jun 17 '21 at 18:25
  • One of the most basic things you can learn in regex is the definition of a character class; also known as square brackets `[]`. Please go read about those. – MonkeyZeus Jun 17 '21 at 18:34
  • 1
    Anyways, you could greatly simplify this by using a lookahead to assert a position instead of consuming your boundaries. See https://regex101.com/r/UKaRJl/1/ – MonkeyZeus Jun 17 '21 at 18:37
  • @MonkeyZeus Thanks for the regex guide. But I still want to find a way to remove duplicates in the content. – Amr Jun 17 '21 at 18:53
  • @Amr Preventing duplicates is much easier than removing them. `If file already contains new IP address then do not modify file` – MonkeyZeus Jun 17 '21 at 19:07
  • @MonkeyZeusso how you suggest to prevent duplicates? – Amr Jun 17 '21 at 19:11
  • 1
    `if( strpos( $htaccess, $new_IP ) === false ){ /* Add IP to file */ }` – MonkeyZeus Jun 17 '21 at 19:47
  • Update the post with the solution. Thanks to all who have contributed! – Amr Jun 19 '21 at 06:30
  • @Amr: Please move the solution into an answer (yes you can answer your own questions) and after some little time you can mark it as _the_ answer then. This will make visible that the question has an answer and is answered (accepted). Thanks. – hakre Jun 27 '21 at 13:16
  • @hakre I can't move the solution into an answer as it has been closed by some guy. That's why I edited it so anyone can benefit from it. – Amr Jun 28 '21 at 23:40

0 Answers0