stas        2002/12/09 08:47:07

  Modified:    src/docs/2.0/user config.cfg
  Added:       src/docs/2.0/user/config custom.pod
  Log:
  a new doc: Apache Server Configuration Customization in Perl
  
  Revision  Changes    Path
  1.1                  modperl-docs/src/docs/2.0/user/config/custom.pod
  
  Index: custom.pod
  ===================================================================
  =head1 NAME
  
  Apache Server Configuration Customization in Perl
  
  =head1 Description
  
  This chapter explains how to create custom Apache configuration
  directives in Perl.
  
  WARNING: This doc is under construction
  
  =head1 Incentives
  
  mod_perl provides several ways to pass custom configuration
  information to the modules.
  
  The simplest way to pass custom information from the configuration
  file to the Perl module is to use the
  C<L<PerlSetVar|docs::2.0::user::config::config/C_PerlSetVar_>> and
  C<L<PerlAddVar|docs::2.0::user::config::config/C_PerlAddVar_>>
  directives. For example:
  
    PerlSetVar Secret "Matrix is us"
  
  and in the mod_perl code this value can be retrieved as:
  
    my $secret = $r->dir_config("Secret");
  
  Another alternative is to add custom configuration directives. There
  are several reasons for choosing this approach:
  
  =over
  
  =item *
  
  When the expected value is not a simple argument, but must be supplied
  using a certain syntax, Apache can verify at startup time that this
  syntax is valid and abort the server start up if the syntax is
  invalid.
  
  =item *
  
  Custom configuration directives are faster because their values are
  parsed at the startup time, whereas C<PerlSetVar> and C<PerlAddVar>
  values are parsed at the request time.
  
  =item *
  
  It's possible that some other modules have accidentally chosen to use
  the same key names but for absolutely different needs. So the two now
  can't be used together. Of course this collision can be avoided if a
  unique to your module prefix is used in the key names. For example:
  
      PerlSetVar ApacheFooSecret "Matrix is us"
  
  =back
  
  Finally, modules can be configured in pure Perl using
  C<L<E<lt>PerlE<gt>
  Sections|docs::2.0::user::config::config/C_E_lt_PerlE_gt___Sections>>
  or L<a startup
  file|docs::2.0::user::config::config/Startup_File>, by simply modifying 
  the global variables in the module's package. This approach could be
  undesirable because it requires a use of globals, which we all try to
  reduce. A bigger problem with this approach is that you can't have
  different settings for different sections of the site (since there is
  only one version of a global variable), something that the previous
  two approaches easily achieve.
  
  =head1 Creating and Using Custom Configuration Directives
  
  In mod_perl 2.0, adding new configuration directives is a piece of
  cake, because it requires no XS code and I<Makefile.PL>, needed in
  case of mod_perl 1.0. In mod_perl 2.0, custom directives are
  implemented in pure Perl.
  
  Here is a very basic module that declares two new configuration
  directives: C<MyParameter>, which accepts one or more arguments, and
  C<MyOtherParameter> which accepts a single argument.
  
    #file:MyApache/MyParameters.pm
    #-----------------------------
    package MyApache::MyParameters;
    
    use strict;
    use warnings FATAL => 'all';
    
    use Apache::Test;
    use Apache::TestUtil;
    
    use Apache::Const -compile => qw(OR_ALL ITERATE);
    
    use Apache::CmdParms ();
    use Apache::Module ();
    
    our @APACHE_MODULE_COMMANDS = (
        {
         name         => 'MyParameter',
         func         => __PACKAGE__ . '::MyParameter',
         req_override => Apache::OR_ALL,
         args_how     => Apache::ITERATE,
         errmsg       => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
        },
        {
         name         => 'MyOtherParameter',
        },
    );
    
    sub MyParameter {
        my($self, $parms, @args) = @_;
        $self->{MyParameter} = [EMAIL PROTECTED];
    }
    1;
  
  And here is how to use it in I<httpd.conf>:
  
    # first load the module so Apache will recognize the new directives
    PerlLoadModule MyApache::MyParameters
    
    MyParameter one two three
    MyOtherParameter Foo
    <Location /perl>
      MyParameter eleven twenty
      MyOtherParameter Bar
    </Location>
  
  The following sections discuss this and more advanced modules in
  detail.
  
  A minimal configuration module is comprised of two groups of elements:
  
  =over
  
  =item * A global array C<@APACHE_MODULE_COMMANDS> for declaring the
  new directives and their behavior.
  
  =item * A subroutine per each new directive, which is called when the
  directive is seen
  
  =back
  
  
  
  =head2 C<@APACHE_MODULE_COMMANDS>
  
  C<@APACHE_MODULE_COMMANDS> is a global array of hash references. Each
  hash represents a separate new configuration directive. In our example
  we had:
  
    our @APACHE_MODULE_COMMANDS = (
        {
         name         => 'MyParameter',
         func         => __PACKAGE__ . '::MyParameter',
         req_override => Apache::OR_ALL,
         args_how     => Apache::ITERATE,
         errmsg       => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
        },
        {
         name         => 'MyOtherParameter',
        },
    );
  
  This structure declares two new directives: C<MyParameter> and
  C<MyOtherParameter>. You have to declare at least the name of the new
  directive, which is how we have declared the C<MyOtherParameter>
  directive. mod_perl will fill in the rest of the configuration using
  the defaults described next.
  
  These are the attributes that can be used to define the directives
  behavior:
  
  =over
  
  =item * name
  
  This is the only required attribute. And it declares the name of the
  new directive as it'll be used in I<httpd.conf>.
  
  =item * func
  
  The I<func> attribute expects a reference to a function or a function
  name. This function is called by httpd every time it encounters the
  directive that is described by this entry while parsing the
  configuration file. Therefore it's invoked once for every instance of
  the directive at the server startup, and once per request per instance
  in the I<.htaccess> file.
  
  This function accepts two or more arguments, L<depending on the
  I<args_how> attribute's value|/Directive_Syntax_Definition_Constants>.
  
  This attribute is optional. If not supplied, mod_perl will try to use
  a function in the current package whose name is the same as of the
  directive in question. In our example with C<MyOtherParameter>,
  mod_perl will use:
  
    __PACKAGE__ . '::MyOtherParameter'
  
  as a name of a subroutine and it anticipates that it exists in that
  package.
  
  =item * req_override
  
  The I<> attribute defines the valid scope in which this directive can
  appear. There are L<several
  constants|/Directive_Scope_Definition_Constants> which map onto the
  corresponding Apache macros. These constants should be imported from
  the C<Apache::Const> package.
  
  For example, to use the C<OR_ALL> constant, which allows directives to
  be defined anywhere, first, it needs to be imported:
  
    use Apache::Const -compile => qw(OR_ALL);
  
  and then assigned to the I<req_override> attribute:
  
    req_override => Apache::OR_ALL,
  
  It's possible to combine several options using the unary
  operators. For example, the following setting:
  
    req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF
  
  will allow the directive to appear anywhere in I<httpd.conf>, but
  forbid it from ever being used in I<.htaccess> files:
  
  This attribute is optional. If not supplied, the default value of
  C<Apache::OR_ALL> is used.
  
  =item * args_how
  
  Directives can receive zero, one or many arguments. In order to help
  Apache validate that the number of arguments is valid, the I<args_how>
  attribute should be set to the desired value. Similar to the
  I<req_override> attribute, the C<Apache::Const> package provides
  special constants which map to the corresponding Apache macros.  There
  are L<several constants|/Directive_Syntax_Definition_Constants> to
  choose from.
  
  In our example, the directive C<MyParameter> accepts one or more
  arguments, therefore we have the C<Apache::ITERATE> constant:
  
         args_how => Apache::ITERATE,
  
  This attribute is optional. If not supplied, the default value of
  C<Apache::TAKE1> is used.
  
  META: the default may change to use a constant corresponding to the
  I<func> prototype.
  
  
  =item * errmsg
  
  The I<errmsg> attribute provides a short but succinct usage statement
  that summarizes the arguments that the directive takes. It's used by
  Apache to generate a descriptive error message, when the directive is
  configured with a wrong number of arguments.
  
  In our example, the directive C<MyParameter> accepts one or more
  arguments, therefore we have chosen the following usage string:
  
         errmsg => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
  
  This attribute is optional. If not supplied, the default value of will
  be a string based on the directive's I<name> and I<args_how>
  attributes.
  
  =back
  
  =head2 Directive Scope Definition Constants
  
  The I<req_override> attribute specifies the configuration scope in
  which it's valid to use a given configuration directive. This
  attribute's value can be any of or a combination of the following
  constants:
  
  (these constants are declared in I<httpd-2.0/include/http_config.h>.)
  
  =head3 C<Apache::OR_NONE>
  
  The directive cannot be overriden by any of the C<AllowOverride>
  options.
  
  =head3 C<Apache::OR_LIMIT>
  
  The directive can appear within directory sections, but not outside
  them.  It is also allowed within I<.htaccess> files, provided that
  C<AllowOverride Limit> is set for the current directory.
  
  =head3 C<Apache::OR_OPTIONS>
  
  The directive can appear anywhere within I<httpd.conf>, as well as
  within I<.htaccess> files provided that C<AllowOverride Options> is
  set for the current directory.
  
  =head3 C<Apache::OR_FILEINFO>
  
  The directive can appear anywhere within I<httpd.conf>, as well as
  within I<.htaccess> files provided that C<AllowOverride FileInfo> is
  set for the current directory.
  
  =head3 C<Apache::OR_AUTHCFG>
  
  The directive can appear within directory sections, but not outside
  them.  It is also allowed within I<.htaccess> files, provided that
  C<AllowOverride AuthConfig> is set for the current directory.
  
  =head3 C<Apache::OR_INDEXES>
  
  The directive can appear anywhere within I<httpd.conf>, as well as
  within I<.htaccess> files provided that C<AllowOverride Indexes> is
  set for the current directory.
  
  =head3 C<Apache::OR_UNSET>
  
  META: details? "unset a directive (in Allow)"
  
  =head3 C<Apache::ACCESS_CONF>
  
  The directive can appear within directory sections.  The directive is
  not allowed in I<.htaccess> files.
  
  =head3 C<Apache::RSRC_CONF>
  
  The directive can appear in I<httpd.conf> outside a directory section
  (C<E<lt>DirectoryE<gt>>, C<E<lt>LocationE<gt>> or C<E<lt>FilesE<gt>>;
  also C<E<lt>FilesMatchE<gt>> and kin).  The directive is not allowed
  in I<.htaccess> files.
  
  =head3 C<Apache::OR_EXEC_ON_READ>
  
  Force directive to execute a command which would modify the
  configuration (like including another file, or C<IFModule>).
  
  META: details???
  
  =head3 C<Apache::OR_ALL>
  
  The directive can appear anywhere.  It is not limited in any way.
  
  
  
  
  =head2 Directive Callback Subroutine
  
  Depending on the value of the I<args_how> attribute the callback
  subroutine, specified with the I<func> attribute, will be called with
  two or more arguments. The first two arguments are always C<$self> and
  C<$parms>. A typical callback function which expects a single value
  (C<Apache::TAKE1>) might look like the following:
  
    sub MyParam {
        my($self, $parms, $arg) = @_;
        $self->{MyParam} = $arg;
    }
  
  In this function we store the passed single value in the configuration
  object, using the directive's name (assuming that it was C<MyParam>)
  as the key.
  
  Let's look at the subroutine arguments in detail:
  
  =over
  
  =item 1
  
  C<$self> is the current container's configuration object.
  
  This configuration object is a reference to a hash, in which you can
  store arbitrary key/value pairs. When the directive callback function
  is invoked it may already include several key/value pairs inserted by
  other directive callbacks or during the
  C<L<SERVER_CREATE|/C_SERVER_CREATE_>> and
  C<L<DIR_CREATE|/C_DIR_CREATE_>> functions, which will be explained
  later.
  
  Usually the callback function stores the passed argument(s), which
  later will be read by C<L<SERVER_MERGE|/C_SERVER_MERGE_>> and
  C<L<DIR_MERGE|/C_DIR_MERGE_>>, which will be explained later, and of
  course at request time.
  
  The convention is use the name of the directive as the hash key, where
  the received values are stored. The value can be a simple scalar, or a
  reference to a more complex structure. So for example you can store a
  reference to an array, if there is more than one value to store.
  
  This object can be later retrieved at request time via:
  
    my $dir_cfg = $self->get_config($s, $r->per_dir_config);
  
  You can retrieve the server configuration object via:
  
    my $srv_cfg = $self->get_config($s);
  
  if invoked inside the virtual host, the virtual host's configuration
  object will be returned.
  
  =item 2
  
  C<$parms> is an I<Apache::CmdParms> object from which you can retrieve
  various other information about the configuration. For example to
  retrieve the server object:
  
    my $s = $parms->server;
  
  See
  C<L<Apache::CmdParms|docs::2.0::api::mod_perl-2.0::Apache::CmdParms>>
  for more information.
  
  =item 3
  
  The rest of the arguments whose number depends on the I<args_how>'s
  value are covered in L<the next
  section|/Directive_Syntax_Definition_Constants>.
  
  =back
  
  
  
  =head2 Directive Syntax Definition Constants
  
  The following values of the I<args_how> attribute define how many
  arguments and what kind of arguments directives can accept. These
  values are constants that can be imported from the C<Apache::Const>
  package. For example:
  
    use Apache::Const -compile => qw(TAKE1 TAKE23);
  
  =head3 C<Apache::NO_ARGS>
  
  The directive takes no arguments.  The callback will be invoked once
  each time the directive is encountered.  For example:
  
    sub MyParameter {
         my($self, $parms) = @_;
         $self->{MyParameter}++;
    }
  
  =head3 C<Apache::TAKE1>
  
  The directive takes a single argument.  The callback will be invoked
  once each time the directive is encountered, and its argument will be
  passed as the third argument. For example:
  
    sub MyParameter {
       my($self, $parms, $arg) = @_;
       $self->{MyParameter} = $arg;
    }
  
  =head3 C<Apache::TAKE2>
  
  The directive takes two arguments.  They are passed to the callback as
  the third and fourth arguments. For example:
  
    sub MyParameter {
       my($self, $parms, $arg1, $arg2) = @_;
       $self->{MyParameter} = {$arg1 => $arg2};
    }
  
  =head3 C<Apache::TAKE3>
  
  This is like C<Apache::TAKE1> and C<Apache::TAKE2>, but the directive
  takes three mandatory arguments. For example:
  
    sub MyParameter {
       my($self, $parms, @args) = @_;
       $self->{MyParameter} = [EMAIL PROTECTED];
    }
  
  =head3 C<Apache::TAKE12>
  
  This directive takes one mandatory argument, and a second optional
  one.  This can be used when the second argument has a default value
  that the user may want to override.  For example:
  
    sub MyParameter {
      my($self, $parms, $arg1, $arg2) = @_;
      $self->{MyParameter} = {$arg1 => $arg2||'default'};
    }
  
  =head3 C<Apache::TAKE23>
  
  C<Apache::TAKE23> is just like C<Apache::TAKE12>, except now there are
  two mandatory arguments and an optional third one.
  
  =head3 C<Apache::TAKE123>
  
  In the C<Apache::TAKE123> variant, the first argument is mandatory and
  the other two are optional.  This is useful for providing defaults for
  two arguments.
  
  =head3 C<Apache::ITERATE>
  
  C<Apache::ITERATE> is used when a directive can take an unlimited
  number of arguments.  The callback is invoked repeatedly with a single
  argument, once for each argument in the list.  It's done this way for
  interoperability with the C API, which doesn't have the flexible
  argument passing that Perl provides. For example:
  
    sub MyParameter {
       my($self, $parms, $args) = @_;
       push @{ $self->{MyParameter} }, $arg;
    }
  
  
  =head3 C<Apache::ITERATE2>
  
  C<Apache::ITERATE2> is used for directives that take a mandatory first
  argument followed by a list of arguments to be applied to the first.
  A familiar example is the C<AddType> directive, in which a series of
  file extensions are applied to a single MIME type:
  
    AddType image/jpeg JPG JPEG JFIF jfif
  
  Apache will invoke your callback once for each item in the list.  Each
  time Apache runs your callback, it passes the routine the constant
  first argument (I<"image/jpeg"> in the example above), and the current
  item in the list (I<"JPG"> the first time around, I<"JPEG"> the second
  time, and so on).  In the example above, the configuration processing
  routine will be run a total of four times.
  
  For example:
  
    sub MyParameter {
       my($self, $parms, $key, $val) = @_;
       push @{ $self->{MyParameter}{$key} }, $val;
    }
  
  
  =head3 C<Apache::RAW_ARGS>
  
  An I<args_how> of C<Apache::RAW_ARGS> instructs Apache to turn off
  parsing altogether.  Instead it simply passes your callback function
  the line of text following the directive.  Leading and trailing
  whitespace is stripped from the text, but it is not otherwise
  processed.  Your callback can then do whatever processing it wishes to
  perform.
  
  This callback receives three arguments (similar to C<Apache::TAKE1>),
  the third of which is a string-valued scalar containing the text
  following the directive.
  
    sub MyParameter {
       my($self, $parms, $val) = @_;
       # process $val
    }
  
  If this mode is used to implement a custom "container" directive, the
  attribute I<req_override> needs to OR C<Apache::EXEC_ON_READ>. e.g.:
  
    req_override => Apache::OR_ALL | Apache::EXEC_ON_READ,
  
  META: complete the details, which are new to 2.0.
  
  There is one other trick to making configuration containers work.  In
  order to be recogized as a valid directive, the I<name> attribute must
  contain the leading C<E<lt>>.  This token will be stripped by the code
  that handes the custom directive callbacks to Apache. For example:
  
    name     => '<MyContainer',
  
  One other trick that is not required, but can provide some more user
  friendliness is to provide a handler for the container end token.  In
  our example, the Apache configuration gears will never see the
  C<E<lt>/MyContainerE<gt>> token, as our C<Apache::RAW_ARGS> handler
  will read in that line and stop reading when it is seen.  However in
  order to catch cases in which the C<E<lt>/MyContainerE<gt>> text
  appears without a preceding C<E<lt>MyContainerE<gt>> opening section,
  we need to turn the end token into a directive that simply reports an
  error and exits. For example:
  
    {
      name         => '</MyContainer>',
      func         => __PACKAGE__ . "::MyContainer_END",
      errmsg       => 'end of MyContainer without beginning?',
      args_how     => Apache::NO_ARGS,
      req_override => Apache::OR_ALL,
    },
    ...
    my $EndToken = "</MyContainer>";
    sub MyContainer_END {
        die "$EndToken outside a <MyContainer> container\n";
    }
  
  Now, should the server admin misplace the container end token, the
  server will not start, complaining with this error message:
  
    Syntax error on line 54 of httpd.conf:
    </MyContainer> outside a <MyContainer> container
  
  =head3 C<Apache::FLAG>
  
  When C<Apache::FLAG> is used, Apache will only allow the argument to
  be one of two values, C<On> or C<Off>.  This string value will be
  converted into an integer, C<1> if the flag is C<On>, C<0> if it is
  C<Off>.  If the configuration argument is anything other than C<On> or
  C<Off>, Apache will complain:
  
    Syntax error on line 73 of httpd.conf:
    MyFlag must be On or Off
  
  For example:
  
    sub MyFlag {
        my($self, $parms, $arg) = @_;
        $self->{MyFlag} = $arg; # 1 or 0
    }
  
  
  
  
  =head2 Enabling the New Configuration Directives
  
  As seen in the first example, the module needs to be loaded before the
  new directives can be used. A special directive C<PerlLoadModule> is
  used for this purpose. For example:
  
    PerlLoadModule MyApache::MyParameters
  
  This directive is similar to C<PerlModule>, but it require()'s the
  Perl module immediately, causing an early mod_perl startup. After
  loading the module it let's Apache know of the new directives and
  installs the callbacks to be called when the corresponding directives
  are encountered.
  
  =head2 Creating and Merging Configuration Objects
  
  By default mod_perl creates a simple hash to store each container's
  configuration values, which are populated by directive callbacks,
  invoked when the I<httpd.conf> and the I<.htaccess> files are parsed
  and the corresponding directive are encountered. It's possible to
  prepopulate the hash entries when the data structure is created, e.g.,
  to provide reasonable default values for cases where they weren't set
  in the configuration file. To accomplish that the optional
  C<L<SERVER_CREATE|/C_SERVER_CREATE_>> and
  C<L<DIR_CREATE|/C_DIR_CREATE_>> functions can be supplied.
  
  When a request is mapped to a container, Apache checks if that
  container has any ancestor containers. If that's the case, it allows
  mod_perl to call special merging functions, which decide whether
  configurations in the parent containers should be inherited, appended
  or overriden in the child container. The custom configuration module
  can supply custom merging functions
  C<L<SERVER_MERGE|/C_SERVER_MERGE_>> and C<L<DIR_MERGE|/C_DIR_MERGE_>>,
  which can override the default behavior. If these functions are not
  supplied the following default behavior takes place: The child
  container inherits its parent configuration, unless it specifies its
  own and then it overrides its parent configuration.
  
  =head3 C<SERVER_CREATE>
  
  C<SERVER_CREATE> is called once for the main server, and once more for
  each virtual host defined in I<httpd.conf>. It's called with two
  arguments: C<$class>, the package name it was created in and C<$parms>
  the already familiar C<Apache::CmdParms> object. The object is
  expected to return a reference to a blessed hash, which will be used
  by configuration directive callbacks to set the values passed by the
  user in the configuration file. But it's possible to preset some
  values here:
  
  For example:
  
    package MyApache::MyParameters;
    ...
    our @APACHE_MODULE_COMMANDS = (...);
    ...
    sub SERVER_CREATE {
        my($class, $parms) = @_;
        #warn "$class->SERVER_CREATE\n";
        return bless {
          name => __PACKAGE__,
        }, $class;
    }
  
  To retrieve that value later, you can use:
  
    my $srv_cfg = $self->get_config($s);
    print $srv_cfg->{name}
  
  =head3 C<SERVER_MERGE>
  
  During the configuration parsing virtual hosts are given a chance to
  inherit the configuration from the main host, append to or override
  it. The C<SERVER_MERGE> subroutine can be supplied to override the
  default behavior, which simply overrides the main server's
  configuration.
  
  The custom subroutine accepts two arguments: C<$base>, the reference
  to the main server configuration object, and C<$add>, the reference to
  a virtual host configuration object. It's expected to return a similar
  object after performing the merge of the two objects it has received.
  
  The following example implements different merging rules for different
  keys. 
  
    package MyApache::MyParametersMath;
    ...
    our @APACHE_MODULE_COMMANDS = (...);
    ...
    sub SERVER_MERGE {
        my($base, $add) = @_;
        #warn "$class->SERVER_CREATE\n";
        my %mrg = %$base;
        for my $key (keys %$add) {
            if ($key eq 'Plus') {
                $mrg{$key} = $base->{$key}||0 + $add->{$key};
            }
            else ($key eq 'Minus') {
                $mrg{$key} = $base->{$key}||0 - $add->{$key};
            }
            else {
                $mrg{$key} = $add->{$key}; # override
            }
            $mrg{$_} = $_ eq 'Append' ? 
        }
        for (keys %$base, keys
        return 
        return bless {
          name => __PACKAGE__,
        }, $class;
    }
  
  =head3 C<DIR_CREATE>
  
  =head3 C<DIR_MERGE>
  
  
    NotifyError [On Off]
    NotifyErrorEmail email_address
  
  
  
  
  =head1 Maintainers
  
  Maintainer is the person(s) you should contact with updates,
  corrections and patches.
  
  =over
  
  =item *
  
  Stas Bekman E<lt>stas (at) stason.orgE<gt>
  
  =back
  
  =head1 Authors
  
  =over
  
  =item *
  
  Stas Bekman E<lt>stas (at) stason.orgE<gt>
  
  =back
  
  Only the major authors are listed above. For contributors see the
  Changes file.
  
  =cut
  
  
  
  
  
  1.17      +1 -0      modperl-docs/src/docs/2.0/user/config.cfg
  
  Index: config.cfg
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/config.cfg,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- config.cfg        5 Dec 2002 08:56:10 -0000       1.16
  +++ config.cfg        9 Dec 2002 16:47:07 -0000       1.17
  @@ -20,6 +20,7 @@
       chapters => [qw(
           install/install.pod
           config/config.pod
  +        config/custom.pod
       )],
   
       group    => 'Coding',
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to