Changes 222
ConfigFile.pm 19195
README 178185
3 files changed (This is a version diff) 391282
@@ -1,36 +1,16 @@
 
 RCS file: /home/nwiger/perlmod/lib/Apache/RCS/ConfigFile.pm,v
 Working file: /home/nwiger/perlmod/lib/Apache/ConfigFile.pm
-head: 1.23
+head: 1.18
 branch:
 locks: strict
 access list:
 symbolic names:
 keyword substitution: kv
-total revisions: 23;	selected revisions: 23
+total revisions: 18;	selected revisions: 18
 description:
 Apache::ConfigFile
 ----------------------------
-revision 1.23
-date: 2003/10/09 18:24:41;  author: nwiger;  state: Exp;  lines: +29 -9
-added some $^W fixes, and the big UNSUPPORTED section
-----------------------------
-revision 1.22
-date: 2003/10/08 19:12:29;  author: nwiger;  state: Exp;  lines: +63 -33
-added inherit_from option to allow inheritance
-----------------------------
-revision 1.21
-date: 2003/10/07 23:52:34;  author: nwiger;  state: Exp;  lines: +45 -42
-added _ self-referrent, fixed misc bugs, workie nice now
-----------------------------
-revision 1.20
-date: 2003/10/07 21:16:06;  author: nwiger;  state: Exp;  lines: +6 -6
-fixed a longstanding bug w/ variable expansion
-----------------------------
-revision 1.19
-date: 2003/10/07 21:02:44;  author: nwiger;  state: Exp;  lines: +66 -23
-added a patch from Michael Grubb to add some ServerRoot override functionality
-----------------------------
 revision 1.18
 date: 2001/09/18 18:31:23;  author: nwiger;  state: Exp;  lines: +5 -2
 changed VERSION to standard CPAN one; is now at 1.17
@@ -1,5 +1,5 @@
 
-# Copyright (c) 1999-2003, Nathan Wiger <nate@wiger.org>
+# Copyright (c) 1999-2001, Nathan Wiger <nate@wiger.org>
 # Try "perldoc Apache/ConfigFile.pm" for documentation
 
 package Apache::ConfigFile;
@@ -104,24 +104,17 @@ use strict;
 use vars qw($VERSION $AUTOLOAD);
 
 # This is a modified VERSION that turns RCS "1.3" into "0.03"
-#$VERSION = do { my($r)=(q$Revision: 1.23 $=~/[\d\.]+/g); $r--; sprintf("%d.%02d", split '\.', $r)};
+#$VERSION = do { my($r)=(q$Revision: 1.18 $=~/[\d\.]+/g); $r--; sprintf("%d.%02d", split '\.', $r)};
 
 # Use regular version or else Changes and VERSION section don't match
-$VERSION = do { my @r=(q$Revision: 1.23 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
-
-# stringify to name
-use overload '""'   => sub { $_[0]->_ },
-             '0+'   => sub { $_[0]->_ },
-             'bool' => sub { $_[0]->_ },
-             'eq'   => sub { $_[0]->_ eq $_[1] };
+$VERSION = do { my @r=(q$Revision: 1.18 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
 
 # Default options
-my %OPT = (
-    ignore_case  => 0,
-    fix_booleans => 0,
-    expand_vars  => 0,
-    raise_error  => 0,
-    root_directive => 'ServerRoot',
+my @OPT = qw(
+    ignore_case   0
+    fix_booleans  0
+    expand_vars   0
+    raise_error   0
 );
 
 sub _error {
@@ -149,20 +142,16 @@ sub read {
     # handle different arg forms - singular and multi
     my %opt;
     if (@_ == 1) {
-        %opt = %OPT;
+        %opt = @OPT;
         $opt{file} = shift;
     } else {
         # hash of stuff
-        %opt = (%OPT, @_);
+        %opt = (@OPT, @_);
     }
 
     # just in case
     $opt{file} ||= "/usr/local/apache/conf/httpd.conf";
 
-    # allow explicit overriding of ServerRoot
-    $opt{"$opt{root_directive}"} = $opt{server_root}
-        if $opt{server_root};
-
     my $s = bless \%opt, $class;
 
     # Now read the config file
@@ -170,38 +159,24 @@ sub read {
     return $s;
 }
 
+my $server_root = '';
 sub _include {
     # This recursively expands any "include" lines
     my $self = shift;
     my $file = shift;
-    my $root = $self->{root_directive};
 
     # add the server root unless it's a /full/path/name
-    $file = "$self->{$root}/$file" if $file !~ m!^/! && $self->{$root};
-
-    # this handles directory includes (i.e. will include all files in a directory)
-    my @conf = ();
-    my @files = ();
-    if (-d $file) {
-        opendir(CONFD, $file) || $self->_error("Cannot open directory '$file': $!");
-        @files = map { "$file/$_" } grep { -f "$file/$_" } readdir CONFD;
-        closedir(CONFD);
-    } else {
-        @files = ($file);
-    }
+    $file = "$server_root/$file" if $file !~ m!^/! && $server_root;
 
-    for my $cf (@files) {
-        open(CONF, "<$cf") 
-            || $self->_error("Cannot read '$cf': $! (did you define $root first?)");
-        push(@conf, <CONF>);
-        chomp(@conf);
-        close(CONF);
-    }
+    open(CONF, "<$file")
+        || croak("Cannot read '$file': $! (do you need to define ServerRoot?)");
+    chomp(my @conf = <CONF>);
+    close(CONF);
 
     # Check for any include lines - must do this inline!
     for (my $i=0; $i < @conf; $i++) {
-        if ($conf[$i] =~ /^(?:$root)\s+"?([^"]+)"?/i) {
-            $self->{$root} = $1;
+        if ($conf[$i] =~ /^(?:ServerRoot)\s+"?([^"]+)"?/i) {
+            $server_root = $1;
         } elsif ($conf[$i] =~ /^(?:Include|AccessConfig|ResourceConfig)\s+"?([^"]+)"?/i) {
             my @f = $self->_include($1);
             splice @conf, $i, 1, @f;    # stick it inline
@@ -219,18 +194,13 @@ sub reread {
     # the lines that make up our config file, in order
     my @conf = $self->_include($file);
 
-    local $^W = 0;      # damn string uninit parsing warnings
-
     # Create a hash and a parse level "pointer"
     my $conf = {};
     my $cmd_context = $conf;
     my @parselevel = ();
     my $line = 0;
 
-    my $base = $self->{inherit_from};   # inheritance (optional)
-	my $curr;
-
-    for (@conf) {
+    foreach (@conf) {
         $line++;
 
         # Strip newlines/comments
@@ -245,48 +215,33 @@ sub reread {
         # are visible for re-substitution
         if ($self->{expand_vars}) { 
             local($^W) = 0 ;
-            s#\$\{?(\w+)\}?#my $k = $self->_fixcase($1); $conf->{$k}[0][0]#eg;
+            s#\$\{?(\w+)\}?#my $k =  $self->_fixcase($1);$conf->{$k}#eg;
         }
 
         # This may be a <stuff> junk </stuff>, in which case we need
         # to nest our data struct!
         if (m#^\s*</(\S+)\s*>\s*$#) {
-            # match </close> - walk up one level
-            my $k = $self->_fixcase($1);
+            # match </close> - walk up
             $cmd_context = pop @parselevel;
-
-            # fill in base class attr if so requested
-            if ($base && $curr && $cmd_context->{$k}{$base}) {
-                for my $d (keys %{$cmd_context->{$k}{$base}}) {
-                    next unless exists $cmd_context->{$k}{$curr};
-					for (@{$cmd_context->{$k}{$curr}}) {
-						next if $_->{$d};	# don't overwrite
-                    	$_->{$d} = $cmd_context->{$k}{$base}[0]{$d};
-					}
-                }
-            }
-
             $self->_error("$file line $line: Mismatched closing tag '$1'") unless $cmd_context;
             next;
         } elsif (m#^\s*<(\S+)\s*(["']*)(.*)\2>\s*$#) {
             # create new sublevel in parsing
+            my $k = $self->_fixcase($1);
             push @parselevel, $cmd_context;
-            my $k = $self->_fixcase($1);	 # "VirtualHost" -> "virtualhost" (optional)
-			$curr = $3 || '';
-
-            # This is complicated - we have to maintain an array of
-            # blocks because of VirtualHost directives (which can be
-            # redefined). As such we have to create another element of
-            # an array which is a hashref on the fly. Whew!
-
-            if ($cmd_context->{$k}{$curr} && ref $cmd_context->{$k}{$curr} eq 'ARRAY') {
-                my $len = @{$cmd_context->{$k}{$curr}};                # get length to extend
-                $cmd_context = $cmd_context->{$k}{$curr}[$len] = {};   # manually so return ref
-                $cmd_context->{_} = [[$curr]];     # self-ref for deep nav
+
+            # this is complicated - we have to maintain an array
+            # of substratum because of VirtualHost directives.
+            # as such we have to create another element of an
+            # array which is a hashref on the fly. whew!
+            #$cmd_context = $cmd_context->{$k}->{$3} = {}; # doesn't support VirtualHost
+
+            if ($cmd_context->{$k}{$3} && ref $cmd_context->{$k}{$3} eq 'ARRAY') {
+                my $len = scalar @{$cmd_context->{$k}{$3}};
+                $cmd_context = $cmd_context->{$k}{$3}[$len] = {};
             } else {
-                $cmd_context->{$k}{$curr} = [];
-                $cmd_context = $cmd_context->{$k}{$curr}[0] = {};
-                $cmd_context->{_} = [[$curr]];     # self-ref for deep nav
+                $cmd_context->{$k}{$3} = [];
+                $cmd_context = $cmd_context->{$k}{$3}[0] = {};
             }
             next;
         }
@@ -294,11 +249,11 @@ sub reread {
         # Split up the key and the value. The @val regexp code dynamically
         # differentiates between "space strings" and array, values.
         my($key, $r) = m!^\s*\s*(\w+)\s*(?=\s+)(.*)!;             # split up key
-        my @val      = $r =~ m!\s+(?:"([^"]*[^\\])"|([^\s,]+))\n?!g;   # split up val
+        my(@val)     = $r =~ m!\s+(?:"([^"]*[^\\])"|([^\s,]+))\n?!g;   # split up val
         @val = grep { defined } @val;                             # lose undef values
 
         # Check for "on/off" or "true/false" or "yes/no"
-        if ($self->{fix_booleans} && @val) {
+        if ($self->{fix_booleans}) {
             $val[0] = 1 if ($val[0] =~ m/^(?:true|on|yes)$/i);
             $val[0] = 0 if ($val[0] =~ m/^(?:false|off|no)$/i);
         }
@@ -306,6 +261,13 @@ sub reread {
         # Make the key lowercase unless we're ignore_case
         $key = $self->_fixcase($key);
 
+        # Now, use eval to correctly assign variables automagically
+        # This implicitly takes care of syntax errors in the value
+        #eval { $cmd_context->{$key} = (@val > 1) ? [ @val ] : $val[0] };
+        #eval { push @{$cmd_context->{$key}}, [ @val ] };
+        #eval { $cmd_context->{$key} = [ @val ] };
+        #$self->_error("$file line $line: Bad config assignment: $@") if $@;
+
         # Must push or else can't handle repeating keys
         # It's up to the user to know how they should parse this if it matters
         push @{$cmd_context->{$key}}, [ @val ];
@@ -343,50 +305,48 @@ sub cmd_context {
     # maybe this exposes too much internal rep, but oh well...
 
     # redo our "pointer"
-    my $ptr;
-    my @ptr = ();
     if (ref $self->{cmd_context}{$dir} eq 'HASH') {
-        if (exists $self->{cmd_context}{$dir}{$spec}) {
-            $ptr = $self->{cmd_context}{$dir}{$spec};
-        } else {
+        if (! exists $self->{cmd_context}{$dir}{$spec}) {
             # With no $spec and no matching section (meaning that
             # it's not a "blank" <Limit> - like block), we return
-            # an array of objects, allowing us to loop thru w/ "for"
-            my @ret;
-            for my $spec (keys %{$self->{cmd_context}{$dir}}) {
-                my $copy = { %{$self} };
-                $copy->{cmd_context} = $copy->{cmd_context}{$dir}{$spec};
-                push @ret, bless($copy, __PACKAGE__);
-                return $ret[0] unless wantarray;    # will exit first iter
-            }
-            return @ret;
+            # a list of the keys from the $dir hash, which will
+            # be the different blocks that can be used
+            return keys %{$self->{cmd_context}{$dir}};
         }
     } else {
         # no matching hash
         return;
     }
 
+    my $ptr = $self->{cmd_context}{$dir}{$spec};
+    my @ptr = ();
+
     # maybe it's a nested hash/array/hash structure?
     if (ref $ptr eq 'ARRAY') {
         if (@_ == 1) {
+            #$ptr = $ptr->[shift()];
             @ptr = ($ptr->[$_[0]]);
         } elsif (@_ == 2) {
             my $ok = 0;
             my $k = $self->_fixcase(shift());
             my $v = shift;
             for my $p (@{$ptr}) {
+                #warn "p{$k} = $p->{$k} && $p->{$k}[0] &&  $p->{$k}[0][0]";
                 if (exists $p->{$k} && ref $p->{$k}[0] eq 'ARRAY'
                     && $p->{$k}[0][0] eq $v)
                 {
+                    #$ptr = $p;
                     push @ptr, $p;
                     $ok++;
                     last unless wantarray;
                 }
             }
+            #$self->_error("Could not find a config context matching that specification") unless $ok;
             return unless $ok;
         } elsif (@_) {
             $self->_error("Sorry, only one additional search param is supported to cmd_context");
         } else {
+            #$ptr = $ptr->[0];
             @ptr = @{$ptr};
         }
     } else {
@@ -399,14 +359,15 @@ sub cmd_context {
 
     # Now we peel off a new object that's a copy of our old
     # one (with the new {cmd_context}) making nav easier
+    # This is time-intensive so only do so if wantarray
     my @ret = ();
+    @ptr = ($ptr[0]) unless wantarray;
     for my $ptr (@ptr) {
         my $copy = { %{$self} };
         $copy->{cmd_context} = $ptr;
         push @ret, bless($copy, __PACKAGE__);
-        return $ret[0] unless wantarray;    # will exit first iter
     }
-    return @ret;
+    return wantarray ? @ret : $ret[0];
 }
 
 *directive_array = \&cmd_config_array;
@@ -424,16 +385,9 @@ sub cmd_config_array {
 
     # point to the value that was requested
     # return the entire current data struct when no args
-    my $ptr;
+    my $ptr = {};
     if ($dir) {
-        my $ref = ref $self->{cmd_context};
-        if ($ref eq 'HASH') {
-            $ptr = $self->{cmd_context}{$dir};
-        } elsif ($ref eq 'ARRAY') {
-            for (@{$self->{cmd_context}}) {
-                $ptr = $_->{$dir} if $_->{$dir};
-            }
-        }
+        $ptr = $self->{cmd_context}{$dir};
     } else {
         $ptr = $self->{cmd_context};
     }
@@ -466,10 +420,9 @@ sub cmd_config {
     # Use an iterator concept to go thru them in turn
     # Store the iterators in our data structure as well
     $self->{_iter}{$ptr} ||= 0;
-    my $len = @{$ptr};
-    if ($self->{_iter}{$ptr} >= $len) {
+    if ($self->{_iter}{$ptr} >= @{$ptr}) {
         $self->{_iter}{$ptr} = 0;
-        return if $len > 1; # otherwise single declares return undef
+        return;
     }
     if (defined(my $el = ${$ptr}[$self->{_iter}{$ptr}++])) {
         return wantarray ? @{$el} : ${$el}[0];
@@ -603,28 +556,10 @@ sub write {
     #close(CONF);
 }
 
-1;      # removing this == bad
+1;	# removing this == bad
 
 __END__
 
-=head1 UNSUPPORTED
-
-I am no longer supporting this module in any way, shape, or form,
-so it is truly provided "as-is". It has some edge-case bugs which
-will not be fixed. It will work on 95+% of Apache config files.
-
-I believe some alternative modules, including B<Apache::Admin::Config>
-and B<Config::ApacheFormat>, are being actively supported still,
-although this may or may not be true by the time you read this.
-
-In case you care, the main reason I wrote this was to support 
-Apache-B<like> config files as a general case. But it turns out the
-core C<httpd.conf> is rife with special cases, and is just plain a pain
-in the ass.
-
-If you would like to take over maintenance of this module, please
-contact me at C<nate@wiger.org>
-
 =head1 DESCRIPTION
 
 This module parses the Apache httpd.conf, or any compatible config
@@ -793,57 +728,6 @@ kind cannot be reused.
 
 If set to 1, any type of error becomes fatal. Defaults to 0.
 
-=item inherit_from
-
-If set, then context blocks inherit from the specified default
-context. For example, say you have the blocks:
-
-    <Category kitchen>
-        Name "Soup Kitchen"
-        Email "soup@kitchen.com"
-        Access all
-    </Category>
-
-    <Category tomato_soup>
-        Name "Tomato Soup"
-    </Category>
-
-If you then specified:
-
-    ->read(..., inherit_from => 'kitchen');
-
-Then all those variables that are not seen in the C<tomato_soup>
-block would be filled in based on their values from the C<kitchen>
-block. So, C<tomato_soup> would inherit C<Email> and C<Access>
-from C<kitchen>, but would provide its own C<Name>.
-
-B<Note:> In order for this to work, the block providing the
-inherited items B<MUST> appear first, as shown above.
-
-=item root_directive
-
-If set this specifies a directive other than RootDirective for
-relative path resolutions.  For example:
-
-    ApplicationRoot /usr/local/etc
-
-    my $ac = Apache::ConfigFile->read(
-                     file => "/usr/local/etc/app.config",
-                     root_directive => 'ApplicationRoot'
-             );
-
-This will cause /usr/local/etc to be added to relative paths for
-includes, etc. With this additional behavior, the term ServerRoot, as
-used elsewhere in this document, comes to mean any directive that is
-specified via this option. Also note that the default value of this
-option is 'ServerRoot'.
-
-=item server_root
-
-This explicitly sets the ServerRoot for relative path resolutions for
-includes, etc. This option overrides any ServerRoot values found in the
-config file.
-
 =back
 
 =head2 cmd_config(directive)
@@ -877,6 +761,18 @@ Which should print:
     For error 404 we're using /errors/404.cgi
     For error 500 we're using /errors/500.cgi
 
+Now, if you just wanted to get the error codes that were being
+handled, you would still use a C<while> loop but in a scalar context:
+
+    while (my $code = $ac->cmd_config('ErrorDocument')) {
+        print "We're handling $code\n";
+    }
+
+Which should print:
+
+    We're handling 404
+    We're handling 500
+
 If you want more flexibility, read the following two functions.
 
 =head2 cmd_config_array(directive)
@@ -989,17 +885,18 @@ could cycle through all of them in sequence:
     }
 
 However, you may not know what you're looking for. In this case,
-if you can iterate through all of them with something like this:
+if you just want to get the "keys" of all the C<VirtualHost>
+definitions and then iterate through all of them, you might do
+something like this:
 
-    for my $vhost ($ac->cmd_context('VirtualHost')) {
-        # ... do stuff ...
+    my @vhkeys = $ac->cmd_context('VirtualHost');
+    for my $vhkey (@vhkeys) {
+        my $vhost = $ac->cmd_context(VirtualHost => $vhkey);
     }
 
-Since you didn't specify a specific block, the special var C<_>
-will be set with the text tag for that block. Printing it out
-will reveal which C<VirtualHost> (or whatever) you're in:
-
-    print $vhost->cmd_config('_');  # "10.1.1.2"
+Note that this is the one situation where the C<cmd_context()>
+function does I<not> return an object, but rather a list of
+string keys.
 
 Conversely, you may know I<exactly> which one you're looking for.
 If so, you can specify one additional "search" parameter. For 
@@ -1180,6 +1077,12 @@ Currently C<LogFormat> and any other directive with embedded quotes,
 even if escaped, are not handled correctly. I know there is a fix for
 it but I have a mental block and can't figure it out. Help!
 
+This module does B<not> mimic the behavior of a live Apache config.
+In particular, there is no configuration "inheritance". This means
+that subdirectories and virtual hosts do not inherit their defaults
+from the upper levels of the configuration. This may or may not
+change in a future version.
+
 Currently, the order of context blocks is not maintained. So, if
 you define two blocks:
 
@@ -1196,16 +1099,16 @@ Normally this should not matter, since the idea of a context section is to
 create a logical entity. However, patches to overcome this limitation
 are welcomed.
 
-This module has only been tested and used on UNIX platforms. It may or
-may not be broke elsewhere.
+This module has only been tested and used on UNIX platforms. Patches
+to fix problems with other OSes are welcome.
 
 =head1 VERSION
 
-$Id: ConfigFile.pm,v 1.23 2003/10/09 18:24:41 nwiger Exp $
+$Id: ConfigFile.pm,v 1.18 2001/09/18 18:31:23 nwiger Exp $
 
 =head1 AUTHOR
 
-Copyright (c) 1999-2003, Nathan Wiger <nate@wiger.org>. All Rights
+Copyright (c) 1999-2001, Nathan Wiger <nate@wiger.org>. All Rights
 Reserved.
 
 This module is free software; you may copy this under the terms of
@@ -1213,3 +1116,4 @@ the GNU General Public License, or the Artistic License, copies of
 which should have accompanied your Perl kit.
 
 =cut
+
@@ -52,7 +52,7 @@ SYNOPSIS
         # In fact, even better you can "search" for one by specifying
         # an additional set of criteria to cmd_config(). To just get
         # the VirtualHost "docs.mydomain.com", for example, try:
-     
+ 
         my $docs_svr = $ac->cmd_context(VirtualHost => '10.1.1.3',
                                         ServerName  => 'docs.mydomain.com');
         my $docs_base_dir = $docs_svr->cmd_config('DocumentRoot');
@@ -89,35 +89,27 @@ SYNOPSIS
         my %config = $self->data;
         warn "DEBUG: ", $self->dump, "\n";
 
-UNSUPPORTED
-    I am no longer supporting this module in any way, shape, or form, so it is truly provided "as-is". It has
-    some edge-case bugs which will not be fixed. It will work on 95+% of Apache config files.
-
-    I believe some alternative modules, including Apache::Admin::Config and Config::ApacheFormat, are being
-    actively supported still, although this may or may not be true by the time you read this.
-
-    In case you care, the main reason I wrote this was to support Apache-like config files as a general case. But
-    it turns out the core `httpd.conf' is rife with special cases, and is just plain a pain in the ass.
-
-    If you would like to take over maintenance of this module, please contact me at `nate@wiger.org'
-
 DESCRIPTION
-    This module parses the Apache httpd.conf, or any compatible config file, and provides methods for you to
-    access the values from the config file. The above examples show basic usage of this module, which boils down
-    to reading a given config file and then using the `cmd_config()' and `cmd_context()' functions to access its
-    information.
-
-    By default, the config file is parsed more or less "verbatim", meaning that directives are case-sensitive,
-    variables are not interpolated, and so forth. These features can be changed by options given to the `read()'
+    This module parses the Apache httpd.conf, or any compatible config file,
+    and provides methods for you to access the values from the config file.
+    The above examples show basic usage of this module, which boils down to
+    reading a given config file and then using the "cmd_config()" and
+    "cmd_context()" functions to access its information.
+
+    By default, the config file is parsed more or less "verbatim", meaning
+    that directives are case-sensitive, variables are not interpolated, and
+    so forth. These features can be changed by options given to the "read()"
     function (see below).
 
-    The `read()' function is the constructor, which reads in a configuration file and returns an object with
-    methods that can be used to access directives from the file. The simplest usage is something like this:
+    The "read()" function is the constructor, which reads in a configuration
+    file and returns an object with methods that can be used to access
+    directives from the file. The simplest usage is something like this:
 
         use Apache::ConfigFile;
         my $ac = Apache::ConfigFile->read("/path/to/httpd.conf");
 
-    Which would parse the Apache `httpd.conf' file and give you back an `$ac' object with the following methods:
+    Which would parse the Apache "httpd.conf" file and give you back an
+    "$ac" object with the following methods:
 
     cmd_config()
         Used to access individual configuration commands
@@ -126,13 +118,16 @@ DESCRIPTION
         Used to change the context of the commands you're accessing
 
     dir_config()
-        Used to access values set via the `PerlSetVar' command (like `mod_perl')
+        Used to access values set via the "PerlSetVar" command (like
+        "mod_perl")
 
-    For more examples of standard Apache usage, you should read the the section on "/"SYNOPSIS" above or skip
-    down to the the section on "/"FUNCTIONS".
+    For more examples of standard Apache usage, you should read the the
+    section on "SYNOPSIS" above or skip down to the the section on
+    "FUNCTIONS".
 
-    In addition to reading an Apache config file, this module provides some options that allow the Apache syntax
-    to be extended. This is useful if you're writing your own application and want to use a config file
+    In addition to reading an Apache config file, this module provides some
+    options that allow the Apache syntax to be extended. This is useful if
+    you're writing your own application and want to use a config file
     resembling Apache's.
 
         use Apache::ConfigFile;
@@ -143,7 +138,8 @@ DESCRIPTION
                         fix_booleans => 1
                  );
 
-    These options would allow us to write a custom config file looking like this:
+    These options would allow us to write a custom config file looking like
+    this:
 
         BaseDir    "/export"
         ImageDir   "$BaseDir/images"
@@ -164,40 +160,45 @@ DESCRIPTION
         # Note that case does not matter
         my $rel = $swcfg->cmd_context(release => 'sw7');
         my $ofn = $rel->cmd_config('bUiLdPaTh');
-        
+    
         # This is autoloading + fix_booleans
         unless ($rel->supported) {
             die "Sorry, that release is not supported";
         } 
 
-    There are several things to note. First, all our `cmd_' functions are now case-insensitive, since we turned
-    on the `ignore_case' flag (which is off by default). Second, notice a couple things about our `unless'
-    statement. Since we specified `fix_booleans', the words "Yes", "True", and "On" will be converted to `1'
-    (true), and "No", "False", and "Off" will become `0' (false). As such, we can use these directives in boolean
+    There are several things to note. First, all our "cmd_" functions are
+    now case-insensitive, since we turned on the "ignore_case" flag (which
+    is off by default). Second, notice a couple things about our "unless"
+    statement. Since we specified "fix_booleans", the words "Yes", "True",
+    and "On" will be converted to "1" (true), and "No", "False", and "Off"
+    will become "0" (false). As such, we can use these directives in boolean
     statements throughout our code.
 
-    In addition, since this module provides autoloading so that all config commands are turned into functions,
-    you can access values directly, as shown by the statement `< $rel-'supported >>. This statement is equivalent
-    to the longer `< $rel-'cmd_config('supported') >>.
+    In addition, since this module provides autoloading so that all config
+    commands are turned into functions, you can access values directly, as
+    shown by the statement "$rel->supported". This statement is equivalent
+    to the longer "$rel->cmd_config('supported')".
 
-    Finally, if you just wish to manually navigate the data structure (which is a huge hash of hashes of arrays)
-    without using the accessor functions, you can return the thing verbatim:
+    Finally, if you just wish to manually navigate the data structure (which
+    is a huge hash of hashes of arrays) without using the accessor
+    functions, you can return the thing verbatim:
 
         my %conf = $ac->data;
         print "Release is $conf{'release'}\n";
 
-    However, note that the internal representation is subject to change, so using the accessor functions is
-    recommended.
+    However, note that the internal representation is subject to change, so
+    using the accessor functions is recommended.
 
 FUNCTIONS
   read(filename)
 
   read(file => filename, opt => val, opt => val)
 
-    The `read()' function reads the configuration file specified and returns an object with methods to access its
-    directives. `read()' has two calling forms. In the simplest version, you just specify a filename, and a new
-    `Apache::ConfigFile' object is returned. Or, if you want to specify options, you specify each one as a
-    key/value pair. For example:
+    The "read()" function reads the configuration file specified and returns
+    an object with methods to access its directives. "read()" has two
+    calling forms. In the simplest version, you just specify a filename, and
+    a new "Apache::ConfigFile" object is returned. Or, if you want to
+    specify options, you specify each one as a key/value pair. For example:
 
        # keep default options
        my $ac = Apache::ConfigFile->read("httpd.conf");
@@ -210,90 +211,54 @@ FUNCTIONS
     The list of valid options is:
 
     file
-        Path to configuration file. If not provided then `/usr/local/apache/conf/httpd.conf' is used by default.
+        Path to configuration file. If not provided then
+        "/usr/local/apache/conf/httpd.conf" is used by default.
 
     ignore_case
-        If set to 1, then all directives will be case-insensitive and stored in lowercase. Defaults to 0.
+        If set to 1, then all directives will be case-insensitive and stored
+        in lowercase. Defaults to 0.
 
     fix_booleans
-        If set to 1, then the words "Yes", "True", and "On" will be converted to `1' (true), and "No", "False",
-        and "Off" will become `0' (false). This allows you to easily use these types of directives in if
-        statements. Defaults to 0.
+        If set to 1, then the words "Yes", "True", and "On" will be
+        converted to "1" (true), and "No", "False", and "Off" will become
+        "0" (false). This allows you to easily use these types of directives
+        in if statements. Defaults to 0.
 
     expand_vars
-        If set to 1, then you can reuse variables that you have defined elsewhere in the config file by prefixing
-        them with a `$'. For example:
+        If set to 1, then you can reuse variables that you have defined
+        elsewhere in the config file by prefixing them with a "$". For
+        example:
 
             BaseDir   "/export"
             HomeDir   "$BaseDir/home"
 
-        Currently, you can only reuse variables defined at the very top-level. Variables defined within context
-        blocks of any kind cannot be reused.
+        Currently, you can only reuse variables defined at the very
+        top-level. Variables defined within context blocks of any kind
+        cannot be reused.
 
     raise_error
         If set to 1, any type of error becomes fatal. Defaults to 0.
 
-    inherit_from
-        If set, then context blocks inherit from the specified default context. For example, say you have the
-        blocks:
-
-            <Category kitchen>
-                Name "Soup Kitchen"
-                Email "soup@kitchen.com"
-                Access all
-            </Category>
-
-            <Category tomato_soup>
-                Name "Tomato Soup"
-            </Category>
-
-        If you then specified:
-
-            ->read(..., inherit_from => 'kitchen');
-
-        Then all those variables that are not seen in the `tomato_soup' block would be filled in based on their
-        values from the `kitchen' block. So, `tomato_soup' would inherit `Email' and `Access' from `kitchen', but
-        would provide its own `Name'.
-
-        Note: In order for this to work, the block providing the inherited items MUST appear first, as shown
-        above.
-
-    root_directive
-        If set this specifies a directive other than RootDirective for relative path resolutions. For example:
-
-            ApplicationRoot /usr/local/etc
-
-            my $ac = Apache::ConfigFile->read(
-                             file => "/usr/local/etc/app.config",
-                             root_directive => 'ApplicationRoot'
-                     );
-
-        This will cause /usr/local/etc to be added to relative paths for includes, etc. With this additional
-        behavior, the term ServerRoot, as used elsewhere in this document, comes to mean any directive that is
-        specified via this option. Also note that the default value of this option is 'ServerRoot'.
-
-    server_root
-        This explicitly sets the ServerRoot for relative path resolutions for includes, etc. This option
-        overrides any ServerRoot values found in the config file.
-
   cmd_config(directive)
 
-    This is the meat-and-potatoes of the module; the method that lets you access configuration directives from
-    your file. Examples:
+    This is the meat-and-potatoes of the module; the method that lets you
+    access configuration directives from your file. Examples:
 
         my $server_name = $ac->cmd_config('ServerName');
         my $doc_root = $ac->cmd_config('DocumentRoot');
 
-    This is a fairly straightforward function. You just give it the name of the directive you wish to access and
-    you get its value back. Each time you call it, you will get the value for the next available instance of that
-    variable. If called in a scalar context, you will just get the first value, assumed to be the "key".
+    This is a fairly straightforward function. You just give it the name of
+    the directive you wish to access and you get its value back. Each time
+    you call it, you will get the value for the next available instance of
+    that variable. If called in a scalar context, you will just get the
+    first value, assumed to be the "key".
 
     What this means is that if you have a config file like this:
 
         ErrorDocument 404 /errors/404.cgi
         ErrorDocument 500 /errors/500.cgi
 
-    To get each line you would use a `while' loop:
+    To get each line you would use a "while" loop:
 
         while (my @line = $ac->cmd_config('ErrorDocument')) {
             print "For error $line[0] we're using $line[1]\n";
@@ -304,16 +269,29 @@ FUNCTIONS
         For error 404 we're using /errors/404.cgi
         For error 500 we're using /errors/500.cgi
 
+    Now, if you just wanted to get the error codes that were being handled,
+    you would still use a "while" loop but in a scalar context:
+
+        while (my $code = $ac->cmd_config('ErrorDocument')) {
+            print "We're handling $code\n";
+        }
+
+    Which should print:
+
+        We're handling 404
+        We're handling 500
+
     If you want more flexibility, read the following two functions.
 
   cmd_config_array(directive)
 
-    This returns the entire data structure for a given directive as an array of arrays. So, you could get all the
-    `ErrorDocument' configs by saying:
+    This returns the entire data structure for a given directive as an array
+    of arrays. So, you could get all the "ErrorDocument" configs by saying:
 
         my @errors = $ac->cmd_config_array('ErrorDocument');
 
-    Then, you would have to iterate over these yourself, since each element is an array reference:
+    Then, you would have to iterate over these yourself, since each element
+    is an array reference:
 
         for my $e (@errors) {
             print "Code is $e->[0] and script is $e->[1]\n";
@@ -328,14 +306,16 @@ FUNCTIONS
 
   cmd_config_hash(directive)
 
-    This is perhaps the most useful form. It returns a set of key/value pairs where the key is the first element
-    and the value is the rest of the line. This is great for handling `FileTypeSuffix' or `AddHandler' lines, for
-    example:
+    This is perhaps the most useful form. It returns a set of key/value
+    pairs where the key is the first element and the value is the rest of
+    the line. This is great for handling "FileTypeSuffix" or "AddHandler"
+    lines, for example:
 
         my %handler = $ac->cmd_config_hash('AddHandler');
 
-    This would return a hash where the keys would be the first field, such as `cgi-script' or `server-parsed',
-    and value is the remaining line as an array reference.
+    This would return a hash where the keys would be the first field, such
+    as "cgi-script" or "server-parsed", and value is the remaining line as
+    an array reference.
 
     As such, you could access a specific one as:
 
@@ -345,15 +325,17 @@ FUNCTIONS
 
         Suffixes for CGI scripts are: .cgi .pl
 
-    Note that you had to derefence the value inside of a `@{}' since the value is an array reference. This is so
-    that you can get a list of values reliably. For example:
+    Note that you had to derefence the value inside of a "@{}" since the
+    value is an array reference. This is so that you can get a list of
+    values reliably. For example:
 
         my %handler = $ac->cmd_config_hash('AddHandler');
         my @cgi_suffixes   = @{$handler{cgi-script}};
         my @shtml_suffixed = @{$handler{server-parsed}};
 
-    That way you get the proper values even in the case of embedded whitespace. In addition, it allows you to
-    define your own complex directives:
+    That way you get the proper values even in the case of embedded
+    whitespace. In addition, it allows you to define your own complex
+    directives:
 
         # Format: key "Real Name" option1 option2 option3
         CustomField lname "Last Name" 
@@ -378,45 +360,50 @@ FUNCTIONS
             }
         }
 
-    That way you could use an Apache style config file to setup a custom form based application.
+    That way you could use an Apache style config file to setup a custom
+    form based application.
 
   cmd_context(context => specification)
 
-    You use this command to change the current context of what you are looking at. When you start, you are
-    looking at the very top-level of the config file. However, you may want to look at a specific virtual host or
+    You use this command to change the current context of what you are
+    looking at. When you start, you are looking at the very top-level of the
+    config file. However, you may want to look at a specific virtual host or
     directory. You can do so with this command.
 
         my $vhost = $ac->cmd_context(VirtualHost => '10.1.1.2');
         my $server_name = $vhost->cmd_config('ServerName');
         my $doc_root    = $vhost->cmd_config('DocumentRoot');
 
-    You'll notice that the `cmd_context()' call returns an object will all the same methods, but the data
-    structure now starts from that point down. The context has been altered so that you are looking at the `<
-    <VirtualHost "10.1.1.2"' >>. block. As such, any commands that you do will affect that part of the
-    configuration.
+    You'll notice that the "cmd_context()" call returns an object will all
+    the same methods, but the data structure now starts from that point
+    down. The context has been altered so that you are looking at the
+    "<VirtualHost "10.1.1.2">". block. As such, any commands that you do
+    will affect that part of the configuration.
 
-    In some cases, you may have multiple definitions for a certain context level. One example is `VirtualHost'
-    blocks if you're using `NameVirtualHosts'. You have two options. First, you could cycle through all of them
-    in sequence:
+    In some cases, you may have multiple definitions for a certain context
+    level. One example is "VirtualHost" blocks if you're using
+    "NameVirtualHosts". You have two options. First, you could cycle through
+    all of them in sequence:
 
         for my $vhost ($ac->cmd_context(VirtualHost => '10.1.1.2')) {
             # ... do stuff ...
         }
 
-    However, you may not know what you're looking for. In this case, if you can iterate through all of them with
-    something like this:
+    However, you may not know what you're looking for. In this case, if you
+    just want to get the "keys" of all the "VirtualHost" definitions and
+    then iterate through all of them, you might do something like this:
 
-        for my $vhost ($ac->cmd_context('VirtualHost')) {
-            # ... do stuff ...
+        my @vhkeys = $ac->cmd_context('VirtualHost');
+        for my $vhkey (@vhkeys) {
+            my $vhost = $ac->cmd_context(VirtualHost => $vhkey);
         }
 
-    Since you didn't specify a specific block, the special var `_' will be set with the text tag for that block.
-    Printing it out will reveal which `VirtualHost' (or whatever) you're in:
-
-        print $vhost->cmd_config('_');  # "10.1.1.2"
+    Note that this is the one situation where the "cmd_context()" function
+    does *not* return an object, but rather a list of string keys.
 
-    Conversely, you may know *exactly* which one you're looking for. If so, you can specify one additional
-    "search" parameter. For example, if you want the `superfoo' server, you could say:
+    Conversely, you may know *exactly* which one you're looking for. If so,
+    you can specify one additional "search" parameter. For example, if you
+    want the "superfoo" server, you could say:
 
         my $sf = $ac->cmd_context(VirtualHost => '10.1.1.2',
                                   ServerName  => 'superfoo');
@@ -428,7 +415,8 @@ FUNCTIONS
             # ... more config options ...
         </VirtualHost>
 
-    you can easily access nested configurations as well. If you had a configuration like this:
+    you can easily access nested configurations as well. If you had a
+    configuration like this:
 
         <Location "/upload">
             SetHandler perl-script
@@ -441,8 +429,8 @@ FUNCTIONS
             </Limit>
         </Location>
 
-    And you wanted to find out what the valid users were who could access this page, you would navigate it like
-    so:
+    And you wanted to find out what the valid users were who could access
+    this page, you would navigate it like so:
 
         my $loc = $ac->cmd_context(Location => '/upload');
         my $lim = $loc->cmd_context('Limit');
@@ -453,44 +441,47 @@ FUNCTIONS
         my @users = $ac->cmd_context(Location => '/upload')
                        ->cmd_context(Limit => '')->cmd_config('require');
 
-    Since `cmd_context()' returns an object pointing to the next context, you can chain calls together to get to
-    a deeply nested level.
+    Since "cmd_context()" returns an object pointing to the next context,
+    you can chain calls together to get to a deeply nested level.
 
   dir_config()
 
-    This routine is provided for `mod_perl' compatibility. It allows you to access configuration commands
-    specified via the `PerlSetVar' directive. So, assuming the above example, you could access the settings for
-    `MyUploadModule' like so:
+    This routine is provided for "mod_perl" compatibility. It allows you to
+    access configuration commands specified via the "PerlSetVar" directive.
+    So, assuming the above example, you could access the settings for
+    "MyUploadModule" like so:
 
         my $upload = $ac->cmd_context(Location => '/upload');
 
         my $maxsize = $upload->dir_config('MyUploadModuleMaxsize');
         my $timeout = $upload->dir_config('MyUploadModuleTimeout');
 
-    The idea is to provide an interface which walks and talks roughly like Apache actually would.
+    The idea is to provide an interface which walks and talks roughly like
+    Apache actually would.
 
   data()
 
-    This returns the entire data structure under the current context verabatim. So, you could get all the values
-    for a `VirtualHost' with:
+    This returns the entire data structure under the current context
+    verabatim. So, you could get all the values for a "VirtualHost" with:
 
         my $vh = $ac->cmd_context(VirtualHost => '10.1.1.4');
         my %vhost = $vh->data;
 
-    If you specified `ignore_case', then all the keys will be lowercase; otherwise, they will be in whatever case
-    they are in the config file.
+    If you specified "ignore_case", then all the keys will be lowercase;
+    otherwise, they will be in whatever case they are in the config file.
 
   dump()
 
-    This returns a dump of the current data structure in string form. So for debugging purposes you can dump the
-    config with something like this:
+    This returns a dump of the current data structure in string form. So for
+    debugging purposes you can dump the config with something like this:
 
         warn "DUMP: ", $ac->dump, "\n";
 
   reread()
 
-    You can use this function to reread the configuration file. For example, maybe you want your application to
-    reread its config if it receives a `SIGHUP':
+    You can use this function to reread the configuration file. For example,
+    maybe you want your application to reread its config if it receives a
+    "SIGHUP":
 
         $SIG{HUP} = \&handler;
         sub handler {
@@ -501,17 +492,18 @@ FUNCTIONS
             }
         }
 
-    The above would handle a `SIGHUP' by rereading the config file.
+    The above would handle a "SIGHUP" by rereading the config file.
 
   write([file])
 
-    This writes the configuration out to disk. If no file is specified, then the one passed to `read()' is used.
-    This method is currently under development and does not work. Patches welcome.
+    This writes the configuration out to disk. If no file is specified, then
+    the one passed to "read()" is used. This method is currently under
+    development and does not work. Patches welcome.
 
   autoloaded calls
 
-    In addition to the above, you can also access values by calling a function named for the config command
-    directly:
+    In addition to the above, you can also access values by calling a
+    function named for the config command directly:
 
         my $server_name = $ac->cmd_config('ServerName');
 
@@ -519,35 +511,38 @@ FUNCTIONS
 
         my $server_name = $ac->server_name;
 
-    Underscores in the function name are taken as a place to put an uppercase letter. So these are all
-    equivalent:
+    Underscores in the function name are taken as a place to put an
+    uppercase letter. So these are all equivalent:
 
         my $doc_root = $ac->cmd_config('DocumentRoot');
         my $doc_root = $ac->DocumentRoot;   # looks silly
         my $doc_root = $ac->document_root;
 
-    Note, though, that the following would not work unless you had set the `ignore_case' option:
+    Note, though, that the following would not work unless you had set the
+    "ignore_case" option:
 
         my $doc_root = $ac->documentroot;   # won't work
 
-    This is because it will look for the directive `Documentroot', which probably doesn't exist.
+    This is because it will look for the directive "Documentroot", which
+    probably doesn't exist.
 
 ALIASES
-    When I initially wrote this module, I tried to follow the internal Apache API pretty closely. However, for
-    those unfamiliar with Apache these method names probably make little sense. As such, the following function
-    aliases are provided
+    When I initially wrote this module, I tried to follow the internal
+    Apache API pretty closely. However, for those unfamiliar with Apache
+    these method names probably make little sense. As such, the following
+    function aliases are provided
 
     directive
-        Same as `cmd_config()'
+        Same as "cmd_config()"
 
     directive_array
-        Same as `cmd_config_array()'
+        Same as "cmd_config_array()"
 
     directive_hash
-        Same as `cmd_config_hash()'
+        Same as "cmd_config_hash()"
 
     section
-        Same as `cmd_context()'
+        Same as "cmd_context()"
 
     So this code:
 
@@ -566,10 +561,18 @@ ALIASES
     These will always be supported so feel free to use them.
 
 NOTES
-    Currently `LogFormat' and any other directive with embedded quotes, even if escaped, are not handled
-    correctly. I know there is a fix for it but I have a mental block and can't figure it out. Help!
+    Currently "LogFormat" and any other directive with embedded quotes, even
+    if escaped, are not handled correctly. I know there is a fix for it but
+    I have a mental block and can't figure it out. Help!
+
+    This module does not mimic the behavior of a live Apache config. In
+    particular, there is no configuration "inheritance". This means that
+    subdirectories and virtual hosts do not inherit their defaults from the
+    upper levels of the configuration. This may or may not change in a
+    future version.
 
-    Currently, the order of context blocks is not maintained. So, if you define two blocks:
+    Currently, the order of context blocks is not maintained. So, if you
+    define two blocks:
 
         <Directory "/">
             Options +MultiViews
@@ -579,18 +582,22 @@ NOTES
             Options +ExecCGI
         </Directory>
 
-    There will be no way for you to tell the order in which these were defined. Normally this should not matter,
-    since the idea of a context section is to create a logical entity. However, patches to overcome this
+    There will be no way for you to tell the order in which these were
+    defined. Normally this should not matter, since the idea of a context
+    section is to create a logical entity. However, patches to overcome this
     limitation are welcomed.
 
-    This module has only been tested and used on UNIX platforms. It may or may not be broke elsewhere.
+    This module has only been tested and used on UNIX platforms. Patches to
+    fix problems with other OSes are welcome.
 
 VERSION
-    $Id: ConfigFile.pm,v 1.23 2003/10/09 18:24:41 nwiger Exp $
+    $Id: ConfigFile.pm,v 1.18 2001/09/18 18:31:23 nwiger Exp $
 
 AUTHOR
-    Copyright (c) 1999-2003, Nathan Wiger <nate@wiger.org>. All Rights Reserved.
+    Copyright (c) 1999-2001, Nathan Wiger <nate@wiger.org>. All Rights
+    Reserved.
 
-    This module is free software; you may copy this under the terms of the GNU General Public License, or the
-    Artistic License, copies of which should have accompanied your Perl kit.
+    This module is free software; you may copy this under the terms of the
+    GNU General Public License, or the Artistic License, copies of which
+    should have accompanied your Perl kit.