#!/usr/bin/env python # # index.cgi - DITrack Web UI CGI script # # Copyright (c) 2006-2007 The DITrack Project, www.ditrack.org. # # $Id: index.cgi 2056 2007-09-11 04:09:15Z vss $ # $HeadURL: https://127.0.0.1/ditrack/src/tags/0.7/webui/index.cgi $ # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # import cgi import os import re import sys import ConfigParser # XXX: debugging import cgitb; cgitb.enable() import DITrack.dt.globals import DITrack.Client import DITrack.DB.Common import DITrack.ThirdParty.ezt class _data_obj: def __init__(self, d): vars(self).update(d) class Issue: def __init__(self, id, issue): self.id = html_escape(str(id)) self.view_url = html_escape("%s?issue=%s" % (script_url, id)) for h in issue.info: vars(self).update({ "hdr_%s" % h.lower().replace("-", "_"): html_escape(issue.info[h]) }) def html_escape(str): if str is None: return "" return cgi.escape(str, quote=True) def generate_page(template_name, data): template = DITrack.ThirdParty.ezt.Template( os.path.join(tpl_dir, "%s.ezt" % template_name) ) data["general"] = general sys.stdout.write("Content-type: text/html\n\n") template.generate(sys.stdout, data) def linkify(s): s = re.sub( r"(i#(\d+))", '\\1' % html_escape(script_url), s ) if viewsvn_url: s = re.sub( r"((\W|^)(r(\d+)))", '\\2\\3' % html_escape(viewsvn_url), s ) return s def do_list(): filters = db.cfg.filters.keys() filters.sort() filters = map(html_escape, filters) current_filter = filter = None if ("filter" in form) and (form["filter"].value in db.cfg.filters): current_filter = html_escape(form["filter"].value) filter = [ db.cfg.filters[form["filter"].value] ] issues = dt.issues(filter) data = { "current_filter": current_filter, "filters": filters, "id": None, # no issue id here "issues": map( lambda (id, issue): Issue(id, issue), issues ), "qty": len(issues) } generate_page("list", data) def do_view(): id = form["issue"].value try: issue = db[id] except KeyError: # Invalid issue id supplied generate_page("invalid-issue", { "id": html_escape(id) }) return general.title = "Issue #%s: %s" % (html_escape(id), html_escape(issue.info["Title"])) data = { "id": html_escape(id), "info": map(html_escape, issue.info_as_strings(terminator="")), "comments": map( lambda (cid, comment): _data_obj({ "author": html_escape(comment.added_by), "datetime": html_escape( " ".join((comment.added_on or "").split()[1:]) ), "header": map( html_escape, comment.header_as_strings(terminator="") ), "id": html_escape(cid), "link_url": html_escape( "%s?issue=%s#c%s" % (script_url, id, cid) ), "text": linkify(html_escape(comment.text)) }), issue.comments() ), "title": html_escape(issue.info["Title"]), } generate_page("view", data) # # ENTRY POINT # if "DTWEB_CONFIG" not in os.environ: sys.stderr.write("DTWEB_CONFIG not set\n") sys.exit(1) cfg = ConfigParser.ConfigParser() cfg.read(os.environ["DTWEB_CONFIG"]) # XXX: catch exceptions here dbroot = cfg.get("paths", "database") tpl_dir = cfg.get("paths", "templates") svn_path = cfg.get("paths", "svn") maxage = cfg.get("misc", "update-interval") try: maxage = int(maxage) except ValueError: sys.stderr.write("Invalid value of misc/update-interval: '%s'\n" % maxage) sys.exit(1) # Not mandatory viewsvn_url = None try: viewsvn_url = cfg.get("misc", "viewsvn-url") except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): pass script_url = os.environ["SCRIPT_NAME"] # XXX: should be combined into a single call to Client(). db = DITrack.DB.Common.Database(dbroot, None, svn_path) dt = DITrack.Client.Client(db) try: dt.update(maxage * 60) except DITrack.Client.Error, e: sys.stderr.write("%s\n" % e.message) sys.exit(1) form = cgi.FieldStorage() general = _data_obj({ "title": "" }) try: general.title = html_escape(cfg.get("appearance", "title")) except NoOptionError: pass if "issue" in form: # Viewing an issue do_view() else: do_list()