Building WML Gadgets: Phone Message Application
Coding the Application
Let's break down the individual processes and then code foreach.
Database Design
Our "database" will be a simple delimited flatfile. Although we could go the fancy route with an actual database format, thedelimited format will work well for our simple application.
The database will contain the following fields:
- Date and time the message was taken
- Caller's name
- Caller's message
- Caller's phone number
We'll use a double vertical bar for our delimiter. We coulduse a more standard delimiter, such as a comma, but we need something thatwouldn't end up in the middle of the message field. In short, our databaserecords will resemble the following:
<data and time>||<caller's name>||<caller'smessage>||<caller's number>
HTML Form for Data Entry
We'll use a simple HTML form for entering the data:
Listing: msgform.html
<html><body><form name="msgform" method="post" action="phonemsg.pl"><center>Telephone Message</center><br><table><tr><td><input type="hidden" name="cmd" value="save">From:</td><td><input type="text" name="from" size="100" maxlength="100"></td></tr><tr><td>Message:</td><td><textarea name="message" cols="100" rows="5" wrap="virtual"></textarea></td></tr><tr><td>Callback #:</td><td><input type="text" name="number" size="12" maxlength="12"></td></tr><tr><td colspan="2"><center><input type="submit" value="Submit"></center></td></tr></table></form></body></html>
Note that we include an extra field, "cmd." Thishidden field will be passed to our CGI script to tell it what to do; namely,"save" the data.
The CGI Script
Our CGI script will be one multipurpose script, performingthe following functions:
- Saving the data (caller info)
- Listing the caller record(s)
- Displaying a selected record's details
- Automatically dialing the caller's number
- Optionally deleting the record and then calling the number
The script could also display the input form. However, formaximum portability, we'll use a simple HTML file. With this method, our formcan easily be included in almost any Web page template, simply by applying astyle sheet or by cutting-and-pasting the "guts" of the form intoanother page.
Saving the Data
The following code fragment saves the data entered into theform:
Listing: phonemsg.pl - Save data fragment
# Start response page print header; print "<html><head>"; print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"2; URL='msgform.html'\">"; print "</head><body>Please wait...<p>"; # Grab the parameters $from = param('from'); $message = param('message'); $callback = param('number'); # Remove any vertical bars $message =~tr/|/ /; # Check file lock $count = 0; if (-e "msgfile.lock") { select(undef,undef,undef,0.1); $count++; if ($count = 10) { die "Can't open message file! </body></html>"; } } open LOCK, ">msgfile.lock"; # Write new record to end of file open FILE, ">>msgfile.txt"; print FILE $date ." ". $time ."||"; print FILE $from ."||". $message ."||". $callback; print FILE "\n"; close FILE; close LOCK; unlink "msgfile.lock"; # All done, close response page print "</body></html>";Because the form and the mobile device could both beutilizing the script (and hence, the database) simultaneously, we must use filelockingto avoid having two processes accessing the database and corrupting ourdata. We'll use a simple method: creating a file to lock the databaseif thefile exists, the process waits for it to be deleted before accessing thedatabase. When a process is done with the database, the lock file is deletedand other processes are allowed to access the database. Instead of failingright away if the file is locked, or waiting forever for the file to beunlocked, the code loops 10 times, waiting a tenth of a second between theiterations. If the file is still locked, we assume that something has gonewrong and exit with an appropriate error message.
Windows users: Some implementations of Perl on the Windowsplatform don't support the four-argument call of "select" used in ourfile-locking loop. If this code generates errors on a Windows system,substitute another delay function.
Listing the Records on the Mobile Device
The following code fragment comprises the code to list fiverecords on the mobile device, along with an option to move to the next fiverecords:
Listing: phonemsg.pl - List records fragment
#Pass WML header print header(-type=>'text/vnd.wap.wml');# Print WML header and beginning tagsprint <<ENDHEADER;<?xml version="1.0"?><!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"><wml><card>ENDHEADER # Print start of cardprint <<BEGINCARD;<p mode="nowrap">Call List<br/><select name="Display" title="Display">BEGINCARD # Check file lock $count = 0; if (-e "msgfile.lock") { select(undef,undef,undef,0.1); $count++; if ($count = 10) { die "Can't open message file! </select></p></card></wml>"; } } open LOCK, ">msgfile.lock"; # Read records into array open FILE,"msgfile.txt"; push(@lines,$_) while (<FILE>); close FILE; close LOCK; unlink "msgfile.lock"; # Nextitem = first item to display $nextitem = param('nextitem'); if ("$nextitem" eq "") { $nextitem = 0; } # Lastitem = last item to display # (nextitem + 4 or end of file) if ($nextitem + 4 <= @lines) { $lastitem = $nextitem + 4; } else { $lastitem = @lines - 1; } # Print first item through last item for ($i = $nextitem; $i <= $lastitem; $i++) { ($datetime,$from,$message,$callback) = split /\|\|/,$lines[$i]; print "<option onpick='phonemsg.pl?cmd=display&rec=$i'>"; print $from ." (". $datetime .") \n"; print "</option> \n"; } # Set nextitem for NEXT function $nextitem = $lastitem + 1; # Display NEXT option print "<option onpick='phonemsg.pl?cmd=list&nextitem=$nextitem'>"; print "Next</option> \n"; print "</select> \n</p> \n"; print "</card> \n</wml> \n";
Most of the work for this fragment happens in the lastquarter of the code. After the stage has been set (WML card defined), thedatabase is read into an array and then the correct set of records isdisplayed, five records at a time. Initially, the first five records aredisplayed and an option is set for the next five to be selected (through the"nextitem" variable). If the user picks the "Next" option,the script is called again, with the name/value pair "nextitem" setto the "next item" to display.
Each record is displayed as an <option> whose "onpick"attribute results in the script being called with the record number to display.(See the next section for the record-display format and the whole scriptsection for details on the format and use of the $cmd variable.)
The file-locking routine for the database differs only inthe message that's displayed if a lock cannot be achieved. The messageincorporates enough WML code to complete the card, ensuring that the user getsthe failure message instead of a WML compile error.
Page 2 of 3
This article was originally published on February 1, 2003