Author: fw Date: 2005-09-29 12:40:28 +0000 (Thu, 29 Sep 2005) New Revision: 2225 Added: bin/tracker.cgi Log: Commit the tracker.cgi Python script. Sorry, this script is a complete mess. 8-( Added: bin/tracker.cgi ==================================================================--- bin/tracker.cgi 2005-09-29 12:39:03 UTC (rev 2224) +++ bin/tracker.cgi 2005-09-29 12:40:28 UTC (rev 2225) @@ -0,0 +1,986 @@ +#!/usr/bin/python + +import cgi +import cgitb +cgitb.enable() # FIXME for production use + +import sys +sys.path.insert(0,''../lib/python'') + +import os +import re +import string +import types +import urllib + +import security_db +import bugs + +def print_header(status): + print "Content-Type: text/html" + print "Status:", status + print "" + +def print_title(title, status=200, selectSearch=False): + print_header(status) + title = cgi.escape(title) + print ''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'' + print ''''''<html><head> +<style type="text/css"> +h1 { font-size : 144%; } +h2 { font-size : 120%; } +h3 { font-size : 100%; } + +table { padding-left : 1.5em } +td, th { text-align : left; + padding-left : 0.25em; + padding-right : 0.25em; } +td { vertical-align: baseline } +span.red { color: red; } +span.dangerous { color: rgb(191,127,0); } +</style> + +<script type="text/javascript" language="JavaScript"> +var old_query_value = ""; + +function onLoad() { +'''''' + if selectSearch: + print '' document.searchForm.query.focus();'' + + print ''''''} + +function onSearch(query) { + if (old_query_value == "") { + if (query.length > 5) { + old_query_value = query; + document.searchForm.submit(); + } else { + old_query_value = query; + } + } +} +</script> +'''''' + print ''<title>%s</title></head><body onload="onLoad()"><h1>%s</h1>'' \ + % (title, title) + +def print_footer(withSearch=True): + print "<hr/>" + if withSearch: + print_paragraph(make_search()) + + print_paragraph(make_a(url_from_rel(""), "Home"), + " - ", make_a("http://secure-testing.debian.net", + "Testing Security Team"), + " - ", make_a("http://www.debian.org/security/", + "Debian Security"), + " - ", make_a("http://www.enyo.de/fw/impressum.html", + "Imprint")) + print "</body></html>" + +class NoEscape: + """Prevent escaping of HTML text.""" + def __init__(self, data): + self.data = data + def __repr__(self): + return "NoEscape(%s)" % `self.data` + +def escape(data): + if type(data) == types.StringType: + return cgi.escape(data) + assert type(data) == types.InstanceType, type(data) + assert data.__class__ == NoEscape, data.__class__ + return data.data + +def print_error(msg): + msg = escape(msg) + print "<p><b>ERROR:</b> %s</p>" % msg + print ''<p>Please contact <a href="mailto:fw@deneb.enyo.de">Florian Weimer</a> and report this problem.</p>'' + +try: + path_info = os.environ[''PATH_INFO''] +except KeyError: + path_info = '''' + +try: + server_name = os.environ[''SERVER_NAME''] +except KeyError: + server_name = ''localhost'' + +try: + script_name = cgi.escape(os.environ[''SCRIPT_NAME'']) +except KeyError: + script_name = '''' +while script_name[0:2] == ''//'': + script_name = script_name[1:] + +def print_no_results(query): + print_title("No results", status=404) + print_error(NoEscape(''Your query "<code>%s</code>" matched no results.'' + % cgi.escape(query))) + print_footer() + +def print_invalid_query(): + print_title("Invalid query", status=404) + print_error("The URL you specified is incorrect for this application.") + print_footer() + +def print_table(gen, caption=(), replacement='''', introduction='''', style=None): + w = sys.stdout.write + if style: + style = '' class="%s"'' % escape(style) + else: + style = '''' + + first_row = True + for row in gen: + if first_row: + w(escape(introduction)) + if style: + w(''<table%s>'' % style) + else: + w(''<table>'') + if caption: + w(''<tr%s>'' % style) + for c in caption: + w(''<th%s>'' % style) + w(escape(c)) + w(''</th>'') + w(''</tr>\n'') + first_row = False + w("<tr>") + for col in row: + w("<td%s>" % style) + w(escape(col)) + w("</td>") + w("</tr>\n") + if first_row: + if replacement: + w(escape(replacement)) + else: + w("</table>\n") + +def print_escaped(*args): + for x in args: + sys.stdout.write(escape(x)) +def print_paragraph(*args): + sys.stdout.write(''<p>'') + apply(print_escaped, args) + sys.stdout.write(''</p>\n'') + +def make_bold(s): + return NoEscape("<b>%s</b>" % escape(s)) +def make_code(s): + return NoEscape("<code>%s</code>" % escape(s)) +def make_red(s): + return NoEscape(''<span class="red">%s</span>'' % escape(s)) +def make_dangerous(s): + return NoEscape(''<span class="dangerous">%s</span>'' % escape(s)) +def url_from_rel(x, full=False): + if full: + return "http://%s%s/%s" % (server_name, script_name, x) + else: + return "%s/%s" % (script_name, x) +url_known_bug = url_from_rel + +def url_source_package(p, full=False): + return url_from_rel("source-package/" + p, full) +def url_binary_package(p, full=False): + return url_from_rel("binary-package/" + p, full) + +def make_xref(x): + url = escape(url_known_bug(x)) + return NoEscape(''<a href="%s">%s</a>'' % (url, escape(x))) +def make_cve_xref(cve, name=None): + cve = escape(cve) + if name is None: + name = cve + else: + name = escape(name) + return NoEscape(''<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s">%s</a>'' % (cve, name)) + +def make_dsa_xref(cursor, dsa, name, + re_dsa=re.compile(r''^DSA-(\d+)(?:-\d+)?$'')): + match = re_dsa.match(dsa) + if name is None: + name = dsa + else: + name = escape(name) + if match: + # We must determine the year because there is no generic URL. + (number,) = match.groups() + for (date,) in cursor.execute( + "SELECT release_date FROM bugs WHERE name = ?", (dsa,)): + (y, m, d) = date.split(''-'') + return NoEscape(''<a href="http://www.debian.org/security/%d/dsa-%d">%s</a>'' + % (int(y), int(number), name)) + + return escape(dsa) + + +def url_debian_bug(bug): + return "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%d" % bug +def url_debian_bug_pkg(pkg): + return ("http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=" + + urllib.quote(pkg)) + +def make_debian_bug(bug, internal=False): + if internal: + assert False + return NoEscape(''<a href="%s">%d</a>'' % (url_debian_bug(bug), bug)) + +def url_pts(src): + return "http://packages.qa.debian.org/common/index.html?src=" \ + + urllib.quote(src) + +def url_testing_status(src): + return "http://bjorn.haxx.se/debian/testing.pl?package=" \ + + urllib.quote(src) + +def make_a(url, text): + return NoEscape(''<a href="%s">%s</a>'' % (escape(url), escape(text))) +def make_pts_ref(pkg, title=None): + if title is None: + title = pkg + return make_a(url_pts(pkg), title) + +def make_source_package_ref(pkg, title=None): + if title is None: + title = pkg + return make_a(url_source_package(pkg), title) +def make_binary_package_ref(pkg, title=None): + if title is None: + title = pkg + return make_a(url_binary_package(pkg), title) +def make_binary_packages_ref(lst): + assert type(lst) <> types.StringType + return make_list(map(make_binary_package_ref, lst)) + +def make_list(lst, separator=NoEscape(", ")): + assert type(lst) <> types.StringType + return NoEscape(escape(separator).join(map(escape, lst))) + +def make_search(): + return NoEscape(\ + (''<form name="searchForm" method="get" action="%s">'' + % escape(url_from_rel(''search/''))) + + ''Search for package or bug name: '' + + ''<input type="text" name="query" onkeyup="onSearch(this.value)"'' + + ''onmousemove="onSearch(this.value)"> '' + + ''<input type="submit" value="Go"/></form>'') + +def print_bug(bug, db): + print_title(bug.name) + + cursor = db.cursor() + + def gen_header(): + yield make_bold("Name"), bug.name + + source = bug.name.split(''-'')[0] + if source in (''CAN'', ''CVE''): + source_xref = make_cve_xref(bug.name, ''CVE'') + elif source == ''DSA'': + source_xref = make_dsa_xref(cursor, bug.name, ''Debian'') + elif source == ''DTSA'': + source_xref = ''Debian Testing Security Team'' + elif source == ''FAKE'': + source_xref = ''Automatically generated temporary name. Not for external reference.'' + else: + source_xref = None + + if source_xref: + yield make_bold("Source"), source_xref + + if bug.description: + yield make_bold("Description"), bug.description + + xref = list(db.getBugXrefs(cursor, bug.name)) + if xref: + yield make_bold("References"), make_list(map(make_xref, xref)) + + debian_bugs = bug.getDebianBugs(cursor) + if debian_bugs: + yield (make_bold("Debian Bugs"), + make_list(map(make_debian_bug, debian_bugs))) + + if bug.not_for_us: + yield make_bold("Status"), "Debian is not affected" + else: + for (release, status, reason) in bug.getStatus(cursor): + if status <> ''fixed'': + reason = make_red(reason) + yield make_bold(''Status of %s'' % release), reason + + print_table(gen_header()) + + if bug.notes: + print """<h2>Vulnerable and fixed packages</h2> +<p>The table below lists information on <em>source packages</em>.</p> +""" + + def gen_source(): + yield (make_bold("Source Package"), + make_bold("Release"), + make_bold("Version"), + make_bold("Status")) + + old_pkg = '''' + for (package, release, version, vulnerable) \ + in db.getSourcePackages(cursor, bug.name): + if package == old_pkg: + package = '''' + else: + old_pkg = package + package = NoEscape("%s (%s)" + % (escape(make_source_package_ref(package)), + escape(make_pts_ref(package, ''PTS'')))) + if vulnerable: + vuln = make_red(''vulnerable'') + version = make_red(version) + else: + vuln = ''fixed'' + + yield package, '', ''.join(release), version, vuln + + print_table(gen_source()) + + print "<p>The next table lists affected <em>binary packages</em>.<p>" + + def gen_binary(): + yield (make_bold("Binary Package"), + make_bold("Release"), + make_bold("Version"), + make_bold("Status"), + make_bold("Arch")) + + old_pkg = '''' + for (packages, releases, version, archs, vulnerable) \ + in db.getBinaryPackages(cursor, bug.name): + pkg = '', ''.join(packages) + if pkg == old_pkg: + packages = '''' + else: + old_pkg = pkg + packages = make_binary_packages_ref(packages) + + if vulnerable: + vuln = make_red(''vulnerable'') + version = make_red(version) + else: + vuln = ''fixed'' + yield (packages, + '', ''.join(releases), + version, vuln, + '', ''.join(archs)) + + print_table(gen_binary()) + + + print """<p>The information above is based on the following +data on fixed versions.</p>""" + + def gen_data(): + yield () + + notes_sorted = bug.notes[:] + notes_sorted.sort(lambda a, b: cmp(a.package, b.package)) + for n in notes_sorted: + if n.release: + rel = str(n.release) + else: + rel = ''(unstable)'' + urgency = str(n.urgency) + if n.fixed_version: + ver = str(n.fixed_version) + if ver == ''0'': + ver = ''(not affected)'' + urgency = '''' + else: + ver = make_red(''(unfixed)'') + + pkg = n.package + pkg_kind = n.package_kind + if pkg_kind == ''source'': + pkg = make_source_package_ref(pkg) + elif pkg_kind == ''binary'': + pkg = make_binary_package_ref(pkg) + elif pkg_kind == ''itp'': + pkg_kind = ''ITP'' + rel = '''' + ver = '''' + urgency = '''' + + bugs = n.bugs + bugs.sort() + bugs = make_list(map(make_debian_bug, bugs)) + if n.bug_origin: + origin = make_xref(n.bug_origin) + else: + origin = '''' + yield (pkg, pkg_kind, rel, ver, urgency, origin, bugs) + + print_table(gen_data(), + caption=("Package", "Type", "Release", "Fixed Version", + "Urgency", "Origin", "Debian Bugs")) + + if bug.comments: + print "<h2>Notes</h2>" + print "<pre>" + for (t, c) in bug.comments: + print escape(c) + print "</pre>" + + print_footer() + +def print_debian_bug(db, bug, buglist): + print_title("Information related to Debian Bug #%d" % bug) + + print_paragraph("The following issues reference to Debian bug ", + make_debian_bug(bug), ":") + + def gen(): + yield make_bold("Name"), make_bold("Urgency"), make_bold("Description") + + for (name, urgency, description) in buglist: + yield make_xref(name), urgency, description + + print_table(gen()) + print_footer() + +def handle_simple_search(query): + db = security_db.DB(''../data/security.db'') + c = db.cursor() + if ''A'' <= query[0] <= ''Z'': + try: + bug = bugs.BugFromDB(c, query) + except ValueError: + print_no_results(query) + return + + if bug.name <> query: + # Bug name was normalized, perform redirect so that the + # browser sees the normalized URL. + print "Location:", url_from_rel(bug.name, full=True) + print + return + + print_bug(bug, db) + return + + elif db.isSourcePackage(c, query): + print "Location:", url_source_package(query, full=True) + print + return + + elif db.isBinaryPackage(c, query): + print "Location:", url_binary_package(query, full=True) + print + return + + elif ''0'' <= query[0] <= ''9'': + # Debian bug number. + if query[-6:] == ''_REDIR'': + query = query[:-6] + redirect = True + else: + redirect = False + + bugnumber = 0 + try: + bugnumber = int(query) + except ValueError: + pass + if bugnumber: + buglist = list(db.getBugsFromDebianBug(c, bugnumber)) + if buglist: + if len(buglist) == 1: + # Single issue, redirect. + print "Location:", url_known_bug(buglist[0][0], full=True) + print + return + else: + print_debian_bug(c, bugnumber, buglist) + return + elif redirect: + print "Location:", url_debian_bug(bugnumber) + print + return + print_no_results(query) + +def print_source_package(pkg): + db = security_db.DB(''../data/security.db'') + c = db.cursor() + + print_title("Information on source package " + pkg) + + print_menu([(url_pts(pkg), + pkg + '' in the Package Tracking System''), + (url_debian_bug_pkg(pkg), + pkg + '' in the Bug Tracking System''), + (url_testing_status(pkg), + pkg + '' in the testing migration checker'')], + relative=False) + + print "<h2>Available versions</h2>" + + def gen_versions(): + yield make_bold("Release"), make_bold("Version") + for (releases, version) in db.getSourcePackageVersions(c, pkg): + yield '', ''.join(releases), version + print_table(gen_versions()) + + print "<h2>Available binary packages</h2>" + + def gen_binary(): + for (packages, releases, archs, version) \ + in db.getBinaryPackagesForSource(c, pkg): + yield (make_binary_packages_ref(packages), + '', ''.join(releases), version, '', ''.join(archs)) + print_table(gen_binary(), + caption=(''Package'', ''Release'', ''Version'', ''Architectures''), + replacement=(''No binary packages are recorded in this database. '' + + ''This probably means that the package is '' + + ''architecture-specific, and the architecture '' + + ''is currently not tracked.'')) + + print "<h2>Open issues</h2>" + + def gen_bug_list(lst): + for (bug, description) in lst: + yield make_xref(bug), description + print_table(gen_bug_list(db.getBugsForSourcePackage(c, pkg, True)), + caption=(''Bug'', ''Description''), + replacement=''No known open issues.'') + + print "<h2>Resolved issues</h2>" + + print_table(gen_bug_list(db.getBugsForSourcePackage(c, pkg, False)), + caption=(''Bug'', ''Description''), + replacement=''No known resolved issues.'') + + print_footer() + +def print_binary_package(pkg): + db = security_db.DB(''../data/security.db'') + c = db.cursor() + + print_title("Information on binary package " + pkg) + + print_menu([(url_debian_bug_pkg(pkg), + pkg + '' in the Bug Tracking System'')], + relative=False) + print "<h2>Available versions</h2>" + + def gen_versions(): + # FIXME: We should include the source package name in this list. + yield () + for (releases, source, version, archs) \ + in db.getBinaryPackageVersions(c, pkg): + yield ('', ''.join(releases), make_source_package_ref(source), + version, '', ''.join(archs)) + print_table(gen_versions(), + caption=("Release", "Source", "Version", "Architectures")) + + print "<h2>Open issues</h2>" + + def gen_bug_list(lst): + for (bug, description) in lst: + yield make_xref(bug), description + print_table(gen_bug_list(db.getBugsForBinaryPackage(c, pkg, True)), + caption=(''Bug'', ''Description''), + replacement=''No known open issues.'') + + print "<h2>Resolved issues</h2>" + + print_table(gen_bug_list(db.getBugsForBinaryPackage(c, pkg, False)), + caption=(''Bug'', ''Description''), + replacement=''No known resolved issues.'') + + print "<h2>Non-issues</h2>" + + print_table(gen_bug_list(db.getNonBugsForBinaryPackage(c, pkg)), + caption=(''Bug'', ''Description''), + replacement=(''No known issues which do not affect '' + + ''this package.'')) + + print_footer() + +def print_todo(): + db = security_db.DB(''../data/security.db'') + print_title("Bugs with TODO items") + + def gen(): + yield make_bold("Bug"), make_bold("Description") + for (bug, description) in db.getTODOs(): + yield make_xref(bug), description + print_table(gen()) + + print_footer() + +def print_menu(entries,relative=True): + w = sys.stdout.write + w("<ul>") + for e in entries: + w("<li>") + if type(e) == types.TupleType: + (relurl, label) = e + if relative: + relurl = url_from_rel(relurl) + sys.stdout.write(escape(make_a(relurl, label))) + else: + w(escape(e)) + w("</li>\n") + w("</ul>\n") + +def print_overview(): + print_title("Security issue tracker", selectSearch=True) + + print """<p>This is the experimental issue tracker for Debian''s testing +security team. Keep in mind that this is merely a prototype. +Please report any problems to <a href="mailto:fw@deneb.enyo.de">Florian +Weimer</a>. Note that some of the data presented here is known +to be wrong (see below), but the data for the testing suite +should be fine. +</p> + +<h2>Starting points</h2> +""" + + print_menu([(''status/release/testing'', + ''Vulnerable packages in the testing suite''), + (''status/release/unstable'', + ''Vulnerable packages in the unstable suite''), + (''status/dtsa-candidates'', "Candidates for DTSAs"), + (''status/todo'', ''TODO items''), + (''status/itp'', ''ITPs with potential security issues''), + (''data/unknown-packages'', + ''Packages names not found in the archive''), + (''data/funny-versions'', + ''Packages with strange version numbers''), + (''data/releases'', + ''Covered Debian releases and architectures (slow)''), + make_search()]) + + print """<h2>A few notes on data sources</h2> + +<p>Data in this tracker comes solely from the bug database +which is maintained by Debian''s testing security team in their +Subversion repository. All external data (this includes +Debian bug reports and official Debian security advisories) +must be added to this database before it appears here, and there +can be some delay before this happens. +</p> + +<p>At the moment, the database only contains information which is +relevant for tracking the security status of the testing suite. +This means that data for stable or oldstable is likely wrong. +The unstable suite should be covered pretty well, though, +because it is relevant to the status of testing. +</p> +""" + print_footer(withSearch = False) + +def handle_cmd(cmd, arg): + if cmd == ''source-package'': + print_source_package(arg) + sys.exit(0) + elif cmd == ''binary-package'': + print_binary_package(arg) + sys.exit(0) + +if path_info in ('''', ''/''): + print_overview() + sys.exit(0) + +re_query = re.compile(r''^/([a-zA-Z0-9_.-]+)$'') +match = re_query.match(path_info) +if match is None: + cmd_list = path_info.split(''/'') + if len(cmd_list) == 3: + handle_cmd(cmd_list[1], cmd_list[2]) + # fall-through if not handled + + def print_releases(): + db = security_db.DB(''../data/security.db'') + + print_title("Available releases") + + print """<p>The security issue database is checked against +the Debian releases listed in the table below. Currently, space +and processing resources are limited, so the list of architectures +is incomplete. +</p>""" + + def gen(): + yield (make_bold("Release"), + make_bold("Subrelease"), + make_bold("Archive"), + make_bold("Sources"), + make_bold("Architectures")) + for (rel, subrel, archive, sources, archs) \ + in db.availableReleases(): + if sources: + sources = ''yes'' + else: + sources = ''no'' + yield rel, subrel, archive, sources, make_list(archs) + + print_table(gen()) + print_footer() + + def print_funny_versions(): + db = security_db.DB(''../data/security.db'') + print_title("Version conflicts between source/binary packages") + + print """<p>The table below lists source packages +which have a binary package of the same name, but with a different +version. This means that extra care is necessary to determine +the version of a package which has been fixed. (Note that +the bug tracker prefers source versions to binary versions +in this case.) +</p>""" + def gen(): + yield (make_bold("Package"), + make_bold("Release"), + make_bold("Archive"), + make_bold("Source Version"), + make_bold("Binary Version")) + + for name, release, archive, version, source_version \ + in db.getFunnyPackageVersions(): + yield name, release, archive, source_version, version + + print_table(gen()) + + print """<p>Technically speaking, these version numbering is fine, +but it makes version-based bug tracking quite difficult for these packages. +</p> + +<p>There are many binary packages which are built from source packages +with different version numbering schemes. However, as long as none of +the binary packages carries the same name as the source package, most +confusion is avoided or can be easily explained.</p>""" + + print_footer() + + def print_unknown_packages(): + db = security_db.DB(''../data/security.db'') + print_title("Unknown packages") + + print_paragraph("Sometimes, a package referenced in a bug report ", + "cannot be found in the database. This can be ", + "the result of a spelling error, or a historic ", + "entry refers to a package which is no longer in ", + "the archive.") + + def gen(): + for name, bugs in db.getUnknownPackages(db.cursor()): + yield name, make_list(map(make_xref, bugs)) + + print_table(gen(), caption=("Package", "Bugs"), + replacement="No unknown packages are referenced in the database.") + + print_footer() + + def print_itp(): + db = security_db.DB(''../data/security.db'') + print_title("ITPs with potential security issues") + + def gen(): + old_pkg = '''' + for pkg, bugs, debian_bugs in db.getITPs(db.cursor()): + if pkg == old_pkg: + pkg = '''' + else: + old_pkg = pkg + yield (pkg, + make_list(map(make_xref, bugs)), + make_list(map(make_debian_bug, debian_bugs))) + + print_table(gen(), caption=("Package", "Issue", "Debian Bugs"), + replacement="No ITPs are currently known.") + + print_footer() + + def print_testing_status(): + db = security_db.DB(''../data/security.db'') + + print_title("Vulnerable source packages in testing") + + print_menu([("status/dtsa-candidates", "Candidates for DTSAs")]) + + def gen(): + yield (make_bold("Package"), + make_bold("Bug")) + + c = db.cursor() + + old_pkg_name = '''' + for (pkg_name, bug_name, archive, urgency, + sid_vulnerable, ts_fixed) in db.cursor().execute( + """SELECT package, bug, section, urgency, unstable_vulnerable, + testing_security_fixed + FROM testing_status"""): + if pkg_name == old_pkg_name: + pkg_name = '''' + else: + old_pkg_name = pkg_name + if archive <> ''main'': + pkg_name = "%s (%s)" % (pkg_name, archive) + + if ts_fixed: + status = ''fixed in testing-security'' + else: + if sid_vulnerable: + status = make_red(''unstable is vulnerable'') + else: + status = make_dangerous(''fixed in unstable'') + + if urgency == ''unknown'': + urgency = '''' + + yield pkg_name, make_xref(bug_name), urgency, status + + print_table(gen()) + + print_footer() + + def print_dtsa_candidates(): + db = security_db.DB(''../data/security.db'') + + print_title("Candidates for DTSAs") + + print_paragraph("The table below lists packages which are fixed ", + "in unstable, but unfixed in testing. ", + "Use the testing migration tracker to find out ", + "why they have not entered testing yet.") + + print_menu([("status/release/testing", + "List of vulnerable packages in testing")]) + + def gen(): + old_pkg_name = '''' + for (pkg_name, bug_name, archive, urgency, stable_later) \ + in db.cursor().execute( + """SELECT package, bug, section, urgency, + (SELECT testing.version_id < stable.version_id + FROM source_packages AS testing, source_packages AS stable + WHERE testing.name = testing_status.package + AND testing.release = ''etch'' + AND testing.subrelease = '''' + AND testing.archive = testing_status.section + AND stable.name = testing_status.package + AND stable.release = ''sarge'' + AND stable.subrelease = ''security'' + AND stable.archive = testing_status.section) + FROM testing_status + WHERE (NOT unstable_vulnerable) + AND (NOT testing_security_fixed)"""): + if pkg_name == old_pkg_name: + pkg_name = '''' + migration = '''' + else: + old_pkg_name = pkg_name + migration = make_a(url_testing_status(pkg_name), + "check") + if archive <> ''main'': + pkg_name = "%s (%s)" % (pkg_name, archive) + else: + pkg_name = make_source_package_ref(pkg_name) + + if urgency == ''unknown'': + urgency = '''' + elif urgency == ''high'': + urgency = make_red(urgency) + + if stable_later: + notes = "(fixed in stable?)" + else: + notes = '''' + + yield pkg_name, migration, make_xref(bug_name), urgency, notes + + print_table(gen(), + caption=("Package", "Migration", "Bug", "Urgency")) + + print_footer() + + def print_unstable_status(): + db = security_db.DB(''../data/security.db'') + + print_title("Vulnerable source packages in unstable") + + print_paragraph( + "Note that the list below is based on source packages. ", + "This means that packages are not listed here once a new, ", + "fixed source version has been uploaded to the archive, even ", + "if there are still some vulnerably binary packages present ", + "in the archive.") + + def gen(): + c = db.cursor() + + old_pkg_name = '''' + for (pkg_name, bug_name, section, urgency) in db.cursor().execute( + """SELECT DISTINCT sp.name, st.bug_name, + sp.archive, st.urgency + FROM source_package_status AS st, source_packages AS sp + WHERE st.vulnerable AND st.urgency <> ''unimportant'' + AND sp.rowid = st.package AND sp.release = ''sid'' + AND sp.subrelease = '''' + ORDER BY sp.name, st.bug_name"""): + if pkg_name == old_pkg_name: + pkg_name = '''' + else: + old_pkg_name = pkg_name + if section <> ''main'': + pkg_name = "%s (%s)" % (pkg_name, section) + else: + pkg_name = make_xref(pkg_name) + + if urgency == ''unknown'': + urgency = '''' + elif urgency == ''high'': + urgency = make_red(urgency) + + yield pkg_name, make_xref(bug_name), urgency + + print_table(gen(), caption=(''Package'', ''Bug'', ''Urgency'')) + + print_footer() + + def do_search(): + form = cgi.FieldStorage() + query = form.getfirst("query", None) + if query is None: + # redirect to start page + print "Location:", url_from_rel("", full=True) + print + else: + re_simple_query = re.compile(r''^[A-Za-z0-9_.-]+$'') + if re_simple_query.match(query): + print "Location:", url_from_rel(query, full=True) + print + else: + print_invalid_query() + + commands = {''/data/releases'' : print_releases, + ''/data/funny-versions'' : print_funny_versions, + ''/data/unknown-packages'' : print_unknown_packages, + ''/status/release/testing'' : print_testing_status, + ''/status/release/unstable'' : print_unstable_status, + ''/status/todo'' : print_todo, + ''/status/dtsa-candidates'' : print_dtsa_candidates, + ''/status/itp'' : print_itp, + ''/search/'' : do_search} + try: + cmd = commands[path_info] + except KeyError: + print_invalid_query() + cmd = None + if cmd: + cmd() +else: + handle_simple_search(match.group(1)) Property changes on: bin/tracker.cgi ___________________________________________________________________ Name: svn:executable + *