#!/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()