[version 1.1.0 ediware**20091202052313 Ignore-this: e7a10769846d0e7480a855609bd7c7d1 ] { hunk ./CHANGELOG.txt 1 +Version 1.1.0 +2009-12-01 +Allowed additional headers to be function designators (suggested by Xiangjun Wu) +Be more liberal when parsing cookies (thanks to Andrei Stebakov) +Added HTTP method PATCH (thanks to Xiangjun Wu) +Don't send GET parameters again when redirecting (reported by Eugene Ossintsev) +Solidify feature expressions (thanks to Joshua Taylor) +Make SEND-COOKIE-P work for pathless URIs (thanks to Tomo Matsumoto) + hunk ./cookies.lisp 114 - (starts-with-p (uri-path uri) (cookie-path cookie)) + (starts-with-p (or (uri-path uri) "/") (cookie-path cookie)) hunk ./cookies.lisp 252 - (with-sequence-from-string (stream string) - (loop with *current-error-message* = (format nil "While parsing cookie header ~S:" string) - for first = t then nil - for next = (and (skip-whitespace stream) - (or first (assert-char stream #\,)) - (skip-whitespace stream) - (skip-more-commas stream)) - for name/value = (and next (read-name-value-pair stream - :cookie-syntax t)) - for parameters = (and name/value (read-name-value-pairs stream - :value-required-p nil - :cookie-syntax t)) - while name/value - collect (list (car name/value) (cdr name/value) parameters)))) + (let ((*current-error-message* (format nil "While parsing cookie header ~S:" string)) + result) + (dolist (substring (split-set-cookie-string string)) + (with-sequence-from-string (stream substring) + (let* ((name/value (read-name-value-pair stream :cookie-syntax t)) + (parameters (read-name-value-pairs stream :value-required-p nil :cookie-syntax t))) + (push (list (car name/value) (cdr name/value) parameters) result)))) + (nreverse result))) hunk ./doc/index.html 657 -The current version is 1.0.0. Drakma can be installed +The current version is 1.1.0. Drakma can be installed hunk ./doc/index.html 663 -and Chunga (1.0.0 or higher). +and Chunga (1.1.0 or higher). hunk ./doc/index.html 938 -additional-headers is a -name/value alist -(like parameters) of additional HTTP headers which -should be sent with the request. +additional-headers +is a +name/value alist +of additional HTTP headers which should be sent with the request. +Unlike in parameters, the cdrs can not only be +strings but also designators for unary functions (which should in turn +return a string) in which case the function is called each time the +header is written. hunk ./drakma.asd 41 -(defvar *drakma-version-string* "1.0.0" +(defvar *drakma-version-string* "1.1.0" hunk ./request.lisp 160 - #+:clisp #+:clisp - (flexi-stream-element-type stream) element-type)) + #+:clisp (flexi-stream-element-type stream) + #+:clisp element-type)) hunk ./request.lisp 207 - #+openmcl + #+:openmcl hunk ./request.lisp 324 -ADDITIONAL-HEADERS is a name/value alist \(like PARAMETERS) of -additional HTTP headers which should be sent with the request. +ADDITIONAL-HEADERS is a name/value alist of additional HTTP headers +which should be sent with the request. Unlike in PARAMETERS, the cdrs +can not only be strings but also designators for unary functions +\(which should in turn return a string) in which case the function is +called each time the header is written. hunk ./request.lisp 452 + :write-timeout hunk ./request.lisp 454 - :write-timeout write-timeout + write-timeout hunk ./request.lisp 460 - #+openmcl #+openmcl - :deadline deadline + #+:openmcl :deadline + #+:openmcl deadline hunk ./request.lisp 463 - #+openmcl + #+:openmcl hunk ./request.lisp 549 - do (write-header name "~A" value)) + do (write-header name "~A" + (cond ((or (functionp value) (symbolp value)) + (funcall value)) + (t value)))) hunk ./request.lisp 663 + ;; don't send GET parameters again in redirect + :parameters (and (not (eq method :get)) parameters) hunk ./specials.lisp 54 + :patch hunk ./util.lisp 283 + +(defun split-set-cookie-string (string) + "Splits the string STRING which is assumed to be the value of a +`Set-Cookie' into parts corresponding to individual cookies and +returns a list of these parts \(substrings). + +The string /should/ be split at commas, but heuristical approach is +used instead which doesn't split at commas which are followed by what +cannot be recognized as the start of the next cookie. This is +necessary because servers send headers containing unquoted commas +which are not meant as separators." + ;; this would of course be a lot easier with CL-PPCRE's SPLIT + (let ((cookie-start 0) + (string-length (length string)) + search-start + result) + (tagbody + ;; at this point we know that COOKIE-START is the start of a new + ;; cookie (at the start of the string or behind a comma) + next-cookie + (setq search-start cookie-start) + ;; we reach this point if the last comma didn't separate two + ;; cookies or if there was no previous comma + skip-comma + (unless (< search-start string-length) + (return-from split-set-cookie-string (nreverse result))) + ;; look is there's a comma + (let* ((comma-pos (position #\, string :start search-start)) + ;; and if so, look for a #\= behind the comma + (equals-pos (and comma-pos (position #\= string :start comma-pos))) + ;; check that (except for whitespace) there's only a token + ;; (the name of the next cookie) between #\, and #\= + (new-cookie-start-p (and equals-pos + (every 'token-char-p + (trim-whitespace string + :start (1+ comma-pos) + :end equals-pos))))) + (when (and comma-pos (not new-cookie-start-p)) + (setq search-start (1+ comma-pos)) + (go skip-comma)) + (let ((end-pos (or comma-pos string-length))) + (push (trim-whitespace (subseq string cookie-start end-pos)) result) + (setq cookie-start (1+ end-pos)) + (go next-cookie)))))) + + }