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 &amp; ham'>
     >>> htmltext('The response was: %s') % response
     <htmltext 'The response was: green eggs &amp; 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 &lt;HEAD&gt;</title>
+      <meta name="description" 
+       content="Discusses the &quot;LINK&quot; and &quot;META&quot; 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