Apache::Admin::Config − A module to read/write Apache like
configuration files

    use Apache::Admin::Config;

    # Parse an apache configuration file

    my $conf = new Apache::Admin::Config "/path/to/config_file.conf"
        or die $Apache::Admin::Config::ERROR;

    my $directive = $conf−>directive('documentroot');

    print $directive−>name;   # "documentroot"
    print $directive−>value;  # "/my/document/root"
    print $directive−>type;   # "directive"

    $directive−>isin($conf);  # true


    # print the directive list

        print $_−>name, "\n";

    # print the virtualhost list

    print $_−>section('servername')−>value(), "\n"
      foreach $conf−>section(−name => "virtualhost");

    # add a directive in all virtualhosts

    foreach($conf−>section(−name => "virtualhost"))
        $_−>add_directive(php_admin_value => 'open_basedir "/path"');

    # Deleting all "AddType" directives

    $_−>delete for $conf−>directive("AddType");

    # saving changes in place


"Apache::Admin::Config" provides an object oriented
interface for reading and writing Apache‐like configuration
files without affecting comments, indentation, or truncated


     You can easily extract informations from the apache
configuration, or manage htaccess files.

     I wrote this class because I work for an IPP, and we
often manipulate apache configuration files for adding new
clients, activate some features or un/locking directories
using htaccess, etc. It can also be useful for writing some
one‐shoot migrations scripts in few lines.


         $obj = new Apache::Admin::Config [/path/to/file|handle],
      [−indent => $integer], ['−create'], ['−no−comment−grouping'],

     Create or read, if given in argument, an apache like
configuration file, and return an Apache::Admin::Config


    Path to the configuration file to parse. If none given,
    create a new one.

    Instead of specify a path to a file, you can give a
    reference to an handle that point to an already openned
    file. You can do this like this :

        my $obj = new Apache::Admin::Config (\*MYHANDLE);

−indent => $integer
    If greater than 0, activates the indentation on added
    lines, the integer tell how many spaces you went per
    level of indentation (suggest 4). A negative value means
    padding with tabulation(s).

    If present and path to an unexisting file is given,
    don’t return an error.

    When there are several successive comment‐lines, if
    comment grouping is enabled only one comment item is

    If present, disable comment grouping at parsing time.
    Enabled by default.

    Same as comment grouping but for blank lines.



         $obj−>save(['/path/to/file'|HANDLE], ['−reformat'])

     Write modifications to the configuration file. If a
path to a file is given, save the modification to this file
instead. You also can give a reference to a filehandle like
this :

         $conf−>save(\*MYHANDLE) or die($conf−>error());

     Note: If you invoke save() on an object instantiated
with a filehandle, you should emptied it before. Keep in
mind that the constructor don’t seek the FH to the begin
neither before nor after reading it.



     Returns the configuration file as same as it will be if
it was saved in a file with the save() method. If you don’t
call this method from the top level section, it returns the
part of the configuration file that is under the object’s



     Same as dump_raw(), but reformat each line. Usefull
used with −indent constructor parameter.


         @result = $obj−>select
        [−type  => $type],
        [−name  => $name],
        [−value => $value],
        [−which => $index],

    @directives    = $obj−>select('directive');
    @sections_foo  = $obj−>select('section', 'Foo');

     This method search in the current context for items
(directives, sections, comments...) that correspond to a
properties given by arguments. It returns a list of matched

     This method can only be called on an object of type
"section". This method search only for elements in the
section pointed by object, and isn’t recursive. So elements


in sub‐sections of current section aren’s seek (it’s not a


    Selects item(s) of "type" type.

    Selects item(s) with "name" name.

    Selects item(s) with "value" value.

    Instead of returning a list of items, returns only a
    single one pointed by index given to the −which option.
    Caution, returns an empty string if none selected, so
    don’t cascade your methodes calls like
    $obj−>select(−which=>0)−>name. Index starts at 0.

     Method returns a list of item(s) founds. Each items is
an Apache::Admin::Config object with same methods but
pointing to a different part of the tree.


         @directives = $obj−>directive(args...)

     Same as calling select(’directive’, args...)


         @sections = $obj−>section(args...)

     Same as calling select(’section’, args...)


         @comments = $obj−>comment(args...)

     Same as calling select(’comment’, args...)


         @blanks = $obj−>blank(args...)

     Same as calling select(’blank’, args...)




     Replace the directive writing engine by you own code.
Code is call for adding new directives, or when you tell
Apache::Admin::Config to reformat the whole configuration
file. See save() and dump_reformat() methods for more

     Your handler receives 3 arguments : $self, $name and
$value. You can call the "indent()" method to get the number
of spaces to put before the current line (see indent()
methods for more details)

      my($self, $name, $value) = @_;
      return $self−>indent . "$name $value\n";



     Same as set_write_directive() but for section.

     Your handler receives 3 arguments: $self, $name and
$value. You can call the "indent()" method to get the number
of spaces to put before the current line (see indent()
methods for more details)

      my($self, $name, $value) = @_;
      return $self−>indent . "<$name $value>\n";



     Same as set_write_directive() but for end of sections.

     Your handler receives 2 arguments: $self and $name. You
can call the "indent()" method to get the number of spaces
to put before the current line (see indent() methods for
more details)

      my($self, $name) = @_;
      return $self−>indent . "</$name>\n";




     Same as set_write_directive() but for comments.

     Your handler receives 2 arguments: $self and $value.
You can call the "indent()" method to get the number of
spaces to put before the current line (see indent() methods
for more details)

      my($self, $value) = @_;
      # handle comment grouping
      $value =~ s/\n/\n# /g;
      return $self−>indent . join('#', split(/\n/, $value));



     Same as set_write_directive() but for blank lines.

     Your handler receives 2 arguments: $self and $number.

      my($self, $number) = @_;
      return $number x "\n";


         $item = $obj−>add
        $type|$item, [$name], [$value],
        [−before => $target | −after => $target | '−ontop' | '−onbottom']

    $item = $obj−>add('section', foo => 'bar', −after => $conf_item_object);
    $item = $obj−>add('comment', 'a simple comment', '−ontop');

     Add a line of type $type with name foo and value bar in
the context pointed by $object.


    Type of object to add (directive, section, comment or


    Only relevant for directives and sections.

    For directive and section, it defines the value, for
    comments it defined the text.

"−before" => target
    Inserts item one line before target. target _have_ to be
    in the same context

"−after" => target
    Inserts item one line after target. target _have_ to be
    in the same context

    Insert item on the fist line of current context;

    Iinsert item on the last line of current context;

     Returns the added item


         $section = $obj−>add_section($name, $value)

     Same as calling add(’section’, $name, $value)


         $directive = $obj−>add_directive($name, $value)

     Same as calling add(’directive’, $name, $value)


         $comment = $obj−>add_comment("string", [$group])

     Same as calling add(’comment’, ’string’, )

     $group is a boolean value that control grouping of
consecutive comment lines. Disabled by default.


         $blank = $obj−>add_blank([$group])

     Same as calling add(’blank’)

     $group is a boolean value that control grouping of
consecutive blank lines. Enabled by default.




     Change the value of a directive or section. If no
argument given, return the value.


     Returns the value of item pointed by the object if any.

     (Actually "value" and "set_value" are the same method)


        −before => target |
        −after => $target |
        '−ontop' |

     Move item into given section. See "add()" method for
options description.


        −before => target |
        −after => $target |
        '−ontop' |

     Copy item into given section. See "add()" method for
options description.


       $clone = $item−>clone();

     Clone item and all its children. Returns the cloned






         $boolean = $obj−>($section_obj, ['−recursif'])

     Returns true if object point to a rule that is in the
section represented by $section_obj. If "−recursif" option
is present, true is also return if object is a sub‐section
of target.

         <section target>
        <sub section>
            directive test

    $test_directive−>isin($target_section)              => return false
    $test_directive−>isin($sub_section)                 => return true
    $test_directive−>isin($target_section, '−recursif') => return true
    $target_section−>isin($target_section)              => return true


     Returns the name of the current pointed object if any


     Returns the parent context of object. This method on
the top level object returns "undef".


     Returns the type of object.


     Synonym for unlink (deprecated). See unlink().


       $boolean = $item−>unlink();

     Unlinks item from the tree, resulting in two separate
trees. The item to unlink becomes the root of a new tree.


       $boolean = $item−>destroy();


     Destroy item and its children. Caution, you should call
delete() method instead if you want destroy a part of a
tree. This method don’t notice item’s parents of its death.


         $booleen = $item−>delete;

     Remove the current item from it’s parent children list
and destroy it and all its children (remove() + destroy()).


     Return the last appended error.

  # Reindent configuration file properly

  my $conf = Apache::Admin::Config
     −indent => 2


  # Managing virtual−hosts:

  my $conf = new Apache::Admin::Config "/etc/apache/httpd.conf";

  # adding a new virtual−host:
  my $vhost = $conf−>add_section(VirtualHost=>'');
  my $location = $vhost−>add_section(Location=>'/admin');
  $location−>add_directive(Require=>'group admin');

  # selecting a virtual−host:
  my $vhost;
  foreach my $vh (@{$conf−>section('VirtualHost')})
      if($vh−>directive('ServerName')−>value eq 'www.localhost.localdomain')
          $vhost = $vh;



  # Suppress all comments in the file

  sub delete_comments

  sub delete_all_comments


  # Transform configuration file into XML format

  my $c = new Apache::Admin::Config "/path/to/file", −indent => 2
    or die $Apache::Admin::Config::ERROR;

  $c−>set_write_directive(sub {
      my($self, $name, $value) = @_;
      return($self−>indent.qq(<directive name="$name" value="$value />\n));
  $c−>set_write_section(sub {
      my($self, $name, $value) = @_;
      return($self−>indent.qq(<section name="$name" value="$value">\n));
  $c−>set_write_section_closing(sub {
      my($self, $name) = @_;
  $c−>set_write_comment(sub {
      my($self, $value) = @_;
      $value =~ s/\n//g;
      return($self−>indent."<!−− $value −−>");
  print $c−>dump_reformat();


Olivier Poitrey <rs@rhapsodyk.net>

The official FTP location is:


     Also available on CPAN.

     anonymous CVS repository:

     CVS_RSH=ssh cvs −d anonymous@cvs.rhapsodyk.net:/devel
co Apache‐Admin‐Config

     (supply an empty string as password)

     CVS repository on the web:


Please send bug‐reports to aac@list.rhapsodyk.net. You can
subscribe to the list by sending an empty mail to

This library is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.

     This library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
PURPOSE.  See the GNU Lesser General Public License for more

     You should have received a copy of the GNU Lesser
General Public License along with this library; if not,
write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA  02111−1307  USA

Copyright (C) 2001 − Olivier Poitrey