Hi guys,

I have a problem here.

I am trying to parse a configuration file and have gotten far before I got stuck at how to exclude unwanted lines (commented ones primarily).

Here is the text file:

Installation path

INSPATH="/usr/local/bfd"
#

Rules path

RPATH="$INSPATH/rules"
#

Track log path

TLOGP="$INSPATH/tlog"
#

Log file

LOG="/var/log/bfd_log"

Do kernel logging

USE_KLOG="1"
#

System kernel log

KLOG="/var/log/messages"
#

System secure log

SLOG="/var/log/secure"

Enable/disable user alerts [0 = off; 1 = on]

ALERT_USR="1"
#

User alert email address

EMAIL_USR="root"
#

User alert email; subject

SUBJ_USR="Brute Force Warning for $HOSTNAME"
#

Path to alert e-mail template

ALERTF="$INSPATH/alert.bfd"

Pattern file containing authentication error strings; these strings are

greped from defined log files in a module to determine an event.

PATTERN_FILE="$INSPATH/pattern.auth"
#
#

Pass $ATT_HOST to firewall or other application/facility (tcpwrappers)

# i.e: BCMD="echo ALL:$ATT_HOST >> /etc/hosts.deny"
BCMD="/etc/apf/apf -d $ATT_HOST {bfd.$MOD}"
#

A flat file where the bans actually reside to ensure the ban is still

in place; if not then we will reban, otherwise the attacker is ignored.

BCMD_FILE="/etc/apf/deny_hosts.rules"
#

Parse files searching for $ATT_HOST; if present assume trusted or already

banned - Add ignore files, deny files and such; line or space seperated.

PRECHK_FILES="$INSPATH/exclude.files"

Grab the systems numeric timezone (e.g: -0500)

TMZ=date +"%z"
#

unix time for lock tracking

UTIME=date +"%s"
#

lock file path

LOCK="$INSPATH/lock.utime"
#

lock file timeout in seconds

LOCK_TIMEOUT="620"

Here is the code:

preg_match_all('/([a-zA-Z0-9_]+)=(\'|\"|\`)(.*?)(\'|\"|\`)\n/si',$bfd_conf,$matches,PREG_SET_ORDER);

The output is :


Array
(
    [0] => Array
        (
            [0] => INSPATH="/usr/local/bfd"

        [1] => INSPATH
        [2] => "/usr/local/bfd"
    )

[1] => Array
    (
        [0] => RPATH="$INSPATH/rules"

        [1] => RPATH
        [2] => "$INSPATH/rules"
    )

[2] => Array
    (
        [0] => TLOGP="$INSPATH/tlog"

        [1] => TLOGP
        [2] => "$INSPATH/tlog"
    )

[3] => Array
    (
        [0] => LOG="/var/log/bfd_log"

        [1] => LOG
        [2] => "/var/log/bfd_log"
    )

[4] => Array
    (
        [0] => USE_KLOG="1"

        [1] => USE_KLOG
        [2] => "1"
    )

[5] => Array
    (
        [0] => KLOG="/var/log/messages"

        [1] => KLOG
        [2] => "/var/log/messages"
    )

[6] => Array
    (
        [0] => SLOG="/var/log/secure"

        [1] => SLOG
        [2] => "/var/log/secure"
    )

[7] => Array
    (
        [0] => ALERT_USR="1"

        [1] => ALERT_USR
        [2] => "1"
    )

[8] => Array
    (
        [0] => EMAIL_USR="root"

        [1] => EMAIL_USR
        [2] => "root"
    )

[9] => Array
    (
        [0] => SUBJ_USR="Brute Force Warning for $HOSTNAME"

        [1] => SUBJ_USR
        [2] => "Brute Force Warning for $HOSTNAME"
    )

[10] => Array
    (
        [0] => ALERTF="$INSPATH/alert.bfd"

        [1] => ALERTF
        [2] => "$INSPATH/alert.bfd"
    )

[11] => Array
    (
        [0] => PATTERN_FILE="$INSPATH/pattern.auth"

        [1] => PATTERN_FILE
        [2] => "$INSPATH/pattern.auth"
    )

[12] => Array
    (
        [0] => BCMD="echo ALL:$ATT_HOST >> /etc/hosts.deny"

        [1] => BCMD
        [2] => "echo ALL:$ATT_HOST >> /etc/hosts.deny"
    )

[13] => Array
    (
        [0] => BCMD="/etc/apf/apf -d $ATT_HOST {bfd.$MOD}"

        [1] => BCMD
        [2] => "/etc/apf/apf -d $ATT_HOST {bfd.$MOD}"
    )

[14] => Array
    (
        [0] => BCMD_FILE="/etc/apf/deny_hosts.rules"

        [1] => BCMD_FILE
        [2] => "/etc/apf/deny_hosts.rules"
    )

[15] => Array
    (
        [0] => PRECHK_FILES="$INSPATH/exclude.files"

        [1] => PRECHK_FILES
        [2] => "$INSPATH/exclude.files"
    )

[16] => Array
    (
        [0] => TMZ=`date +"%z"`

        [1] => TMZ
        [2] => `date +"%z"`
    )

[17] => Array
    (
        [0] => UTIME=`date +"%s"`

        [1] => UTIME
        [2] => `date +"%s"`
    )

[18] => Array
    (
        [0] => LOCK="$INSPATH/lock.utime"

        [1] => LOCK
        [2] => "$INSPATH/lock.utime"
    )

[19] => Array
    (
        [0] => LOCK_TIMEOUT="620"

        [1] => LOCK_TIMEOUT
        [2] => "620"
    )

)

As you can tell, I wanted to leave out the 12th array which was parsed from the commented line ,
# i.e: BCMD="echo ALL:$ATT_HOST >> /etc/hosts.deny".
As the comments start with a #, I have tried adding a !# at the beginning of my regular expression but it didn't help at all.

Could somebody shed a light?

    preg_match_all('/[#]([a-zA-Z0 ...

    is what you need.

      If it is possible to change the "#" to ";", then you could simply use the [man]parse_ini_file/man function.

        halfabee,

        That didn't do the trick. The commented line was still being parsed.

        HalfaBee wrote:

        preg_match_all('/[#]([a-zA-Z0 ...

        is what you need.

        nogdog, the format of the file is not within my control as it is a third-party script.

          I tested putting the [#] in and it strips lines starting with #, but to make it work completly add \n[#].

          This strips out the commented settings.

          preg_match_all( "/\n#=(\'|\"|`)(.*?)(\'|\"|`)\n/si", ...

          Note that the regex should be in " not '.

            This seems to work:

            preg_match_all('/(?<=^|\n)\s*(\w*)\s*=\s*(.*)(?=\n|$)/U', $text, $matches, PREG_SET_ORDER);
            

              And just to be silly:

              class VariableStream {
                  var $position;
                  var $varname;
              
              function stream_open($path, $mode, $options, &$opened_path) 
              {
                  $url = parse_url($path);
                  $this->varname = $url["host"];
                  $this->position = 0;
              
                  return true;
              }
              
              function stream_read($count) 
              {
                  $ret = substr($GLOBALS[$this->varname], $this->position, $count);
                  $this->position += strlen($ret);
                  return $ret;
              }
              
              function stream_write($data) 
              {
                  $left = substr($GLOBALS[$this->varname], 0, $this->position);
                  $right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
                  $GLOBALS[$this->varname] = $left . $data . $right;
                  $this->position += strlen($data);
                  return strlen($data);
              }
              
              function stream_tell() 
              {
                  return $this->position;
              }
              
              function stream_eof() 
              {
                  return $this->position >= strlen($GLOBALS[$this->varname]);
              }
              
              function stream_seek($offset, $whence) 
              {
                  switch ($whence) {
                      case SEEK_SET:
                          if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
                               $this->position = $offset;
                               return true;
                          } else {
                               return false;
                          }
                          break;
              
                      case SEEK_CUR:
                          if ($offset >= 0) {
                               $this->position += $offset;
                               return true;
                          } else {
                               return false;
                          }
                          break;
              
                      case SEEK_END:
                          if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
                               $this->position = strlen($GLOBALS[$this->varname]) + $offset;
                               return true;
                          } else {
                               return false;
                          }
                          break;
              
                      default:
                          return false;
                  }
              }
              }
              
              stream_wrapper_register("var", "VariableStream")
                  or die("Failed to register protocol");
              
              $test = preg_replace('/(?<=^|[\r\n])#/', ';', file_get_contents('config.file'));
              $test = parse_ini_file('var://test');

                If this file were read in as an array of lines (i.e., what you'd get from [man]file[/man]) then stripping out lines that start with '#' would be

                preg_grep('/^#/', $file, PREG_GREP_INVERT)

                  Nogdog,

                  Thanks, your pattern works but I would really love to know what B[/B] is all about.
                  Would you mind breaking it down ?

                  Cheers!
                  :evilgrin:

                  NogDog wrote:

                  This seems to work:

                  preg_match_all('/(?<=^|\n)\s*(\w*)\s*=\s*(.*)(?=\n|$)/U', $text, $matches, PREG_SET_ORDER);
                  

                    It's a lookbehind assertion, says make sure that before the \s* is either the beginning of the string OR a line break.

                    More info on lookbehinds can be found here.

                      bradgrafelman wrote:

                      It's a lookbehind assertion, says make sure that before the \s* is either the beginning of the string OR a line break.

                      More info on lookbehinds can be found here.

                      Yep. And the end of the regex is a look-ahead assertion looking for either another newline or the end of the string.

                        Write a Reply...