Go to the first, previous, next, last section, table of contents.


Changing the GUI

The SDSI graphical user interface, in `sdsi2ui', uses sdsi2sh's code as its foundation. What it adds is a collection of Perl 4 scripts that issue commands to the shell, read its output, and dress it up into HTML pages that it feeds to the user's Netscape.

These Perl scripts are kept in `tools/sdsi2ui-scripts'. When sdsi2ui is compiled, they are combined into one large perl-ready script, which is checked for syntax and then compressed with gzip. The resulting image is converted into a C source file defining a string with that image's contents. sdsi2sh is then compiled with `-DSDSI2UI', which, among other things, makes it #include that C source file.

When run, sdsi2ui invokes perl and connects to its standard input and output. After feeding perl the monster script through a `gzip -cd', the sdsi2sh heart of sdsi2ui just waits for the Perl scripts to print commands for it on its standard output. The results are made available to the scripts on their standard input.

The "root" of the sdsi2ui scripts is `main.pl'. This script is responsible for requireing the other scripts, creating the secure directory from which the user's pages will be served, starting its HTTP server, and kicking off the page generation and the user's browser. You probably shouldn't touch this file, `network.pl', or `pages.pl'.

To add support for browsers other than Netscape, change `browser.pl'. The idea is that at the top of the browser_start subroutine, you decide on the browser to use and put a name for it in $user_browser_name. The remainder of that subroutine is a big if...else, branching on that name, that gets that browser to display $first_page, a URL for the first page. The subroutine browser_still_running should return nonzero if, when called, that browser is still running.

All of the remaining files have functions that create HTML pages, accept POST input, and interact with the sdsi2sh heart. For page generation, any subroutine that ends in _generate that is defined at start time is automatically called with the filehandle PAGE open to a file for accepting its content. The base name of the file is the name of that generating subroutine, less the _generate, with remaining underscores changed to parentheses, and `.html' tacked on the end.

For example, the subroutine new_pubkey_name_generate is called with PAGE opened for writing a file in the secure directory with the base name `new-pubkey-name.html'. HTML links can be forged between pages by knowing that the filenames for other pages will be similarly named.

The HTML pages generated by the GUI should use POST forms for soliciting user input. The names of the methods used in the pages must match Perl subroutines that will accept the values from the form, and all forms must include a hidden value named cookie. The value of cookie is used by the HTTP server in `main.pl' to authenticate an HTTP POST as being from the user's Web browser, as opposed to anyone else's.

For example, the HTML generated by the new_pubkey_name_generate subroutine includes:

<form action=$server_url_base/new-pubkey-name method=post>
<input type=hidden name=cookie value=$session_cookie>

What do you want to name that public key?<br>
<input type=text name=the-name maxlen=40>

followed by more HTML defining the rest of the form.

The POST data will be fed back to a subroutine called new_pubkey_name_post. These _post subroutines are always called with an associative array as the argument list. The keys of the array are the variable names used in the POST form. For example, in:

# accepts a new-pubkey-name POST:
sub new_pubkey_name_post {
    local(%params) = @_;

$params{'cookie'} is the value of the cookie, $params{'the-name'} is the value the user entered for the HTML form's the-name variable, etc. All values have already been decoded.

Some functions in main.pl are available for helping these _post functions for further checking their variable values. &main_check_parameters takes a single string, which has newline-separated records. A record consists of a variable's name, a colon, and the Perl regular expression that the variable's value must match. &main_check_parameters returns undef if everything is okay, or the name of a variable whose value isn't acceptable.

new_pubkey_name_post uses this to check its variables:

    # make sure that we have all of our parameters, and they look valid:
    if ($_ = &main_check_parameters(<<'EOF', %params)) {
pk-type:page|file
pk-where:[\w\-\.\/:]+
the-name:
not-before:now|specified
not-before-date:\d{4}-\d\d-\d\d_\d\d:\d\d:\d\d
not-after:never|specified
not-after-date:\d{4}-\d\d-\d\d_\d\d:\d\d:\d\d
EOF
        # FIXME - can do better than just saying this:
	&main_return_error_page("Malformed CGI invocation - value for ${_}, $params{$_}, looked bad");
	return;
    }

A function main_sh_define is available to define a sdsi2sh variable with a value. It takes two strings: the name of the variable followed by its value. If the definition fails (say, if the value is a cert object that doesn't parse), this function returns a ::-separated set of pairs of the major error code and its text, the minor error code and its text, and the error locus and its text.

A function main_sh_get returns a shell variable's current value. It takes the name of the variable as its argument.

main_sh_commands can run a series of commands (none of them can be defines). It takes the commands as a newline-separated string, and returns a list. The first value of the list is undef if no errors were encountered. The remaining values are the return values from the commands.


Go to the first, previous, next, last section, table of contents.