Web function scripts

The functions subdirectory contains all of the screen definitions for all panels. Each screen definition is a CGI script which displays the screen and also handles the CGI form submission. The scripts are written using the CGI::FormMagick toolkit, which separates the screen layout from the panel implementation code, facilitates form validation and provides full support for localisation of the manager.

An overview of FormMagick

Layout of a FormMagick script

This section describes the FormMagick panel which is used in the Section called Exercise 5: Adding a user interface screen in Chapter 12. A typical FormMagick web function starts with the script preamble, which notes it as a perl script and informs the vi editor that the majority of the file is XML, rather than perl.

#!/usr/bin/perl -wT
# vim: ft=xml:

This is followed by the navigation settings metadata, which determine where the script should appear in the manager menu bar.

#----------------------------------------------------------------------
# heading     : Demo
# description : Logger
# navigation  : 1000 1000
#----------------------------------------------------------------------

Next is a small number of lines of perl which create a FormMagick object and then call the display method to draw the page.

use strict;
use warnings;

use esmith::FormMagick::Panel::loggerdemo;

my $f = esmith::FormMagick::Panel::loggerdemo->new();
$f->display();

And finally there is the FormMagick XML page description, which starts at the __DATA__ marker and continues to the end of file. We will examine that in the next section.

The FormMagick XML description

The FormMagick XML is divided into a preamble and then a set of pages. The preamble contains references to the title, header and footer of the page. These are usually the same on all pages so that a consistent header and footer is displayed.

<form
    title="FORM_TITLE"
    header="/etc/e-smith/web/common/head.tmpl"
    footer="/etc/e-smith/web/common/foot.tmpl">

The upper-case word FORM_TITLE is a placemarker token for a phrase which needs to be localised. There is an associated lexicon file which provides the translation of this token into the appropriate language for the user accessing the panel, as specified by their browser settings. For example, here is the English lexicon entry for that token:

    <entry>
        <base>FORM_TITLE</base>
        <trans>Logger demo</trans>
    </entry>

If the user browses the panel with English as their chosen language, the panel will display in English. If they choose French, French will be displayed. If an unsupported language is chosen, FormMagick will fall back to US English. Adding another language is basically a matter of providing the lexicon for that language.

The rest of the XML description is a series of pages. In this example there is a single page. Each page starts with a page tag, which gives the page a name for later reference and can optionally specify a pre-event and post-event.

    <page name="First" pre-event="print_status_message()"
        post-event="change_settings">

The pre-event is a reference to a function in the panel implementation (described later) and called before the page is loaded. The post-event is called after the user submits the information on the page, for example by pressing the Save button.

Each page is then composed of a number of fields

        <field
            type="select"
            id="loggerdemo_Interval"
            options="10,20,30,40,50"
            value="get_interval()">
            <label>LABEL_LOGGERDEMO_INTERVAL</label>
        </field>

        <field
            type="select"
            id="loggerdemo_status"
            options="'disabled' => 'DISABLED', 'enabled' => 'ENABLED'"
            value="get_status()">
            <label>LABEL_LOGGERDEMO_STATUS</label>
        </field>

Each field describes a user interface widget (e.g. a select box) and provides the data required for that widget. These data may be static lists (the options of the first field above), a set of key/value pairs (the options of the second field above) or dyanamic data returned from a subroutine (the value parameters in each of the fields).

The command perldoc CGI::FormMagick provides detailed documentation about the supported field types.

It is also possible to call subroutines which generate the required HTML for a section of a page. For example, buttons are often added by calling the print_button routine:

        <subroutine src="print_button('SAVE')" />

Note: Buttons should be part of the FormMagick XML description, and hopefully will be in the future. The print_button routine is a workaround for the lack of a button widget.

Each page must finish with a closing page tag:

    </page>

After all of the pages have been described there is a single XML tag to close the form.

</form>

Navigation metadata

The web manager's navigation frame is generated automatically by examining the contents of the /etc/e-smith/web/functions/ directory.

In order to be listed in the navigation frame, your CGI script must contain heading, description and navigation lines, usually at the top of the script:

# heading     : Configuration
# description : E-mail
# navigation  : 6000 6700

These define the category heading under which your add-on's admin interface should be listed, the title it should have, and the priority it should have in the listing order. The first number gives the priority of the heading (usually a multiple of 1000) and the second number gives the priority of this particular item within that heading group. In other words, a heading with a priority of 1000 will come before one with 6000 in the navigation panel, and within that heading category the individual items are listed in order from highest to lowest.

To figure out what numbers to give your own script, figure out where you want it to appear in the navigation panel then check source code for the scripts which appear before and after where you want to be. For instance, if you want your item to appear before "Remote Access" and after "Local Networks" in the navigation menu, you would look at /etc/e-smith/web/functions/remoteaccess and /etc/e-smith/web/functions/localnetworks and find the following:

# heading     : Security
# description : Remote access
# navigation  : 5000 5200

# heading     : Security
# description : Local networks
# navigation  : 5000 5300

You might then put something these lines in your own script:

# heading     : Security
# description : Advanced security
# navigation  : 5000 5250

Tip: When naming your script, use a name which closely resembles the description (and hence the name in the navigation panel). This makes it easier to correlate menu items to Perl scripts. Just take the descriptive name and remove capital letters, punctuation and spaces. For instance, "Advanced security" might become /etc/e-smith/web/functions/advancedsecurity

Permissions and security

The CGI scripts must have elevated permissions (setuid root) in order to write to the configuration database, since they will be run by the web server (which runs as user www). To ensure that these scripts can only be run by system administrators, the permissions on the parent directory and the scripts are set so that only the members of the admin group can run them. These panels are also restricted in the web server configuration so that only the admin user can access them.