[Zope-dev] Another fix for UserDB

Phillip J. Eby pje@telecommunity.com
Tue, 22 Jun 1999 12:07:48 -0500


When you use UserDB cookie authentication to log in on a URL that is a GET
form with a query string, the page you were originally going to acts as
though the query string weren't there.  That's because cgi.FieldStorage
only pays attention to the query string as a source of fields if the
request is a GET or HEAD, and the default login document for UserDB has a
POST method.  Further, if you log in to a page that is a POST form, the
field data from the original POST will be gone.  There is, however, a
simple solution to both problems.  First, change the ACTION="" attribute of
the FORM tag to remove the

<!--#if QUERY_STRING-->?<!--#var QUERY_STRING--><!--#/if-->

block.  It is superfluous, since Zope will subsequently ignore the query
string anyway.

Second, add the following block somewhere within the FORM block
(indentation added for clarity):

<!--#in "REQUEST.form.items()"-->
<!--#if "_['sequence-key'] not in ('__ac_name','__ac_password')"-->
<input type="hidden" 
       name="<!--#var sequence-key html_quote-->"
       value="<!--#var sequence-item html_quote-->">
<!--#/if-->
<!--#/in-->

This will add in any form variables from the original request, whether they
came from the query string or a POST form.  The loop checks and excludes
__ac_name and __ac_password from the hidden fields, in case the page is
being redisplayed due to a bad login.

Note that this is only a partial fix, however.  For example, it doesn't
check for multi-valued fields such as tokens, lines, lists, etc.  And
non-string fields (e.g. integers) will turn into strings.  :(  So short of
writing an ExternalMethod to marshal arbitrary objects into hidden fields,
this is as good as it gets.  If at some point I write code that can do the
marshalling, I'll post it here.  Meanwhile, this is good enough for the
relatively small number of entry points in my existing apps.