Discussion:
escaping attributes question
Simon Cusack
2007-05-22 04:03:50 UTC
Permalink
Hi all,

I have read the syntax and semantics chapter and was just wondering why
values in the attribute position aren't escaped by default? Or is there
something I am missing?

- sim
Mac Chan
2007-05-22 04:50:12 UTC
Permalink
Post by Simon Cusack
I have read the syntax and semantics chapter and was just wondering why
values in the attribute position aren't escaped by default? Or is there
something I am missing?
I guess it's the same reason why body text ain't escaped by default,
because the lib can't assume too much about that data that you are
feeding.

In my experience 95% of the time the attribute values are constant
html attributes like :width "100%" or :colspan 2 etc that don't
require escaping.

But your use case might be different.

-- Mac
Simon Cusack
2007-05-22 06:02:51 UTC
Permalink
Hi Mac,
----- Original message -----
Date: Mon, 21 May 2007 21:50:12 -0700
Subject: Re: [cl-who-devel] escaping attributes question
Post by Simon Cusack
I have read the syntax and semantics chapter and was just wondering why
values in the attribute position aren't escaped by default? Or is there
something I am missing?
I guess it's the same reason why body text ain't escaped by default,
because the lib can't assume too much about that data that you are
feeding.
Values in the attribute position get treated differently to body text
already. They are included in the html stream by default and the
result of lisp forms are emited when used in this position.

It just feels natural to me that it goes the extra step and also
escapes the value so that it is 'safe'.
In my experience 95% of the time the attribute values are constant
html attributes like :width "100%" or :colspan 2 etc that don't
require escaping.
But your use case might be different.
-- Mac
Well I'm in the unfortunate position where we regularly included the
results of calculations as attributes for a javascript library to hook
into. Something like the following is pretty common.

(defun emit-ajaxy-button (url)
(with-html-output (*html-stream*)
((:input :type :button :onclick (format nil
"javascript:doMyAjaxyThing('~A')" url)) "whatever...")))

It gets pretty messy having to remember which ones to escape all the
time.

I patched my convert-attributes (added calls to escape-string code in
all caps)
to do the following;

(defun convert-attributes (attr-list)
"Helper function for CONVERT-TAG-TO-STRING-LIST which converts the
alist ATTR-LIST of attributes into a list of strings and/or Lisp
forms."
(declare (optimize speed space))
(loop with =var= = (gensym)
with attribute-quote = (string *attribute-quote-char*)
for (attr . val) in attr-list
unless (null val) ;; no attribute at all if VAL is NIL
if (constantp val)
if (and (eq *html-mode* :sgml) (eq val t)) ; special case
for SGML
nconc (list " " (string-downcase attr))
else
nconc (list " "
;; name of attribute
(string-downcase attr)
(format nil "=~C" *attribute-quote-char*)
;; value of attribute
(cond ((stringp val)
;; a string, just use it - this case is
;; actually not necessary because of
;; the last case
(ESCAPE-STRING val))
((eq val t)
;; VAL is T, use attribute's name
(string-downcase attr))
(t
;; constant form, PRINC it -
;; EVAL is OK here because of CONSTANTP
(ESCAPE-STRING (FORMAT NIL "~A" (eval
val)))))
attribute-quote)
end
else
;; do the same things as above but at runtime
nconc (list `(let ((,=var= ,val))
(cond ((null ,=var=))
((eq ,=var= t)
,(case *html-mode*
(:sgml
`(htm ,(format nil " ~A"
(string-downcase
attr))))
;; otherwise default to :xml
mode
(t
`(htm ,(format nil " ~A=~C~A~C"
(string-downcase
attr)
*attribute-quote-char*
(string-downcase
attr)
*attribute-quote-char*)))))
(t
(htm ,(format nil " ~A=~C"
(string-downcase attr)
*attribute-quote-char*)
(STR (ESCAPE-STRING (FORMAT NIL
"~A" ,=var=)))
,attribute-quote)))))))

It seems like a sane thing to do to me but was wondering if I had
missed the CL-WHO way of doing the same thing.

Any comments would be most appreciated.

- sim.
Edi Weitz
2007-05-22 06:35:58 UTC
Permalink
Post by Simon Cusack
It seems like a sane thing to do to me
Not to me because you never know where the data you feed into the the
macro comes from. It might as well be the case that it is already
escaped. Turning escaping on by default with no means of turning it
off seems very wrong to me.

Cheers,
Edi.
Simon Cusack
2007-05-22 07:07:59 UTC
Permalink
Hi Edi,
----- Original message -----
Date: Tue, 22 May 2007 08:35:58 +0200
Subject: Re: [cl-who-devel] escaping attributes question
On Tue, 22 May 2007 16:02:51 +1000, "Simon Cusack"
Post by Simon Cusack
It seems like a sane thing to do to me
Not to me because you never know where the data you feed into the the
macro comes from. It might as well be the case that it is already
escaped. Turning escaping on by default with no means of turning it
off seems very wrong to me.
Cheers,
Edi.
Yeah not being able to control it for special cases is bad.

But you know that all values in the attribute position are always
going to the html output stream and for it to be interpreted properly
it should be escaped.

The decision to always emit to the html stream rather than requiring
an esc, fmt or prn for all attribute values means that the values
being emitted here are already getting special treatment from CL-WHO.

If the default position is a hands off one, then strictly speaking
shouldn't all attribute values them be enclosed in (str ...), etal?

What if it was optional behaviour?

Regards, sim.
Edi Weitz
2007-05-22 20:04:43 UTC
Permalink
Post by Simon Cusack
But you know that all values in the attribute position are always
going to the html output stream and for it to be interpreted
properly it should be escaped.
The decision to always emit to the html stream rather than requiring
an esc, fmt or prn for all attribute values means that the values
being emitted here are already getting special treatment from
CL-WHO.
If the default position is a hands off one, then strictly speaking
shouldn't all attribute values them be enclosed in (str ...), etal?
I don't think so. The "evaluation model" (so to say) for the body is
different from the attribute values, because the body can contain
other, nested elements while the attribute values can only be
character content.

Loading...