diff options
-rwxr-xr-x | pagehandler.py | 184 | ||||
-rwxr-xr-x | patchtracker/ReqHandler.py | 175 |
2 files changed, 192 insertions, 167 deletions
diff --git a/pagehandler.py b/pagehandler.py index 639ac04..b5a12cd 100755 --- a/pagehandler.py +++ b/pagehandler.py @@ -1,175 +1,25 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import cgi +# main (mod_python) request handler for patch-tracking system +# this handler file basically farms out all its work to the ReqHandler +# module, which in turn splits up the request URI and acts accordingly. + +from mod_python import apache import os import sys -import patchtracker.Conf as Conf -from patchtracker.Templates import ErrorTemplate, PatchTemplate, PackageVersTemplate, LetterTocTemplate, FrontPageTemplate, SearchResultsTemplate -from patchtracker.DiffGzHandler import DiffGzHandler -import patchtracker.DB as DB -from patchtracker.DB import PatchTrackerDB -import pygments -from pygments.lexers import DiffLexer -from pygments.formatters import HtmlFormatter -import patchtracker.SourceArchive as SourceArchive - -def error(msg): - print "Content-Type: text/html\n\n" - print ErrorTemplate(msg) - sys.exit(1) - -class PatchCmd: - def __init__(self, args): - self.db = PatchTrackerDB() - self.patchtype,mode,pkgname,version = args[0:4] - self.parsemode(mode) - dh = self.make_diffhandler(pkgname,version) - if self.patchtype == "series": - self.patchname = os.sep.join(args[4:]) - self.content = dh.series().fetch(self.patchname) - elif self.patchtype == "debianonly": - self.patchname = "debian-dir only changes" - self.content = dh.debiandir() - elif self.patchtype == "nondebian": - self.patchname = "direct (non packaging) changes" - self.content = dh.nondebiandir() - elif self.patchtype == "misc": - self.patchname = os.sep.join(args[4:]) - self.content = dh.filterdiff(include=self.patchname) - else: - error("unhandled patch type '%s'"%(self.patchtype)) - self.pkgname = pkgname - self.version = version - - def parsemode(self, mode): - if mode == "view" or mode == "dl": - self.mode = mode - else: - error("unhandled display mode '%s'"%(mode)) - - def make_diffhandler(self, pkgname, vers): - dfile = self.db.findDiffGz(pkgname,vers) - if dfile: - return DiffGzHandler(dfile) - else: - error("can not find diff file for %s / %s"%(pkgname,vers)) - - def output(self): - if self.mode == "dl": - print "Content-Type: text/x-diff\n\n" - print self.content - else: - print "Content-Type: text/html\n\n" - print PatchTemplate(pkg=self.pkgname,vers=self.version, - patch=self.content,name=self.patchname, - patchtype=self.patchtype) - -class PackageCmd: - def __init__(self, args): - db = PatchTrackerDB() - self.name = args[0] - if len(args) > 1: - version = args[1] - else: - version = None - self.toc = db.findCollection(package=self.name, version=version) - if self.toc.size() == 0: - if len(self.name) >= 3: - self.toc = db.findCollection(package="%"+self.name+"%", version=version) - - def output(self): - plist = self.toc.getletter(self.name) - if len(self.name) < 3: - error("search terms must be 3 or more letters...") - if not plist or len(plist) == 0: - error("can't find any package named or containing '%s'"%self.name) - else: - p = self.toc.getpackage(self.name) - print "Content-Type: text/html\n\n" - # if there is no match, or if multiple versions were returned - if not p or len(set(map(lambda x: x.version, p.values()))) > 1: - querydesc = "package name contains" - print SearchResultsTemplate(self.name, querydesc, self.toc) - else: - print PackageVersTemplate(p.popitem()[1]) - - -class IndexCmd: - def __init__(self, args): - if len(args) < 1 or not len(args[0]): - error("please provide a letter on which to index") - else: - self.db = PatchTrackerDB() - self.letter = args[0] - self.toc = self.db.findLetterToc(self.letter) - - def output(self): - print "Content-Type: text/html\n\n" - print LetterTocTemplate(self.letter, self.toc) - -class MaintCmd: - def __init__(self, args): - if len(args) < 1 or not len(args[0]): - error("please provide a email address on which to index") - else: - self.db = PatchTrackerDB() - self.email = args[0] - self.toc = self.db.findCollection(email=self.email) - - def output(self): - print "Content-Type: text/html\n\n" - print SearchResultsTemplate(self.email, "maintainer email", self.toc) - -class JumpCmd: - def __init__(self): - form = cgi.FieldStorage() - self.name = form.getfirst("package") - - def output(self): - print "Location: http://%s%s/package/%s\n\n"%( - os.getenv("HTTP_HOST"), Conf.root_url, self.name) - -class FrontPageCmd: - def __init__(self): - self.db = PatchTrackerDB() - self.index = self.db.findIndices() - - def output(self): - print "Content-Type: text/html\n\n" - print FrontPageTemplate(self.index) - - -class CmdHandler: - def __init__(self, uri): - if len(uri)<len(Conf.root_url) or uri[0:len(Conf.root_url)]!=Conf.root_url: - error("Invalid URL!") - args = uri[len(Conf.root_url)+1:].split("/") - cmdarg = args[0] - if cmdarg == "patch": - self.cmd = PatchCmd(args[1:]) - elif cmdarg == "package": - self.cmd = PackageCmd(args[1:]) - elif cmdarg == "index": - self.cmd = IndexCmd(args[1:]) - elif cmdarg == "jump": - self.cmd = JumpCmd() - elif cmdarg == "email": - self.cmd = MaintCmd(args[1:]) - elif not len(cmdarg): - self.cmd = FrontPageCmd() - else: - error("invalid command/location %s"%(cmdarg)) +def handler(req): + # the apache config sets a hint of where we are installed, which is + # needed in mod_python since cwd is not automatically set + try: + sys.path+=[req.subprocess_env["PT_INSTALLROOT"]] + os.chdir(req.subprocess_env["PT_INSTALLROOT"]) + except: + pass - def output(self): - self.cmd.output() + import patchtracker.ReqHandler as ReqHandler + ReqHandler.Client.req = req -if __name__ == "__main__": - uri = os.getenv("REQUEST_URI") - if not uri: - uri = sys.argv[1] - else: - import cgitb; - cgitb.enable() - CmdHandler(uri).output() + req.write(ptcgi.CmdHandler(req).output()) + return apache.OK diff --git a/patchtracker/ReqHandler.py b/patchtracker/ReqHandler.py new file mode 100755 index 0000000..7f0dbc0 --- /dev/null +++ b/patchtracker/ReqHandler.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +from mod_python import apache, util + +import cgi +import os +import sys + +import patchtracker.Conf as Conf +from patchtracker.Templates import ErrorTemplate, PatchTemplate, PackageVersTemplate, LetterTocTemplate, FrontPageTemplate, SearchResultsTemplate +from patchtracker.DiffGzHandler import DiffGzHandler +import patchtracker.DB as DB +from patchtracker.DB import PatchTrackerDB +import pygments +from pygments.lexers import DiffLexer +from pygments.formatters import HtmlFormatter +import patchtracker.SourceArchive as SourceArchive + +def error(msg, code=apache.HTTP_INTERNAL_SERVER_ERROR): + Client.req.status = code + Client.req.write(str(ErrorTemplate(msg))) + raise apache.SERVER_RETURN, apache.OK + +class Error404Cmd: + def __init__(self, msg): + Client.req.status = apache.HTTP_NOT_FOUND + self.msg = msg + + def output(self): + return str(ErrorTemplate(self.msg)) + +class Client: + req = None + +class PatchCmd: + def __init__(self, args): + self.db = PatchTrackerDB() + self.patchtype,mode,pkgname,version = args[0:4] + self.parsemode(mode) + dh = self.make_diffhandler(pkgname,version) + if self.patchtype == "series": + self.patchname = os.sep.join(args[4:]) + self.content = dh.series().fetch(self.patchname) + elif self.patchtype == "debianonly": + self.patchname = "debian-dir only changes" + self.content = dh.debiandir() + elif self.patchtype == "nondebian": + self.patchname = "direct (non packaging) changes" + self.content = dh.nondebiandir() + elif self.patchtype == "misc": + self.patchname = os.sep.join(args[4:]) + self.content = dh.filterdiff(include=self.patchname) + else: + error("unhandled patch type '%s'"%(self.patchtype)) + self.pkgname = pkgname + self.version = version + + def parsemode(self, mode): + if mode == "view" or mode == "dl": + self.mode = mode + else: + error("unhandled display mode '%s'"%(mode)) + + def make_diffhandler(self, pkgname, vers): + dfile = self.db.findDiffGz(pkgname,vers) + if dfile: + return DiffGzHandler(dfile) + else: + error("can not find diff file for %s / %s"%(pkgname,vers)) + + def output(self): + if self.mode == "dl": + Client.req.content_type = "text/x-diff" + return str(self.content) + else: + return str(PatchTemplate(pkg=self.pkgname,vers=self.version, + patch=self.content,name=self.patchname, + patchtype=self.patchtype)) + +class PackageCmd: + def __init__(self, args): + db = PatchTrackerDB() + self.name = args[0] + if len(args) > 1: + version = args[1] + else: + version = None + self.toc = db.findCollection(package=self.name, version=version) + if self.toc.size() == 0: + if len(self.name) >= 3: + self.toc = db.findCollection(package="%"+self.name+"%", version=version) + + def output(self): + plist = self.toc.getletter(self.name) + if len(self.name) < 3: + error("search terms must be 3 or more letters...") + if not plist or len(plist) == 0: + error("can't find any package named or containing '%s'"%self.name) + else: + p = self.toc.getpackage(self.name) + # if there is no match, or if multiple versions were returned + if not p or len(set(map(lambda x: x.version, p.values()))) > 1: + querydesc = "package name contains" + return str(SearchResultsTemplate(self.name, querydesc, self.toc)) + else: + return str(PackageVersTemplate(p.popitem()[1])) + +class IndexCmd: + def __init__(self, args): + if len(args) < 1 or not len(args[0]): + error("please provide a letter on which to index") + else: + self.db = PatchTrackerDB() + self.letter = args[0] + self.toc = self.db.findLetterToc(self.letter) + + def output(self): + return str(LetterTocTemplate(self.letter, self.toc)) + +class MaintCmd: + def __init__(self, args): + if len(args) < 1 or not len(args[0]): + error("please provide a email address on which to index") + else: + self.db = PatchTrackerDB() + self.email = args[0] + self.toc = self.db.findCollection(email=self.email) + + def output(self): + return str(SearchResultsTemplate(self.email, "maintainer email", self.toc)) + +class JumpCmd: + def __init__(self): + form = util.FieldStorage(Client.req) + self.name = form.getfirst("package") + + def output(self): + uri = "http://%s%s/package/%s"%(Client.req.hostname, Conf.root_url, self.name) + Client.req.headers_out["Location"] = uri + raise apache.SERVER_RETURN, apache.HTTP_MOVED_TEMPORARILY + +class FrontPageCmd: + def __init__(self): + self.db = PatchTrackerDB() + self.index = self.db.findIndices() + + def output(self): + return str(FrontPageTemplate(self.index)) + +class CmdHandler: + def __init__(self, req): + req.content_type = "text/html" + uri=req.uri + if len(uri)<len(Conf.root_url) or uri[0:len(Conf.root_url)]!=Conf.root_url: + error("Invalid URL!") + + args = uri[len(Conf.root_url)+1:].split("/") + cmdarg = args[0] + if cmdarg == "patch": + self.cmd = PatchCmd(args[1:]) + elif cmdarg == "package": + self.cmd = PackageCmd(args[1:]) + elif cmdarg == "index": + self.cmd = IndexCmd(args[1:]) + elif cmdarg == "jump": + self.cmd = JumpCmd() + elif cmdarg == "email": + self.cmd = MaintCmd(args[1:]) + elif not len(cmdarg): + self.cmd = FrontPageCmd() + else: + self.cmd = Error404Cmd("invalid command/location '%s'"%(cmdarg)) + + def output(self): + return self.cmd.output() |