chiark / gitweb /
chpwd, userv.rc: Change Userv service protocol to parse options properly.
[chopwood] / cgi.py
diff --git a/cgi.py b/cgi.py
index 01fb868862dca5ad83ffaf8d76a8232cecca1b25..8009eafcd3f5abef6ee15a5c10abae9f602174a8 100644 (file)
--- a/cgi.py
+++ b/cgi.py
@@ -105,6 +105,7 @@ class HTTPOutput (O.FileOutput):
     """Constructor: initialize `headerp' flag."""
     super(HTTPOutput, me).__init__(*args, **kw)
     me.headerp = False
+    me.warnings = []
 
   def write(me, msg):
     """Output protocol: print a header if we've not written one already."""
@@ -126,6 +127,15 @@ class HTTPOutput (O.FileOutput):
     if METHOD == 'HEAD':
       HEADER_DONE()
 
+  def warn(me, msg):
+    """
+    Report a warning message.
+
+    The warning is stashed in a list where it can be retrieved using
+    `warnings'.
+    """
+    me.warnings.append(msg)
+
 def cookie(name, value, **kw):
   """
   Return a HTTP `Set-Cookie' header.
@@ -272,7 +282,8 @@ def page(template, header = {}, title = 'Chopwood', **kw):
   header = dict(header, content_type = 'text/html')
   OUT.header(**header)
   format_tmpl(TMPL['wrapper.fhtml'],
-              title = title, payload = TMPL[template], **kw)
+              title = title, warnings = OUT.warnings,
+              payload = TMPL[template], **kw)
 
 ###--------------------------------------------------------------------------
 ### Error reporting.
@@ -392,7 +403,7 @@ def cgiparse():
 
   ## Acquire the query string.
   if METHOD in ['GET', 'HEAD']:
-    q = getenv('QUERY_STRING')
+    q = ENV.get('QUERY_STRING', '')
 
   elif METHOD == 'POST':
 
@@ -401,7 +412,8 @@ def cgiparse():
     if not n.isdigit():
       raise U.ExpectedError, (500, "Invalid CONTENT_LENGTH")
     n = int(n, 10)
-    if getenv('CONTENT_TYPE') != 'application/x-www-form-urlencoded':
+    ct = getenv('CONTENT_TYPE')
+    if ct != 'application/x-www-form-urlencoded':
       raise U.ExpectedError, (500, "Unexpected content type `%s'" % ct)
     q = SYS.stdin.read(n)
     if len(q) != n:
@@ -418,7 +430,8 @@ def cgiparse():
     else:
       PARAM.append((k, v))
       if k in seen:
-        del PARAMDICT[k]
+        try: del PARAMDICT[k]
+        except KeyError: pass
       else:
         PARAMDICT[k] = v
         seen.add(k)
@@ -452,6 +465,11 @@ class Subcommand (SC.Subcommand):
   CGI parameters.
   """
 
+  def __init__(me, name, contexts, desc, func,
+               methods = ['GET', 'POST'], *args, **kw):
+    super(Subcommand, me).__init__(name, contexts, desc, func, *args, **kw)
+    me.methods = set(methods)
+
   def cgi(me, param, path):
     """
     Invoke the subcommand given a collection of CGI parameters.
@@ -483,6 +501,12 @@ class Subcommand (SC.Subcommand):
     want = {}
     kw = {}
 
+    ## Check the request method against the permitted list.
+    meth = METHOD
+    if meth == 'HEAD': meth = 'GET'
+    if meth not in me.methods:
+      raise U.ExpectedError, (500, "Unexpected request method `%s'" % METHOD)
+
     def set_value(k, v):
       """Set a simple value: we shouldn't see multiple values."""
       if k in kw: