eXtropia: the open web technology company
Technology | Support | Tutorials | Development | About Us | Users | Contact Us
Free support
 ::   Support forums
 ::   Frequently asked questions
 ::   Functional Specifications
 ::   eXtropia Tutorials
 ::   Books by eXtropia
 ::   Other books
 ::   Offsite resources
eXtropia ADT Documentation

Customizing eXtropia Applications


[ TOC ]
[ TOC ]

Overview

    NOTE: If you are not familiar with installing eXtropia applications You should consider reading the enclosed chapter on Installing eXtropia Applications.

The application executable, typically called app_name.cgi (eg. webdb.cgi), serves two purposes. It is both the executable file that is called from the browser and is the file that defines the configuration of the application.

As you can see if you read through any of the eXtropia application executables, there is really only a half dozen lines of real Perl code. Most of the file is actually composed of configuration parameters in the form of arrays and hashes.

In order to configure the application, you must edit the configuration parameters in this file.

[ TOC ]


Modifying the Application Executable

As we said earlier, all configuration parameters in eXtropia applications are defined in the application executable. Let’s look through the contents of a generic application executable to understand what configuration options are available.

[ TOC ]


Understanding the Application Executable Preamble

Each application executable begins with a standard preamble shown below.

 
    #!/usr/bin/perl -wT
    
    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);
    
    use lib qw(
        ./Modules
        ./Apps
        ./Views/Extropia/AppName
        ./Views/Extropia/AuthManager
        ./Views/Extropia/StandardTemplates
    );
    
    use Extropia::AppName;
    use Extropia::View;
    use Extropia::SessionManager;
    
    my $CGI = new CGI() or
         die("Unable to construct the CGI object in  app_name.cgi. " .
             "Please contact the webmaster.");
    
    my $VIEW_LOADER = new Extropia::View() or
        die("Unable to construct the VIEW LOADER object in " .
            "app_name.cgi. Please contact the webmaster.");
    
    foreach ($CGI->param()) {
        $CGI->param($1,$CGI->param($_)) if (/(.*)\.x/);
    }

    NOTE: Don’t forget that we expect you to move all files other than the application executable out of the web documents tree. As a result, you will need to modify the paths specified in the 'use lib' command to point to the directory which you have moved the other files to.

    Performing this step is not only cleaner in terms of how the web server is programmed, it is also more secure. Nothing should be accessible from web browser clients other than the CGI script itself.

The preamble performs six functions:

  1. Execute Perl using -Tw.

  2. Import supporting Perl modules.

  3. Define the library path for eXtropia modules.

  4. Import eXtropia modules.

  5. Instantiate helper objects.

  6. Standardize incoming HTML form submit button data.

Step 1: Execute perl

 
    #!/usr/bin/perl -wT

As with all CGI applications, the first thing that the application executable does is to specify the location of the Perl interpreter. In this case, we have specified that the web server should be able to find the Perl interpreter in the directory /usr/bin.

As we mentioned earlier, you may need to modify this line to point to the Perl interpreter on your local web server.

Also, notice that we use the -T and -w pragmas when calling the Perl interpreter. This assures that our application will be secure (-T turns on taint mode which treats all user-defined input as bad unless it is specifically dealt with by the developer) and that we will receive warnings (-w turns on warnings).

While -w is primarily useful for debugging. The -T is crucial if you want to assure that your application meets minimum security requirements. If you have questions about taint mode, you can consult the taint mode section of the Security chapter in this guide.

    NOTE: Don’t underestimate the benefits of warnings. Warnings are excellent tools that can help you track down the most pesky and elusive of bugs such as uninitialized variables that can be so subtle and random appearing in how they break your program that there is no other way to realistically find them.

Step 2: Import Supporting Perl Modules

 
    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

All eXtropia applications import the functionality of the strict.pm and CGI.pm modules (which should both be installed by default with most modern Perl distributions. If they are not installed on your server, just ask your systems administrator to install them or download them from CPAN: http://www.cpan.org/).

    NOTE: "use" is a command that tells the Perl interpreter to read and compile a module, then call the module's import() method, with any parameters that have been provided (eg. _rearrange() and _rearrangeAsHash()).

The strict Module

The strict module works like an anal retentive guardian angel. Essentially, it reviews your code for certain types of careless errors. If you have declared and used all your variables correctly, strict will disappear into the background.

But if you use a variable without first declaring it, strict will warn you that you are probably making a typo. We use strict in our applications because though it can be a pain in the neck to declare everything, it often makes for more maintainable code in which bugs are more easily found.

The CGI Module

CGI.pm is a module that we use to parse incoming data from the web browser. Of course, the module itself does many more useful things as documented in the wonderful book The Official Guide to Programming with CGI.pm by Lincoln Stein. However, though it does lots of other things, for our purposes, parsing the form data and providing access to it with a simple API is all we need.

As you will see later, we can access the value of any incoming form field using the param() method in CGI.pm. Thus, if you had an HTML form such as the following:

 
    <FORM>
        <INPUT TYPE = "TEXT" NAME = "fname">
        <INPUT TYPE = "SUBMIT">
    </FORM>

We could access whatever the user typed in the fname <INPUT> text field by using:

 
    $first_name = $cgi->param('fname');

Quite simple. And the fact that we don't need to worry about all the intricacies of parsing HTTP streams is wonderful.

Note that we also import the Carp module of CGI.pm so that if errors occur in the execution of our application, the text of the error messages will be displayed in the browser window. Without using this pragma, when errors occur, we'd get the dreaded and utterly useless ``500 Server Error'' message rather than the detailed error messages provided by Perl.

Step 3: Define the Library Path for Extropia Modules

 
    use lib qw(
        ./Modules 
        ./Apps
        ./Views/Extropia/AppName
        ./Views/Extropia/AuthManager
        ./Views/Extropia/StandardTemplates
    );

All eXtropia applications must also define a library search path for eXtropia Modules. This is done using the ``lib'' module that adds a set of Module directories to the @INC array so that we can use modules in those directories.

Step 4: Import eXtropia Modules

 
    use Extropia::AppName;
    use Extropia::View;
    use Extropia::SessionManager;

Every eXtropia application must also load eXtropia-specific modules that it will need.

Typically, we first import the functionality of the application object that is located in app_name/Apps/ by default.

For example, if you were installing WebGuestbook, you would use:

 
    use Extropia::WebGuestbook;

Next we import View.pm. And for those applications that require session management, we import SessionManager.pm (both modules can be found in the app_name/Modules/Extropia directory).

The application object does most of the work for any given application. If you want to learn more about how it works, consult the chapter specific to the application.

Extropia::View defines how to load the user interface modules (views are located by default in appname/Views/Extropia) and display them to the web browser. Consult the look-and-feel chapter in this guide if you have questions about how views work.

Extropia::SessionManager helps us manage sessions and is included only in applications that require session management. Consult the Session and Session Management documentation (see the Further References appendix) if you have require more information on how to customize these.

Step 5: Instantiate Helper Objects

 
    my $CGI = new CGI() or
        die("Unable to construct the CGI object in appname.cgi. " .
            "Please contact the webmaster.");
    
    my $VIEW_LOADER = new Extropia::View() or
        die("Unable to construct the VIEW LOADER object in " .
            "appname.cgi. Please contact the webmaster.");

All eXtropia applications require the support of helper objects. $CGI is the instantiated CGI object. $VIEW_LOADER is a basic View object. Notice that we will exit gracefully using die() if there is a problem creating either of these objects.

Step 6: Standardize Incoming Form Data

 
    foreach ($CGI->param()) {
        $CGI->param($1,$CGI->param($_)) if (/(.*)\.x/);
    }

Finally, a simple foreach loop is used to standardize all incoming submit button values. In particular, we would like to be able to treat submit buttons of type IMAGE just as we would standard submit buttons.

When an IMAGE submit button is clicked, the browser does not simply send a button name=value pair in the HTTP stream as it would do for a standard button. Instead, the browser sends a set of coordinates corresponding to the position on the image that the user clicked such as:

 
    button_name.x=value&button_name.y=value

In the case of eXtropia applications however, we are primarily interested in the fact that a button was clicked rather than the actual position on an image map.

Thus, we use the foreach loop to strip out the .x and .y portions of the button name so that IMAGE submit events look exactly like any other standard button input. This gives us the flexibility to change the user interface without changing the application code.

[ TOC ]


How to Modify and Test Configuration Options

How will your particular installation of the application work? How will it authenticate users, send email, or log its usage? Configuration for all eXtropia applications is done by modifying arrays and hashes of NAME => VALUE pairs that can be found in the application executable (eg. webguestbook.cgi).

For example, consider the following two alternatives for @MAIL_CONFIG_PARAMS.

In the first case, we'll configure @MAIL_CONFIG_PARAMS to use the Mail::MailSender driver:

 
    my @MAIL_CONFIG_PARAMS = (
            -TYPE => 'MailSender'
        );

NOTE: Notice that the NAME in this example is -TYPE and the VALUE is 'MailSender'

Alternatively, you could configure @MAIL_CONFIG_PARAMS to use the Mail::Sendmail driver:

 
        my @MAIL_CONFIG_PARAMS = (
            -TYPE              => 'Sendmail',
            -MAIL_PROGRAM_PATH => '/usr/lib/sendmail'
        );

Notice that unlike MailSender, the Sendmail driver takes an optional -PATH name/value parameter. Different drivers usually require different configuration parameters.

As a result, if you want to use a driver other than the default one, you will need to consult the documentation for each driver to get the details. For example, to read about all the configuration parameters required for Mail drivers, you could consult the documentation for Extropia::Mail and all Extropia::Mail drivers such as Extropia::Mail::Blat.

Regardless, the main point that you should take away from this section is that configuration of an application is a matter of defining the name/value pairs for whatever driver you wish to use.

Read the documentation on Mail for more detail (refer to the Further References section for this section).

[ TOC ]


Spotting Configuration Errors

As you modify these name/value pairs, there are several rules you should keep in mind. We have summarized a list of these rules and the consequences of breaking those rules:

[ TOC ]


Declaring Configuration Variables

RULE: Declare your variables using 'my'.

INCORRECT:

 
    @MY_CONFIG_ARRAY = (
        -NAME => 'value'
    );

CORRECT:

 
    my @MY_CONFIG_ARRAY = (
        -NAME => 'value'
    );

COMMAND LINE ERROR MESSAGE:

 
    Global symbol "@CONFIG_PARAM_NAME" requires explicit 
    package name at appname.cgi line [#].

WEB BROWSER ERROR MESSAGE:

 
    500 Server Error or Software Error

[ TOC ]


Name/Value Pairs

RULE: All NAME/VALUE pairs must be separated by a comma and the final pair should not have a comma after it.

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender'
        -SMTP_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
       -TYPE         => 'MailSender',
       -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    Argument "[PARAM FOLLOWING MISSING COMMA]" isn't numeric in 
    subtract at appname.cgi line [#].

WEB BROWSER ERROR MESSAGE:

 
    Required Parameter: -XXX was missing from a method call! 
    Required Parameter: -YYY was missing from a method call! 
    Required Parameter: -ZZZ was missing from a method call!"

or depending on the parameter:

 
    Required Parameter: -PARAM was missing from a method call! 
    Possible Parameters Are: -PARAM.

or alternatively:

 
    _getDriver() failed: [Sat Jan 15 13:56:42 2000] appname.cgi: 
    [Sat Jan 15 13:56:42 2000] appname.cgi: Can't locate 
    Extropia/ModuleName/0.pm in @INC

[ TOC ]


Configuration Name Formatting

RULE: All NAMEs should be preceded by a ``-'', be composed of ALL CAPITAL LETTERS, and be spelled correctly.

INCORRRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        TYPE         => 'MailSender', 
        -SMTP_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender', 
        -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    Possibly None unless the loading of the driver is triggered
    in application code.

or

 
    _getDriver() failed: [Sat Jan 15 14:03:57 2000] 
    appname.cgi: [Sat Jan 15 14:03:57 2000] appname.cgi: Can't 
    locate Extropia/Module/BadName.pm in @INC

WEB BROWSER ERROR MESSAGE:

 
    Possibly None unless the loading of the driver is triggered
    in the application code.

or

 
    _getDriver() failed: [Sat Jan 15 14:03:57 2000] 
    appname.cgi: [Sat Jan 15 14:03:57 2000] appname.cgi: Can't 
    locate Extropia/Module/BadName.pm in @INC

[ TOC ]


Name/Value Pair Separation Rule

RULE: All NAMEs should be separated from the VALUE with a =>. There may not be a space between = and >.

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         = > 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender', 
        -SMTP_ADDRESS => '10.10.1.10'
    );  

COMMAND LINE ERROR MESSAGE:

 
    syntax error at mlm.cgi line 312, near "= >"

or

 
    "Can't modify constant item in scalar assignment at 
    mlm.cgi line 204..."

WEB BROWSER ERROR MESSAGE:

 
    500 Server Error or Software Error

[ TOC ]


Another Name/Value Pair Separation Rule

RULE: All NAMEs should be separated from the VALUE with a =>. Don’t forget the >.

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         = 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    Can't modify constant item in scalar assignment at 
    appname.cgi line [#], near ""paramName","

WEB BROWSER ERROR MESSAGE:

 
    500 Server Error or Software Error

[ TOC ]


Enclose Values in Quotes

RULE: All values should be enclosed in single or double quotes. You can use single quotes ('') if there are no variables to interpret (such as $some_variable) in the value.

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => MailSender,
        -SMTP_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    Bareword "MailSender" not allowed while "strict subs" in 
    use at mlm.cgi line 312.

or in the case of a perl special character like '@'

 
    In string, @domainanname now must be written as \@domainname 
    at appname.cgi line [#], near "name@domainname" [Sat Jan 15 
    14:13:04 2000] appname.cgi: Global symbol "@domainname" requires 
    explicit package name at appname.cgi line [#].

WEB BROWSER ERROR MESSAGE:

 
    500 Server Error or Software Error

[ TOC ]


Named Parameter Naming Convention

RULE: All named parameter must be capital letters

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTp_ADDRESS => '10.10.1.10'
    );

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    Required Parameter: -XXX was missing from a method call!

WEB BROWSER ERROR MESSAGE:

 
    Required Parameter: -XXX was missing from a method call!

[ TOC ]


Delimit Config Setting with Parentheses and Semi-Colons

RULE: Don't forget the semi-colon at the end of the definition and the embracing parentheses () around the array definition.

INCORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    )

CORRECT:

 
    my @MAIL_CONFIG_PARAMS = (
        -TYPE         => 'MailSender',
        -SMTP_ADDRESS => '10.10.1.10'
    );

COMMAND LINE ERROR MESSAGE:

 
    "syntax error at mlm.cgi line XYZ, near "my " mlm.cgi: 
    Global symbol "@SOME_CONFIG_VAR_NAME" requires explicit 
    package name at mlm.cgi line XYZ.

WEB BROWSER ERROR MESSAGE:

 
    500 Server Error or Software Error

[ TOC ]


How To Modify List-Based Configuration Parameters

Note that many configuration parameters accept ``lists'' as the value part of a name/value pair. For example, the parameter -IS_FILLED_IN shown below specifies two required fields: fname and lname.

 
    my @ADD_FORM_DH_MANAGER_CONFIG_PARAMS = (
        -TYPE         => 'CGI',
        -CGI_OBJECT   => $CGI,
        -DATA_TYPES   => [qw(
                Exists
                HTML
            )],
        -TRANSFORM_REMOVE_HTML => [(qw
                fname
                lname  
            )], 
        -IS_FILLED_IN => [qw(
                fname
                lname
            )]
    );

It is worth mentioning that these lists are typically anonymous arrays that use the qw command to specify quoted whitespace. qw is a handy tool that makes configuration of lists far more resistant to careless errors.

Essentially, qw means that you do not have to use commas and quotes when defining lists. Any whitespace is assumed to delimit list elements.

For example, an array defined as:

 
        my @array = ('first', 'second', 'third');

could also be defined using qw as:

 
        my @array = qw(first second third);

In other words, without qw, the same definition would look like:

 
    my @ADD_FORM_DH_MANAGER_DEFINE = (
        -TYPE                  => 'CGI',
        -CGI_OBJECT            => $CGI,
        -DATA_TYPES            => [
                'Exists',
                'HTML'
            ],
        -TRANSFORM_REMOVE_HTML => [
                'fname'
                'lname' 
            ], 
        -IS_FILLED_IN          => [
                'fname',
                'lname'
            ]
        );

As you might imagine, in long lists it is easy to make a mistake typing all those commas and quote marks. Can you find the error in the code above (hint: look at the definition for -TRANSFORM_REMOVE_HTML)?

[ TOC ]


Understanding Reference-Based Config Parameters

In complex configuration scenarios in which a configuration might involve lists of parameters that themselves contain lists of parameters, it is best to simplify configuration by defining each list as a reference to a list that is defined elsewhere.

[ TOC ]


References In eXtropia Config Files

For example, consider the following session manager definition that uses a reference to a session configuration.

 
        my @SESSION_CONFIG_PARAMS = (
            -TYPE            => 'File',
            -MAX_ACCESS_TIME => 60 * 20,
            -SESSION_DIR     => './Datafiles/Sessions'
        );
    
        my @SESSION_MANAGER_CONFIG_PARAMS = (
            -TYPE           => 'FormVar',
            -CGI_OBJECT     => $CGI,
            -SESSION_PARAMS => \@SESSION_CONFIG_PARAMS

Breaking out complex definitions into their own parameters makes the configuration easier to follow. If you have any questions about what references are and how to use them, you should consult the References and Data Structures documentation (see the Further References Section). Otherwise, the list below should give you the basic idea.

[ TOC ]


Reference Syntax Reference

The following list gives a quick overview of the syntax behind using references for the various variable types that may be used in a configuration file.

  • scalar

     
        Creating a Reference        Dereferencing                   Accessing Data
        
        $ref = \$scalar_variable    $$ref                           Not available

  • array

     
        Creating a Reference        Dereferencing                   Accessing Data
        
        $ref = \@array              $ref = ['anonymous', 'array'];  @$ref
                                                                    $ref->[x]

  • hash

     
        Creating a Reference        Dereferencing                   Accessing Data
        
        $ref  = \%hash              $ref = {'key1' => 'anon',       %$ref
                                            'key2' => 'hash'};      $ref->{x}

  • subroutine

     
        Creating a Reference        Dereferencing                   Accessing Data
        
        $ref = \&subroutine         $ref = sub ('anon subroutine'); &$ref
                                                                    $ref->(x)>

[ TOC ]


Standard Config Options for eXtropia Applications

Because we wanted the eXtropia applications to be as understandable and as cross-platform as possible, we have taken care to distribute the applications with configurations that are fairly standard between all the applications and that are tuned to the least common denominator.

Our thought was that users could upgrade to bigger and better drivers as needs demanded but that by keeping the default configuration simple and broad, it would be easy for most users, with less demanding requirements, to install the applications and have them work right out of the box.

For example, we use file-based data sources and sessions, CGI-based authentication, and file-based locking because every web server will be able to handle these drivers. However, it is our expectation that many users will upgrade to more powerful drivers such as DataSource::DBI and Lock::Flock.

There are ten major components to applications that are configured in the application executable (eg webguestbook.cgi). These are

  1. Session

  2. Session Management

  3. Authentication

  4. Authentication Manager

  5. DataHandler

  6. DataSource

  7. Logging

  8. Mailing

  9. Encryption

  10. View

Of course, not every eXtropia application will use all of the components. Let’s take a look at each type of configuration individually.

[ TOC ]


Session and Session Manager Configuration

In order to maintain state in a CGI application, it is necessary to store information after each form submission. That is, since HTTP does not keep a record of communication, the application must.

For example, a web store usually maintains a list of products that a client has ordered in a virtual shopping cart. It would not do if the application kept forgetting what the client had already ordered every time the client added a new item to their cart!

That is where session and session managers come in. A session manager provides the glue necessary to create and manage a unique session in an otherwise stateless environment. The following figure shows how session setup integrates with the rest of eXtropia application setup.

To maintain state, eXtropia applications use Extropia::SessionManager which in turn uses Extropia::Session. Session configuration is achieved by defining two variables: @SESSION_CONFIG_PARAMS and @SESSION_MANAGER_PARAMS. A sample set of parameters that are used to define these values is shown below.

  1. @SESSION_CONFIG_PARAMS

    Specifies the configuration parameters used for the Extropia::Session object that will implement your session.

    • -TYPE

      Specifies the driver type. By default, eXtropia applications use Session::File.

    • -MAX_ACCESS_TIME

      Specifies how long sessions should remain active. By default, eXtropia applications maintain sessions for 20 minutes (60 seconds * 20).

    • -SESSION_DIR

      Specifies the location of the directory in which session files are stored. By default, eXtropia applications use the ./Datafiles/Sessions directory but you are advised to move this directory outside of the web documents tree.

  2. @SESSION_MANAGER_PARAMS

    Specifies the configuration parameters used for the Extropia::SessionManager object that performs session management.

    • -TYPE

      Specifies the type of session manager to use. By default, eXtropia applications use SessionManager::FormVar.

    • -CGI_OBJECT

      Contains a reference to a CGI object.

    • -SESSION_PARAMS

      Contains a reference to @SESSION_CONFIG_PARAMS.

    NOTE: FormVar session managers pull their session id parameter from an incoming form value keyed to the name session by default.

    Thus, it is crucial that every form that is managed by a FormVar SessionManager has the session id embedded such as in the following HIDDEN form tag:

     
        <INPUT TYPE = "HIDDEN" NAME = "session" VALUE = "XJDKFUREHJDKD">

    You will see that for all the Views that require session management a hidden tag such as the above is used.

    All URLs must also be encoded with the session id such as in the following example:

    http://www.mydomain.com/cgi-bin/my_app.cgi?session=XJDKFUREHJDKD

    Session id values can be extracted from any session object using the getId() method such as:

     
        $session_id = $session->getId();

    To help you get a better feel for what session configuration looks like, below is a standard configuration:

     
        my @SESSION_CONFIG_PARAMS = (
            -TYPE            => 'File',
            -MAX_ACCESS_TIME => 60 * 20,
            -SESSION_DIR     => './Datafiles/Sessions'
        );
        
        my @SESSION_MANAGER_CONFIG_PARAMS = (
                -TYPE           => 'FormVar',
                -CGI_OBJECT     => $CGI,
                -SESSION_PARAMS => \@SESSION_CONFIG_PARAMS
        );

    Authentication Configuration

    In eXtropia applications, session configuration often goes hand in hand with authentication configuration because the primary usage for session objects in eXtropia applications is to maintain state during an authenticated session.

    Authentication configuration is achieved by defining six variables:

    Each of these variables should be configured according to the specifics of the drivers you wish to use. However, to achieve cross-platform compatibility, eXtropia applications use file-based authentication.

    1. @AUTH_USER_DATASOURCE_FIELD_NAMES

      Specifies the list of all of the fields in the user data source.

    2. @AUTH_USER_DATASOURCE_CONFIG_PARAMS

      Specifies the configuration for the datasource driver used for user details.

      • -TYPE

        Specifies the name of the data source driver to use for the user details file. By default, eXtropia applications use DataSource::File.

      • -FIELD_DELIMITER

        Specifies the character used to delimit fields in the user details data source. By default, eXtropia applications use the pipe character (``|'').

        -FIELD_NAMES

        Specifies an ordered list of field names representing the fields in the data source. By default, contains a reference to @AUTH_USER_DATASOURCE_FIELD_NAMES.

      • -FILE

        Specifies the location of the file used as the user details data source. By default, eXtropia applications use ./Datafiles/users.dat. However, remember to move the Datafiles directory outside the web document tree.

    3. @AUTH_ENCRYPT_CONFIG_PARAMS

      Defines the configuration for the encryption driver used to encrypt the passwords in a registered user’s data source.

      • -TYPE

        Specifies the encryption driver used for encrypting passwords. By default, eXtropia applications use the Crypt driver. This driver may not be available on your system, especially on older Windows installations. so you may have to change this.

    4. %USER_FIELDS_TO_DATASOURCE_MAPPING

      Specifies the mappings used between the registration form generated by the AuthManager and the actual datasource that stores user information.

    5. @AUTH_CACHE_CONFIG_PARAMS

      Specifies the means by which the authentication object is cached.

      • -TYPE

        Specifies the type of caching to use. By default, eXtropia applications use Extropia::Session-based caching.

      • -SESSION_OBJECT

        Contains a reference to a session object.

    6. @AUTH_CONFIG_PARAMS

      Contains references to the five configuration variables defined above.

      • -TYPE

        Specifies the type of auth param to use.

        -USER_DATASOURCE_PARAMS

        Specifies the Datasource configuration parameters to use for the session. Contains a reference to @AUTH_USER_DATASOURCE_CONFIG_PARAMS

      • -ENCRYPT_PARAMS

        Specifies the Encryption configuration parameters to use for the session. Contains a reference to @AUTH_ENCRYPT_CONFIG_PARAMS

      • -AUTH_CACHE_PARAMS

        Specifies the Cache configuration parameters to use for the session. Contains a reference to @AUTH_CACHE_CONFIG_PARAMS

      • -ADD_REGISTRATION_TO_USER_DATASOURCE

        Specifies whether or not to allow user registration. A 1 specifies that the application should allow registration. 0 specifies that only registered users may log in.

      • -USER_FIELDS_TO_DATASOURCE_MAPPING

        References an ordered list specifying the fields in the data source. Contains a reference to %USER_FIELDS_TO_DATASOURCE_MAPPING.

      NOTE: If you want to add or subtract fields from the user file (eg. Datafiles/users.dat), you can focus on the following parameters that together must be consistent:

     
            %USER_FIELDS_TO_DATASOURCE_MAPPING
            @AUTH_USER_DATASOURCE_FIELD_NAMES
            @USER_FIELDS
            %USER_FIELD_NAME_MAPPINGS
            @AUTH_REGISTRATION_DATAHANDLER_PARAMS.

      You must also modify the package Extropia::Auth::RegistrationScreen in the view defined in Apps/Views/AuthManager/CgiViews.pm.

    To help you get a better feel for what authentication configuration looks like, the following shows a standard configuration.

     
            my @AUTH_USER_DATASOURCE_FIELD_NAMES = qw(
                username
                password
                groups
                firstname
                lastname
                email
            );
        
            my @AUTH_USER_DATASOURCE_CONFIG_PARAMS = (
                -TYPE                 => 'File',
                -FIELD_DELIMITER     => '|',
                -FIELD_NAMES         => \@AUTH_USER_DATASOURCE_FIELD_NAMES,
                -FILE                => './Datafiles/users.dat'
            );
        
            my @AUTH_ENCRYPT_CONFIG_PARAMS = (
                -TYPE => 'Crypt'
            );
        
            my %USER_FIELDS_TO_DATASOURCE_MAPPING = (
            'auth_username'     => 'username',
            'auth_username'     => 'username',
            'auth_password'     => 'password',
            'auth_firstname'    => 'firstname',
            'auth_lastname'     => 'lastname',
            'auth_groups'       => 'groups',
            'auth_email'        => 'email'
            );      
        
            my @AUTH_CACHE_CONFIG_PARAMS = (
                -TYPE           => 'Session',
                -SESSION_OBJECT => $SESSION
            );
        
            my @AUTH_CONFIG_PARAMS = (
                -TYPE                                => 'DataSource',
                -USER_DATASOURCE_PARAMS              => \@AUTH_USER_DATASOURCE_CONFIG_PARAMS,
                -ENCRYPT_PARAMS                      => \@AUTH_ENCRYPT_CONFIG_PARAMS,
                -AUTH_CACHE_PARAMS                   => \@AUTH_CACHE_CONFIG_PARAMS,
                -ADD_REGISTRATION_TO_USER_DATASOURCE => 1,
                -USER_FIELDS_TO_DATASOURCE_MAPPING   => \%USER_FIELDS_TO_DATASOURCE_MAPPING
            );

    Authentication Manager Configuration

    The authentication object that we previously configured is useful for providing raw access to whether a user is who they say they are and whether they have access to a particular resource.

    However, authentication is not just about a raw username/password mechanism. Authentication usually involves some sort of workflow.

    For example, in a CGI-based workflow, a CGI form to allow the user to enter their name and password is presented while a RemoteUser-based workflow would rely on the web server passing the previously validated username to the script using the REMOTE_USER environment variable.

    Workflows around authenticating users can also be more complex. For example, you might allow users to register themselves if they have not previously logged in to the web application.

    Authentication managers enter the picture in order to provide the workflow around a core authentication mechanism.

    There are five variables involved with configuring an authentication manager.

    Each of these variables should be configured according to the specifics of the drivers you wish to use. However, to achieve cross-platform compatibility, eXtropia applications use CGI-based authentication managers. The following section explains a sample default configuration that is shown at the end of this section while the figure immediately below illustrates visually how auth manager fits into the application setup.

    1. @AUTH_REGISTRATION_DH_MANAGER_CONFIG_PARAMS

      Specifies the configuration for the data handler that will handle the registration forms.

      • -DATAHANDLERS

        Specifies which data handler drivers must be loaded in order to perform all handling. By default, eXtropia authentication forms require DataHandler::Email and DataHandler::Exists.

      • -FIELD_MAPPINGS

        Defines a mapping of fields in the registration form and their 'display' names.

      • -IS_FILLED_IN

        Specifies a list of fields that must be filled-in in order for the form to be submitted. By default, eXtropia registration screens require that all fields are filled in.

      • -IS_EMAIL

        Specifies a list of fields that must be valid email addresses. By default, eXtropia registration screens only have one email field.

    2. @USER_FIELDS

      Specifies the list of fields in the datasource that represent user details.

    3. %USER_FIELD_NAME_MAPPINGS

      Specifies a mapping between variable names and display names.

    4. %USER_FIELD_TYPES

      Specifies three field types that the AuthManager needs to know about: the field that should be considered a username, the field that should be considered a password, and the field that contains group information.

    5. @AUTH_MANAGER_PARAMS

      Specifies the parameters for an authentication manager.

      • -TYPE

        Specifies the type of AuthManager to use. By default eXtropia applications use SessionManager::CGI.

      • -SESSION_OBJECT

        Contains a reference to a Session object.

      • -AUTH_VIEWS

        Contains a pointer to a View module containing authentication views. By default, eXtropia applications use a View file located in appname/Views/ExtropiaAuthManager/CGIView.pm.

      • -VIEW_LOADER

        Contains a reference to a view loader.

      • -AUTH_PARAMS

        Contains a reference to @AUTH_PARAMS.

      • -CGI_OBJECT

        Contains a reference to a CGI object.

      • -SESSION_FORM_VAR

        Specifies a string that will be used to specify the incoming form variable used to pass the session id. By default, eXtropia applications use 'session'.

      • -ALLOW_REGISTRATION

        Specifies whether the application will allow users to register themselves. If set to 0, users will not be able to register new usernames and passwords. By default, eXtropia applications allow registration.

      • -ALLOW_USER_SEARCH

        Specifies whether users should be able to search for their account information. By default, eXtropia applications allow searches.

      • -USER_SEARCH_FIELD

        Specifies the field used to search for when users search for their account information. By default, eXtropia application uses the email field.

      • -GENERATE_PASSWORD

        Specifies whether the application should generate passwords on behalf of users. If you set it to 0, users can choose their own passwords. By default, eXtropia applications allow users to choose their own passwords.

      • -DEFAULT_GROUPS

        Specifies the string used for the group field by default. By default, eXtropia applications use the word 'normal'.

      • -ADMIN_EMAIL_FROM

        Specifies the email address of the administrator. It is used to send mail 'from'.

      • -ADMIN_EMAIL_ADDRESS

        Specifies the email address of the administrator. It is used to send mail 'to'.

      • -USER_FIELDS

        Contains a reference to @USER_FIELDS.

      • -USER_FIELD_TYPES

        Contains a reference to %USER_FIELD_TYPES.

      • -EMAIL_REGISTRATION_TO_ADMIN

        Specifies whether the administrator should be emailed on new registrations. If set to 1, administrators will be emailed upon new registrations. By default, eXtropia applications are set to not send email.

      • -DISPLAY_REGISTRATION_AGAIN_AFTER_FAILURE

        Specifies whether a user should be able to try to register again after registration failure. If set to 1, users will be able to try again. By default, eXtropia applications allow retries.

      • -USER_FIELD_NAME_MAPPINGS

        Contains a reference to %USER_FIELD_NAME_MAPPINGS.

      • -AUTH_REGISTRATION_DATAHANDLER_PARAMS

        Contains a reference to @AUTH_REGISTRATION_DATAHANDLER_MANAGER_PARAMS.

    To help you get a better feel for what authentication manager configuration looks like, the following shows a standard configuration.

     
        my @AUTH_REGISTRATION_DH_MANAGER_CONFIG_PARAMS = (
            -TYPE         => 'CGI',
            -CGI_OBJECT   => $CGI,
            -DATAHANDLERS => [qw(
                Email
                Exists
            )],
            -FIELD_MAPPINGS => {
                'auth_username'     => 'Username',
                'auth_password'     => 'Password',
                'auth_password2'    => 'Confirm Password',
                'auth_firstname'    => 'First Name',
                'auth_lastname'     => 'Last Name',
                'auth_email'        => 'E-Mail Address'
            },
            -IS_FILLED_IN => [qw(
                auth_username
                auth_firstname
                auth_lastname
                auth_email
            )],
            -IS_EMAIL => [qw(
                auth_email
            )]
        );
       
        my @USER_FIELDS = (qw(
            auth_username
            auth_password
            auth_groups
            auth_firstname
            auth_lastname
            auth_email
        ));
                       
        my %USER_FIELD_NAME_MAPPINGS = (
            'auth_username'  => 'Username',
            'auth_password'  => 'Password',
            'auth_group'     => 'Groups',
            'auth_firstname' => 'First Name',
            'auth_lastname'  => 'Last Name',
            'auth_email'     => 'E-Mail'
        );
                       
        my %USER_FIELD_TYPES = (
            -USERNAME_FIELD => 'auth_username',
            -PASSWORD_FIELD => 'auth_password',
            -GROUP_FIELD    => 'auth_groups'
        );
                
        my @AUTH_MANAGER_CONFIG_PARAMS = (
            -TYPE                => 'CGI',
            -SESSION_OBJECT      => $SESSION,
            -AUTH_VIEWS          => './Views/ExtropiaAuthManager/CGIViews.pm',
            -VIEW_LOADER         => $VIEW_LOADER,
            -AUTH_PARAMS         => \@AUTH_PARAMS,
            -CGI_OBJECT          => $CGI,
            -ALLOW_REGISTRATION  => 1,
            -ALLOW_USER_SEARCH   => 1,
            -USER_SEARCH_FIELD   => 'auth_email',
            -GENERATE_PASSWORD   => 0,
            -DEFAULT_GROUPS      => 'normal',
            -ADMIN_EMAIL_FROM    => 'you@yourdomain.com',
            -ADMIN_EMAIL_ADDRESS => 'you@yourdomain.com',
            -USER_FIELDS         => \@USER_FIELDS,
            -USER_FIELD_TYPES    => \%USER_FIELD_TYPES,
            -EMAIL_REGISTRATION_TO_ADMIN                  => 0,
            -DISPLAY_REGISTRATION_AGAIN_AFTER_FAILURE     => 1,
            -USER_FIELD_NAME_MAPPINGS                     => \%USER_FIELD_NAME_MAPPINGS,
            -AUTH_REGISTRATION_DH_MANAGER_CONFIG_PARAMS => 
            \@AUTH_REGISTRATION_DH_MANAGER_CONFIG_PARAMS
        );

    Datahandler Manager Configuration

    Data handlers perform all sorts of data manipulation such as untainting, validation and transformations. Data handler managers conveniently manage whole sets of data handlers in one place.

    Typically, eXtropia applications will contain one data handler manager configuration for each form generated by the application work flow. Thus if an application had an 'Add' form and a 'Send Mail' form, you would expect there to be two configurations. The following figure illustrates how data handler manager setup integrates with the rest of an eXtropia application setup.

    Data handler manager configurations require only one variable per manager that takes the form of:

     
            @[FORM_NAME]_FORM_DH_MANAGER_CONFIG_PARAMS

    Thus, in our two-form application, we might have two variables called:

     
            @ADD_FORM_DH_MANAGER_CONFIG_PARAMS
            @SEND_FORM_DH_MANAGER_CONFIG_PARAMS

    Each of these variables should be configured according to the specifics of the drivers you wish to use. However, because they are CGI applications, eXtropia applications use CGI-based data handler managers.

    1. @XXXX_FORM_DH_MANAGER_CONFIG_PARAMS

      Contains parameters for a data handler manager for a particular form in the application (Form XXX).

      • -TYPE

        Specifies the type of data handler manager to use

      • -CGI_OBJECT

        Contains a reference to a CGI object.

      • -DATAHANDLERS

        Specifies which DataHandler drivers must be loaded in order to perform all handling. By default, eXtropia applications require DataHandler::Exists, DataHandler::Email, and DataHandler::HTML.

      • -ESCAPE_HTML_TAGS

        Contains a list of fields that should not be able to contain HTML. All HTML is escaped, replacing < with < and > with >.

      • -IS_EMAIL

        Contains a list of fields that must conform to valid email address formatting.

      • -IS_FILLED_IN

        Contains a list of fields that must be filled-in in order for the form to be submitted.

    To help you get a better feel for what data handler configuration looks like, the following shows a standard configuration.

     
        my @COMMENT_FORM_DH_MANAGER_CONFIG_PARAMS = (
            -TYPE         => 'CGI',
            -CGI_OBJECT   => $CGI,
            -DATAHANDLERS => [qw(
                    Email
                    Exists
                    HTML
            )],
            -ESCAPE_HTML_TAGS => [qw(
                    fname
                    lname
                    email
                    comments
            )],
            -IS_EMAIL => [qw(
                    email
            )],
            -IS_FILLED_IN => [qw(   
                    fname  
                    lname
                    email 
                    comments
            )]
         );

    DataSource Configuration

    Because they require some form of data storage and retrieval, a data source of one form or another will be required by most eXtropia applications.

      SECURITY ALERT: Move those administrative files now! As we said previously in the chapter on installation, it is crucial that you move all administrative and data files outside of the web documents tree. For example, suppose you have a directory structure like the following:

     
            c:/program files
                apache group
                    apache
                        bin
                        cgi-bin
                            webresponder
                                Datafiles
                                    webresponder.data
                        htdocs

      In this case, we would recommend moving the Datafiles directory out of the cgi-bin area and placing it an area unavailable to web browsers such as in the following example:

     
            c:/program files
                apache group
                    apache
                        bin
                        cgi-bin
                            webresponder
                        datafiles
                            webresponder
                                datafiles
                                    webresponder.data
                            htdocs

      If you do this, you would also need to change @DATA_SOURCE_CONFIG_PARAMS to read:

     
            my @DATASOURCE_CONFIG_PARAMS = (
              -TYPE            => "File",
              -FILE            => 
                            "../datafiles/webresponder/datafiles/webguestbook.data",
              -FIELD_DELIMITER => "|",
              -LOCK_TYPE       => "File",
              -FIELD_NAMES     => \@DATASOURCE_FIELD_NAMES,
              -FIELD_TYPES     => {
                  item_id => 'auto',
                  },
            );

    There are two variables involved with configuring a data source:

    Each of these variables should be configured according to the specifics of the drivers you wish to use. However, to achieve cross-platform compatibility, eXtropia applications use file-based data sources.

    NOTE: In many cases, you will want to use the data files generated by eXtropia applications in other applications. In particular, many users prefer to read large data files in Microsoft Excel.

    Loading eXtropia data files into Excel is simple. Fortunately, Excel provides a useful importing feature in its 'Open' function that allows you to specify not only that you wish to import a delimited file, but what character should be considered the delimiter.

    By default, eXtropia applications use the '|' character as the default delimiter.

    The following figure outlines how the datasource setup integrates with the rest of the configuration of an eXtropia application.

    The following is a sample list of variables used to set up a datasource along with an example of the parameters used to set them up. The two variables listed below, @DATASOURCE_FIELD_NAMES and @DATASOURCE_CONFIG_PARAMS are directly data source related and we go over those immediately below.

    However, when eXtropia applications use views that are datasource-aware, they contain code which understand two additional configuration variables so that the views will understand how to build the datasource related forms and tables. These two variables are %INPUT_WIDGET_DEFINITIONS and @INPUT_WIDGET_DISPLAY_ORDER.

    1. @DATASOURCE_FIELD_NAMES

      Specifies an ordered list of fields representing the fields in the datasource. Reference to a list Contains an ordered list of fields in the datasource.

    2. @DATASOURCE_CONFIG_PARAMS

      Specifies the configuration of the data source.

      • -TYPE

        Specifies the driver type. By default eXtropia applications use DataSource::File.

      • -FILE

        Specifies the file that contains the data.

      • -COUNTER_FILE

        Specifies the name and path of the file that is used to store unique, incrementally- updated record ID’s.

      • -FIELD_DELIMITER

        Specifies the character that you will use to delimit fields in every row of the database. By default, eXtropia applications use the pipe ('|') character.

      • -LOCK_TYPE

        Specifies the locking driver used to protect the data file. By default, eXtropia applications use Lock::File.

      • -FIELD_NAMES

        References @DATASOURCE_FIELD_NAMES.

      • -FIELD_TYPES

        Specifies the types associated with fields in the data source (simple string assumed by default). At very least for the purposes of searching, it can be very useful to define field types for each of your fields. If you consult the documentation for DataSource, you will see a whole list of types including number, date, and auto (increment).

          NOTE: In some cases, there will be fields in the data source that are meant primarily to be used for administrative purposes. That is, the data in these fields is not added or modified by users. One field in particular is represented in all default data sources since all default data sources use the Datasource::File driver.

          This field is item_id. The item_id field is used to assure that every row in the datasource can be uniquely identified in cases of modification. In order to implement the uniqueness, the item_id field is set to be auto incrementing using the -FIELD_TYPES parameter. As a result, the item_id field will be set to the current number specified in the counter file (eg ./Datafiles/app_name.count.dat).

    Now that we've gone over the variables related directly to configuring the data source, we can go on to how you configure the views to recognize what fields are in a datasource from a user interface perspective. These variables are $INPUT_WIDGET_DEFINITIONS and @INPUT_WIDGET_DISPLAY_ORDER.

    1. %INPUT_WIDGET_DEFINITIONS

      Specifies the HTML form widgets used for capturing information about datasource fields. The format is almost identical to Lincoln Stein's CGI.pm HTML generation routines specified in the CGI.pm documentation.

    2. @INPUT_WIDGET_DISPLAY_ORDER

      Specifies the order in which to display HTML form widgets.

    The following is a sample of how %INPUT_WIDGET_DEFINITIONS would be configured for a data source containing last name and email.

     
        %INPUT_WIDGET_DEFINITIONS = (
            lname => [
                -DISPLAY_NAME => 'Last Name',
                -TYPE         => 'textfield',
                -NAME         => 'lname',
                -DEFAULT      => '',
                -SIZE         => 30,
                -MAXLENGTH    => 80
            ],
        
            email => [
                -DISPLAY_NAME => 'Email',
                -TYPE         => 'textfield',
                -NAME         => 'email',
                -DEFAULT      => '',
                -SIZE         => 30,
                -MAXLENGTH    => 80
            ]
        );

    The format for these variables leverages off the HTML generation methods provided by CGI.pm with the exception that -DISPLAY_NAME (to be used as a display name for the widget) and -TYPE (specifying a CGI.pm widget) are specified.

    As such, you can generate any form widget using the CGI.pm syntax. You should consult the documentation for CGI.pm to get a thorough explanation of the API, but below are a few examples of common input widgets.

    • Generating a TextField

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'textfield',
              -NAME         => 'widget_name',
              -DEFAULT      => '',
              -SIZE         => 30,
              -MAXLENGTH    => 80
          ]

    • Generating a TextArea

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'textarea',
              -NAME         => 'widget_name',
              -DEFAULT      => '',
              -ROWS         => 5,
              -COLS         => 30
          ]

    • Generating a Password Field

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'password_field',
              -NAME         => 'widget_name',
              -DEFAULT      => '',
              -SIZE         => 30,
              -MAXLENGTH    => 80
          ]

    • Generating a File Upload Field

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'filefield',
              -NAME         => 'widget_name',
              -DEFAULT      => '',
              -SIZE         => 30,
              -MAXLENGTH    => 80
          ]

    • Generating a Drop Down Menu

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'popup_menu',
              -NAME         => 'widget_name',
              -DEFAULT      => 'one_value',
              -VALUES       => \@VALUES,
              -LABELS       => \%labels
          ]

    • Generating a List Box

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'scrolling_list',
              -NAME         => 'widget_name',
              -DEFAULT      => 'one_value',
              -VALUES       => \@VALUES,
              -LABELS       => \%labels,
              -SIZE         => 5
              -MULTIPLE     => ‘TRUE’
          ]

    • Generating a Checkbox Group

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'checkbox_group',
              -NAME         => 'widget_name',
              -DEFAULT      => 'one_value',
              -VALUES       => \@VALUES,
              -LABELS       => \%labels,
              -LINEBREAK    => ‘TRUE’,
              -ROWS         => 2,
              -COLS         => 2
          ]

    • Generating a Standalone Checkbox

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'checkbox',
              -NAME         => 'widget_name',
              -CHECKED      => 'checked',
              -VALUE        => ‘ON’,
              -LABEL        => ‘Click Me’,
          ]

    • Generating a Radio Button Group

       
          widget_name => [
              -DISPLAY_NAME => 'Widget Name',
              -TYPE         => 'radio_group',
              -NAME         => 'widget_name',
              -VALUES       => \@VALUES,
              -DEFAULT      => ‘value’,
              -LABELS       => \%labels,
              -LINEBREAK    => ‘TRUE’,
              -ROWS         => 2,
              -COLS         => 2
          ]

      NOTE: The usage of input widget related variables is best understood by example. We recommend that you take a moment to examine their usage by example in the Configuration by Example section later in this guide.

    To help you get a better feel for what a data source configuration looks like, the following shows a standard configuration:

     
        my @DATASOURCE_CONFIG_PARAMS = (
            -TYPE            => 'File',
            -FIlE            => './Datafiles/webresponder.data',
            -FIELD_DELIMITER => '|',
            -LOCK_TYPE       => 'File',
            -FIELD_TYPES     => {
                item_id => 'auto'
                },
            -FIELD_NAMES     => [qw(
                item_id
                fname
                lname 
                email
                comments
                )]
        );
        
        my %INPUT_WIDGET_DEFINITIONS = (
            category => [
                -DISPLAY_NAME => 'Category',
                -TYPE         => 'popup_menu',
                -NAME         => 'category',
                -DEFAULT      => '',
                -VALUES       => [qw(Business Misc Personal)]
            ],
        
            fname => [
                -DISPLAY_NAME => 'First Name',
                -TYPE         => 'textfield',
                -NAME         => 'fname',
                -DEFAULT      => '',
                -SIZE         => 30,
                -MAXLENGTH    => 80
            ],
        
            lname => [
                -DISPLAY_NAME => 'Last Name',
                -TYPE         => 'textfield',
                -NAME         => 'lname',
                -DEFAULT      => '',
                -SIZE         => 30,
                -MAXLENGTH    => 80
            ],
        
            email => [
                -DISPLAY_NAME => 'Email',
                -TYPE         => 'textfield',
                -NAME         => 'email',
                -DEFAULT      => '',
                -SIZE         => 30,
                -MAXLENGTH    => 80
            ]
        );
        
        my @INPUT_WIDGET_DISPLAY_ORDER = qw(
                category
                fname
                lname
                email
        );

    Logging Configuration

    Logging is a very useful utility for any application. For example, it is often advisable for an administrator to check through logs in order to look for errors, hack attempts, or to analyze general usage. It may also be useful to use a log to recover lost data.

    One useful bit of information to know about is the state of the environment when a logged event occurs. As a result, all eXtropia applications use a small routine to add the environment state to every log entry.

    In order to append the environment information such as REMOTE_USER and REMOTE_HOST to the log, we need to first get it using the %ENV hash given to all CGI scripts by the web server that executes them.

    The routine, to gather the data, called _generateEnvVarsString(), is pretty trivial. It simply runs through each of the ENV keys and stores the name and value in a string to hand off to the Log object.

     
        sub _generateEnvVarsString {
            my @env_values;
        
            my $key;
            foreach $key (keys %ENV) {
                push (@env_values, "$key=" . $ENV{$key});
            }
            return join ("\|", @env_values);
        }   

    The following figure illustrates how the log integrates with the rest of the eXtropia application setup.

    There is only one variable involved with defining the log.

    This variable should be configured according to the capability of the driver you wish to use. However, to achieve cross platform compatibility, eXtropia applications use file-based logs by default so we will go over it's parameters here.

    1. @LOG_CONFIG_PARAMS

      Specifies the configuration of the log object.

      • -TYPE

        Specifies the type of log driver to use. By default, eXtropia applications use Log::File.

      • -LOG_FILE

        Specifies the location of the file used for logging. By default, eXtropia applications use ./Datafiles/app_name.log.

      • -LOG_ENTRY_SUFFIX

        Specifies a string of text added to the end of the log entry. By default, eXtropia applications add the environment string discussed above.

      • -LOG_ENTRY_PREFIX

        Specifies a string of text added to the beginning of the log entry. By default, eXtropia applications append the name of the application itself.

    To help you get a better feel for what log configuration looks like, the following example shows a standard configuration.

     
            my @LOG_CONFIG_PARAMS = ( 
                -TYPE             => 'File',
                -LOG_FILE         => './Datafiles/webguestbook.log',
                -LOG_ENTRY_SUFFIX => '|' . _generateEnvVarsString() . '|',
                -LOG_ENTRY_PREFIX => 'WebGuestbook|'
            );

    Mail Configuration

    To send mail, eXtropia applications use Extropia::Mail. Specifically, by default, eXtropia applications use the Extropia::Mail::Sendmail driver.

    We recommend using sendmail, because we are partial to Apache running on LINUX. However, you can easily use any number of mail drivers for Windows, UNIX, or Macintosh. See the Further References section to find out where to get more information about the various mail drivers available for eXtropia applications. However, you can use the following as a rule of thumb:

    If you run a Mac web server, we recommend MailSender.pm. MailSender.pm is available at CPAN (if it is not already included in your distribution of Perl) and uses a raw SMTP connection to send mail to valid email addresses.

    If you are a Windows user, you can also use MailSender. However, Mail::Blat, and Mail::NTSendmail are also options and available as drivers from eXtropia.

    The following figure illustrates the sections of a setup file that typically are required in order to enable an application to send mail.

    There are essentially two variables involved with mail configuration

      NOTE: The parameters defined in the MAIL_SEND_PARAMS can easily be expanded to include any parameters that a mail driver's send() method can accept. For example, if you wanted to attach a file to the email sent you might use.

     
            my @LIST_MAILING_EVENT_MAIL_SEND_PARAMS = (
                -FROM           => 'me@mydomain.com',
                -REPLY_TO       => 'her@herdomain.com',
                -TO             => 'you@yourdomain.com',
                -SUBJECT        => $CGI->param('subject'),
                -ATTACH         => ‘/somedirectory/attach/file.dat’
            );

    Each of these variables should be configured according to the specifics of the drivers you wish to use.

    1. @MAIL_CONFIG_PARAMS

      Specifies the configuration of the Mail Driver.

      • -TYPE

        Specifies the type of mail driver to use. By default, eXtropia applications use Mail::Sendmail.

      • -MAIL_PROGRAM_PATH

        Specifies the path to Sendmail.

    2. @XXX_MAIL_SEND_PARAMS

      Specifies the parameters of each type of mail that the application can send. This parameter works much like the data handler manager configuration we discussed earlier. As in the case of data handler managers, an application may have several mail send variables to configure. For example, in WebDB, the administrator may wish to send an email for successful additions, modifications, and deletions. As a result, individual emails must be configurable for each type of event. Thus, three mail send parameters would have to be configured, one for each WebDB event.

    3. @EMAIL_DISPLAY_FIELDS

      Specifies a list of fields that should be added to the body of any email sent out.

      • -FROM

        Specifies who the mail will be sent from.

      • -TO

        Specifies who the email should be sent to. This variable can be either a scalar for a single value or a reference to an array of email addresses.

      • -CC

        Specifies who should be copied. Like -TO, this parameter can be a scalar or a reference to an array.

      • -BCC

        Specifies who should be blind copied. Like -TO, this parameter can be a scalar or a reference to an array.

      • -REPLY_TO

        Specifies an email address to be used in the reply to field.

      • -SUBJECT

        Specifies the subject of the email.

    To help you get a better feel for what mail configuration looks like, the following example shows a standard configuration:

     
            my @MAIL_CONFIG_PARAMS = (
                -TYPE              => 'Sendmail',
                -MAIL_PROGRAM_PATH => '/usr/lib/sendmail'
            );
        
            my @DELETE_EVENT_ADMIN_MAIL_SEND_PARAMS = (  
                -FROM     => 'me@me.com',
                -TO       => $CGI->param('email'),
                -BCC      => ['me@me.com', ‘you@yourdomain.com’],
                -CC       => ['her@her.com', ‘you@yourdomain.com’],
                -REPLY_TO => 'me@me.com',
                -SUBJECT  => 'Mailing List Un-Subscription',
            );
        
            my @ADD_EVENT_ADMIN_MAIL_SEND_PARAMS = (
                -FROM     => 'me@me.com',
                -TO       => $CGI->param('email'),
                -REPLY_TO => 'me@me.com',
                -SUBJECT  => 'Mailing List Subscription',
            );
        
            my @MODIFY_EVENT_ADMIN_MAIL_SEND_PARAMS = (
                -FROM     => 'me@me.com',
                -TO       => ['me@me.com', ‘you@yourdomain.com’],
                -REPLY_TO => 'me@me.com',
                -SUBJECT  => 'Mailing List Subscription',
            );

    NOTE: If you are reading carefully, you might notice that by default, eXtropia applications don’t actually include a -BODY parameter in the mail send configuration. Although you can certainly define a body here, we generally prefer to leave the creation of the body until run time.

    That is, since the body of an email message is usually defined by the actual event of user submission and the logical path the specific instance of the application takes, we do not like to define the body in the setup file (which does its work before any application logic really begins.)

    Instead, eXtropia applications will generally include one view per mail send parameter. Thus, in the case of the example above, we would typically create three views, one for the add event, one for the delete event, and one for the modify event.

    These views would be used to dynamically create the body of the email message at runtime. Consider the display() method from a standard body-generating view:

     
            sub display {
                my $this = shift;
                @_ = _rearrange([-EMAIL_DISPLAY_FIELDS, -CGI_OBJECT],
                    [-EMAIL_DISPLAY_FIELDS, -CGI_OBJECT],@_
                );
            
                my $display_fields_ref  = shift;
                my $cgi                 = shift;
                my $content = qq[
                    The following guestbook entry was submitted.
                ];
            
                my $field;
                foreach $field (@$display_fields_ref) {
                    $content .= $field . substr((" " x 25), length($field));
                    $content .= $cgi->param($field) . "\n";
                }
                return $content;
            }

    This can be used in the application by saving the view output to a variable that is added to the mail send parameters at runtime:

     
            my $view = $view_loader->create("AddEventUserEmailView");
            my $body = $view->display(@$view_display_params);
            my $mailer = Extropia::Mail->create(@$mail_config_params)
                or die("Mail error.");
            $mailer->send(
                @$add_event_user_mail_send_params,
                -BODY => $body
            );

    Encryption Configuration

    Though not used in every eXtropia application, encryption is a crucial part of some. If data security is an important part of your requirements, you'll certainly wish to encrypt data in and out of the application. Extropia::Encrypt will form a big part of the solution.

    Encryption configuration is achieved by defining one variable. This variable should be configured according to the specifics of the drivers you wish to use. By default, eXtropia applications use no encryption, but we have added this configuration parameter to most applications as a convenience to you should you wish to implement encryption.

    1. @ENCRYPT_CONFIG_PARAMS

      Specifies the configuration for the Encrypt object.

      • -TYPE

        Here we enable the Extropia::Encrypt::Crypt driver because it is the most cross platform password encryption mechanism. However, some systems (especially Windows with older versions of Perl) may not have crypt() implemented. In this case, simply replace the

         
            -TYPE => 'Crypt'

        with

         
            -TYPE => 'None'

        which will turn off encryption.

        See the section on Further References to get an idea of what other encryption drivers are available.

    To help you get a better feel for what encrypt configuration looks like, the following example shows a standard configuration.

     
        my @ENCRYPT_CONFIG_PARAMS = (
            -TYPE             => 'None',
        );

    View Configuration

    Views define the application's user interface. You can find all the Views for an application in the appName/Views/ExtropiaAppName directory. For example, if you want to modify the 'Comment Form' for WebResponder, you need only edit the file webresponder/Views/Extropia/WebResponder/CommentFormView.pm.

    However, views also have a configuration piece. In order to save you typing time, all views can accept a set of global parameters. For example, if you have a background image that you want to use for all pages, you would want to send it to all views rather than hardcode it into each view. If you hardcode it, when the background image changes, you'll need to modify every view. Using a global view parameter assures that if you want to change the image, you change it in the configuration and all views will find out about it automatically.

    Primarily, views are just HTML. After all, they are used to define the user interface and are not supposed to be bulky with code. If you want to make a change to the HTML, you should read Step Seven: Modifying the Application Look and Feel.

    There are a couple of variables used to configure views. They are shown graphically in the figure below, and then explained in detail in the list that comes after the figure.

    1. @VIEW_DISPLAY_PARAMS

      Specifies the parameters that are sent to all the views.

      • -CGI_OBJECT

        Specifies the CGI object that has been used to gather incoming form data from the user.

      • -DOCUMENT_ROOT_URL

        Specifies the URL of the web document root.

      • -IMAGE_ROOT_URL

        Specifies the URL of the web images root.

      • -APPLICATION_LOGO

        Specifies the name of the image file used as the application logo.

      • -APPLICATION_LOGO_WIDTH

        Specifies the width of the application logo.

      • -APPLICATION_LOGO_HEIGHT

        Specifies the height of the application logo.

      • -APPLICATION_LOGO_ALT

        Specifies the text used in the ALT tag of the application logo IMAGE tag.

      • -HEADER_BG_COLOR

        Specifies the background color to use for section headers.

      • -HEADER_BG_COLOR

        Specifies the color to use for fonts within section headers.

      • -TABLE_BG_COLOR_1

        Specifies the background color to use for <TH> tags.

      • -TABLE_BG_COLOR_1

        Specifies the background color to use for <TD> tags.

      • -SCRIPT_DISPLAY_NAME

        Specifies a formatted name to be displayed such as 'Bob’s Fish Emporium'.

      • -SCRIPT_NAME

        Specifies the name of the .cgi file itself.

      • -PAGE_BACKGROUND_COLOR

        Specifies a color to be used for page backgrounds. Value would be something like FFFFFF for white.

      • -PAGE_BACKGROUND_IMAGE

        Specifies the URL of an image to be used as the page background.

      • -PAGE_LINK_COLOR

        Specifies a color to be used for page links. Value would be something like FFFFFF for white.

      • -PAGE_ALINK_COLOR

        Specifies a color to be used for page links onclick() event. Value would be something like FFFFFF for white.

      • -PAGE_VLINK_COLOR

        Specifies a color to be used for page links once the user has visited the page in question. Value would be something like FFFFFF for white.

      • -PAGE_FONT_COLOR

        Specifies a color to be used for fonts. Value would be something like FFFFFF for white.

      • -PAGE_FONT_SIZE

        Specifies a font size.

      • -PAGE_FONT_FACE

        Specifies a font face.

      • -HOME_VIEW

        Specifies the initial, or default, view of the application.

      • -EMAIL_DISPLAY_FIELDS

        Specifies a set of data source parameters that should be displayed in emails. This parameter is generally only used in email-related views.

      • -FILED_NAME_MAPPINGS

        Maps the list of data source fields to a 'user friendly' format.

    2. @VALID_VIEWS

      In order to triple check that no hacker is using this application to snoop files that they should not have access to, we will explicitly list all the views that the application will be allowed to display to a web browser.

      For example, if you look at the list in @VALID_VIEWS, and you look in the directory mailinglistmanager/Views/Extropia/MLM, you'll see that they are the same.

      Note that if you add a new View object, you'll need to add its name to this list or you will not be allowed to view it. Likewise, if you want to prevent a user from seeing a view provided by default, you can remove it from this list.

    To help you get a better feel for what view configuration looks like, consider the standard configuration shown below.

     
            my @VALID_VIEWS = qw(
                MyView1View
                MyView2View
            );
          
            my @VIEW_DISPLAY_PARAMS = (
            -INPUT_WIDGET_DEFINITIONS   => $INPUT_WIDGET_DEFINITIONS,
            -INPUT_WIDGET_DISPLAY_ORDER => \@INPUT_WIDGET_DISPLAY_ORDER,
            -ROW_COLOR_RULES         => \@ROW_COLOR_RULES,
            -FIELD_COLOR_RULES       => \@FIELD_COLOR_RULES,
                -CGI_OBJECT              => $CGI,
                -DOCUMENT_ROOT_URL       => 'http://somedomain.com/',
                -APPLICATION_LOGO        => 'app_logo.gif',
                -APPLICATION_LOGO_HEIGHT => '63',
                -APPLICATION_LOGO_WIDTH  => '225',
                -APPLICATION_LOGO_ALT    => 'WebDB Demo'
                -HEADER_BG_COLOR         => '000000',
                -HEADER_FONT_COLOR       => 'FFFFFF',
                -TABLE_BG_COLOR_1        => '6699CC',
                -TABLE_BG_COLOR_2        => 'E5E5E5',
                -IMAGE_ROOT_URL          => 'http://somedomain.com/images/',
                -SCRIPT_DISPLAY_NAME     => 'APPNAME',
                -SCRIPT_NAME             => 'app_name.cgi',
                -PAGE_BACKGROUND_COLOR   => 'FFFFFF',
                -PAGE_BACKGROUND_IMAGE   => 'none defined',
                -PAGE_LINK_COLOR         => 'FFFFFF',
                -PAGE_ALINK_COLOR        => 'FFFFFF',
                -PAGE_VLINK_COLOR        => 'FFFFFF',
                -PAGE_FONT_COLOR         => '000000',
                -PAGE_FONT_SIZE          => '-1',
                -PAGE_FONT_FACE          => 'VERDANA, ARIAL, HELVETICA, SANS-SERIF',
                -HOME_VIEW               => 'TOCView',
                -EMAIL_DISPLAY_FIELDS    => \@EMAIL_DISPLAY_FIELDS
            );

    Filter Configuration

    Filters are convenient tools that you can apply globally to all views in order to perform logical operations. By default, eXtropia applications don’t actually use filters because they are often too situation-dependent to activate for every client.

    However, because we expect users to apply filters to all the applications, we have embedded a filter configuration parameter into every application so that you could easily add filtering to your applications should you decide to.

    Filter configuration involves two types of configuration variables which are shown in the figure below:

    These variables should be configured according to the specifics of the drivers you wish to use. By default, in order to show an example, we have included the Filter::Censor driver in every application.

    1. @CENSOR_FILTER_CONFIG_PARAMS

      Specifies the configuration parameters of a specific filter. You can specify as many filter configurations as you would like simply by adding additional configuration variables such as @[YYY]_FILTER_CONFIG_PARAMS

      • -TYPE

        Specifies the filter driver. In this case, we want a Censor filter.

      • -WORDS_TO_FILTER

        Specifies the list of words to censor.

    2. @VIEW_FILTERS_CONFIG_PARAMS

      Specifies a list of filter configuration parameters. In this case, there is only one, @CENSOR_FILTER_CONFIG_PARAMS.

    To help you get a better feel for what session configuration looks like, consider the standard configuration shown below.

     
            my @CENSOR_FILTER_CONFIG_PARAMS = (
                -TYPE            => 'Censor',
                -WORDS_TO_FILTER => [qw(
                    eric
                )]
            );
        
            my @VIEW_FILTERS_CONFIG_PARAMS = (
                 \@CENSOR_FILTER_CONFIG_PARAMS
            );

    Application Configuration

    Finally, every configuration concludes with the configuration of the application itself. Generally, the configuration is a matter of referencing all the configurations we have already discussed, but at times, it also involves application-workflow specific configuration. This configuration usually takes the form of flags that turn on or off specific features. Consider the sample application configuration shown below. Note that several application specific parameters are set.

     
        my @APPLICATION_SETUP = (
            -DH_MANAGER_CONFIG_PARAMS         => \@DH_MANAGER_CONFIG_PARAMS,
            -CGI_OBJECT                       => $CGI,
            -DATASOURCE_CONFIG_PARAMS         => \@DATASOURCE_CONFIG_PARAMS,
            -FORM_VIEW_NAME                   => 'CommentFormView',
            -LOG_CONFIG_PARAMS                => \@LOG_CONFIG_PARAMS,
            -ENCRYPT_CONFIG_PARAMS            => \@ENCRYPT_CONFIG_PARAMS,
            -ENCRYPT_EMAIL_SENT_TO_ADMIN_FLAG => 1,
            -LOG_FORM_SUBMISSION_FLAG         => 1,
            -THANK_YOU_VIEW_NAME              => 'ThankYouView',
            -DEFAULT_VIEW_NAME                => 'FrameView',
            -VALID_VIEWS                      => \@VALID_VIEWS,
            -VIEW_DISPLAY_PARAMS              => \@VIEW_DISPLAY_PARAMS,
            -VIEW_FILTERS_CONFIG_PARAMS       => \@VIEW_FILTERS_CONFIG_PARAMS,
            -VIEW_LOADER                      => $VIEW_LOADER,
            -MAIL_CONFIG_PARAMS               => \@MAIL_CONFIG_PARAMS,
            -USER_RECEIPT_SEND_PARAMS         => \@USER_RECEIPT_SEND_PARAMS,
            -ADMIN_RECEIPT_SEND_PARAMS        => \@ADMIN_RECEIPT_SEND_PARAMS,
            -USER_EMAIL_BODY_VIEW             => 'UserEmailBodyView',
            -ADMIN_EMAIL_BODY_VIEW            => 'AdminEmailBodyView',
            -SEND_ADMIN_RECEIPT_FLAG          => 1,
            -SEND_USER_RECEIPT_FLAG           => 1,
            -CLIENT_EMAIL_ADDRESS             => $CGI->param('email') || ""
        };
    [ TOC ]


    [ TOC ]


    [ TOC ]
    Master Copy URL: http://www.extropia.com/support/docs/adt/
    Copyright © 2000-2001 Extropia. All rights reserved.
    [ TOC ]
    Written by eXtropia.
    Last Modified at 10/19/2001