due 01/29/01
This homework also contains a small project. The end result of this project will be a simple web guest-book application. Typical web guest-books work by allowing people on the web to fill in a form on your web page and submit this form to a program running on the web server. This program can then save the data submitted to a file containing the guest-book information. The guest-book program has to communicate with the web server in order to get its input data, what the person that filled in the form typed, and to output data back to the server to be shown to the person after they submit their data. This is done via the Common Gateway Interface (CGI). CGI is a very simple interface that will be explained in more detail later in this assignment. You are to have your web application installed and running on cubist.cs.washington.edu. By now, you should have received email account information for cubist. An example of the guest-book application you will be writing is available at: http://gurgle.cs.washington.edu/~hartline/cgi/show-guestbook.cgi.
Try these questions out before section on 01/18/01. First try to figure out the answers in your head. Then try typing them into the scheme interpreter.
(define x 5) (define y 4)What would the values of the following scheme expressions?
(let ((x 3) (z (+ x 1)) ) (* x y z) )
(let* ((x 3) (z (+ x 1)) ) (* x y z) )
(let* ((z (+ x 1)) (x 3) ) (* x y z) )
(list (let ((x 3) (z (+ x 1)) ) (* x y z) ) x y )
(define x 5) (define y 4) (define (foo x) (+ x y) ) (define (bar y) (foo y) )What is the value of
(bar 10)
(flatten `(1 ((2) 3) (4))) => (1 2 3 4)
These are some sample problems that we will be discussing in section on 01/18/01. Use the error function for handling errors.
;; assuming f has no side-effects and that ;; x and y are defined and are valid arguments to f (define g (curry f x)) (equal? (g y) (f x y)) => #t ;; more examples (define add5 (curry + 5)) (define add2 (curry + 2)) (add5 10) => 15 (add5 2) => 7 (add2 10) => 12
(filter number? '(a b 1 3 c 4 d)) => (1 3 4) (filter symbol? '(a b 1 3 c 4 d)) => (a b c d) (filter symbol? '()) => ()
Try these questions out before section on 01/25/01. First try to figure out the answers in your head. Then try typing them into the scheme interpreter.
(define a '(1 2 3)) (define b '(a b c)) (define c '(#t #f)) (define d '(4)) (define x (cons 10 a)) (define y (append a b)) (define z (list a c)) (set-car! a 99) (set-car! b 'z) (set-cdr! c '(9 10 11)) (set-cdr! d d)
What are the values of:
x
y
z
c
(car d)
(cadr d)
(caddr d)
(cadddr d)
These are some sample problems that we will be discussing in section on 01/25/01. Use the error function for handling errors.
(define x 0) (define (f) (set! x (+ x 1)) x ) (repeatl f 3) => (1 2 3) (repeatr f 3) => (6 5 4)
... <FORM ACTION=emailform.cgi METHOD=POST> <INPUT TYPE=TEXT NAME=TO SIZE=40> <INPUT TYPE=TEXT NAME=SUBJECT SIZE=40> <TEXTAREA NAME=TEXT COLS=60 ROWS=10> </TEXTAREA> <INPUT TYPE=SUBMIT VALUE="Send Email"> </FORM> ...The HTML form for a get looks like this:
... <FORM ACTION=websearch.cgi METHOD=GET> <INPUT TYPE=TEXT NAME=QUERY SIZE=40> <INPUT TYPE=SUBMIT VALUE="Search"> </FORM> ...
The following CGI script prints out ``Hello World'' in a web browser when invoked:
#!/usr/bin/guile -s !# (display "Content-type: text/html\n") ; Header: Output is HTML. (newline) ; End of headers. (display "<BLINK>Hello World</BLINK>")
Some discussion of the above CGI program:
The server encountered, like, an internal error or misconfiguration and was unable to complete your request "..." Bummer!
It means that your program was not executable or that it tried to print stuff out that did not look like the CGI script headers. There will be a link at the bottom of the error message that will sometimes give you more details. Usually it will say premature end of script headers. Typically when a Guile program crashes (one of the reasons for getting a premature end of script headers) it prints out messages to standard error. These messages can be looked at by viewing the system web server error log. One way to view this error log is to type, tail /www/htdocs/logs/error_log, from the cubist prompt. This prints out the end of the error log file.
CGI output can get fancier than this hello world program, but most CGI is not. CGI input is communicated from the web server to the CGI program through UNIX environment variables and sometimes the standard input. In Guile, you can get the value of a UNIX environment variable with the function getenv which works as follows (getenv is not a standard Scheme function):
guile> (getenv "USER") "hartline" guile> (getenv "SHELL") "/usr/bin/tcsh"You can tell whether the CGI program is invoked as get or post by looking at the environment variable REQUEST_METHOD. It will have value "GET" or "POST" respectively.
Modify the hello world CGI script above to read in the CGI input and print it out. You may use <PRE>...</PRE> tags in your output HTML so that the output is printed with a fixed width font. See http://cubist.cs.washington.edu/~hartline/test-forms.html.
Complete the following. You do not have to handle errors in input gracefully; however, if you want to you may use the error primitive function; e.g. (error "error in input"). Do not forget to turn in a print out of your source code as well as example executions of your code on test cases.
Some of the functions you are asked to implement in this assignment should call functions your wrote in Assignment 1. You may use either your own solutions from Assignment 1 or the posted solutions. However, please include these in your electronic turnin.
(foldl + 0 '(1 2 3)) => 6 (reverse '(1 2 3)) => (3 2 1)
(define (my-cons the-car the-cdr) (lambda (which) (cond ((eq? which 'car) the-car) ((eq? which 'cdr) the-cdr) (else (error "cons cell usage error")) ) ) ) (define (my-car the-pair) (the-pair 'car) ) (define (my-cdr the-pair) (the-pair 'cdr) )Define my-set-car! and my-set-cdr!. You may make any modifications to the above definitions that you need (but you may not use primitives car, cdr, cons, set-car!, or set-cdr!).
NAME1=VALUE1&NAME2=VALUE2&NAME3=VALUE3Here NAME1, VALUE1, etc. are arbitrary strings that are encoded such that:
You'll note that the decode-hex-string from Assignment 1 will correctly decode NAME1, VALUE1, etc.
Write a function parse-cgi that takes a string of the above form as its only input and returns an association list (R4RS 6.3). That is a list of lists of the form:
((NAME1 VALUE1) (NAME2 VALUE2) ...)For example:
(parse-cgi "FOO=this+is+a+test&B+A+R=In+hex+5+%2b+5+is+%27a%27.") => (("FOO" "this is a test") ("B A R" "In hex 5 + 5 is 'a'."))Your implementation of parse-cgi should not be recursive (nor should your write any recursive helper functions besides decode-hex-string and split that you wrote in Assignment 1). Instead, use map.
See http://gurgle.cs.washington.edu/~hartline/cgi/show-guestbook.cgi for an example implementation.
To open a file for appending, use the Guile builtin function (open-file <file-name> ä"). This returns a file handle much like (open-output-file <file-name>) does, except that new data written to the file will go at the end of the file instead of replacing its current contents (open-file is not a standard Scheme function).
You will be graded on the style; your organization of scheme code, appropriate use of side-effects, and use of higher order functions; as well as the correctness of your implementation.