2 ;; @description Basic CGI processing tools for GET and POST requests
3 ;; @version v 2.2 - comments redone for automatic documentation
4 ;; @author Lutz Mueller, lutz@nuevatec.com
6 ;; This module defines basic CGI processing tools for processing
7 ;; CGI GET and POST requests and cookies.
9 ;; Include this file at the beginning of each file performing CGI processing:
11 ;; (load "/usr/share/newlisp/modules/cgi.lsp")
14 ;; <center><h2>Overview</h2></center>
15 ;; On loading 'cgi.lsp' will retrieve 'GET', 'POST' and cookie
16 ;; parameters via standard input and the environment variables:
17 ;; 'QUERY_STRING' and 'HTTP_COOKIE'. These environment variables are set
18 ;; by the webserver (tested with Apache 1.3). The webserver is receiving information
19 ;; back from 'cgi.lsp' via std I/O channels.
21 ;; After having loaded this file all parameters from either 'GET' or 'POST'
22 ;; method are stored as an association list and in 'CGI:params'
23 ;; and individual parameters can be accessed using 'CGI:get'.
25 ;; All cookies can be accessed in an association list 'CGI:cookies' and
26 ;; are accessed similar to the 'GET' and 'PUT' parameters using 'CGI:get-cookie'.
27 ;; A function 'CGI:set-cookie' is available for setting cookies.
29 ;; The function 'CGI:put-page' outputs a HTML page to the webserver after
30 ;; processing newLISP source embedded in '<%' and '%>' tags.
32 ;; 'CGI:params' and 'CGI:cookies' contain the empty list '()' when no
33 ;; parameters or cookies are present
35 ;; The function 'CGI:put-page' can be used to output web pages containing
36 ;; newLISP source embedded in <%, %> tags. Inside these tags are newLISP
37 ;; statements printing output/HTML to the webpage.
41 ;; @syntax (CGI:put-page <str-file-name>)
42 ;; @return The page output to standard out.
44 ;; Processes an HTML page by evaluating newLISP source
45 ;; embedded into the HTML text between '<%' and '%>' tags.
46 ;; The newLISP source typically contains 'print' and 'println'
47 ;; statements to output strings to standard out.
52 ;; <% (set 'site "example.com") %>;
53 ;; <a href="http://<% (print site) %>"><% (print site) %></a>
62 ;; <a href="http://example.com">example.com</a>
67 (define (put-page file-name
, page start end
)
68 (set 'page
(read-file file-name
))
69 (set 'start
(find "<%" page
))
70 (set 'end
(find "%>" page
))
71 (while (and start end
)
72 (print (slice page
0 start
))
74 (eval-string (slice page
(+ start
2) (- end start
2)))
76 (set 'page
(slice page
(+ end
2)))
77 (set 'start
(find "<%" page
))
78 (set 'end
(find "%>" page
)))
81 ;; @syntax (CGI:url-translate <str-url-format>)
82 ;; @return An ASCII formatted string.
84 ;; Translates all URL formatted characters to ASCII. Translates '+' into spaces
85 ;; and '%nn' hexdigits into characters. 'nn' is a 2-nibble hex number.
88 ;; (CGI:url-translate "What+time+is+it%3f") => "What time is it?"
90 (define (url-translate str
)
92 (replace "%([0-9A-F][0-9A-F])" str
(char (int (append "0x" $
1))) 1))
95 ; This is not an user function, but used internally.
97 ; get-vars returns all parameter value pairs in an association list
98 ; i.e.: ( ("name" "johndoe") ("password" "secret") )
99 ; they can than be accessed using:
100 ; (assoc "name" params) => "johndoe"
101 ; where params is the return value from get-vars
103 (define (get-vars input
, var value var-value
)
104 (set 'vars
(parse input
"&"))
108 (set 'var
(first (parse elmnt
"=")))
109 (set 'value
((+ (find "=" elmnt
) 1) elmnt
)))
113 (push (list var
(url-translate value
)) var-value
))
117 ; get QUERY_STRING parameters from GET method if present
119 (set 'params
(env "QUERY_STRING"))
120 (if (not params
) (set 'params
""))
122 (set 'params
(get-vars params
)))
124 ; get stdin POST method parameters if present
126 (set 'inline
(read-line))
128 (set 'params
(get-vars inline
)))
130 (if (not params
) (set 'params
'()))
134 (if (env "HTTP_COOKIE")
135 (dolist (elmnt (parse (env "HTTP_COOKIE") ";"))
136 (set 'var
(trim (first (parse elmnt
"="))))
137 ; (set 'value (trim (last (parse elmnt "="))))
138 (set 'value
(slice elmnt
(+ 1 (find "=" elmnt
))))
139 (push (list var value
) cookies
))
142 ;; @syntax (CGI:set-cookie <str-var> <str-value> <str-domain> <str-path>)
143 ;; @param <str-var> The cookie variable name as a string.
144 ;; @param <str-value> The cookie value as a string.
145 ;; @param <str-domain> The domain where to set the cookie.
146 ;; @param <str-path> The path for the domain.
147 ;; @return The string sent to standard out by 'CGI:set-cookie'.
149 ;; This function should be called immedeately before
150 ;; closing the header with '(print "Content-type: text/html\r\n\r\n")',
151 ;; which is typically the first statement in a CGI script written in
152 ;; newLISP after the '(load "cgi.lsp")' statement.
157 ;; (CGI:set-cookie "password" "secret" "asite.com" "/somedir")
158 ;; (print "Content-type: text/html\r\n\r\n")
161 (define (set-cookie var value domain path
)
162 (set 'value
(string value
))
163 (print (format "Set-Cookie: %s=%s; domain=.%s; path=%s;\n" var value domain path
)))
166 ;; @syntax (CGI:get-cookie <str-key>)
167 ;; @param <str-key> The string for the cookie variable name.
168 ;; @return The string for the cookie value.
171 ;; (CGI:get-cookie "login") => "somebody"
173 (define (get-cookie keystr
)
174 (lookup keystr cookies
) )
176 ;; @syntax (CGI:get <str-key>)
177 ;; @param The name of the 'GET' or 'POST' variable as a string.
178 ;; @return The value string of the 'GET' or 'POST' variable.
181 (lookup keystr params
))
184 ;; (CGI:get "city") => "San Francisco"