This is Info file pm.info, produced by Makeinfo version 1.68 from the
input file bigpm.texi.


File: pm.info,  Node: Config/Access,  Next: Config/FreeForm,  Prev: Config,  Up: Module List

Perform simple access control
*****************************

NAME
====

   `Config::Access' - Perform simple access control

SYNOPSIS
========

     use strict;                  # not optional (-:
     use Config::Access;

DESCRIPTION
===========

   The `Config::Access' module provides a method of authenticating
arbitrary client/service pairs in a way very similar to that provided by
the TCP wrappers by Wietse Venema <wietse@wzv.win.tue.nl> but not limited
to inetd services and IP/host names.

   This module can be useful for restricting access to certain parts of a
script to a certain domain.  For example, a front end program to some
device might deny certain users access to certain commands or only allow
trusted users access to dangerous commands.  The semantics of what the
client and service names actually mean is totally up to the programmer.

   The access control language is very similar to the access control
language specified in hosts_access(5) for the TCP wrappers.  Two
configuration files specify access rules.  A file ending in .allow
specifies rules to allow access and a file ending in .deny specifies rules
to deny access.  The prefix of these files is specified when a
`Config::Access' object is created.

ACCESS CONTROL FILES
====================

   As per the TCP wrappers, a request for authorisation consults the
.allow and .deny files.  The search stops at the first match.

   * Access is granted if a $client/$service matches a rule in the .allow
     file.

   * Access is denied if a $client/$service matches a rule in the .deny
     file.

   * Otherwise, if no match is made access is granted.

ACCESS CONTROL RULES
====================

   Access control rules appear in the configuration files in the following
format.

     service_list : client_list

   Each item in a list is separated by a comma and optional whitespace.
Newlines and lines beginning with a '#' character are ignored.  A line may
be continued if a backslash character is present as the end of the line.

   A service or client may be specified as the string 'ALL' which means it
will be matched by anything.  An optional parameter to the access_query
method described below allows the caller to determine whether the request
was granted (or denied) using a rule containing the ALL wildcard.

   `Config::Access' also supports IP address matching of clients and
services using the network/netmask number format.

   The EXCEPT operator present in the TCP wrappers access control language
is not supported.

Public Methods
--------------

new
     Usage:

     $obj = new Config::Access($prefix);     $obj = new
     Config::Access($prefix, $debug);     $obj =
     'Config::Access'->new($prefix);     $obj =
     'Config::Access'->new($prefix, $debug);

     Returns a newly-initialised `Config::Access' object.  The
     configuration files are read and parsed.  The allow and deny
     configuration file names are generated from the prefix argument by
     appending the string '`.allow'' and '`.deny'' to the prefix,
     respectively.

     If the $debug parameter is true, then debugging information will be
     printed to standard output.  A list of all access rules will be
     printed when a `Config::Access' object is created and a line will be
     printed for each invocation of the `access_query()' method.

access_query
     Usage:

          $result = $obj->access_query($service, $client);

     Perform an access query for the specified $service/$client pair.  The
     return value is true if access to the service is allowed for the
     client, and undefined otherwise.

          $result = $obj->access_query($service, $client, $mtype);

     Perform an access query for the $service/$client pair and return the
     match type for the client in the $mtype parameter.  The match type
     refers to the type of rule that allowed or denied the match for the
     client and can take the following values.

    MATCH_SPECIFIC
          The match was made to a directly specified rule in either the
          allow or deny file without using the ALL wildcard.

    MATCH_NET_MASK
          The match was made using a network/netmask pair.

    MATCH_ALL
          The match was made using a rule containing the ALL wildcard.

    MATCH_FALLTHRU
          No matches were made in either the allow or deny file and the
          match fell through.

Exports
-------

default
     none

exportable
     MATCH_SPECIFIC MATCH_ALL MATCH_FALLTHRU MATCH_NET_MASK

tags
     none

EXAMPLE
=======

   The following scripts form a simple example of using the
`Config::Access' module.  The access controls for the example correspond
to the "mostly closed" model of the TCP wrappers.

     cat > test.pl << 'EOF'
     #!/usr/bin/perl

     use strict;
     use Config::Access;

     my($access) = Config::Access->new("example");
     my($user) = getpwuid($UID);

     if (!$access->access_query("beans", $user)) {
         print("Access to service 'beans' denied for user ", $user, "\n");
     }

     if ($access->access_query("ham", $user)) {
         print("Access to service 'ham' allowed for user ", $user, "\n");
     }
     EOF

     cat > example.allow << 'EOF'
     # Example allow file.  Allow all users to service 'ham' and only
     # selected users to service 'beans'.
     beans: tpot, markus
     ham: ALL
     EOF

     cat > example.deny << 'EOF'
     # Example deny file.  Deny all clients access to all services unless
     # specifically allowed above.
     ALL: ALL
     EOF

COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998 ANU and CSIRO on behalf of the
     participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <Tim.Potter@anu.edu.au>


File: pm.info,  Node: Config/FreeForm,  Next: Config/General,  Prev: Config/Access,  Up: Module List

Provide in-memory configuration data
************************************

NAME
====

   Config::FreeForm - Provide in-memory configuration data

SYNOPSIS
========

     use Config::FreeForm %options;

DESCRIPTION
===========

   *Config::FreeForm* provides in-memory configuration data in a free-form
manner. Many existing configuration modules attempt to provide some
structure to your configuration data; in doing so, they force you to use
their own configuration paradigm (association of keywords with values,
etc.). Often this isn't what you need in a complex application-you need
complete control over your configuration data, and you need the ability to
structure it however you like. This is what *Config::FreeForm* gives you.

   In *Config::FreeForm* configuration data is stored as a Perl data
structure. The logic behind this is that you know Perl-you shouldn't need
to learn another little language to set up your configuration data,
however simple that language may be. Of course, this works best if
programmers or tools do the updating of your configuration files; it does
make it more difficult for other possible users to edit the files. If this
is a problem for you, try some of the other configuration modules listed
in MISCELLANEOUS.

   Still here? Good. You might then ask what *Config::FreeForm* gives you
that rolling your own light module using Data::Dumper and do would not.
It's a good question, considering in particular that *Config::FreeForm*
uses Data::Dumper and do to write and read your data, respectively.
*Config::FreeForm* adds some very nice features, though:

   * Configuration File Management

     So as not to clutter one file with configuration for all purposes,
     you can separate your configuration data into multiple files, and
     specify which files to load when you load in the module:

          use Config::FreeForm sets => [ ... ];

     *Config::FreeForm* manages the various configuration files that
     you've told it to load, and lets you update your data in memory, then
     write it back to its original location on disk, using the *rewrite*
     function (below, in UPDATING CONFIGURATION).

   * Automated Reloading

     In a mod_perl context, your configuration data will be loaded once,
     at webserver startup; subsequent access to the configuration data
     will come from memory. If you update your configuration on disk,
     then, you'll want those changes to be reflected in the in-memory
     versions of the configuration. *Config::FreeForm* will handle this
     automatically for you if you install it as a *PerlInitHandler* on
     your mod_perl-enabled server. For more details, see AUTOMATED
     RELOADING, below.

HOW TO USE IT
=============

   To create a configuration file, add its configuration to a file like
*Foo.conf*:

     $conf = {
         Foo => { Bar => 1 }
     }

   Once you've written your *Foo.conf* configuration file, load that file
explicitly (without the *.conf*):

     use Config::FreeForm sets => [ 'Foo' ];

   When the module is loaded, it will attempt to find a configuration file
for the set *Foo*; it will load the data in this file using do; then it
will loop over the top-level variables in the tree structure and alias
variables into the *Config::FreeForm* namespace to the values in the
structure.

   For example, if you have the above *Foo.conf*, the variable
*$Config::FreeForm::Foo* will be equal to the following structure:

     {   Bar => 1   }

   So you could access the value of the *Bar* attribute by treating the
aliased variable as a hash reference:

     my $value = $Config::FreeForm::Foo->{Bar};

   In addition to specifying which configuration files to load, you can
use the %options in the import list to set the directory holding the
configuration files. By default *Config::FreeForm* looks in the directory
*FreeForm* within the directory from which it was loaded for the files.
For example, if the module were loaded from `/foo/bar/Config/FreeForm.pm',
the *Foo.conf* configuration file would be default be looked up in
`/foo/bar/Config/FreeForm/Foo.conf'.

   By using the dir import list parameter, though, you can override this
default behavior:

     use Config::FreeForm dir => '/foo', sets => [ 'Foo' ];

   This would look up `Foo.conf' in the directory */foo*.

UPDATING CONFIGURATION
======================

   If you wish to update the configuration files programatically (as
opposed to editing them by hand), you can use the *rewrite* function.

   This is a two-step process. First, you'll need to update the in-memory
configuration-just make a change to one of the variables. For example:

     $Config::FreeForm::Foo->{Bar} = 2;

   This updates the configuration in memory; now you need to write the
configuration to the disk. You can do that using *rewrite*, which takes
the name of a configuration "set" (which corresponds to the name of the
configuration file). In this case, that set would be *Foo*:

     Config::FreeForm::rewrite('Foo');

   And you're done. The configuration is now updated on disk.

   If you'd like to write the configuration data to a file different than
that from which it was read, you can pass a filepath as a second argument.
For example:

     Config::FreeForm::rewrite('Foo', './myfoo.conf');

   This will write out the *Foo* configuration data to `./myfoo.conf'.

   Keep in mind that, if you're rewriting your configuration in a
webserver context, you'll want your on-disk changes to propagate to the
other webserver children (the children in which you didn't already change
the in-memory configuration). Read on-this can be made to happen
automatically.

AUTOMATED RELOADING
===================

   When used in a webserver context, the configuration files are parsed
once at webserver startup, then stored in memory. If changes occur in the
configuration files, under normal circumstances the configuration stored
in memory would not be reloaded. However, *Config::FreeForm* has a
built-in capability to automatically reload configuration files that have
changed on disk. This allows you to make a change to a config file, then
let the webserver automatically pick up the new changes.

   This is particularly important when using the *rewrite* function; if
you alter the in-memory configuration, then write the file to disk, you
want the other webserver children to pick up the changes, in addition to
the child where you actually made the in-memory changes. Using the
automated reloading, these changes will be automatically picked up by all
of the webserver children.

   To use this capability, just install *Config::FreeForm* as a
*PerlInitHandler* in the webserver. Add this to the configuration:

     PerlInitHandler Config::FreeForm

   You can either stick this into a Location block or make it global for
your entire server. The latter may be easier in terms of maintenance, but
the former may give you more flexibility.

   By default, *Config::FreeForm* will go about its business quietly. If
you'd like it to write a message to the error log each time it reloads a
configuration file, you can add a configuration directive to do so:

     PerlSetVar ConfigDebug on

   Now, each time *Config::FreeForm* reloads a configuration file, it will
write a message to the log file telling you the process ID, the
configuration set, and the modified-time comparison that caused the reload.

MISCELLANEOUS
=============

   If the so-called freeform nature of *Config::FreeForm* doesn't appeal
to you, and you'd like a more structured approach to your configuration
files, check out *App-Config*, *Boulder*, or *XML::Simple*.

AUTHOR
======

   Benjamin Trott, ben@rhumba.pair.com


File: pm.info,  Node: Config/General,  Next: Config/General/Extended,  Prev: Config/FreeForm,  Up: Module List

Generic Config Module
*********************

NAME
====

   Config::General - Generic Config Module

SYNOPSIS
========

     use Config::General;
     $conf = new Config::General("rcfile");
     my %config = $conf->getall;

     # or
     $conf = new Config::General(\%somehash);

DESCRIPTION
===========

   This small module opens a config file and parses it's contents for you.
The new method requires one parameter which needs to be a filename. The
method getall returns a hash which contains all options and it's
associated values of your config file.

   The format of config files supported by *Config::General* is inspired
by the well known apache config format, in fact, this module is 100%
compatible to apache configs, but you can also just use simple name/value
pairs in your config files.

   In addition to the capabilities of an apache config file it supports
some enhancements such as here-documents, C-style comments or multiline
options.

METHODS
=======

new()
     Possible ways to call new():

          $conf = new Config::General("rcfile");

          $conf = new Config::General(\%somehash);

          $conf = new Config::General(
                                -file => "rcfile",
                                -AllowMultiOptions => "no"
                                     );

          $conf = new Config::General(
                                -hash => \%somehash,
                                     );

     This method returns a *Config::General* object (a hash blessed into
     "Config::General" namespace.  All further methods must be used from
     that returned object. see below.

     You can use the new style with hash parameters or the old style which
     is of course still supported. Possible parameters are:

          a filename of a configfile

          a hash reference

          or a hash with one or more of the following keys set:

          -file               - a filename.
          -hash               - a hash reference.
          -AllowMultiOptions  - if the value is "no", then multiple
                                identical options are disallowed.

NoMultiOptions()
     This method only exists for compatibility reasons.  Now you should
     set the new() flag *-AllowMultiOptions* to "no".

    The old description: This Turns off the feature of allwing multiple options with identical names. The default behavior is to create an array if an option occurs more than once. But under certain circumstances you may not be willed to allow that. In this case use this method before you call getall to turn it off.
     Please note, that there is no method provided to turn this feature on.

getall()
     Returns a hash structure which represents the whole config.

save("filename", %confighash)
     Writes the config hash back to the harddisk. Please note, that any
     occurence of comments will be ignored and thus be lost after you
     called this method.

     You need also to know that named blocks will be converted to nested
     blocks (which is the same from the perl point of view). An example:

          <user hans>
            id 13
          </user>

     will become the following after saving:

          <user>
            <hans>
               id 13
            </hans>
          </user>

CONFIG FILE FORMAT
==================

   Lines begining with *#* and empty lines will be ignored. (see section
COMMENTS!)  Spaces at the begining and the end of a line will also be
ignored as well as tabulators.  If you need spaces at the end or the
beginning of a value you can use apostrophs *"*.  An optionline starts
with it's name followed by a value. An equalsign is optional.  Some
possible examples:

     user    max
     user  = max
     user            max

   If there are more than one statements with the same name, it will
create an array instead of a scalar. See the example below.

   The method getall returns a hash of all values.

BLOCKS
======

   You can define a block of options. A block looks much like a block in
the wellknown apache config format. It starts with <*blockname*> and ends
with </*blockname*>. An example:

     <database>
        host   = muli
        user   = moare
        dbname = modb
        dbpass = D4r_9Iu
     </database>

   Blocks can also be nested. Here is a more complicated example:

     user   = hans
     server = mc200
     db     = maxis
     passwd = D3rf$
     <jonas>
            user    = tom
            db      = unknown
            host    = mila
            <tablestructure>
                    index   int(100000)
                    name    char(100)
                    prename char(100)
                    city    char(100)
                    status  int(10)
                    allowed moses
                    allowed ingram
                    allowed joice
            </tablestructure>
     </jonas>

   The hash which the method getall returns look like that:

     print Data::Dumper(\%hash);
     $VAR1 = {
              'passwd' => 'D3rf$',
              'jonas'  => {
                           'tablestructure' => {
                                                 'prename' => 'char(100)',
                                                 'index'   => 'int(100000)',
                                                 'city'    => 'char(100)',
                                                 'name'    => 'char(100)',
                                                 'status'  => 'int(10)',
                                                 'allowed' => [
                                                                'moses',
                                                                'ingram',
                                                                'joice',
                                                              ]
                                               },
                           'host'           => 'mila',
                           'db'             => 'unknown',
                           'user'           => 'tom'
                         },
              'db'     => 'maxis',
              'server' => 'mc200',
              'user'   => 'hans'
            };

   If the module cannot find an end-block statement, then this block will
be ignored.

IDENTICAL OPTIONS
=================

   You may have more than one line of the same option with different
values.

   Example:  log  log1  log  log2  log  log2

   You will get a scalar if the option occured only once or an array if it
occured more than once. If you expect multiple identical options, then you
may need to check if an option occured more than once:

     $allowed = $hash{jonas}->{tablestructure}->{allowed};
     if(ref($allowed) eq "ARRAY") {
         @ALLOWED = @{$allowed};
     else {
         @ALLOWED = ($allowed);
     }

   If you don't want to allow more than one identical options, you may
turn it off by setting the flag *AllowMutliOptions* in the new() method to
"no".  If turned off, Config::General will complain about multiple
occuring options whit identical names!

If you need multiple blocks of the same name, then you have to name every block. This works much like apache config. If the module finds a named block, it will create a hashref with the left part of the named block as the key containing one or more hashrefs with the right part of the block as key containing everything inside the block(which may again be nested!). As examples says more than words:
***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

NAMED BLOCKS
============

   If you need multiple blocks of the same name, then you have to name
every block.  This works much like apache config. If the module finds a
named block, it will create a hashref with the left part of the named
block as the key containing one or more hashrefs with the right part of
the block as key containing everything inside the block(which may again be
nested!). As examples says more than words:

     # given the following sample
     <Directory /usr/frisco>
            Limit Deny
            Options ExecCgi Index
     </Directory>
     <Directory /usr/frik>
            Limit DenyAll
            Options None
     </Directory>

     # you will get:
     $VAR1 = {
              'Directory' => {
                               '/usr/frik' => {
                                                'Options' => 'None',
                                                'Limit' => 'DenyAll'
                                              },
                               '/usr/frisco' => {
                                                  'Options' => 'ExecCgi Index',
                                                  'Limit' => 'Deny'
                                                }
                             }
            };

   You cannot have more than one named block with the same name because it
will be stored in a hashref and therefore be overwritten if a block occurs
once more.

LONG LINES
==========

   If you have a config value, which is too long and would take more than
one line, you can break it into multiple lines by using the backslash
character at the end of the line. The Config::General module will
concatenate those lines to one single-value.

   Example:

   command = cat /var/log/secure/tripwire | \            mail -s "report
from tripwire" \            honey@myotherhost.nl

   command will become:  "cat /var/log/secure/tripwire | mail -s 'report
from twire' honey@myotherhost.nl"

HERE DOCUMENTS
==============

   You can also define a config value as a so called "here-document". You
must tell the module an identifier which identicates the end of a here
document. An identifier must follow a "<<".

   Example:

     message <<EOF
       we want to
       remove the
       homedir of
       root.
     EOF

   Everything between the two "EOF" strings will be in the option message.

   There is a special feature which allows you to use indentation with
here documents.  You can have any amount of whitespaces or tabulators in
front of the end identifier. If the module finds spaces or tabs then it
will remove exactly those amount of spaces from every line inside the
here-document.

   Example:

     message <<EOF
             we want to
             remove the
             homedir of
             root.
          EOF

   After parsing, message will become:

     we want to
     remove the
     homedir of
     root.

   because there were the string "     " in front of EOF, which were
cutted from every line inside the here-document.

INCLUDES
========

   You can include an external file at any posision in you config file
using the following statement in your config file:

     <<include externalconfig.rc>>

   This file will be inserted at the position where it was found as if the
contents of this file were directly at this position.

   You can also recurively include files, so an included file may include
another one and so on.  Beware that you do not recursively load the same
file, you will end with an errormessage like "too many files in system!".

   Include statements will be ignored within C-Comments and here-documents.

COMMENTS
========

   A comment starts with the number sign *#*, there can be any number of
spaces and/or tabstops in front of the #.

   A comment can also occur after a config statement. Example:

     username = max  # this is the comment

   If you want to comment out a large block you can use C-style comments.
A */** signals the begin of a comment block and the **/* signals the end
of the comment block.  Example:

     user  = max # valid option
     db    = tothemax
     /*
     user  = andors
     db    = toand
     */

   In this example the second options of user and db will be ignored.
Please beware of the fact, the if the Module finds a */** string which is
the start of a comment block, but no matching end block, it will ignore
the whole rest of the config file!

COPYRIGHT
=========

   Copyright (c) 2000 Thomas Linden

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   none known yet.

AUTHOR
======

   Thomas Linden <tom@daemon.de>

VERSION
=======

   1.18


File: pm.info,  Node: Config/General/Extended,  Next: Config/Ini,  Prev: Config/General,  Up: Module List

Extended access to Config files
*******************************

NAME
====

   Config::General::Extended - Extended access to Config files

SYNOPSIS
========

     use Config::General::Extended;
     $conf = new Config::General::Extended("rcfile");
     # or
     $conf = new Config::General::Extended(\%somehash);

DESCRIPTION
===========

   This module is a subclass of *Config::General*. You can use it if you
want OO access to parts of your config file. The following methods are
directly inherited from Config::General: *new() getall()*.

   Please refer to the *Note Config/General: Config/General,, if you want
to learn about the usage of the two methods mentioned above. The possible
format of config files supported by this module is also well described in
*Note Config/General: Config/General,.

METHODS
=======

new('filename') or new(\%somehash)
     This method returns a *Config::General* object (a hash blessed into
     "Config::General::Extended" namespace. All further methods must be
     used from that returned object. see below.

     Read a more detailed discussion on how to use the new() method in
     *Note Config/General: Config/General,.

NoMultiOptions()
     This method only exists for compatibility reasons.  Now you should
     set the new() flag *-AllowMultiOptions* to "no".

     Refer to *Note Config/General: Config/General, for details about this
     method.

getall()
     Returns a hash structure which represents the whole config.

     If you use this method, then it would be probably better to use the
     simpler module *Config::General*. It is just mentioned here for
     completeness.

save()
     Writes the current config hash back to the harddisk.  It takes an
     optional argument: filename. If you omit a filename, save() will use
     the filename configured by the method *configfile()* or new() (see
     below).

configfile('filename')
     Set the filename to be used by save to "filename". It returns the
     current configured filename if called without arguments.

obj('key')
     Returns a new object (of Config::General::Extended Class) from the
     given key.  Short example: Assume you have the following config:

          <individual>
               <martin>
                  age   23
               </martin>
               <joseph>
                  age   56
               </joseph>
          </individual>
          <other>
               blah     blubber
               blah     gobble
          </other>

     and already read it in using *Config::General::Extended::new()*, then
     you can get a new object from the "individual" block this way:

          $individual = $conf->obj("individual");

     Now if you call getall on *$individual* (just for reference) you
     would get:

          $VAR1 = (
             martin => { age => 13 }
                  );

     Or, here is another use:

          my $individual = $conf->obj("individual");
          foreach my $person ($conf->keys("individual")) {
             $man = $individual->obj($person);
             print "$person is " . $man->value("age") . " years old\n";
          }

     See the discussion on *hash()* and value() below.

hash('key')
     This method returns a hash(if it *is* one!) from the config which is
     referenced by "key". Given the sample config above you would get:

          my %sub_hash = $conf->hash("individual");
          print Dumper(\%sub_hash);
          $VAR1 = {
             martin => { age => 13 }
                  };

array('key')
     This the equivalent of *hash()* mentioned above, except that it
     returns an array.  Again, we use the sample config mentioned above:

          $other = $conf->obj("other");
          my @blahs = $other->array("blah");
          print Dumper(\@blahs);
          $VAR1 = [ "blubber", "gobble" ];

value('key')
     This method returns the scalar value of a given key. Given the
     following sample config:

          name  = arthur
          age   = 23

     you could do something like that:

          print $conf->value("name") . " is " . $conf->value("age") . " years old\n";

     You can use this method also to set the value of "key" to something
     if you give over a hash reference, array reference or a scalar in
     addition to the key. An example:

          $conf->value("key", \%somehash);
          # or
          $conf->value("key", \@somearray);
          # or
          $conf->value("key", $somescalar);

     Please note, that this method does not complain about existing values
     within "key"!

is_hash('key') is_array('key') is_scalar('key')
     As seen above, you can access parts of your current config using
     hash, array or scalar methods. But you are right if you guess, that
     this might become problematic, if for example you call *hash()* on a
     key which is in real not a hash but a scalar. Under normal
     circumstances perl would refuse this and die.

     To avoid such behavior you can use one of the methods is_hash()
     is_array() is_scalar() to check if the value of "key" is really what
     you expect it to be.

     An example(based on the config example from above):

          if($conf->is_hash("individual") {
             $individual = $conf->obj("individual");
          }
          else {
             die "You need to configure a "individual" block!\n";
          }

exists('key')
     This method returns just true if the given key exists in the config.

keys('key')
     Returns an array of the keys under the specified "key". If you use
     the example config above you yould do that:

          print Dumper($conf->keys("individual");
          $VAR1 = [ "martin", "joseph" ];

     You can use this method in foreach loops as seen in an example
     above(obj() ).

AOTOLOAD METHODS
================

   Another usefull feature is implemented in this class using the AUTOLOAD
feature of perl. If you know the keynames of a block within your config,
you can access to the values of each individual key using the method
notation. See the following example and you will get it:

   We assume the following config:

     <person>
        name    = Moser
        prename = Peter
        birth   = 12.10.1972
     </person>

   Now we read it in and process it:

     my $conf = new Config::General::Extended("configfile");
     my $person = $conf->obj("person");
     print $person->prename . " " . $person->name . " is " . $person->age . " years old\n";

   This notation supports only scalar values! You need to make sure, that
the block <person> does not contain any subblock or multiple identical
options(which will become an array after parsing)!

   Of course you can use this kind of methods for writing data too:

     $person->name("Neustein");

   This changes the value of the "name" key to "Neustein". This feature
behaves exactly like value(), which means you can assign hash or array
references as well and that existing values under the given key will be
overwritten.

COPYRIGHT
=========

   Copyright (c) 2000 Thomas Linden

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   none known yet.

AUTHOR
======

   Thomas Linden <tom@daemon.de>

VERSION
=======

   1.0


File: pm.info,  Node: Config/Ini,  Next: Config/IniFiles,  Prev: Config/General/Extended,  Up: Module List

Perl interface to MS-Windows registry files, Windows .ini     and Unreal style .ini files.
******************************************************************************************

NAME
====

   Config::Ini - Perl interface to MS-Windows registry files, Windows .ini
   and Unreal style .ini files.

SYNOPSIS
========

     use Config::Ini;
     $ini = new Config::Ini('system.ini');

     # MS-Windows style
     print $ini->get(['system', 'path']);
     $oldpath = $ini->put(['system', 'path', 'C:\\windows']);
     if ($ini->exists(['system', 'path'])) ...
     $ini->delete(['system', 'path']);

     # Unreal style (multi-valued keys)
     $ini = new Config::Ini('UnrealTournament.ini');
     print map "$_\n", $ini->get(['Engine.GameEngine', 'ServerPackages']);
     $ini->put(['Engine.GameEngine', 'ServerPackages', 'New Mod'], -add => 1);
     if ($ini->exists(['Engine.GameEngine', 'ServerPackages', 'Old Mod'])) ...
     $ini->delete(['Engine.GameEngine', 'ServerPackages', 'Some Mod']);

     $ini->save;

     # Save it in the registry file format
     $ini->registry(1);
     $ini->save('system.reg');

DESCRIPTION
===========

   This package provides easy access to MS-Windows style .ini files, Unreal
style extended .ini files (where multiple values can be associated with a
single key), as well as registry files with automatic conversion from
native Perl to Windows registry data encoding and vice versa.

   For an .ini file to be recognized it must be of the following format:

     [section]
     key=value           ; comments

   In our implementation the key must be no longer than 1024 characters,
and contain no high-ASCII nor control character.

   On a line, everything after the semicolon (;) is ignored.  Backslash (\)
right before the end of line is treated as line continuation marker and
the contents of the next line will be appended after stripping off
preceeding whitespaces.  Comment delimiter takes precedence over line
continuation marker.  Spaces surrounding the delimiting equation sign are
stripped.  If there are more than one equation sign on a line the first
one is treated as the delimiter, the rest of them are considered part of
the value.

   The comment delimiter can be specified during calls to new or open via
the *-commentdelim* option as a regular expression.  If no comment
stripping is desired supply the empty string (") as the argument.

   Specifcations of section, key and value are to be supplied to methods
via an array reference containing just a section name, or the section name
plus a key name, or the section name plus a key name with its associated
value.

   If the first line of a file starts with "REGEDIT4" it will be treated
as a registry file. See the `"Registry Format"' in this node section below
for more details.  Invoking the save method on such a file will have it
saved in registry file format.  If this is not desirable the output mode
can be forced by calling the *registry* method.

Registry Format
---------------

   If the module is processing a Windows "registry" style file, or is
placed into registry mode, all values are automatically converted to and
from native Perl/Windows registry formats.  For special situations you can
use the *decode_reg_value* subroutine for manual decoding.

   A registry file follows the same format described above, except that
keys are expected to be enclosed in double quotes.  The first line of a
registry file starts with "REGEDIT4".


     Strings - A string is stored in the registry as a sequence of
     alphanumeric symbols that are enclosed in a pair of double quotation
     marks (").  When retrieving a string from a registry file, only the
     actual data is returned in the scalar variable.  When writting a
     string, you need to enclose it within the double quotations marks.

          $ini->put(['sys', 'mystr', '"hi there"'], -add => 1);
          print $ini->get(['sys', 'mystr']);

     This will result in the un-quoted 8 character long "hi there" string
     being printed.

     The registry file contains:

          [sys]
          "mystr"="hi there"


     *32 bit numbers* - The registry format allows for special handling of
     32 bit numbers.  When you pass in a scalar that is not enclosed in
     double quotations, this library will assume you are tring to store a
     number.  When retrieving a number it is returned as a Perl number.

          $ini->put(['sys', 'Number', 100], -add => 1);
          print $ini->get(['sys', 'Number']);

     This will result in "100" being printed.

     The registry file contains:

          [sys]
          "Number"=dword:00000064


     *Arrays of 8 bit numbers* - If you need to store value that is an
     array of numbers, you can pass in an array or list of non-quote
     enclosed scalars.  When retrieving that key's value this module will
     return an array or list of scalars.

          $ini->put(['sys', 'ListOfNumbers', ( 1...9) ], -add => 1);
          @nums = $ini->get(['sys', 'ListOfNumbers']);

     This will result in an array containing 10 elements.

     The registry file contains:

          [sys]
          "ListOfNumbers"=hex:00,01,02,03,04,05,06,07,08,09


     *Multiple Strings* - Registries can also store a list of strings.
     They are stored as a sequence of null terminated arrays of 8 bit
     numbers, and there is a final null marking the end of the sequence.
     When saving multiple strings, you pass in an array or list of scalars
     that contains double-quote delimited strings.  When retrieving one of
     these values, you will receive an array of strings (without the
     enclosing quotation marks).

          $ini->put(['sys', 'ListOfStr', ( '"str1"', '"str2"', '"str3"' ) ], -add => 1);
          @strs = $ini->get(['sys', 'ListOfStr']);

     This will result in an array containing 3 elements: "str1", "str2"
     and "str3".

     The registry file contains:

          [sys]
          "ListOfStr"=hex(7):73,74,72,31,00,73,74,72,32,00,73,74,\
          72,33,00,00

     Note that this example contains a line continuation marker "\".

METHODS
=======

new([filename])
     Constructor.  If a filename is supplied it will be opened as an .ini
     file with its content read as the initial configuration of the object.

*open(self[, filename])*
     Open the .ini file and read in all valid entries.  New entries will be
     merged with the existing configuration.

*save(self[, filename])*
     Save the current configuration into file in the .ini format.  Both
     the section order and the order of key=value pairs within a section
     are preserved.  If a filename is given the file will be used as the
     save target, otherwise the configuration will be save to the last
     used (via new, open or save) file.  The original content of the file
     will be clobbered.  Be careful not to inadvertently merge two .ini
     files into one by opening them in turn and then saving.

     True will be returned if the save is successful, false otherwise.

*file(self[, filename] )*
     Set or retrieve the filename that was last used.  new, open and save
     will all update the last used filename if a filename was supplied to
     them.

lastpos(self)
     Set or retrieve the byte offset into the file immediately after the
     last line that conforms to the .ini format.

registry(self)
     Set or retrieve the registry flag which determines whether the file is
     to be treated as a registry file or .ini file.  If this flag is true
     all subsequent file operations will work in registry file mode,
     otherwise the .ini mode is used.  Normally this flag need not be
     altered manually because it is automatically set to a value matching
     the format of the most recently read file.

commentdelim(self)
     Set or retrieve the comment delimiter.

*exists(self, [ section[, key[, value]] ])*
     Return true if the specified section exists, or if the specified key
     exists in the specified section.  If a value is specified, return true
     if it is any one of the values of the key.

*get(self, [ section[, key[, value]] ][, -mapping =* ('single'|'multiple'))>
     Depending on how many elements are specified in the array reference,
     retrieve the entire specified section or the values of the specified
     key.

     If nothing is specified the entire file is returned as a hash
     reference.

     If only a section name is specified the matching section is returned
     in its entirety as a hash reference.

     If both a section name and a key name are specified, the associated
     values are returned.  If the key has multiple values the returned
     result is an array reference containing all the values, otherwise if
     the key has only one value that single value is returned as a scalar.

     The decision of whether to return a single or multiple values can be
     forced via the *-mapping* argument.  If the multiple mapping option is
     applied to a single value result an array of one element that is the
     single value will be returned.  If on the other hand the single
     mapping option is forced upon a mutli-valued result only the first
     value will be returned.

     In general, don't specify any mapping when dealing with standard
     MS-Windows style .ini files and use the multiple mapping when dealing
     with multivalued keys in an Unreal style .ini files.

*put(self, [ section[, key[, value]] ][, -add =* boolean])>
     Set the value for the specified key in the specified section and
     return the old value.  If the optional *-add* argument is true a new
     value will be added to the key if that value does not already exist.

decode_reg_value(value)
     Returns a decoded value or list of values from a registry key.  See
     the section above on `"Registry Format"' in this node. This routine
     accepts the raw value field from a registry entry, and return a Perl
     specific data structure that natively represents the data.

     This routine is called automatically when either get or set methods
     are called specifying a particular key.  If you used get to retrieve
     a whole section, the values of the registry keys will be in their
     native file format.  You must use this method call to convert them
     from registry to Perl format.

*delete(self, [ section[, key[, value]] ][, -keep =* boolean])>
     If section, key and value are all given the corresponding key=value
     pair will be deleted from the specified section.  If a specific value
     is not given the entire key including all its values will be deleted.
     If the path only specifies a section the entire section will be
     deleted.

     If the optional *-keep* argument evaluates to true, when performing
     section deletion all the keys along with their values are deleted but
     the now empty section will still exist to mimic the bahavior of the
     Unreal uninstaller.

*adjustfilecase(filename[, dirname])*
     Return the properly cased filename by performing a case-insensitive
     match of the specified file within the specified parent directory.  If
     there is no match the filename passed in is return as-is.  If the
     dirname argument is not given the current directory will be used.

adjustpathcase(pathname)
     Return the properly cased and slashed pathname, unless running on a
     brain-damaged OS that is too dumb to handle pathnames in a modern,
     case-sensitive manner.  Each path components are inspected from left
     to right to see if a file or directory of the same name, in any case
     combination, already exists.  If any match results the first match is
     used, otherwise the original path component is used verbatim.  No
     backtracking is performed, so if any path component in the middle
     fails to match an existing directory, all subsequent path components
     are used as-is.  All backslashes are also changed to forward-slashes.

AUTHOR
======

   Avatar <`avatar@deva.net'>, based on a prototype by Mishka Gorodnitzky
<`misaka@pobox.com'>.  Registry file support by Fulko Hew
<`fulko@wecan.com'>.


File: pm.info,  Node: Config/IniFiles,  Next: Config/Properties,  Prev: Config/Ini,  Up: Module List

A module for reading .ini-style configuration files.
****************************************************

NAME
====

   Config::IniFiles - A module for reading .ini-style configuration files.

SYNOPSIS
========

     use Config::IniFiles;
     my $cfg = new Config::IniFiles( -file => "/path/configfile.ini" );
     print "We have parm $cfg->val( 'Section', 'Parameter' )." if $cfg->val( 'Section', 'Parameter' );

DESCRIPTION
===========

   Config::IniFiles provides a way to have readable configuration files
outside your Perl script.  Configurations can be imported (inherited,
stacked,...), sections can be grouped, and settings can be accessed from a
tied hash.

USAGE - Object Interface
========================

   Get a new Config::IniFiles object with the new method:

     $cfg = Config::IniFiles->new( -file => "/path/configfile.ini" );
     $cfg = new Config::IniFiles -file => "/path/configfile.ini";

   Optional named parameters may be specified after the configuration file
name.  See the new in the METHODS section, below.

   INI files consist of a number of sections, each preceeded with the
section name in square brackets.  The first nonblank character of the line
indicating a section must be a left bracket and the last nonblank
character of a line indicating a section must be a right bracket. The
characters making up the section name can be any symbols at all. However
section names must be unique.

   Parameters are specified in each section as Name=Value.  Any spaces
around the equals sign will be ignored, and the value extends to the end
of the line. Parameter names are localized to the namespace of the
section, but must be unique within a section.

     [section]
     Parameter=Value

   Both the hash mark (#) and the semicolon (;) are comment characters.
Lines that begin with either of these characters will be ignored.  Any
amount of whitespace may preceed the comment character.

   Multiline or multivalued fields may also be defined ala UNIX "here
document" syntax:

     Parameter=<<EOT
     value/line 1
     value/line 2
     EOT

   You may use any string you want in place of "EOT".  Note that what
follows the "<<" and what appears at the end of the text MUST match
exactly, including any trailing whitespace.

   See the METHODS section, below, for settable options.

   Values from the config file are fetched with the val method:

     $value = $cfg->val('Section', 'Parameter');

   If you want a multi-line/value field returned as an array, just specify
an array as the receiver:

     @values = $cfg->val('Section', 'Parameter');

METHODS
=======

new ( [-option=>value ...] )
----------------------------

   Returns a new configuration object (or "undef" if the configuration
file has an error).  One Config::IniFiles object is required per
configuration file.  The following named parameters are available:

*-file*  filename
     Specifies a file to load the parameters from. If this option is not
     specified, (ie: you are creating a config file from scratch) you must
     specify a target file using SetFileName in order to save the
     parameters.

*-default* section
     Specifies a section is used for default values.  For example, if you
     look up the "permissions" parameter in the "users" section, but there
     is none, Config::IniFiles will look to your default section for a
     "permissions" value before returning undef.

*-reloadwarn* 0|1
     Set -reloadwarn => 1 to enable a warning message (output to STDERR)
     whenever the config file is reloaded.  The reload message is of the
     form:

          PID <PID> reloading config file <file> at YYYY.MM.DD HH:MM:SS

*-nocase* 0|1
     Set -nocase => 1 to handle the config file in a case-insensitive
     manner (case in values is preserved, however).  By default, config
     files are case-sensitive (i.e., a section named 'Test' is not the same
     as a section named 'test').  Note that there is an added overhead for
     turning off case sensitivity.

*-import* object
     This allows you to import or inherit existing setting from another
     Config::IniFiles object. When importing settings from another object,
     sections with the same name will be merged and parameters that are
     defined in both the imported object and the *-file* will take the
     value of given in the *-file*.

     If a *-default* section is also given on this call, and it does not
     coincide with the default of the imported object, the new default
     section will be used instead. If no *-default* section is given, then
     the default of the imported object will be used.

val ($section, $parameter)
--------------------------

   Returns the value of the specified parameter in section $section,
returns undef if no section or no parameter for the given section exists.

   If you want a multi-line/value field returned as an array, just specify
an array as the receiver:

     @values = $cfg->val('Section', 'Parameter');

setval ($section, $parameter, $value, [ $value2, ... ])
-------------------------------------------------------

   Sets the value of parameter $parameter in section $section to $value (or
to a set of values).  See below for methods to write the new configuration
back out to a file.

   You may not set a parameter that didn't exist in the original
configuration file.  setval will return undef if this is attempted. See
*newval* below to do this. Otherwise, it returns 1.

newval($setion, $parameter, $value [, $value2, ...])
----------------------------------------------------

   Adds a new value to the configuration file.

delval($section, $parameter)
----------------------------

   Deletes the specified value from the configuration file

ReadConfig
----------

   Forces the config file to be re-read. Returns undef if the file can not
be opened.

Sections
--------

   Returns an array containing section names in the configuration file.
If the *nocase* option was turned on when the config object was created,
the section names will be returned in lowercase.

Parameters ($sectionname)
-------------------------

   Returns an array containing the parameters contained in the specified
section.

Groups
------

   Returns an array containing the names of available groups.

   Groups are specified in the config file as new sections of the form

     [GroupName MemberName]

   This is useful for building up lists.  Note that parameters within a
"member" section are referenced normally (i.e., the section name is still
"Groupname Membername", including the space) - the concept of Groups is to
aid people building more complex configuration files.

GroupMembers ($group)
---------------------

   Returns an array containing the members of specified $group. Each
element of the array is a section name. For example, given the sections

     [Group Element 1]
     ...

     [Group Element 2]
     ...

   GroupMembers would return ("Group Element 1", "Group Element 2").

WriteConfig ($filename)
-----------------------

   Writes out a new copy of the configuration file.  A temporary file
(ending in .new) is written out and then renamed to the specified
filename.  Also see BUGS below.

RewriteConfig
-------------

   Same as WriteConfig, but specifies that the original configuration file
should be rewritten.

SetFileName ($filename)
-----------------------

   If you created the Config::IniFiles object without initialising from a
file, or if you just want to change the name of the file to use for
ReadConfig/RewriteConfig from now on, use this method.

   Returns $filename if that was a valid name, undef otherwise.

SetSectionComment($section, @comment)
-------------------------------------

   Sets the comment for section $section to the lines contained in
@comment.  Each comment line will be prepended with "#" if it doesn't
already have a comment character (ie: if $line !~ m/^\s*[#;]/)

   To clear a section comment, use DeleteSectionComment ($section)

GetSectionComment ($section)
----------------------------

   Returns a list of lines, being the comment attached to section
$section. In scalar context, returns a string containing the lines of the
comment separated by newlines.

   The lines are presented as-is, with whatever comment character was
originally used on that line.

DeleteSectionComment ($section)
-------------------------------

   Removes the comment for the specified section.

SetParameterComment ($section, $parameter, @comment)
----------------------------------------------------

   Sets the comment attached to a particular parameter.

   Any line of @comment that does not have a comment character will be
prepended with "#".

GetParameterComment ($section, $parameter)
------------------------------------------

   Gets the comment attached to a parameter.

DeleteParameterComment ($section, $parameter)
---------------------------------------------

   Deletes the comment attached to a parameter.

GetParameterEOT ($section, $parameter)
--------------------------------------

   Accessor method for the EOT text (in fact, style) of the specified
parameter. If any text is used as an EOT mark, this will be returned. If
the parameter was not recorded using HERE style multiple lines,
GetParameterEOT returns undef.

SetParameterEOT ($section, $EOT)
--------------------------------

   Accessor method for the EOT text for the specified parameter. Sets the
HERE style marker text to the value $EOT. Once the EOT text is set, that
parameter will be saved in HERE style.

   To un-set the EOT text, use DeleteParameterEOT ($section, $parameter).

DeleteParameterEOT ($section, $parameter)
-----------------------------------------

DeleteSection ( $section_name )
     Completely removes the entire section from the configuration.

Delete
     Deletes the entire configuration file.

USAGE - Tied Hash
=================

tie $ini, 'Config::Inifiles', (-file=>$filename, [-option=>value ...] )
-----------------------------------------------------------------------

   Using tie, you can tie a hash to a Config::IniFiles object. This
creates a new object which you can access through your hash, so you use
this instead of the new method. This actually creates a hash of hashes to
access the values in the .ini-file.

   Here's an example:

     use Config::IniFiles;
     
     my %ini
     tie %ini, 'Config::IniFiles', ( -file => "/path/configfile.ini" );

     print "We have parm %ini{Section}{Parameter}." if %ini{'Section'}{'Parameter'};

   Accessing and using the hash works just like accessing and using an
object, except in the way you reference it. More information about using
the hash interface is descibed below under the corresponding object
methods.

   For those methods that do not coincide with the hash paradigm, you can
use the Perl tied function to get at the underlying object tied to the hash
and call methods on that object. For example, to write the hash out to a
new ini file, you would do something like this:

     tied( %ini )->WriteConfig( "/newpath/newconfig.ini" ) ||
       die "Could not write settings to new file.";

$val = $ini{$section}{$parameter}
---------------------------------

   Returns the value of $parameter in $section, through the hash tie
interface.

   Because of limitations in Perl's tie implementation, multiline values
accessed through a hash will always be returned as a single value with
each line joined by the default line separator ($\). To break them apart
you can simple do this:

     @lines = split( "$\", $ini{section}{multi_line_parameter} );

$ini{$section}{$parameter} = $value;
------------------------------------

   Sets the value of $parameter in $section to value given.  through the
hash interface. If the parameter did not exist in the original file, it
will be created.

   To set a multiline or multivalue parameter use something like this:

     $ini{$section}{$parameter} = [$value1, $value2, ...];

   However, Perl does not seem to extend autovivification to tied hashes.
That means that if you try to say

     $ini{new_section}{new_paramters} = $val;

   and the section 'new_section' does not exist, then Perl won't properly
create it. In order to work around this you will need to create a hash
reference in that section and then assign the parameter value. Something
like this should do nicely:

     $ini{new_section} = {};
     $ini{new_section}{new_paramters} = $val;

%hash = %{$ini{$section}}
-------------------------

   Using the tie interface, you can copy whole sections of the ini file
into another hash. Note that this makes a copy of the entire section. The
new hash in no longer tied to the ini file, In particular, this means
-default and -nocase settings will not apply to `%hash'.

$ini{$section} = {}; %{$ini{$section}} = %parameters;
-----------------------------------------------------

   Through the hash interface, you have the ability to replace the entire
section with a new set of parameters. This call will fail, however, if the
argument passed in NOT a hash reference. You must use both lines, as shown
above so that Perl recognizes the section as a hash reference context
before COPYing over the values from your `%parameters' hash.

delete $ini{$section}{$parameter}
---------------------------------

   When tied to a hash, you can use the Perl delete function to completely
remove a parameter from a section.

delete $ini{$section}
---------------------

   The tied interface also allows you to delete an entire section from the
ini file using the Perl delete function.

$ini = ();
----------

   If you really want to delete all the items in the ini file, this will
do it. Of course, the changes won't be written to the actual file unless
you call RewriteConfig on the object tied to the hash.

Parameter names
---------------

my @keys = keys %{$ini{$section}}
while (($k, $v) = each %{$ini{$section}}) {...}
if( exists %{$ini{$section}}, $parameter ) {...}
   When tied to a hash, you use the Perl keys and each functions to
iteratively list the parameters (keys) or parameters and their values
(each) in a given section.

   You can also use the Perl exists function to see if a parameter is
defined in a given section.

   Note that none of these will return parameter names that are part if
the default section (if set), although accessing and unknown parameter in
the specified section will return a value from the default section if
there is one.

Section names
-------------

keys %ini, $section
while (($k, $v) = each %ini) {...}
if( exists %ini, $section ) {...}
   When tied to a hash, you use the Perl keys and each functions to
iteratively list the sections in the ini file.

   You can also use the Perl exists function to see if a section is
defined in the file.

DIAGNOSTICS
===========

@Config::IniFiles::errors
-------------------------

   Contains a list of errors encountered while parsing the configuration
file.  If the new method returns undef, check the value of this to find
out what's wrong.  This value is reset each time a config file is read.

BUGS
====

   * The output from [Re]WriteConfig/OutputConfig might not be as pretty as
     it can be.  Comments are tied to whatever was immediately below them.

   * No locking is done by [Re]WriteConfig.  When writing servers, take
     care that only the parent ever calls this, and consider making your
     own backup.

Data Structure
==============

   Note that this is only a reference for the package maintainers - one of
the upcoming revisions to this package will include a total clean up of the
data structure.

     $iniconf->{cf} = "config_file_name"
             ->{startup_settings} = \%orginal_object_parameters
             ->{firstload} = 0
             ->{nocase} = 0
             ->{reloadwarn} = 0
             ->{sects} = \@sections
             ->{sCMT}{$section} = \@comment_lines
             ->{group}{$group} = \@group_members
             ->{parms}{$section} = \@section_parms
             ->{EOT}{$sect}{$parm} = "end of text string"
             ->{pCMT}{$section}{$parm} = \@comment_lines
             ->{v}{$section}{$parm} = $value   OR  \@values

AUTHOR and ACKNOWLEDGEMENTS
===========================

   The original code was written by Scott Hutton.  It has since been taken
over by Rich Bowen, with many contributions from various other people.

   In particular, special thanks go to (in roughly chronological order):

   Bernie Cosell, Alan Young, Alex Satrapa, Mike Blazer, Wilbert van de
Pieterman, Steve Campbell, Robert Konigsberg, Scott Dellinger, R.
Bernstein, Jeremy Wadsack, Daniel Winkelmann, Pires Claudio,  and Adrian
Phillips.

   Geez, that's a lot of people. And apologies to the folks I missed.

   If you want someone to bug about this, that would be:

     Rich Bowen <rbowen at rcbowen dot com>

   If you want more information, or want to participate, go to:

     http://sourceforge.net/projects/config-inifiles/

   Please send bug reports to config-inifiles-bugs@lists.sourceforge.net

   Development discussion occurs on the mailing list
config-inifiles-dev@lists.sourceforge.net, which you can subscribe to by
going to the project web site (link above).

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Change log
==========

     $Log: IniFiles.pm,v $
     Revision 2.14  2001/01/08 18:02:32  wadg
     [Bug #127325] Fixed proken import; changelog; moved

     Revision 2.13  2000/12/18 07:14:41  wadg
     [Bugs# 122441,122437] Alien EOLs and OO delete method

     Revision 2.12  2000/12/18 04:59:37  wadg
     [Bug #125524] Writing multiline of 2 with tied hash

     Revision 2.11  2000/12/16 12:53:13  grail
     [BUG #122455] Problem with File Permissions

     Revision 2.10  2000/12/13 17:40:18  rbowen
     Updated version number so that CPAN will stop being angry with us.

     Revision 1.18  2000/12/08 00:45:35  grail
     Change as requested by Jeremy Wadsack, for Bug 123146

     Revision 1.17  2000/12/07 15:32:36  grail
     Further patch to duplicate sections bug, and replacement of repeated values handling code.

     Revision 1.14  2000/11/29 11:26:03  grail
     Updates for task 22401 (no more reloadsig) and 22402 (Group and GroupMember doco)

     Revision 1.13  2000/11/28 12:41:42  grail
     Added test for being able to add sections with wierd names like section|version2

     Revision 1.11  2000/11/24 21:20:11  rbowen
     Resolved SourceForge bug #122445 - a parameter should be split from its value on the first = sign encountered, not on the last one. Added test suite to test this, and put test case in test.ini

     Revision 1.10  2000/11/24 20:40:58  rbowen
     Updated MANIFEST to have file list of new files in t/
     Updated IniFiles.pm to have mention of sourceforge addresses, rather than rcbowen.com addresses
     Regenerated README from IniFiles.pm

     Revision 1.9  2000/11/23 05:08:08  grail
     Fixed documentation for bug 122443 - Check that INI files can be created from scratch.

     Revision 1.1.1.1  2000/11/10 03:04:01  rbowen
     Initial checkin of the Config::IniFiles source to SourceForge

     Revision 1.8  2000/10/17 01:52:55  rbowen
     Patch from Jeremy. Fixed "defined" warnings.

     Revision 1.7  2000/09/21 11:19:17  rbowen
     Mostly documentation changes. I moved the change log into the POD rather
     than having it in a separate Changes file. This allows people to see the
     changes in the Readme before they download the module. Now I just
     need to make sure I remember to regenerate the Readme every time I do
     a commit.

     1.6 September 19, 2000 by JW, AS
     * Applied several patches submitted to me by Jeremy and Alex.
     * Changed version number to the CVS version number, so that I won't
     have to think about changing it ever again. Big version change
     should not be taken as a huge leap forward.

     0.12 September 13, 2000 by JW/WADG
     * Added documentation to clarify autovivification issues when
     creating new sections
     * Fixed version number (Oops!)

     0.11 September 13, 2000 by JW/WADG
     * Applied patch to Group and GroupMembers functions to return empty
     list when no groups are present (submitted by John Bass, Sep 13)

     0.10 September 13, 2000 by JW/WADG
     * Fixed reference in POD to ReWriteFile. changes to RewriteConfig
     * Applied patch for failed open bug submitted by Mordechai T. Abzug Aug 18
     * Doc'd behavior of failed open
     * Removed planned SIG testing from test.pl as SIGs have been removed
     * Applied patch from Thibault Deflers to fix bug in parameter list
     when a parameter value is undef

     0.09
     Hey! Where's the change log for 0.09?

     0.08
     2000-07-30  Adrian Phillips  <adrianp@powertech.no>
     
     * test.pl: Fixed some tests which use $\, and made those that try
     to check a non existant val check against ! defined.

     * IniFiles.pm: hopefully fixed use of $\ when this is unset
     (problems found when running tests with -w).  Similar problem with
     $/ which can be undefined and trying to return a val which does
     not exist. Modified val docs section to indicate a undef return
     when this occurs.

     0.07
     Looks like we missed a change log for 0.07. Bummer.

     0.06 Sun Jun 25, 2000 by Daniel Winkelmann
     * Patch for uninitialized value bug in newval and setval
     
     0.05 Sun Jun 18, 2000 by RBOW
     * Added something to shut up -w on VERSIONS
     * Removed unused variables

     0.04 Thu Jun 15 - Fri Jun 16, 2000 by JW/WADG
     * Added support for -import option on ->new
     * Added support for tying a hash
     * Edited POD for grammer, clarity and updates
     * Updated test.pl file
     * Fixed bug in multiline/single line output
     * Fixed bug in default handling with tie interface
     * Added bugs to test.pl for regression
     * Fixed bug in {group} vs. {groups} property (first is valid)
     * Fixed return value for empty {sects} or {parms}{$sect} in
     Sections and Parameters methods

     0.03 Thu Jun 15, 2000 by RBOW
     * Modifications to permit 'use strict', and to get 'make test' working
     again.

     0.02 Tue Jun 13, 2000 by RBOW
     * Fixed bug reported by Bernie Cosell - Sections, Parameters,
     and GroupMembers return undef if there are no sections,
     parameters, or group members. These functions now return
     () if the particular value is undefined.
     * Added some contributed documentation, from Alex Satrapa, explaining
     how the internal data structure works.
     * Set up a project on SourceForge. (Not a change, but worth
     noting).
     * Added Groups method to return a list of section groups.

     0.01  Mon Jun 12, 2000 by RBOW
     Some general code cleanup, in preparation for changes to
     come. Put up Majordomo mailing list and sent invitation to
     various people to join it.


