Digital Media
Moshell-Spring 98
 
Lecture 13 - Advanced Form Applications
G Chapter 6 (end) and 7
 

Most of this lecture comes from Chapter 7, but I do want to discuss the Animation section of Chapter 6, on pages 136 to 142.

 

Animation can be accomplished by Java or Javascript, with the advantage that you are not waiting on the Internet’s highly variable timing. However, if you are trying to animate something that depends on new data - such as a stock ticker tape - you have to ask the server for information anyhow. So Java has no special advantage in that case.

 

Animation can be controlled by the client or the server. If the client asks to run a script over and over, that would obviously produce animation.

 

Client Pull. To ask for a dynamic graphical image, one simply calls the script inside an IMG tag, like this:

 

print <<End_of_HTML;

... various HTML details

... down to:

<IMG SRC="/cgi-bin/digital.pl">

....some more HTML

End_of_HTML

 

This will, however, only get ONE copy of the image. To get multiple copies, you have to tell the browser to repeatedly ask for the document, like this:

 

<META HTTP-EQUIV="Refresh" CONTENT=5>

 

This will generate a call every 5 seconds, by the brute force method of re-fetching and rendering the entire HTML document - including its dynamic call or calls. In fact, Refresh only works once. But in the new copy of the HTML that is fetched, there is another identical copy of the Refresh meta-command.

 

Server Push. If the browser is "warned" to stay open to continuous input, the server can be set up to send the animation information continuously. Here’s the setup command:

 

Content-type: multipart/x-mixed-replace; boundary=End

 

--End

Content-type: image/gif

Image #1

--End

Content-type: image/gif

Image #2

--End

...

--End--

 

The first line declares that each successive image will end with the characters "--End". This continues until the boundary symbol appears with two "-" characters on either side of it - like --End--

 

The server push example code:

 

#!usr/local/bin/perl

 

$|=1;

$webmaster="shishir/@bu\.edu";

 

$boundary_string="\n"."--End"."\n";

$end_of_data = "\n"."--End--"."\n";

$delay_time = 1;

 

@image_list = ("image_1.gif", image_2.gif","image_3.gif","image_4.gif","image_5.gif")

 

$browser = $ENV{‘HTTP_USER_AGENT’};

 

if ($browser =~ m#^Mozilla/(1.[^0]|[2-9])#) # What’s with this RE?

{

for ($loop=0; $loop<scalar(@image_list); $loop++)

{

&open_and_display_GIF($image_list[$loop]);

print $boundary_string;

sleep($delay_time);

}

print $end_of_data;

}

else

{

&open_and_display_GIF ($image_list[0]); # Just one image

}

exit (0);

 

####################

 

sub open_and_display_GIF

{

local ($file) = $_;

local ($content_length);

if ((open (FILE, "<". $file))

{

$content_length = (stat (FILE) [7];

print "Content-type: image/gif", "\n";

print "Content-length:",$content_length, "\n\n";

print <FILE>;

close (FILE);

}

else

{

&return_error(500, "File Access Error",

"Cannot open graphic file $file!");

}

}

 

There is also some advice on page 141 if you’re using an NCGA server.

 

CHAPTER 7: Advanced Form Applications

 

This chapter describes four applications of increasing sophistication. I’ll highlight the key features of each, rather than reproducing the whole lot.

 

EXAMPLE 1: Guestbook. This program’s main innovation is that it uses a single server for three services: to provide the initial form, to receive the form to store it in the guestbook file, and to display the entire guestbook upon request.

 

QUERY 13.1: What "kludge" method does the author use in this example to determine which of these three behaviors the server is being asked to do. By "kludge" I mean a simple technique which would not easily generalize to a situation with more cases.

 

The logical phases of this program are unfortunately displayed in the illogical order of 1,3,2. I’ve sorted them into logical order here.

 

Phase 1: Emitting the form

 

The Perl script simply prints out the form.

 

Phase 2: Receiving the form and storing the data.

 

The form data is stored in the FORM associative array, by the usual tricks of the &parse_form_data procedure we saw before. However there are a couple of default fixups, as follows:

 

$FORM{‘name’} = "Anonymous User" if !$FORM{‘name’};

$FORM{‘from"} = $ENV{‘REMOTE_HOST’} if !$FORM{‘from’};

 

This incorporates the famous Perl backwards-if, which saves a total of two brackets {!}.

 

QUERY 13.2: Describe another way to set these defaults, without using an ‘if’ of any species.

 

$FORM{‘comments’} =~ s/\n/<BR>/g;

 

means "replace all the newline characters with the HTML trag <BR>."

 

QUERY 13.3: This raises the interesting question, "what if our client included a message like "Do you know how the HTML <BR> tag works?" in his guestbook message. What would happen?

 

Phase 3: Emitting the guestbook

 

This phase is implemented with an almost trivial loop:

$exclusive_lock=2;

$unlock = 8; # Some conventional codes

$full_path = # here you name the full path to your guestbook file.

 

if (open (GUESTBOOK, "<".$full_path)

{ flock (GUESTBOOK, $exclusive_lock);

&MIME_header ("text/html", "Here is my guestbook!");

 

while (<GUESTBOOK>) # Here’s the simple minded loop.

{ print;}

 

flock (GUESTBOOK, $unlock);

close(GUESTBOOK);

}

else

{&return_error(500,"Guestbook File Error",

"Cannot read from the guestbook file[$full_path].");

}

 

The procedure "&MIME_header" is the author’s compact way of providing the header and a centered title in H1 (maximum-huge headline) style.

 

QUERY 13.4: Why is he locking the file, when he’s just reading it? I don’t actually know, but maybe you do!

 

EXAMPLE 2: Survey/Poll, producing Pie Graphs.

 

The first trick we observe is that the ice cream survey results can be displayed by a link, right on the survey form.

 

<A HREF="/cgi-bn/pie.pl/ice_cream.dat">

 

Notice that down to pie.pl, this is a pathname to an executable script. Anything after that point gets dumped into the PATH_INFO environment variable, and is picked up by the script.

 

DON’T DO IT THIS WAY. The footnote on page 152 points out how such a technique opens your script to security violations.

 

The script which processes the queries, dumps the results into a cumulative file referred to in the text as POLL. This file’s structure is as follows:

 

Vanilla::Strawberry::Chocolate::Other

0::0::0::0

red::yellow::blue::green

 

The separators :: have the obvious role of helping a ‘split’ operator break out the data into appropriate arrays. Putting the options here in a file, instead of inside the script, is a wise way to make your scripts more generally useful. These data items are stored in arrays named ‘@options’, ‘@data’ and ‘@colors’ respectively.

 

 

The only interesting parts of the program are the data acquisition loop, and the way the data is put back out.

 

$item_no = 3; # So ‘other’ gets the credit if nothing is found.

for ($loop=0; $loop<=$#options; $loop++)

{

if ($options[$loop] eq $user_selection)

{

$item_no = $loop;

last; # Break out of the loop

}

}

$data[$item_no]++;

 

The operator "$#options" returns the highest used index in the "options "array. That is, it’s a kind of a size operator, but for an array of 4 elements, it returns the number 3. This means that the program is adaptive. If you had ten kinds of ice cream, all you’d need to do is change the details in POLL.

 

Query 13.5: There’s one "fixed" feature in POLL which is somewhat less than general, however. What is it?

The second interesting thing about this program is the way the data is reassembled for writing back into POLL:

 

print POLL join ("::", @options), "\n";

 

The ‘join’ operator takes the contents of the array @options and strings them back together with :: separators.

 

Drawing the Pie Chart involves a long and complex, but not particularly difficult-to-understand program.

 

EXAMPLE 3: Quiz/Test Form Application

 

This section involves a script which dynamically modifies a master document, converting non-HTML into legitimate HTML. The author used new tags which look like HTML tags, which I would not have done in his place.

 

Rather than working through this rather complex app in detail, I’m going to pose to you a simpler design problem for in-class work. As follows:

 

The Widget Company wants to develop a server which can put up any catalog page, and insert into the page the current price and inventory information. It is also desired to be able to put up "special notices", such as flagging an item as being on closeout.

 

Therefore, we will have three associative arrays pre-loaded with data:

 

$PRICE{item}, $INVENTORY{item} and $SPECIAL{item}.

 

The $item selector will consist of a product code, which is of form ‘C4324-5’, so we have to treat it as a string.

 

We want three kinds of tags that we can embed in our master form, as follows:

 

~p(C4324-5) will cause the price of that product to be displayed.

~I(C4324-5) will cause the inventory of that product to be displayed, and

~s(C4324-5) will cause that product’s special information – including embedded HTML-to be displayed.

 

Your code simply reads through the master form (using a while loop), performs the necessary substitutions, and emits the resulting code.