[hunchentoot-devel] multiple POST/GET values
Jaap de Heer
jaap at streamtech.nl
Mon Jul 21 18:54:41 UTC 2008
Howdy,
I ran into trouble with Hunchentoot trying to process the result
of a form containing a select multiple:
<select multiple name="foo-or-bar">
<option value="foo">Foo
<option value="bar">Bar
</select>
The user can select both foo and bar, which results in both being
submitted.
In the POST request, this looks something like:
"other-field-1=x&foo-or-bar=foo&foo-or-bar=bar&other-field-2=x"
Hunchentoot will pick up on only one of them, i.e.
(get-post-parameter "foo-or-bar") will be either "foo" or
"bar" but not both; it should be both.
I've baked a patch for this that will make (get-post-parameter)
et al return a list containing all submitted values for this
field, if there is more than 1 value; otherwise, it just returns
the string as usual.
My Lisp fu is limited, and this is only one of a few possible
solutions, so feel free to write a better one ;-)
BTW. I suppose the same problem and fix applies for multiple
checkboxes with the same names, and (though this may be invalid)
even multiple <input> fields with the same name.
Cheers,
Jaap
--- util.lisp.org 2008-07-21 20:29:31.000000000 +0200
+++ util.lisp 2008-07-21 20:29:57.000000000 +0200
@@ -168,6 +168,25 @@
(loop for code across (md5:md5sum-sequence string)
do (format s "~2,'0x" code))))
+(defun group-by (lst &key (key #'identity) (test #'eq))
+ "Transform a sorted list into a list of lists, grouping together elements with equal key."
+ (labels ((lp (lst result current-group)
+ (cond ((null lst) (nreverse (if (null current-group)
+ result
+ (cons (nreverse current-group) result))))
+ ((or (null current-group)
+ (funcall test
+ (funcall key (first lst))
+ (funcall key (first current-group))))
+ (lp (rest lst)
+ result
+ (cons (first lst) current-group)))
+ (t
+ (lp (rest lst)
+ (cons (nreverse current-group) result)
+ (list (first lst)))))))
+ (lp lst nil nil)))
+
(defun escape-for-html (string)
"Escapes the characters #\\<, #\\>, #\\', #\\\", and #\\& for HTML output."
(with-output-to-string (out)
@@ -281,12 +300,18 @@
&optional (external-format *hunchentoot-default-external-format*))
"Converts a list FORM-URL-ENCODED-LIST of name/value pairs into an
alist. Both names and values are url-decoded while doing this."
- (mapcar #'(lambda (entry)
- (destructuring-bind (name &optional value)
- (split "=" entry :limit 2)
- (cons (string-trim " " (url-decode name external-format))
- (url-decode (or value "") external-format))))
- form-url-encoded-list))
+ (mapcar (lambda (x) (cons (caar x)
+ (if (> (length x) 1)
+ (mapcar #'cdr x)
+ (cdar x))))
+ (group-by (sort (mapcar #'(lambda (entry)
+ (destructuring-bind (name &optional value)
+ (split "=" entry :limit 2)
+ (cons (string-trim " " (url-decode name external-format))
+ (url-decode (or value "") external-format))))
+ form-url-encoded-list)
+ #'string< :key #'car)
+ :key #'car :test #'equal)))
(defun url-encode (string &optional (external-format *hunchentoot-default-external-format*))
"URL-encodes a string using the external format EXTERNAL-FORMAT."
More information about the Tbnl-devel
mailing list