* Patch for guile-www-2.9 (www cgi), multiple fixes
@ 2005-04-12 1:09 Alan Grover
0 siblings, 0 replies; only message in thread
From: Alan Grover @ 2005-04-12 1:09 UTC (permalink / raw)
Fixes the following:
* Change a use-module statement to (ice-9 optargs) instead of (ice-9
optargs-kw). Not deeply investigated.
* Tolerates query-strings without a "=" for empty names. Thus:
http://gnu.org?a=1&b will give two names (a and b), where b has the
value "".
* Tolerates query-strings where the name is empty. Thus:
http:/gnu.org?=b will give a key of "" whose value is b.
* Applies url-decode to each name. Thus: http://gnu.org?x%26y=1 will
give a name of "x=y" whose value is 1.
* Adds the variable cgi:names-values which holds the parsed name/value
pairs in the same order as found in the query-string: ("a" . 1) ("b" .
2), etc. If a name repeats, it also repeats in the list.
* Should be more friendly for mod-list/fastcgi style use. The "cgi:init"
function should re-initialize the module completely (not thoroughly
tested: works for query-string parsing).
This incorporates fixes to bugs reported by awgrover@mail.msen on 11
April 2005:
* guile-www-2.9 (www cgi) names in query-string not url-decoded
* guile-www-2.9 (www cgi) form-data loses original order
* guile-www-2.9 (www cgi) bad cgi:values when a name has no "="
* guile-www-2.9 (www cgi) does not support mod-lisp/fastcgi style uses
* guile-www uses obsolete optargs-kw
Notes:
* Does not use shared-substrings (these are deprecated).
* I did not concern myself with time/space optimization since
query-string parsing happens only once per request, and the query-string
is typically of reasonable size. Instead of append!, one could cons onto
the head and reverse later. No doubt other optimizations can be done.
Patch:
cgi.scm
< #:use-module (ice-9 optargs-kw))
<
---
> #:use-module (srfi srfi-1)
> #:use-module (ice-9 optargs))
42c42,44
< (define *env-alist*
---
> (define *env-alist* #f)
> (define (make-env-alist)
> (set! *env-alist*
97c99
< #\, types)))))))))
---
> #\, types))))))))))
116a119,120
> (make-env-alist)
> (set! form-variables '())
178a183,187
> ;; Return the key-value pairs (as cons), in the
> ;; order they appeared. Thus, you can exactly reconstruct the
query-string.
> ;;
> (define-public cgi:names-values #f) ; Stable order of name-value pairs
>
179a189
> ;; At least '(). It is possible for a name to be "".
273,290c283,336
< (define (parse-form raw-data)
< ;; get-name and get-value are used to parse individual `name=value'
pairs.
< ;; Values are URL-encoded, so each must be decoded.
< (define (get-name pair)
< (let ((p (string-index pair #\=)))
< (and p (subs pair 0 p))))
< (define (get-value pair)
< (let ((p (string-index pair #\=)))
< (and p (url-coding:decode (subs pair (+ p 1))))))
< (for-each (lambda (pair)
< (let* ((name (get-name pair))
< (value (get-value pair))
< (old-value (cgi:values name)))
< (set! form-variables
< (assoc-set! form-variables
< name
< (cons value (or old-value '()))))))
< (separate-fields-discarding-char #\& raw-data)))
---
> ; The results are nearly stable. cgi:names will give
> ; the names back as they are left-to-right in the query-string,
> ; and the cgi:values will be in the original left-to-right order.
> ; Except, if a name appears more than once in the query-string,
> ; it will only appear once in cgi:names, in the first position.
> ;
>
> (define (parse-form qstring)
> "url-decoded (key . values), values is "" if no value. updates
form-variables"
> (set! cgi:names-values '())
> (let* (
> (dictionary '()) ; alist for key . (values)
> (key-value-strings
> (filter (lambda (x) (not (eq? x '()))) ; remove empties (e.g.
"&&")
> (string-split qstring #\& ))) ; split on &
> (split-to-key-value (lambda (kv-string)
> (let* (
> (index-of-equals (string-index kv-string #\=)) ; find '='
> (key ; key part
> (begin
> (if index-of-equals
> (if (> index-of-equals 0)
> (substring kv-string 0 index-of-equals )
> "") ; '=' at beginning
> (if (> (string-length kv-string) 0)
> kv-string
> #f)))) ; 0 length, which shouldn't happen here
> (value ; value part (as list) or #f
> (if (and key index-of-equals (< index-of-equals (-
(string-length kv-string) 1)))
> (substring kv-string (+ index-of-equals 1))
> #f))
> )
> (if key
> (cons (url-coding:decode key) (if value (url-coding:decode
value) #f))
> #f))))
> (update-dictionary (lambda (kv)
> "The assoc list is kept in order of query-string, append entry
or value"
> (let* (
> (key (car kv)) ; don't call with #f for key
> (value (cdr kv))
> (current-entry (assoc key dictionary))
> )
> (if current-entry
> (append! (cdr current-entry) (list value))
>
> (set! dictionary (append! dictionary (list (cons key (list
(or value "")))))))
> )))
> )
> (begin
> (for-each update-dictionary ; insert into dictionary (or
append values)
> (filter identity ; remove empty key-value, e.g. "="
> (map split-to-key-value
> key-value-strings ))) ; get "k=v"
> (set! form-variables dictionary))))
--
Alan Grover
awgrover@mail.msen.com
+1.734.476.0969
_______________________________________________
Bug-guile mailing list
Bug-guile@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-guile
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-04-12 1:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-12 1:09 Patch for guile-www-2.9 (www cgi), multiple fixes Alan Grover
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).