#!/usr/bin/env python
# vim:set et ts=4 sw=4:
-# Utility functions
+""" Utility functions """
# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 James Troup <james@nocrew.org>
################################################################################
sys, tempfile, traceback, stat
import apt_pkg
import database
+import time
from dak_exceptions import *
+from regexes import re_html_escaping, html_escaping, re_single_line_field, \
+ re_multi_line_field, re_srchasver, re_verwithext, \
+ re_parse_maintainer, re_taint_free, re_gpg_uid
################################################################################
-re_comments = re.compile(r"\#.*")
-re_no_epoch = re.compile(r"^\d+\:")
-re_no_revision = re.compile(r"-[^-]+$")
-re_arch_from_filename = re.compile(r"/binary-[^/]+/")
-re_extract_src_version = re.compile (r"(\S+)\s*\((.*)\)")
-re_isadeb = re.compile (r"(.+?)_(.+?)_(.+)\.u?deb$")
-re_issource = re.compile (r"(.+)_(.+?)\.(orig\.tar\.gz|diff\.gz|tar\.gz|dsc)$")
-
-re_single_line_field = re.compile(r"^(\S*)\s*:\s*(.*)")
-re_multi_line_field = re.compile(r"^\s(.*)")
-re_taint_free = re.compile(r"^[-+~/\.\w]+$")
-
-re_parse_maintainer = re.compile(r"^\s*(\S.*\S)\s*\<([^\>]+)\>")
-re_gpg_uid = re.compile('^uid.*<([^>]*)>')
-
-re_srchasver = re.compile(r"^(\S+)\s+\((\S+)\)$")
-re_verwithext = re.compile(r"^(\d+)(?:\.(\d+))(?:\s+\((\S+)\))?$")
-
-re_srchasver = re.compile(r"^(\S+)\s+\((\S+)\)$")
-
default_config = "/etc/dak/dak.conf"
default_apt_config = "/etc/dak/apt.conf"
################################################################################
+def html_escape(s):
+ return re_html_escaping.sub(lambda x: html_escaping.get(x.group(0)), s)
+
+################################################################################
+
def open_file(filename, mode='r'):
try:
f = open(filename, mode)
rejmsg = []
for f in files.keys():
+ file_handle = None
try:
- file_handle = open_file(f)
-
- # Check for the hash entry, to not trigger a KeyError.
- if not files[f].has_key(hash_key(hashname)):
- rejmsg.append("%s: misses %s checksum in %s" % (f, hashname,
- where))
+ try:
+ file_handle = open_file(f)
+
+ # Check for the hash entry, to not trigger a KeyError.
+ if not files[f].has_key(hash_key(hashname)):
+ rejmsg.append("%s: misses %s checksum in %s" % (f, hashname,
+ where))
+ continue
+
+ # Actually check the hash for correctness.
+ if hashfunc(file_handle) != files[f][hash_key(hashname)]:
+ rejmsg.append("%s: %s check failed in %s" % (f, hashname,
+ where))
+ except CantOpenError:
+ # TODO: This happens when the file is in the pool.
+ # warn("Cannot open file %s" % f)
continue
-
- # Actually check the hash for correctness.
- if hashfunc(file_handle) != files[f][hash_key(hashname)]:
- rejmsg.append("%s: %s check failed in %s" % (f, hashname,
- where))
- except CantOpenError:
- # XXX: IS THIS THE BLOODY CASE WHEN THE FILE'S IN THE POOL!?
- continue
finally:
- file_handle.close()
+ if file_handle:
+ file_handle.close()
return rejmsg
################################################################################
rejmsg = []
for f in files.keys():
- actual_size = os.stat(f)[stat.ST_SIZE]
+ try:
+ entry = os.stat(f)
+ except OSError, exc:
+ if exc.errno == 2:
+ # TODO: This happens when the file is in the pool.
+ continue
+ raise
+
+ actual_size = entry[stat.ST_SIZE]
size = int(files[f]["size"])
if size != actual_size:
rejmsg.append("%s: actual file size (%s) does not match size (%s) in %s"
field = 'checksums-%s' % hashname
if not field in manifest:
return rejmsg
- input = manifest[field]
- for line in input.split('\n'):
+ for line in manifest[field].split('\n'):
if not line:
break
- hash, size, file = line.strip().split(' ')
- if not files.has_key(file):
- rejmsg.append("%s: not present in files but in checksums-%s in %s" %
- (file, hashname, where))
- if not files[file]["size"] == size:
+ checksum, size, checkfile = line.strip().split(' ')
+ if not files.has_key(checkfile):
+ # TODO: check for the file's entry in the original files dict, not
+ # the one modified by (auto)byhand and other weird stuff
+ # rejmsg.append("%s: not present in files but in checksums-%s in %s" %
+ # (file, hashname, where))
+ continue
+ if not files[checkfile]["size"] == size:
rejmsg.append("%s: size differs for files and checksums-%s entry "\
- "in %s" % (file, hashname, where))
- files[file][hash_key(hashname)] = hash
+ "in %s" % (checkfile, hashname, where))
+ continue
+ files[checkfile][hash_key(hashname)] = checksum
for f in files.keys():
if not files[f].has_key(hash_key(hashname)):
- rejmsg.append("%s: no entry in checksums-%s in %s" % (file,
+ rejmsg.append("%s: no entry in checksums-%s in %s" % (checkfile,
hashname, where))
return rejmsg
format = format[:2]
if is_a_dsc:
- if format != (1,0):
+ # format = (1,0) are the only formats we currently accept,
+ # format = (0,0) are missing format headers of which we still
+ # have some in the archive.
+ if format != (1,0) and format != (0,0):
raise UnknownFormatError, "%s" % (changes.get("format","0.0"))
else:
if (format < (1,5) or format > (1,8)):
def send_mail (message, filename=""):
# If we've been passed a string dump it into a temporary file
if message:
- filename = tempfile.mktemp()
- fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
+ (fd, filename) = tempfile.mkstemp()
os.write (fd, message)
os.close (fd)
# Perform a substition of template
def TemplateSubst(map, filename):
- file = open_file(filename)
- template = file.read()
+ templatefile = open_file(filename)
+ template = templatefile.read()
for x in map.keys():
template = template.replace(x,map[x])
- file.close()
+ templatefile.close()
return template
################################################################################
################################################################################
def result_join (original, sep = '\t'):
- list = []
+ resultlist = []
for i in xrange(len(original)):
if original[i] == None:
- list.append("")
+ resultlist.append("")
else:
- list.append(original[i])
- return sep.join(list)
+ resultlist.append(original[i])
+ return sep.join(resultlist)
################################################################################
return "%s: tainted filename" % (filename)
# Invoke gpgv on the file
- status_read, status_write = os.pipe();
+ status_read, status_write = os.pipe()
cmd = "gpgv --status-fd %s --keyring /dev/null %s" % (status_write, filename)
(_, status, _) = gpgv_get_status_output(cmd, status_read, status_write)
return None
# Build the command line
- status_read, status_write = os.pipe();
+ status_read, status_write = os.pipe()
cmd = "gpgv --status-fd %s %s %s %s" % (
status_write, gpg_keyring_args(keyrings), sig_filename, data_filename)
if keywords.has_key("NODATA"):
reject("no signature found in %s." % (sig_filename))
bad = 1
+ if keywords.has_key("EXPKEYSIG"):
+ args = keywords["EXPKEYSIG"]
+ if len(args) >= 1:
+ key = args[0]
+ reject("Signature made by expired key 0x%s" % (key))
+ bad = 1
if keywords.has_key("KEYEXPIRED") and not keywords.has_key("GOODSIG"):
args = keywords["KEYEXPIRED"]
+ expiredate=""
if len(args) >= 1:
- key = args[0]
- reject("The key (0x%s) used to sign %s has expired." % (key, sig_filename))
+ timestamp = args[0]
+ if timestamp.count("T") == 0:
+ expiredate = time.strftime("%Y-%m-%d", time.gmtime(timestamp))
+ else:
+ expiredate = timestamp
+ reject("The key used to sign %s has expired on %s" % (sig_filename, expiredate))
bad = 1
if bad:
################################################################################
-def temp_filename(directory=None, dotprefix=None, perms=0700):
+def temp_filename(directory=None, prefix="dak", suffix=""):
"""Return a secure and unique filename by pre-creating it.
If 'directory' is non-null, it will be the directory the file is pre-created in.
-If 'dotprefix' is non-null, the filename will be prefixed with a '.'."""
-
- if directory:
- old_tempdir = tempfile.tempdir
- tempfile.tempdir = directory
+If 'prefix' is non-null, the filename will be prefixed with it, default is dak.
+If 'suffix' is non-null, the filename will end with it.
- filename = tempfile.mktemp()
-
- if dotprefix:
- filename = "%s/.%s" % (os.path.dirname(filename), os.path.basename(filename))
- fd = os.open(filename, os.O_RDWR|os.O_CREAT|os.O_EXCL, perms)
- os.close(fd)
-
- if directory:
- tempfile.tempdir = old_tempdir
+Returns a pair (fd, name).
+"""
- return filename
+ return tempfile.mkstemp(suffix, prefix, directory)
################################################################################