Milestone 2 - Target Date: 12/5
You'll be reading some and writing a bit of Perl code for this milestone. In particular, you will be working on the step 6 of the process shown on the application structure diagram.The basic idea here is that cseBay will have many web pages. Some of what goes on the web page is data obtained from the DB, but much of it is likely to be just static text (and possibly images, etc.). We have to use (
perl) code to talk with the DB, and so to compose the data dependent parts of the pages, but we'd rather not hardcode what a page looks like into a program. Instead, we'd like decisions about how to lay out the data to be represented in data files.We do that by creating files that are basically
.html, except that:To distinguish these files from
- They contain only content that comes between <body> and </body> tags (i.e., not the
HTMLheader, nor the closing tags of the document.- They contain placeholder tokens of the form %NAME% that indicate places in the document to place data obtained from the DB.
.htmlfiles, we give them the file extent.template. We won't be reading anything from the DB for this milestone, but we will be implementing the basic scheme of substituting some value for placeholder (%NAME%) tokens.Here is an example
.templatefile. You can see how it might be used (eventually, when all milestones are completed) here.Name/Value Maps
(This description is generic only. How this is actually implemented inperlis described next.)A map is composed of two parts, a 1-d array of strings, NAMES[K], and a 2-d array of values, VALUES[N][K]. If %NAMES[k]% is seen in a
.templatefile, it should be replaced by VALUES[n][k], for an n described next.In the usual case, we replace %NAMES[k]% with VALUES[0][k]. However, sometimes we want a single line of the
.templatefile to expand into a list. In our example.templatefile, we do this because we want to create a table with a number of rows that depends on how many cseBay users there are in the DB (which we don't know when we're writing the.templatefile). We indicate that we want a list by beginning the template file line with '{' and ending it with '}'. Lines flagged in that way should have %NAME% replacement applied to them N times (where N is the number of rows in the VALUES array). We use row 0<n<N of the VALUES array to produce the nth output line. Each of the N substitutions occurs based on the original line from the.templatefile -- that is, the substitutions are not cumulative.Map Implementation in
perlA (cseBay) map is implemented inperllike this:![]()
The "(....)"s are
perlarrays. The arrows areperlreferences. This map says that substitutions should occur for tokens %ONE%, %TWO%, etc., and that if the input line is not enclosed in braces the substitutions should be "First %ONE% val", etc.Setup
I've dumped the starter files into yourcvsrepository. To get them,cdinto your working directory andcvs update -d. That should introduce the following files into your working directory:Makefile index.html templateDebug.pm htmlTemplates processTemplate.pm templateTest.cgihtmlTemplatesis a directory containing:Makefile listUsers.template templateTest.template userBids.template(as well as theCVSdirectory CVS creates itself).Running the Test Program
The starter files you just fetched include a single test case,templateTest.cgi.Running Locally (as a Program)
You can run it locally, on whatever machine your working directory is on (so long as you have a version ofperlinstalled on that machine):perl templateTest.cgiA bunch of output should appear: because it's a .cgi, anHTTPheader followed by a lot ofHTML.Alternatively, you can run the program under the debugger:
perl -d templateTest.cgiThat will let you step through your code. (You can also type arbitraryperlstatements in at any time, e.g.,print $myVar;.)The upside of this approach is that it is convenient: you don't have to be connected to debug, for instance. The downside is that the output, being
HTMLis tough to read. You can address that by redirecting the output from your execution to a file, and then drag-and-drop'ing the output file onto Mozilla.Running as a .cgi (on abstract)
If you copy all the files to yourabstract:www/cse490cdirectory, you can run your code as a.cgiusing Mozilla:http://abstract.cs.washington.edu/~<yourlogin>/templateTest.cgiThis is a satisfying experience, but it's a lot harder to debug a.cgithan a program (because you have put the web server, the browser, andHTTPbetween you and your bugs).The
Makefilewill automate copying everything to yourabstractaccount if you want to try this, though. You must first create directorywww/cse490c/htmlTemplatesonabstractfor it to work.Note: On a least one windows machine I use,
scp'ing my files toabstractends up with the horrible end of line problem: I have '\r' characters in the files. This prevents the.cgifrom being launched.To deal with that, I wrote a routine, deWinify.c, that gets rid of them, and a shell script, deWin.sh that invokes
deWinify, and a.cgi, deWin.cgi, that lets me rundeWin.shfrom a link on a web page.If you find you need them, (a) copy them all to your
wwwdirectory onabstract, and then (b) compile the.cto produce an executable nameddeWinify. You can execute./deWin.shwhile logged into abstract, or you can embed this link in a web page and invoke the thing remotely:<a href="http://abstract.cs.washington.edu/~yourlogin/cse490c/deWin.cgi">deWinify me!</a>What To Do
This page shows what your code will produce, once it's working. (It also is intended to be useful in understanding what maps are, what templates are, and how they're useful.)Control flow starts in
templateTest.cgi. It creates a test map, then calls some library routines to print out the various sections of its output.templateTest.cgiis a fully working program - you don't have to do anything to it.In fact, the only code required is in two well-marked locations in
processTemplate.pm. A.pmfile is aperllibrary. If you look intemplateTest.cgi, you'll see at the topuse processTemplate; use templateDebug;That imports the two libraries it uses. If you look at the top ofprocessTemplate.pmyou'll see a small set of syntax-challenged statements that enable and control exporting of the routines in that file for use in otherperlprograms. For this assignment, there's no need to worry about the details of all that, though. ("It just works.")In
processTemplate.pmare two spots marked withThe second one is in routine# CODE MISSING HEREProcessTemplate, which is called directly fromtemplateTest.cgi. This routine takes a filename and a map and is supposed to return a string representing the contents of the file after applying the substitutions indicated by the map.There is code in that routine already to read each line of the file, and to apply the "standard map" to it, a map that replaces the string %TIME% with a string representing the current time, for instance. (The standard map is implemented in that file, so you can easily find the details if you want.) What is missing is code to apply the map supplied as an argument to the call. You need to provide that.
The other missing piece of code is in routine
ApplyMap.ApplyMaptakes a string, a map, and an integer index. It does replacement on the string using the names in the map and the row of the values array given by the index. It returns the results of those replacements.