3 # This program is quite incomplete. I might complete it with more
4 # features as I need them. It will probably never be entirely
5 # compliant with Apache's version due to architectural differences.
24 def simpleerror(out, code, title, msg):
25 html = """<?xml version="1.0" encoding="US-ASCII"?>
26 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
27 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
36 """ % (title, title, htmlquote(msg))
37 out.write("HTTP/1.1 %d %s\n" % (code, title))
38 out.write("Content-Type: text/html\n")
39 out.write("Content-Length: %d\n" % len(html))
45 def parsecmd(line, p):
47 while line[p].isspace(): p += 1
49 while not line[p].isspace():
54 while line[p].isspace(): p += 1
55 if line[p:p + 3] == "-->":
56 return cmd, pars, p + 3
58 while line[p].isalnum():
63 while line[p].isspace(): p += 1
67 while line[p].isspace(): p += 1
69 if q != '"' and q != "'" and q != '`':
79 return None, {}, len(line)
81 class ssifile(object):
82 def __init__(self, s, url, path):
90 def initvars(self, vars):
92 vars["DOCUMENT_NAME"] = os.path.basename(self.path)
93 vars["DATE_GMT"] = time.asctime(time.gmtime(now))
94 vars["DATE_LOCAL"] = time.asctime(time.localtime(now))
95 vars["LAST_MODIFIED"] = time.asctime(time.localtime(os.stat(self.path).st_mtime))
97 def includefile(self, path):
98 path = os.path.join(os.path.dirname(self.path), path)
100 f = ssifile(open(path), url, path)
102 sys.stderr.write("serve-ssi: included file not found: %s\n" % path)
109 def docmd(self, cmd, pars):
112 self.includefile(pars["file"])
113 elif "virtual" in pars:
114 # XXX: For now, just include the file as-is. Change
116 self.includefile(pars["virtual"])
119 if "encoding" in pars:
120 if pars["encoding"] == "entity":
123 if pars["var"] in ssivars:
124 sys.stdout.write(enc(ssivars[pars["var"]]))
126 sys.stderr.write("serve-ssi: unknown SSI command: %s\n" % cmd)
132 p2 = line.find("<!--#", p)
134 sys.stdout.write(line[p:])
136 sys.stdout.write(line[p:p2])
137 cmd, pars, p = parsecmd(line, p2 + 5)
139 self.docmd(cmd, pars)
141 if len(sys.argv) < 4:
142 sys.stderr.write("usage: serve-ssi METHOD URL REST\n")
144 method, url, rest = sys.argv[1:]
145 path = os.getenv("REQ_X_ASH_FILE")
147 sys.stderr.write("serve-ssi: must be called with the X-Ash-File header\n")
150 simpleerror(sys.stdout, 404, "Not Found", "The resource specified by the URL does not exist.")
155 f = ssifile(open(path), url, path)
157 simpleerror(sys.stdout, 500, "Server Error", "The server could not access its data.")
160 sys.stdout.write("HTTP/1.1 200 OK\n")
161 sys.stdout.write("Content-Type: text/html\n")
162 sys.stdout.write("\n")
168 # This is for catching EPIPE, when the client has closed the
169 # connection. This shouldn't *really* be necessary since the
170 # process should terminate with SIGPIPE, but apparently Python