[araneida: html-escaped-stream Alan-Shields@omrf.ouhsc.edu**20051018190807 Trying to keep track of whether or not you've escaped the HTML properly is quite a pain. Doing it instead at the stream level seems to work out much better. Of course, if you have code that already does escaping then you shouldn't use this call. ] { hunk ./defpackage.lisp 43 - :html :html-escape :html-stream :search-html-tree + :html :html-escape :html-stream :html-escaped-stream :search-html-tree hunk ./html.lisp 48 +(defun html-attr-escaped (attr) + (with-output-to-string (o) + (loop for (att val . rest) on attr by #'cddr do + (if (symbolp att) + (progn + (princ " " o) + (princ (string-downcase (symbol-name att)) o) + (princ "=\"" o) + (princ (html-escape val) o) + (princ "\"" o)) + (error "attribute ~S is not a symbol in attribute list ~S" att attr))))) + hunk ./html.lisp 123 + t) + +(defun html-escaped-stream (stream things &optional inline-elements) + "Format supplied argument as HTML, escaping properly. +Just like html-stream except certain things are now html-escaped. +Content - in '(p \"foo\") \"foo\" is the content - is escaped, +as well as the values of attributes. Please note that this CAN +result in double escaping if calling code also escapes." + (declare (optimize (speed 3)) + (type stream stream)) + (cond ((and (consp things) (not (stringp (car things)))) + (let* ((tag (if (consp (car things)) (caar things) (car things))) + (attrs (if (consp (car things)) (cdar things) ())) + (content (cdr things))) + (if (not (empty-element-p tag)) + (progn + (format stream "<~A~A>" (string-downcase (symbol-name tag)) (html-attr-escaped attrs)) + (dolist (c content) + (html-escaped-stream stream c inline-elements)) + (format stream "~A>~:[~;~%~]" (string-downcase (symbol-name tag)) (not (member tag inline-elements)))) + (format stream "<~A~A>" (string-downcase (symbol-name tag)) (html-attr-escaped attrs))))) + ((consp things) + (dolist (thing things) (princ thing stream))) + ((keywordp things) + (format stream "<~A>" (string-downcase (symbol-name things)))) + ((functionp things) + (funcall things stream)) + (t + (princ (html-escape things) stream))) hunk ./test-server-walker.pl 58 +# HTML stream basics +urlin "/html/html-stream", qr[\s*
+ \s*\s*\s*foo\s*\s*
+ \s*\s*\s*foo\s&\#62;\sbar\s*\s*
+ \s*