python: Rewrote SSI handler as a reusable module, and in Python3.
[ashd.git] / python / serve-ssi
diff --git a/python/serve-ssi b/python/serve-ssi
deleted file mode 100755 (executable)
index abdb701..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/python
-
-# This program is quite incomplete. I might complete it with more
-# features as I need them. It will probably never be entirely
-# compliant with Apache's version due to architectural differences.
-
-import sys, os, time
-
-def htmlquote(text):
-    ret = ""
-    for c in text:
-        if c == '&':
-            ret += "&"
-        elif c == '<':
-            ret += "&lt;"
-        elif c == '>':
-            ret += "&gt;"
-        elif c == '"':
-            ret += "&quot;"
-        else:
-            ret += c
-    return ret
-
-def simpleerror(out, code, title, msg):
-    html = """<?xml version="1.0" encoding="US-ASCII"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
-<head>
-<title>%s</title>
-</head>
-<body>
-<h1>%s</h1>
-<p>%s</p>
-</body>
-</html>
-""" % (title, title, htmlquote(msg))
-    out.write("HTTP/1.1 %d %s\n" % (code, title))
-    out.write("Content-Type: text/html\n")
-    out.write("Content-Length: %d\n" % len(html))
-    out.write("\n")
-    out.write(html)
-
-ssivars = {}
-
-def parsecmd(line, p):
-    try:
-        while line[p].isspace(): p += 1
-        cmd = ""
-        while not line[p].isspace():
-            cmd += line[p]
-            p += 1
-        pars = {}
-        while True:
-            while line[p].isspace(): p += 1
-            if line[p:p + 3] == "-->":
-                return cmd, pars, p + 3
-            key = ""
-            while line[p].isalnum():
-                key += line[p]
-                p += 1
-            if key == "":
-                return None, {}, p
-            while line[p].isspace(): p += 1
-            if line[p] != '=':
-                continue
-            p += 1
-            while line[p].isspace(): p += 1
-            q = line[p]
-            if q != '"' and q != "'" and q != '`':
-                continue
-            val = ""
-            p += 1
-            while line[p] != q:
-                val += line[p]
-                p += 1
-            p += 1
-            pars[key] = val
-    except IndexError:
-        return None, {}, len(line)
-
-class ssifile(object):
-    def __init__(self, s, url, path):
-        self.s = s
-        self.url = url
-        self.path = path
-
-    def close(self):
-        self.s.close();
-
-    def initvars(self, vars):
-        now = time.time()
-        vars["DOCUMENT_NAME"] = os.path.basename(self.path)
-        vars["DATE_GMT"] = time.asctime(time.gmtime(now))
-        vars["DATE_LOCAL"] = time.asctime(time.localtime(now))
-        vars["LAST_MODIFIED"] = time.asctime(time.localtime(os.stat(self.path).st_mtime))
-
-    def includefile(self, path):
-        path = os.path.join(os.path.dirname(self.path), path)
-        try:
-            f = ssifile(open(path), url, path)
-        except Exception:
-            sys.stderr.write("serve-ssi: included file not found: %s\n" % path)
-            return
-        try:
-            f.process()
-        finally:
-            f.close
-
-    def docmd(self, cmd, pars):
-        if cmd == "include":
-            if "file" in pars:
-                self.includefile(pars["file"])
-            elif "virtual" in pars:
-                # XXX: For now, just include the file as-is. Change
-                # when necessary.
-                self.includefile(pars["virtual"])
-        elif cmd == "echo":
-            enc = htmlquote
-            if "encoding" in pars:
-                if pars["encoding"] == "entity":
-                    enc = htmlquote
-            if "var" in pars:
-                if pars["var"] in ssivars:
-                    sys.stdout.write(enc(ssivars[pars["var"]]))
-        else:
-            sys.stderr.write("serve-ssi: unknown SSI command: %s\n" % cmd)
-
-    def process(self):
-        for line in self.s:
-            p = 0
-            while True:
-                p2 = line.find("<!--#", p)
-                if p2 < 0:
-                    sys.stdout.write(line[p:])
-                    break
-                sys.stdout.write(line[p:p2])
-                cmd, pars, p = parsecmd(line, p2 + 5)
-                if cmd is not None:
-                    self.docmd(cmd, pars)
-
-if len(sys.argv) < 4:
-    sys.stderr.write("usage: serve-ssi METHOD URL REST\n")
-    sys.exit(1)
-method, url, rest = sys.argv[1:]
-path = os.getenv("REQ_X_ASH_FILE")
-if path is None:
-    sys.stderr.write("serve-ssi: must be called with the X-Ash-File header\n")
-    sys.exit(1)
-if rest != "":
-    simpleerror(sys.stdout, 404, "Not Found", "The resource specified by the URL does not exist.")
-    sys.exit(0)
-
-try:
-    try:
-        f = ssifile(open(path), url, path)
-    except Exception:
-        simpleerror(sys.stdout, 500, "Server Error", "The server could not access its data.")
-        sys.exit(1)
-    try:
-        sys.stdout.write("HTTP/1.1 200 OK\n")
-        sys.stdout.write("Content-Type: text/html\n")
-        sys.stdout.write("\n")
-        f.initvars(ssivars)
-        f.process()
-    finally:
-        f.close()
-except IOError:
-    # This is for catching EPIPE, when the client has closed the
-    # connection. This shouldn't *really* be necessary since the
-    # process should terminate with SIGPIPE, but apparently Python
-    # ignores that.
-    sys.exit(1)