Various revisions (quixote/doc/PTL.txt)
Andrew Kuchling <akuchlin-fVcApmY9cLvQ3/1i3zOLAti2O/[email protected]> Mon, 06 Jan 2003 15:05:38 -0500
| Newsgroups | gmane.comp.web.quixote.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /home/cvs/quixote/doc
In directory hewson:/tmp/cvs-serv17235
Modified Files:
PTL.txt
Log Message:
Various revisions
Index: PTL.txt
===================================================================
RCS file: /home/cvs/quixote/doc/PTL.txt,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- PTL.txt 2 Jan 2003 19:38:28 -0000 1.14
+++ PTL.txt 6 Jan 2003 20:05:35 -0000 1.15
@@ -4,16 +4,17 @@
Introduction
------------
-PTL is the templating language used by Quixote. PTL inverts the usual
-model used by web templating languages -- embed a real programming
-language in HTML -- by merely tweaking Python to make it easier to
-generate HTML pages (or other forms of text). In other words, PTL is
-basically Python with a novel way to specify function return values.
-Specifically, a PTL template is designated by inserting a ``[plain]`` or
-``[html]`` modifier after the function name. The value of expressions
-inside templates are kept, not discarded. If the type is ``[html]``
-then non-literal strings are passed through a function that escapes HTML
-special characters.
+PTL is the templating language used by Quixote. Most web templating
+languages embed a real programming language in HTML, but PTL inverts
+this model by merely tweaking Python to make it easier to generate
+HTML pages (or other forms of text). In other words, PTL is basically
+Python with a novel way to specify function return values.
+
+Specifically, a PTL template is designated by inserting a ``[plain]``
+or ``[html]`` modifier after the function name. The value of
+expressions inside templates are kept, not discarded. If the type is
+``[html]`` then non-literal strings are passed through a function that
+escapes HTML special characters.
Plain text templates
@@ -111,18 +112,28 @@
--------------
Since PTL is usually used to generate HTML documents, a ``[html]``
-template type has been provided to make generating HTML easier. When
-generating HTML, it is extremely difficult to correctly escape special
-characters. The PTL solution to this problem is to use a separate data
-type for data that does not need to be escaped. Any data that is not of
-this type will be converted to this type after escaping any special
-characters.
+template type has been provided to make generating HTML easier.
-In PTL, the separate data type is ``htmltext``. The function
-``htmlescape()`` is used to escape data and it returns a ``htmltext``
-instance. It does nothing if the argument is already ``htmltext``.
-Both ``htmltext`` and ``htmlescape`` are available in the global
-namespace of PTL modules.
+A common error when generating HTML is to grab data from the browser
+or from a database and incorporate the contents without escaping
+special characters such as '<' and '&'. This leads to a class of
+security bugs called "cross-site scripting" bugs, where a hostile user
+can insert arbitrary HTML in your site's output that can link to other
+sites or contain JavaScript code that does something nasty (say,
+popping up 10,000 browser windows).
+
+Such bugs occur because it's easy to forget to HTML-escape a string,
+and forgetting one is enough to open a hole. The PTL solution to this
+problem is to handle it for you, automatically escaping strings
+when generating HTML output.
+
+Here's how this feature works. PTL defines a class called
+``htmltext`` that represents a string that's already been HTML-escaped
+and can be safely sent to the client. The function ``htmlescape(string)``
+is used to escape data, and it always returns an ``htmltext``
+instance. It does nothing if the argument is already ``htmltext``.
+Both ``htmltext`` and ``htmlescape`` are available from the global
+namespace in PTL modules.
If a template function is declared ``[html]`` instead of ``[text]`` then
two things happen. First, all literal strings in the function become
@@ -141,18 +152,17 @@
>>> htmltext('a%s') % 'b'
<htmltext 'ab'>
>>> response = 'green eggs & ham'
- <htmltext 'The response was: green eggs & ham'>
>>> htmltext('The response was: %s') % response
<htmltext 'The response was: green eggs & ham'>
Note that calling ``str()`` strips the ``htmltext`` type and should be
avoided since it usually results in characters being escaped more than
once. While ``htmltext`` behaves much like a regular string, it is
-sometimes necessary to insert a ``str()`` inside a template in order to
-obtain a genuine string. For example, the ``re`` module requires
+sometimes necessary to insert a ``str()`` inside a template in order
+to obtain a genuine string. For example, the ``re`` module requires
genuine strings. We have found that explict calls to ``str()`` can
often be avoided by splitting some code out of the template into a
-helper function.
+helper function written in regular Python.
It is also recommended that the ``htmltext`` constructor be used as
sparingly as possible. The reason is that when using the htmltext
@@ -162,6 +172,41 @@
HTML code injected by a user. Don't escape HTML special characters
because I want them."
+Note that literal strings in template functions declared with
+``[html]`` are htmltext instances, and therefore won't be escaped.
+You'll only need to use ``htmltext`` when HTML markup comes from
+outside the template. For example, if you want to include a file
+containing HTML::
+
+ def output_file [html] ():
+ '<html><body>' # does not get escaped
+ htmltext(open("myfile.html").read())
+ '</body></html>'
+
+In the common case, templates won't be dealing with HTML markup from
+external sources, so you can write straightforward code. Consider
+this function to generate the contents of the ``HEAD`` element:
+
+ def meta_tags [html] (title, description):
+ '<title>%s</title>' % title
+ '<meta name="description" content="%s">\n' % description
+
+There are no calls to ``htmlescape()`` at all, but string literals
+such as ``<title>%s</title>`` have all be turned into ``htmltext``
+instances, so the string variables will be automatically escaped::
+
+ >>> t.meta_tags('Catalog', 'A catalog of our cool products')
+ <htmltext '<title>Catalog</title>
+ <meta name="description" content="A catalog of our cool products">\n'>
+ >>> t.meta_tags('Dissertation on <HEAD>',
+ ... 'Discusses the "LINK" and "META" tags')
+ <htmltext '<title>Dissertation on <HEAD></title>
+ <meta name="description"
+ content="Discusses the "LINK" and "META" tags">\n'>
+ >>>
+
+Note how the title and description have had HTML-escaping applied to them.
+(The output has been manually pretty-printed to be more readable.)
PTL modules