Advanced-Config

 view release on metacpan or  search on metacpan

lib/Advanced/Config/Options.pm  view on Meta::CPAN

###
###  Copyright (c) 2007 - 2026 Curtis Leach.  All rights reserved.
###
###  Module: Advanced::Config::Options

=head1 NAME

Advanced::Config::Options - Options manager for L<Advanced::Config>.

=head1 SYNOPSIS

 use Advanced::Config::Options;
 or 
 require Advanced::Config::Options;

=head1 DESCRIPTION

F<Advanced::Config::Options> is a helper module to L<Advanced::Config>.  So it
should be very rare to directly call any methods defined by this module.

It's main job is to help manage the settings of the B<Read>, B<Get> and B<Date>
options hashes.  It was implemented as a separate module to make it simpler to
document the various supported options without cluttering up the POD of the main
module.  So you are not expected to ever call any of these methods yourself.
It's here mainly as an FYI.

If you don't specify the options below, this module will assume you wish to use
the default behavior for that option.  So only override what you need to.
Also all options are in lower case.  But you may provide them in mixed case if
you wish.  This module will auto downshift them for you.

If an option is misspelled, or you don't provide a valid value, a warning will
be written to the screen and that option will be ignored.

=head1 ==================================================================

=head2 Z<>

=head1 The Read Options

In most cases the defaults should do nicely for you.  But when you share config
files between applications, you may not have any control over the config file's
format.  This may also apply if your organization requires a specific format
for its config files.

So this section deals with the options you can use to override how it parses and
interprets the config file when it is loaded into memory.  None of these options
below allows leading or trailing spaces in the option's value.  And if any are
found, they will be automatically trimmed off before their value is used.
Internal spaces are OK when non-numeric values are expected.  In most cases
values with a length of B<0> or B<undef> are not allowed.

Just be aware that some combinations of I<Read> options may result in this
module being unable to parse the config file.  If you encounter such a
combination open a CPAN ticket and I'll see what I can do about it.  But some
combinations may just be too ambiguous to handle.

Also note that some I<Read> options have B<left> and B<right> variants.  These
options are used in pairs and both must anchor the target in order for the rule
to be applied to it.  These start/end anchors can be set to the same string or
different strings.  Your choice.

=head2 Tag(s) Best Set in Call to the Constructor new().

While not required to set these options during the call to B<new>, changing
their settings later on can cause unexpected issues if you are not careful.

But it's still recommended that most I<Read> Options be set during the call to
B<new> to avoid having to keep on resetting them all the time and limit these
later changes to handle exceptions to your defaults.

=over 4

B<tag_case> - Config files are made up of tag/value pairs.  This option controls
whether the tags are case sensitive (B<0>, the default) or case insensitive
(B<1>).  IE do tags B<ABC> and B<abc> represent the same tag or not?  So if set,
all tags are assumed to be in lower case for the get/set methods!

=back

=head2 Generic Read Options

These options are also usually set during the call to B<new>, but setting them
later on doesn't produce strange behavior if you change the settings later on.

=over 4

B<croak> - This controls what happens when a function hits an unexpected error
while parsing the config file.  Set to B<0> to return an error code (default),
B<-1> to return an error code and print a warning to your screen, B<1> to call
die and terminate your program.

B<export> - Tells if we should export all tag/value pairs to perl's %ENV hash
or not.  The default is B<0> for I<No>.  Set to B<1> if you want this to happen.
But if set, it reverses the meaning of the B<export_lbl> option defined later
on.

B<use_utf8> - Defaults to B<0>.  Set to B<1> if the config file was created
using utf8 encoding.  (IE Unicode or Wide Characters.)  Guessing this
setting wrong means the file will be unusable as a config file.

B<disable_quotes> - Defaults to B<0>.  Set to B<1> if you want to disallow
the stripping of balanced quotes in your config files.

B<disable_variables> - Defaults to B<0>.  Set to B<1> if you want to disable
variable expansion in your config files when they are loaded into memory.

B<disable_variable_modifiers> - Defaults to B<0>.  Set to B<1> if you want to
disable this feature.  See L<http://wiki.bash-hackers.org/syntax/pe> for more
details.  This feature allows you to put logic into your config files via
your variable definitions.  Automatically disabled when variables are
disabled.  Useful when you put a lot of special chars into your variable
names.

B<disable_decryption> - Defaults to B<0>.  Set to B<1> if you want to disable
decrypting values that have been marked as encrypted.  If a variable references
an encrypted value while disable_decription is active, that variable isn't
expanded.

=cut 

lib/Advanced/Config/Options.pm  view on Meta::CPAN

ignores the recursion request to prevent infinite loops.

B<source_cb_opts> - A work area for holding values between calls to the
callback function.  This is expected to be a hash reference to provide any
needed configuration values needed to parse the next config file.  This way
you can avoid global variables.  Defaults to an empty hash reference.

B<source_cb> - An optional callback routine called each time your config file
sources in another config file.  It's main use is when the I<Read Options>
and/or I<Date Format Options> required to parse each config file change between
files.  It's automatically called right before the sourced in file is opened up
for parsing.

Once the new file is sourced in, it inherits most of the options currently used
unless you override them.  The only ones not inherited deal with decryption.

Here is the callback function's expected definition:

  my ($rOpts, $dOpts) = source_callback_func ($file[, $cbOpts]);

  $file --> The file being sourced in.

  $cbOpts --> A hash reference containing values needed by your callback
              function to decide what options are required to source in the
              requested file.  You may update the contents of this hash to
              preserve info between calls.  This module will "never" examine
              the contents of this hash!

  $rOpts --> A reference to the "Read Options" hash used to parse the file
             you want to source in.  Returns "undef" if the options don't
             change.  The returned options override what's currently in use by
             "load_config" when loading the current file.

  $dOpts --> A reference to the "Date Formatting Options" hash used to tell how
             to format the special date variables.  Returns "undef" if the
             options don't change.  The returned options override what's
             currently in use by "load_config" when loading the current file.

=back

=head2 Parse Read Options

These options deal with how to parse the config file itself.  All values are
literal values.  No regular expressions are supported.  If you don't want to
allow a particular option to be supported in your config file, and there is
no disable option, feel free to set it to some unlikely long string of
characters that will never match anything in your config files.  Such as
"#"x100.  (A string of 100 #'s.)

=over 4

B<assign> - Defaults to B<=>.  You may use this option to override what string
of characters make up the assignment operator.  It's used to split a line
into a tag/value pair.  If you want the special case of no separator, IE the
first space separates a tag/value pair, try setting it to B<\\s> since the
interface doesn't allow whitespace as a value.

B<comment> - Defaults to B<#>.  This is the comment symbol used when parsing
your config file and everything after it is ignored in most cases.  The first
case is when it appears between balanced quotes as part of a tag's value, it's
not considered the start of a comment.  The other case is when you put one
of the labels in the comments to override default behavior.  (See next section)

B<source> - Defaults to "B<.>".  When followed by a file name, this is an
instruction to source in another config file (similar to how it works in a
I<Unix> shell script.)  Another common setting for this option is "include".

B<section_left> & B<section_right> - This pair is used to anchor breaking
your config file into multiple independent sections.  The defaults are B<[>
and B<]>.

B<variable_left> & B<variable_right> - This pair is used to anchor a variable
definition.  Any value between these anchors will be a variable name and it's
value will be used instead, unless you've disabled this expansion.  The defaults
are B<${> and B<}>.  If you override these anchors to both have the same value,
then the optional variable modifiers are not supported nor are nested variables.

B<quote_left> & B<quote_right> - This pair is used to define what balanced
quotes look like in your config file.  By default, it allows you to use either
B<"> or B<'> as a matching pair.  But if you override one of them you must
override both.  And in that case it can only be with literal values.  If the
quotes surrounding a tag's value are balanced, the quotes will be automatically
removed from the value.  If they are unbalanced the quotes will not be removed.

=cut

# B<backquote_left> & B<backquote_right> - This pair is used to surround a command
# you wish to run, just like in Perl itself.  What the command writes to STDOUT
# becomes the tag's value.  Assumes the command takes nothing from STDIN.  Due to
# security concerns you must explicitly set these values yourself before they are
# usable.  A good value is the backqoute itself (B<`>).  But use something else
# if you don't want to be so obvious about it.

=pod

=back

=head2 Modifiers in the trailing Comments for tag/value pairs.

In some cases we need to handle exceptions to the rule.  So we define labels
to tell this module that we need to apply special rules to this tag/value pair.
These labels may appear anywhere in the comment.  So when looking for "EXPORT",
it will match "B<# Please EXPORT me.>", but won't match "B<# EXPORTED>".  This
allows you to put multiple labels in a single comment if needed.

As long as the text is surrounded by white space or punctuation a match will
be found.  It is strongly recommended that you don't use punctuation in your
label when you override one with values of your own.

Here are the labels you may override.

=over 4

B<export_lbl> - Defaults to "B<EXPORT>".  Tells this module to export this
particular tag/value pair to perl's B<%ENV> hash.  If the I<export> option
was also set, it inverts the meaning of this label to mean don't export it!
You can also gain the same functionality by doing one of the following
instead:

    export tag = value    # Optional unix type shell script prefix.

lib/Advanced/Config/Options.pm  view on Meta::CPAN

}


# ==============================================================
# A stub of the encryption/decryption callback function ...
sub _encryption_callback_stub
{
   DBUG_MASK_NEXT_FUNC_CALL (2);   # Mask $value!
   DBUG_ENTER_FUNC ( @_ );
   my $mode   = shift;
   my $tag    = shift;
   my $value  = shift;   # Clear text sensitive value ...
   my $file   = shift;
   my $cbOpts = shift;
   DBUG_MASK ( 0 );
   DBUG_RETURN ( $value );
}


# ==============================================================
# Initialize the global hashes with their default values ...
BEGIN
{
   DBUG_ENTER_FUNC ();

   # ---------------------------------------------------------------------
   # Make sure no hash value is undef !!!
   # ---------------------------------------------------------------------

   # You can only add to this list, you can't remove anything from it!
   # See should_we_hide_sensitive_data () on how this list is used.
   DBUG_PRINT ("INFO", "Initializing the tag patterns to hide from fish ...");
   push ( @hide_from_fish, "password" );
   push ( @hide_from_fish, "pass" );
   push ( @hide_from_fish, "pwd" );

   # ---------------------------------------------------------------------

   DBUG_PRINT ("INFO", "Initializing the READ options global hash ...");
   # Should always be set in the constructor ...
   $default_read_opts{tag_case}   = 0;         # Case sensitive tags.

   # The generic options ...
   my %src_empty;
   $default_read_opts{croak}      = 0;         # Don't croak by default.
   $default_read_opts{export}     = 0;         # Don't export any tag/val pairs.
   $default_read_opts{use_utf8}   = 0;         # Doesn't support utf8/Unicode/Wide Chars.
   $default_read_opts{disable_quotes}     = 0; # Don't disable balanced quotes.
   $default_read_opts{disable_variables}  = 0; # Don't disable variables!
   $default_read_opts{disable_variable_modifiers} = 0; # Don't disable variable modifiers!
   $default_read_opts{disable_decryption} = 0; # Don't disable decryption!
 # $default_read_opts{enable_backquotes}  = 0; # Don't allow random command execution.
   $default_read_opts{trap_recursion}     = 0; # Recursion is ignored, not fatal
   $default_read_opts{source_cb}  = __PACKAGE__->can ("_source_callback_stub");
   $default_read_opts{source_cb_opts} = \%src_empty;

   # The file parsing options ...
   $default_read_opts{assign}          = '=';   # The assignment operator
   $default_read_opts{comment}         = '#';   # The comment symbol
   $default_read_opts{source}          = '.';   # The file source symbol
   $default_read_opts{section_left}    = '[';   # The start section string
   $default_read_opts{section_right}   = ']';   # The end section string
   $default_read_opts{variable_left}   = '${';  # The start variable string
   $default_read_opts{variable_right}  = '}';   # The end variable string

   # Unlikely default values due to security concerns.
   # $default_read_opts{backquote_left}  = '`'x101;  # The start backquote string
   # $default_read_opts{backquote_right} = '`'x102;  # The end backquote string

   # The quote chars ... (Special case doesn't work for anything else.)
   # See  using_default_quotes()  if this changes ...
   $default_read_opts{quote_left} = $default_read_opts{quote_right} = "['\"]";

   # The tag/value modifiers.  These labels are found inside the comments!
   $default_read_opts{export_lbl}  = "EXPORT";    # Label for a single %ENV.
   $default_read_opts{hide_lbl}    = "HIDE";      # Mark as sensitive.
   $default_read_opts{encrypt_lbl} = "ENCRYPT";   # Pending encryption.
   $default_read_opts{decrypt_lbl} = "DECRYPT";   # Already encrypted.
   $default_read_opts{source_file_section_lbl} = "DEFAULT";  # Override default.

   # The Encrypt/Decrypt options ... (Encode/Decode)
   my %empty_encrypt;
   $default_read_opts{alias}               = "";
   $default_read_opts{pass_phrase}         = "";
   $default_read_opts{inherit_pass_phrase} = 0;
   $default_read_opts{encrypt_by_user}     = 0;
   $default_read_opts{encrypt_cb}      = __PACKAGE__->can ("_encryption_callback_stub");
   $default_read_opts{encrypt_cb_opts} = \%empty_encrypt;

   # Special undocumented test prog option for overriding fish in parse_line().
   $default_read_opts{dbug_test_use_case_parse_override} = 0;  # Always off.

   # Special undocumented test prog option for overriding fish in read_config().
   $default_read_opts{dbug_test_use_case_hide_override} = 0;   # Always off.


   # ---------------------------------------------------------------------

   DBUG_PRINT ("INFO", "Initializing the GET options global hash ...");
   # Should always be set in the constructor ...
   $default_get_opts{inherit} = 0;        # Can inherit from the parent section.

   # The generic options ... Who cares where set!
   $default_get_opts{required}  = 0;         # Return undef by default.
   $default_get_opts{vcase}     = 0;         # Case of the value. (0 = as is)
   $default_get_opts{split_pattern} = qr /\s+/;  # Space separated lists.

   # Used in parsing dates for get_date() ...
   $default_get_opts{date_language}      = "English"; # The language to use in parsing dates.
   $default_get_opts{date_language_warn} = 0;         # Disable warnings in Date.pm.
   $default_get_opts{date_dl_conversion} = 0;         # 1-Enable 0-Disable using Date::Language for parsing.
   $default_get_opts{date_enable_yy}     = 0;         # 1-Enable 0-Disable using 2 digit years in a date!
   $default_get_opts{date_format}        = 3;         # Hints are 0 to 8.

   # These special case options not to show up in the POD ...
   # All associated with special "get_*()" functions that will auto set if needed.
   $default_get_opts{numeric}     = 0;       # 0-no, 1-integer (truncate), 2-integer (round), 3-real.
   $default_get_opts{auto_true}   = 0;       # Don't return as boolean.
   $default_get_opts{filename}    = 0;       # Tag doesn't do a file test.
   $default_get_opts{directory}   = 0;       # Tag doesn't do a directory test.
   $default_get_opts{split}       = 0;       # Don't split the value.
   $default_get_opts{sort}        = 0;       # Don't sort the split value. (1 - sort, -1 - reverse sort)
   $default_get_opts{date_active} = 0;       # 0-No, 1-Yes expecing it to be a date.


   # ---------------------------------------------------------------------



( run in 0.917 second using v1.01-cache-2.11-cpan-39bf76dae61 )