"""
Print a header, if none has yet been printed.
- Keyword arguments can be passed to emit HTTP headers: see `http_header'
+ Keyword arguments can be passed to emit HTTP headers: see `http_headers'
for the formatting rules.
"""
if me.headerp: return
for h in O.http_headers(content_type = content_type, **kw):
me.writeln(h)
me.writeln('')
+ if METHOD == 'HEAD':
+ HEADER_DONE()
def cookie(name, value, **kw):
"""
package = PACKAGE,
version = VERSION,
script = CFG.SCRIPT_NAME,
- static = CFG.STATIC)
+ static = CFG.STATIC,
+ allowop = CFG.ALLOWOP)
class TemplateFinder (object):
"""
with open(OS.path.join(me._dir, key)) as f: tmpl = f.read()
me._cache[key] = tmpl
return tmpl
-TMPL = TemplateFinder(TMPLDIR)
+STATE.kw['TMPL'] = TMPL = TemplateFinder(TMPLDIR)
@CTX.contextmanager
def tmplkw(**kw):
"""
~H: escape output suitable for inclusion in HTML.
- With `:', instead apply form-urlencoding.
+ With `:', additionally apply quotification.
"""
def _convert(me, arg):
if me.colonp: return html_quotify(arg)
else: return htmlescape(arg)
FORMATOPS['H'] = FormatHTML
+class FormatWrap (F.BaseFormatOperation):
+ """
+ ~<...~@>: wrap enclosed material in another formatting control string.
+
+ The argument is a formatting control. The enclosed material is split into
+ pieces separated by `~;' markers. The formatting control is performed, and
+ passed the list of pieces (as compiled formatting operations) in the
+ keyword argument `wrapped'.
+ """
+ def __init__(me, *args):
+ super(FormatWrap, me).__init__(*args)
+ pieces = []
+ while True:
+ piece, delim = F.collect_subformat('>;')
+ pieces.append(piece)
+ if delim.char == '>': break
+ me.pieces = pieces
+ def _format(me, atp, colonp):
+ op = F.compile(me.getarg.get())
+ with F.FORMAT.bind(argmap = dict(F.FORMAT.argmap, wrapped = me.pieces)):
+ op.format()
+FORMATOPS['<'] = FormatWrap
+
def format_tmpl(control, **kw):
with F.COMPILE.bind(opmaps = [FORMATOPS, F.BASEOPS]):
with tmplkw(**kw):
### CGI input.
## Lots of global variables to be filled in by `cgiparse'.
+METHOD = None
COOKIE = {}
SPECIAL = {}
PARAM = []
PARAMDICT = {}
PATH = []
SSLP = False
+HEADER_DONE = lambda: None
## Regular expressions for splitting apart query and cookie strings.
R_QSPLIT = RX.compile('[;&]')
True if the client connection is carried over SSL or TLS.
"""
- global SSLP
+ global METHOD, SSLP
def getenv(var):
try: return ENV[var]
except KeyError: raise U.ExpectedError, (500, "No `%s' supplied" % var)
## Yes, we want the request method.
- method = getenv('REQUEST_METHOD')
+ METHOD = getenv('REQUEST_METHOD')
## Acquire the query string.
- if method == 'GET':
+ if METHOD in ['GET', 'HEAD']:
q = getenv('QUERY_STRING')
- elif method == 'POST':
+ elif METHOD == 'POST':
## We must read the query string from stdin.
n = getenv('CONTENT_LENGTH')
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:
raise U.ExpectedError, (500, "Failed to read correct length")
else:
- raise U.ExpectedError, (500, "Unexpected request method `%s'" % method)
+ raise U.ExpectedError, (500, "Unexpected request method `%s'" % METHOD)
## Populate the `SPECIAL', `PARAM' and `PARAMDICT' tables.
seen = set()
the list of path elements is non-empty.
"""
+ global HEADER_DONE
+
## We're going to make a pass over the supplied parameters, and we'll
## check them off against the formal parameters as we go; so we'll need
## to be able to look them up. We'll also keep track of the ones we've