Merge ~techalchemy/ubuntu-security-tools:feature/python3-migration into ubuntu-security-tools:master

Proposed by Dan Ryan
Status: Needs review
Proposed branch: ~techalchemy/ubuntu-security-tools:feature/python3-migration
Merge into: ubuntu-security-tools:master
Diff against target: 2788 lines (+994/-686)
39 files modified
audits/pk-list (+12/-10)
audits/test/data/encryption/ex_twisted.py (+1/-0)
audits/test/test-mir-code-audit.py (+2/-1)
audits/uaudit (+24/-15)
build-tools/buildlog-compare (+18/-14)
build-tools/diff-reorder (+5/-3)
build-tools/umt (+105/-102)
bzr-tools/plugins/uct-check_syntax.py (+10/-3)
bzr-tools/plugins/uct-check_syntax_full.py (+11/-3)
p-l-p/bug-status.py (+30/-23)
p-l-p/cookies-sql2txt.py (+23/-18)
p-l-p/dump-bug.py (+37/-30)
p-l-p/in-english.py (+28/-21)
p-l-p/is-cache.py (+25/-18)
p-l-p/is-private.py (+48/-20)
p-l-p/is-support.py (+21/-15)
p-l-p/not-a-bug.py (+56/-28)
p-l-p/not-private.py (+4/-3)
p-l-p/not-security-in-dups.py (+11/-8)
p-l-p/not-security-without-comment.py (+48/-20)
p-l-p/not-security.py (+49/-20)
p-l-p/reassign.py (+24/-22)
p-l-p/requires-trojaned-account.py (+2/-1)
p-l-p/set-package.py (+3/-2)
p-l-p/sub-security.py (+20/-13)
p-l-p/tag.py (+3/-2)
p-l-p/unsub-in-dups.py (+5/-4)
package-tools/debcompare (+28/-23)
repo-tools/count-hardened-pkgs (+74/-56)
repo-tools/count-hash-sources (+65/-52)
repo-tools/for-archive-tools/has-execstack (+30/-15)
repo-tools/for-archive-tools/has-symbols (+30/-15)
repo-tools/packages-support-status (+61/-52)
repo-tools/universe-binaries-with-sources-in-main.py (+7/-3)
snaps/coverity-ubuntu-security/files/bin/refresh-auth-key (+2/-1)
utilities/build_failures.py (+20/-14)
utilities/ceviche (+40/-25)
utilities/maildir2mbox.py (+10/-9)
utilities/mugshot (+2/-2)
Reviewer Review Type Date Requested Status
Alex Murray Pending
Review via email: mp+378297@code.launchpad.net

Commit message

Add support for python 3 across UST

- Add general compatibility for python 3 across UST
- Code convention & minor performance cleanup
- Safer file handle management
- str/bytes consciousness at the filesystem layer

Description of the change

Add python 3 support and minor implementation tweaks described below

- Begin implementing context managers around file handles
- Begin moving unguarded execution blocks to `if __name__ == '__main__'
    blocks in case code is ever used as a library (i.e. imported)
- Change print statements to functions
- Use `contextlib.closing` context manager around `urlopen` calls to
    ensure connections are closed
- Add alternative config parser using `ConfigParser` by adding a dummy
    section header when loading config files to avoid `configobj`
- Prefer to decompress remote gzipped content in memory to avoid writing
    to disk
- `yaml.safe_load` and `yaml.safe.dump` instead of `load` and `dump

To post a comment you must log in.
ceede68... by Dan Ryan

syntax fixes

Signed-off-by: Dan Ryan <email address hidden>

Unmerged commits

ceede68... by Dan Ryan

syntax fixes

Signed-off-by: Dan Ryan <email address hidden>

41f83d0... by Dan Ryan

Merge branch 'master' into feature/python3-migration

16ad204... by Dan Ryan

Add support for python 3 across UST

- Begin implementing context managers around file handles
- Begin moving unguarded execution blocks to `if __name__ == '__main__'
  blocks
- Change print statements to functions
- Use `contextlib.closing` context manager around `urlopen` calls to
  ensure connections are closed
- Add alternative config parser using `ConfigParser` by adding a dummy
  section header when loading config files to avoid `configobj`
- Prefer to decompress remote gzipped content in memory to avoid writing
  to disk
- `yaml.safe_load` and `yaml.safe.dump` instead of `load` and `dump`

Signed-off-by: Dan Ryan <email address hidden>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/audits/pk-list b/audits/pk-list
index 48857b5..8faa81a 100755
--- a/audits/pk-list
+++ b/audits/pk-list
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# Author: Jamie Strandboge <jamie@ubuntu.com>3# Author: Jamie Strandboge <jamie@ubuntu.com>
4# Copyright 2012 Canonical Ltd.4# Copyright 2012 Canonical Ltd.
@@ -13,7 +13,7 @@
13# TODO: Drop privs13# TODO: Drop privs
14# TODO: add dbus reporting14# TODO: add dbus reporting
1515
16from __future__ import print_function16from __future__ import absolute_import, print_function
1717
18import glob18import glob
19import optparse19import optparse
@@ -71,12 +71,12 @@ def get_merged_mapping(default_mapping, package_mapping, local_mapping):
71 pat = re.compile(r'%s' % k)71 pat = re.compile(r'%s' % k)
72 for i in merged.keys():72 for i in merged.keys():
73 if pat.search(i):73 if pat.search(i):
74 if i not in merged.keys():74 if i not in merged:
75 continue75 continue
76 merged[i]['overrides']['package'] = package_mapping[k]76 merged[i]['overrides']['package'] = package_mapping[k]
77 #print "%s: %s" % (k, merged[i]['overrides']['package'])77 #print "%s: %s" % (k, merged[i]['overrides']['package'])
78 else:78 else:
79 if k not in merged.keys():79 if k not in merged:
80 continue80 continue
81 merged[k]['overrides']['package'] = package_mapping[k]81 merged[k]['overrides']['package'] = package_mapping[k]
82 #print "%s: %s" % (k, merged[k]['overrides']['package'])82 #print "%s: %s" % (k, merged[k]['overrides']['package'])
@@ -221,10 +221,10 @@ class PKOverridesHandler():
221 entries[key] = value221 entries[key] = value
222 _debug(entries)222 _debug(entries)
223223
224 if "action" not in entries.keys():224 if "action" not in entries:
225 _warn("No action for '%s'. Skipping" % (section))225 _warn("No action for '%s'. Skipping" % (section))
226 continue226 continue
227 elif "identity" not in entries.keys():227 elif "identity" not in entries:
228 _warn("No identity for '%s'. Skipping" % (section))228 _warn("No identity for '%s'. Skipping" % (section))
229 continue229 continue
230230
@@ -260,7 +260,7 @@ class PKActionsHandler(xml.sax.handler.ContentHandler):
260 def startElement(self, name, attrs):260 def startElement(self, name, attrs):
261 _debug("PKActionsHandler.startElement()")261 _debug("PKActionsHandler.startElement()")
262 if name == "action":262 if name == "action":
263 if 'id' in attrs.keys():263 if 'id' in attrs:
264 self.curr_action = attrs['id']264 self.curr_action = attrs['id']
265 self.mapping[self.curr_action] = dict()265 self.mapping[self.curr_action] = dict()
266 self.in_action = True266 self.in_action = True
@@ -276,11 +276,11 @@ class PKActionsHandler(xml.sax.handler.ContentHandler):
276 return276 return
277277
278 if re.search(r'_?description', name):278 if re.search(r'_?description', name):
279 if 'xml:lang' not in attrs.keys(): # skip translated strings279 if 'xml:lang' not in attrs: # skip translated strings
280 self.in_description = True280 self.in_description = True
281 self.mapping[self.curr_action]['description'] = ""281 self.mapping[self.curr_action]['description'] = ""
282 elif re.search(r'_?message', name):282 elif re.search(r'_?message', name):
283 if 'xml:lang' not in attrs.keys(): # skip translated strings283 if 'xml:lang' not in attrs: # skip translated strings
284 self.in_message = True284 self.in_message = True
285 self.mapping[self.curr_action]['message'] = ""285 self.mapping[self.curr_action]['message'] = ""
286 elif name == "defaults":286 elif name == "defaults":
@@ -353,7 +353,9 @@ class PKActionsHandler(xml.sax.handler.ContentHandler):
353353
354 cleaned_lines = []354 cleaned_lines = []
355 skipped_doctype = False355 skipped_doctype = False
356 for line in open(f).readlines():356 with open(f, "r") as fh:
357 lines = fh.readlines()
358 for line in lines:
357 if line.startswith("<policyconfig>"):359 if line.startswith("<policyconfig>"):
358 skipped_doctype = True360 skipped_doctype = True
359 if not skipped_doctype:361 if not skipped_doctype:
diff --git a/audits/test/data/encryption/ex_twisted.py b/audits/test/data/encryption/ex_twisted.py
index 891ca40..6a112a9 100644
--- a/audits/test/data/encryption/ex_twisted.py
+++ b/audits/test/data/encryption/ex_twisted.py
@@ -1,2 +1,3 @@
1from __future__ import absolute_import, print_function
1from twisted.internet import reactor, ssl2from twisted.internet import reactor, ssl
2from twisted.internet.ssl import ClientContextFactory3from twisted.internet.ssl import ClientContextFactory
diff --git a/audits/test/test-mir-code-audit.py b/audits/test/test-mir-code-audit.py
index 4e6d548..73d8b6b 100755
--- a/audits/test/test-mir-code-audit.py
+++ b/audits/test/test-mir-code-audit.py
@@ -147,7 +147,8 @@ class T(unittest.TestCase):
147 for line in report.splitlines():147 for line in report.splitlines():
148 if '%s:' % f in line:148 if '%s:' % f in line:
149 content += pat.sub('<path>', line) + "\n"149 content += pat.sub('<path>', line) + "\n"
150 open(tmp, 'w').write(content)150 with open(tmp, 'w') as fh:
151 fh.write(content)
151152
152 # now compare each test result153 # now compare each test result
153 results = glob.glob("%s/*.result" % self.tmpdir)154 results = glob.glob("%s/*.result" % self.tmpdir)
diff --git a/audits/uaudit b/audits/uaudit
index 2ef95cf..1da183b 100755
--- a/audits/uaudit
+++ b/audits/uaudit
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# Author: Jamie Strandboge <jamie@ubuntu.com>3# Author: Jamie Strandboge <jamie@ubuntu.com>
4# Copyright 2012 Canonical Ltd.4# Copyright 2012 Canonical Ltd.
@@ -16,7 +16,8 @@
16# along with this program. If not, see <http://www.gnu.org/licenses/>.16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17#17#
1818
19from __future__ import print_function19from __future__ import absolute_import, print_function
20
20from pathlib import Path21from pathlib import Path
21import glob22import glob
22import optparse23import optparse
@@ -28,6 +29,11 @@ import sys
28import tempfile29import tempfile
29import json30import json
3031
32if sys.version_info[0] == 2:
33 raw_input = raw_input
34else:
35 raw_input = input
36
31DEBUGGING = False37DEBUGGING = False
32ust = {}38ust = {}
3339
@@ -125,13 +131,14 @@ def parse_package_details():
125 global ust131 global ust
126 details = {}132 details = {}
127133
134 header = []
128 try:135 try:
129 changelog = open('debian/changelog', 'r')136 with open("debian/changelog", "r") as fh:
137 # Extract info from the first line of the changelog
138 header = fh.readline().split()
130 except Exception:139 except Exception:
131 error("Could not open debian/changelog. Aborting.")140 error("Could not open debian/changelog. Aborting.")
132141
133 # Extract info from the first line of the changelog
134 header = changelog.readline().split()
135 details['package'] = header[0]142 details['package'] = header[0]
136 details['version'] = header[1].strip('()')143 details['version'] = header[1].strip('()')
137144
@@ -186,7 +193,7 @@ def find_build_log(pkg, ver):
186 latest = None193 latest = None
187 modified = None194 modified = None
188 for log in glob.glob(ust['pkgbuild_logs'] + '/*%s_*' % (pkg)):195 for log in glob.glob(ust['pkgbuild_logs'] + '/*%s_*' % (pkg)):
189 with open(log) as log_file:196 with open(log, "r") as log_file:
190 line = log_file.readline()197 line = log_file.readline()
191 if not line.startswith("Automatic build of"):198 if not line.startswith("Automatic build of"):
192 # Skip the first three lines of the file for newer sbuild199 # Skip the first three lines of the file for newer sbuild
@@ -213,8 +220,10 @@ def load_ust_config(config_file):
213220
214 config = {}221 config = {}
215 # no python-configobj in python3 yet, so read what we need ourselves222 # no python-configobj in python3 yet, so read what we need ourselves
216 for line in open(config_file, 'r').readlines():223 with open(config_file, "r") as fh:
217 line.strip()224 lines = fh.readlines()
225 for line in lines:
226 line = line.strip()
218 if line.startswith('#'):227 if line.startswith('#'):
219 continue228 continue
220 if '=' not in line:229 if '=' not in line:
@@ -264,7 +273,7 @@ def query_user_consent_to_install_tool(tool):
264273
265 while True:274 while True:
266 sys.stdout.write(question)275 sys.stdout.write(question)
267 choice = input().lower()276 choice = raw_input().lower()
268 if choice in valid_answers:277 if choice in valid_answers:
269 return valid_answers[choice]278 return valid_answers[choice]
270 else:279 else:
@@ -623,8 +632,8 @@ def cov_analyze(covdir):
623 return632 return
624633
625 # parse auth token for host and port634 # parse auth token for host and port
626 fp = open(cov_auth_key, 'r')635 with open(cov_auth_key, 'r') as fp:
627 token = json.load(fp)636 token = json.load(fp)
628 host = token['comments']['host']637 host = token['comments']['host']
629 port = token['comments']['port']638 port = token['comments']['port']
630 project = details['package']639 project = details['package']
@@ -1013,13 +1022,13 @@ if __name__ == "__main__":
1013 if not os.path.exists(txt):1022 if not os.path.exists(txt):
1014 msg("Creating %s" % txt)1023 msg("Creating %s" % txt)
1015 # replace variables in file1024 # replace variables in file
1016 s = open(base).read()1025 with open(base, "r") as fh:
1026 s = fh.read()
1017 s = s.replace('$package', package)1027 s = s.replace('$package', package)
1018 s = s.replace('$version', details['version'])1028 s = s.replace('$version', details['version'])
1019 s = s.replace('$release', details['release'])1029 s = s.replace('$release', details['release'])
1020 f = open(txt, 'w')1030 with open(txt, "w") as f:
1021 f.write(s)1031 f.write(s)
1022 f.close()
1023 else:1032 else:
1024 warn("Could not find %s template to copy" % base)1033 warn("Could not find %s template to copy" % base)
10251034
diff --git a/build-tools/buildlog-compare b/build-tools/buildlog-compare
index 6225e69..697e3c1 100755
--- a/build-tools/buildlog-compare
+++ b/build-tools/buildlog-compare
@@ -1,15 +1,18 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# Copyright (C) 2007-2018 Canonical, Ltd.2# Copyright (C) 2007-2018 Canonical, Ltd.
3# Author: Kees Cook <kees@ubuntu.com>3# Author: Kees Cook <kees@ubuntu.com>
4# Jamie Strandboge <jamie@canonical.com>4# Jamie Strandboge <jamie@canonical.com>
5# Marc Deslauriers <marc.deslauriers@canonical.com>5# Marc Deslauriers <marc.deslauriers@canonical.com>
6# License: GPLv36# License: GPLv3
7from __future__ import absolute_import, print_function
7import sys, subprocess, tempfile, re, os8import sys, subprocess, tempfile, re, os
8import optparse9import optparse
910
10def pull_build_log(filename):11def pull_build_log(filename):
11 sep = '\nChecking correctness of source dependencies...\n'12 sep = '\nChecking correctness of source dependencies...\n'
12 log = file(filename).read()13 log = ""
14 with open(filename, "r") as fh:
15 log = fh.read()
13 if sep in log:16 if sep in log:
14 log = log.split(sep,1)[1]17 log = log.split(sep,1)[1]
15# log = sep.join(log.split(sep)[:-1])+"\n"18# log = sep.join(log.split(sep)[:-1])+"\n"
@@ -345,15 +348,16 @@ newlog = re.sub('\[[ 0-9]{4}/[ 0-9]{4}\] Linking', '[XXXX/XXXX] Linking', newlog
345oldlog = re.sub('-DBUILD_DATETIME=...?[0-9]{4}-[0-9]{2}-[0-9]{2}T1?\d:[0-5]\d:[0-5]\d...? ', '-DBUILD_DATETIME=0000-00-00T00:00:00 ', oldlog)348oldlog = re.sub('-DBUILD_DATETIME=...?[0-9]{4}-[0-9]{2}-[0-9]{2}T1?\d:[0-5]\d:[0-5]\d...? ', '-DBUILD_DATETIME=0000-00-00T00:00:00 ', oldlog)
346newlog = re.sub('-DBUILD_DATETIME=...?[0-9]{4}-[0-9]{2}-[0-9]{2}T1?\d:[0-5]\d:[0-5]\d...? ', '-DBUILD_DATETIME=0000-00-00T00:00:00 ', newlog)349newlog = re.sub('-DBUILD_DATETIME=...?[0-9]{4}-[0-9]{2}-[0-9]{2}T1?\d:[0-5]\d:[0-5]\d...? ', '-DBUILD_DATETIME=0000-00-00T00:00:00 ', newlog)
347350
348# Write out the files for diffing351# Write out the files for diffing, use context managers to clean up temporary
349oldfile = tempfile.NamedTemporaryFile(prefix='buildlog-')352# file handles & avoid leaking handles at interpreter exit
350write_log(oldfile, oldlog, opt.deparallel, pkg)353with tempfile.NamedTemporaryFile(prefix='buildlog-', mode="w+") as oldfile:
351354 write_log(oldfile, oldlog, opt.deparallel, pkg)
352newfile = tempfile.NamedTemporaryFile(prefix='buildlog-')355 oldfile.flush()
353write_log(newfile, newlog, opt.deparallel, pkg)356
354357 with tempfile.NamedTemporaryFile(prefix='buildlog-', mode="w+") as newfile:
355# To debug, useful to do:358 write_log(newfile, newlog, opt.deparallel, pkg)
356#shutil.copy(oldfile.name, "/tmp/old")359 newfile.flush()
357#shutil.copy(newfile.name, "/tmp/new")360 subprocess.call(['diff', '-ub', oldfile.name, newfile.name])
358361 # To debug, useful to do:
359subprocess.call(['diff', '-ub', oldfile.name, newfile.name])362 #shutil.copy(oldfile.name, "/tmp/old")
363 #shutil.copy(newfile.name, "/tmp/new")
diff --git a/build-tools/diff-reorder b/build-tools/diff-reorder
index ef641de..2a9232f 100755
--- a/build-tools/diff-reorder
+++ b/build-tools/diff-reorder
@@ -1,4 +1,4 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# This tool attempts to balance out +/- lines in the same or2# This tool attempts to balance out +/- lines in the same or
3# adjacent diff chunks. When doing parallel builds, output3# adjacent diff chunks. When doing parallel builds, output
4# frequently gets out of order, needlessly filling the diff4# frequently gets out of order, needlessly filling the diff
@@ -8,6 +8,8 @@
8#8#
9# Copyright (C) 2009, Canonical Ltd.9# Copyright (C) 2009, Canonical Ltd.
10# Author: Kees Cook <kees@ubuntu.com>10# Author: Kees Cook <kees@ubuntu.com>
11from __future__ import absolute_import, print_function
12
11import sys13import sys
1214
13def plus_minus_lines(hunk):15def plus_minus_lines(hunk):
@@ -99,7 +101,7 @@ class Hunk(object):
99 for line in self.lines:101 for line in self.lines:
100 if line.startswith('@@') and self.is_empty():102 if line.startswith('@@') and self.is_empty():
101 break103 break
102 print prefix + line104 print(prefix + line)
103105
104collector = ""106collector = ""
105minus = 0107minus = 0
@@ -130,7 +132,7 @@ for line in sys.stdin:
130 plus = plus - 1132 plus = plus - 1
131 else:133 else:
132 # Broken patch!134 # Broken patch!
133 raise ValueError, "Corrupted patch? '%s'" % (line.replace('\n',''))135 raise ValueError("Corrupted patch? '%s'" % (line.replace('\n','')))
134 if minus == 0 and plus == 0:136 if minus == 0 and plus == 0:
135 # HUNK FINISHED137 # HUNK FINISHED
136 counting = False138 counting = False
diff --git a/build-tools/umt b/build-tools/umt
index 400294d..69fcb93 100755
--- a/build-tools/umt
+++ b/build-tools/umt
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>3# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>
4# Author: Kees Cook <kees@ubuntu.com>4# Author: Kees Cook <kees@ubuntu.com>
@@ -845,114 +845,119 @@ def cmd_compare_log():
845 err("Could not find 'diff-reorder' (is '$UST' set?). Aborting.")845 err("Could not find 'diff-reorder' (is '$UST' set?). Aborting.")
846 sys.exit(1)846 sys.exit(1)
847847
848 diff = tempfile.NamedTemporaryFile(suffix='.diff',prefix='umt_compare-log_')848 with tempfile.NamedTemporaryFile(
849 diff.write(b"Log file line counts:\n")849 suffix='.diff',prefix='umt_compare-log_', mode='w+b'
850 diff.flush()850 ) as diff, tempfile.NamedTemporaryFile(
851 subprocess.call(['wc','-l','--',old_logfile],stdout=diff)851 suffix='.diff', prefix='umt_compare-log_', mode='w+b'
852 subprocess.call(['wc','-l','--',new_logfile],stdout=diff)852 ) as patches_diff:
853 diff.write(b"\n")853 diff.write(b"Log file line counts:\n")
854 diff.flush()854 diff.flush()
855 command = [buildlog_compare]855 subprocess.check_call(['wc','-l','--',old_logfile], stdout=diff)
856 if opt.deparallel:856 subprocess.check_call(['wc','-l','--',new_logfile], stdout=diff)
857 diff.write(b"\n")
858 diff.flush()
859 command = [buildlog_compare]
860 if opt.deparallel:
861 if opt.balance:
862 err("Skipping --balance with --deparallel")
863 else:
864 command.append("--deparallel")
865 command += [details['package'],details['base_version_prior'],old_logfile,details['base_version'],new_logfile]
866
857 if opt.balance:867 if opt.balance:
858 err("Skipping --balance with --deparallel")868 p1 = subprocess.Popen(command, stdout=subprocess.PIPE)
869 p2 = subprocess.Popen([diff_reorder], stdin=p1.stdout, stdout=subprocess.PIPE)
870 diff.write(p2.communicate()[0])
859 else:871 else:
860 command.append("--deparallel")872 try:
861 command += [details['package'],details['base_version_prior'],old_logfile,details['base_version'],new_logfile]873 subprocess.check_call(command, stdout=diff)
862874 except subprocess.CalledProcessError as e:
863 if opt.balance:875 sys.exit(e.returncode)
864 p1 = subprocess.Popen(command, stdout=subprocess.PIPE)876 diff.flush()
865 p2 = subprocess.Popen([diff_reorder], stdin=p1.stdout, stdout=subprocess.PIPE)
866 diff.write(p2.communicate()[0])
867 else:
868 if subprocess.call(command,stdout=diff) != 0:
869 sys.exit(1)
870877
871 diff.flush()878 if opt.dump_to_stdout:
872 if opt.dump_to_stdout:879 subprocess.call(['cat', diff.name])
873 subprocess.call(['cat', diff.name])880 return
874 return
875881
876 editor = os.getenv('EDITOR') or 'vi'882 editor = os.getenv('EDITOR') or 'vi'
877 if editor.find('vi') >= 0:883 if editor.find('vi') >= 0:
878 subprocess.call([editor,'+set syntax=diff', diff.name])884 subprocess.call([editor,'+set syntax=diff', diff.name])
879 else:885 else:
880 subprocess.call([editor, diff.name])886 subprocess.call([editor, diff.name])
881887
882 # Show what is happening to the patches in a build888 # Show what is happening to the patches in a build
883 patches_diff = tempfile.NamedTemporaryFile(suffix='.diff',prefix='umt_compare-log_')889 patches_diff.write(b"Listing of applied patch differences:\n")
884 patches_diff.write(b"Listing of applied patch differences:\n")890 patches_diff.write(("%s\n%s\n" % (old_logfile, new_logfile)).encode())
885 patches_diff.write(("%s\n%s\n" % (old_logfile, new_logfile)).encode())891 patches_diff.flush()
886 patches_diff.flush()
887892
888 (rc, report) = runcmd(['what-patch'])893 (rc, report) = runcmd(['what-patch'])
889 if rc != 0:894 if rc != 0:
890 err("running 'what-patch':\n%s" % report)895 err("running 'what-patch':\n%s" % report)
891 sys.exit(1)896 sys.exit(1)
892 patch_system = report.strip()897 patch_system = report.strip()
893898
894 if patch_system == "quilt" or patch_system == "dpatch" or patch_system == "cdbs":899 if patch_system == "quilt" or patch_system == "dpatch" or patch_system == "cdbs":
895 patch_list = []900 patch_list = []
896 skip = False901 skip = False
897 if patch_system == "cdbs":902 if patch_system == "cdbs":
898 fn = "debian/patches"903 fn = "debian/patches"
899 if not os.path.isdir(fn):904 if not os.path.isdir(fn):
900 patches_diff.write(("Skipping checks for patch system '%s', missing '%s'" % (patch_system, fn)).encode())905 patches_diff.write(("Skipping checks for patch system '%s', missing '%s'" % (patch_system, fn)).encode())
901 skip = True906 skip = True
907 else:
908 for p in os.listdir(fn):
909 if p.endswith('.patch') or p.endswith('.diff'):
910 patch_list.append(".".join(p.split('.')[:-1]))
911 else:
912 patch_list.append(p)
913 patch_list.sort()
902 else:914 else:
903 for p in os.listdir(fn):915 if patch_system == "quilt":
904 if p.endswith('.patch') or p.endswith('.diff'):916 fn = "debian/patches/series.in"
905 patch_list.append(".".join(p.split('.')[:-1]))917 if not os.path.exists(fn):
906 else:918 fn = "debian/patches/series"
907 patch_list.append(p)919 elif patch_system == "dpatch":
908 patch_list.sort()920 fn = "debian/patches/00list"
909 else:921
910 if patch_system == "quilt":
911 fn = "debian/patches/series.in"
912 if not os.path.exists(fn):922 if not os.path.exists(fn):
913 fn = "debian/patches/series"923 patches_diff.write(("Skipping checks for patch system '%s', missing '%s'" % (patch_system, fn)).encode())
914 elif patch_system == "dpatch":924 skip = True
915 fn = "debian/patches/00list"925 else:
926 for p in open(fn).readlines():
927 p = p.strip()
928 if p.startswith('#') or re.search(r'^\s*$', p):
929 continue
930 if p.endswith('.dpatch') or p.endswith('.patch') or p.endswith('.diff'):
931 patch_list.append(".".join(p.split('.')[:-1]))
932 else:
933 patch_list.append(p)
934 if not skip:
935 tmp = ""
936 for p in patch_list:
937 (rc, report) = runcmd(['egrep', p, diff.name])
916938
917 if not os.path.exists(fn):939 tmp = ""
918 patches_diff.write(("Skipping checks for patch system '%s', missing '%s'" % (patch_system, fn)).encode())940 for line in report.splitlines():
919 skip = True941 if patch_system == "cdbs" and re.search(r'^[+-]patches: ', line):
920 else:942 continue
921 for p in open(fn).readlines():943 if (line.startswith('-') or line.startswith('+')) and not re.search(r'^[+-] ', line):
922 p = p.strip()944 if line.startswith('+revert'):
923 if p.startswith('#') or re.search(r'^\s*$', p):945 tmp += "# UMT WARNING: This patch was reverted. This may be a problem.\n"
924 continue946 tmp += "# UMT WARNING: Check debian/rules and/or README.source for details.\n"
925 if p.endswith('.dpatch') or p.endswith('.patch') or p.endswith('.diff'):947 tmp += line + "\n"
926 patch_list.append(".".join(p.split('.')[:-1]))
927 else:
928 patch_list.append(p)
929 if not skip:
930 tmp = ""
931 for p in patch_list:
932 (rc, report) = runcmd(['egrep', p, diff.name])
933948
934 tmp = ""949 if tmp == "":
935 for line in report.splitlines():
936 if patch_system == "cdbs" and re.search(r'^[+-]patches: ', line):
937 continue950 continue
938 if (line.startswith('-') or line.startswith('+')) and not re.search(r'^[+-] ', line):951 else:
939 if line.startswith('+revert'):952 patches_diff.write(("\n%s:" % (p)).encode())
940 tmp += "# UMT WARNING: This patch was reverted. This may be a problem.\n"953 patches_diff.write(tmp.encode())
941 tmp += "# UMT WARNING: Check debian/rules and/or README.source for details.\n"954 else:
942 tmp += line + "\n"955 patches_diff.write(("Skipping checks for patch system '%s'" % (patch_system)).encode())
943956 patches_diff.flush()
944 if tmp == "":957 if editor.find('vi') >= 0:
945 continue958 subprocess.call([editor,'+set syntax=diff', patches_diff.name])
946 else:959 else:
947 patches_diff.write(("\n%s:" % (p)).encode())960 subprocess.call([editor, patches_diff.name])
948 patches_diff.write(tmp.encode())
949 else:
950 patches_diff.write(("Skipping checks for patch system '%s'" % (patch_system)).encode())
951 patches_diff.flush()
952 if editor.find('vi') >= 0:
953 subprocess.call([editor,'+set syntax=diff', patches_diff.name])
954 else:
955 subprocess.call([editor, patches_diff.name])
956961
957def cmd_compare_bin():962def cmd_compare_bin():
958 '''Compare binary debs with prior version'''963 '''Compare binary debs with prior version'''
@@ -1352,10 +1357,8 @@ Acquire::Languages "none";
1352 continue1357 continue
13531358
1354 path = os.path.join(reports_dest, b + '_' + arch + '.txt')1359 path = os.path.join(reports_dest, b + '_' + arch + '.txt')
1355 handle = open(path,"w+")1360 with open(path,"w+") as handle:
1356 handle.write(report)1361 handle.write(report)
1357 handle.flush()
1358 handle.close()
13591362
1360 if opt.edit:1363 if opt.edit:
1361 editor = os.getenv('EDITOR') or 'vi'1364 editor = os.getenv('EDITOR') or 'vi'
diff --git a/bzr-tools/plugins/uct-check_syntax.py b/bzr-tools/plugins/uct-check_syntax.py
index c22e3a7..5f7b56c 100644
--- a/bzr-tools/plugins/uct-check_syntax.py
+++ b/bzr-tools/plugins/uct-check_syntax.py
@@ -1,13 +1,20 @@
1#!/usr/bin/python1#!/usr/bin/env python3
22
3from __future__ import print_function3from __future__ import absolute_import, print_function
4
5import sys
46
5from bzrlib.branch import Branch7from bzrlib.branch import Branch
68
9if sys.version_info[0] == 2:
10 raw_input = raw_input
11else:
12 raw_input = input
13
7def run_tests(local, master, old_revno, old_revid, new_revno, new_revid, tree_delta, new_tree):14def run_tests(local, master, old_revno, old_revid, new_revno, new_revid, tree_delta, new_tree):
8 # print(local, master, old_revno, old_revid, new_revno, new_revid, tree_delta, new_tree)15 # print(local, master, old_revno, old_revid, new_revno, new_revid, tree_delta, new_tree)
9 import os16 import os
10 if 'ubuntu-cve-tracker' in master.base and not os.environ.has_key('UCT_IGNORE_CHECK_SYNTAX'):17 if 'ubuntu-cve-tracker' in master.base and 'UCT_IGNORE_CHECK_SYNTAX' not in os.environ:
11 import subprocess18 import subprocess
12 print('')19 print('')
1320
diff --git a/bzr-tools/plugins/uct-check_syntax_full.py b/bzr-tools/plugins/uct-check_syntax_full.py
index a9e2d5c..14eaea0 100644
--- a/bzr-tools/plugins/uct-check_syntax_full.py
+++ b/bzr-tools/plugins/uct-check_syntax_full.py
@@ -1,12 +1,20 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2from __future__ import absolute_import, print_function
3import sys
2from bzrlib.branch import Branch4from bzrlib.branch import Branch
35
6if sys.version_info[0] == 2:
7 raw_input = raw_input
8else:
9 raw_input = input
10
11
4def run_tests(local, master, old_revno, old_revid, new_revno, new_revid, seven, eight):12def run_tests(local, master, old_revno, old_revid, new_revno, new_revid, seven, eight):
5 #print local, master, old_revno, old_revid, new_revno, new_revid, seven, eight13 #print local, master, old_revno, old_revid, new_revno, new_revid, seven, eight
6 import os14 import os
7 if 'ubuntu-cve-tracker' in master.base and not os.environ.has_key('UCT_IGNORE_CHECK_SYNTAX'):15 if 'ubuntu-cve-tracker' in master.base and 'UCT_IGNORE_CHECK_SYNTAX' not in os.environ:
8 import subprocess16 import subprocess
9 print ''17 print('')
10 rc = subprocess.call(['./scripts/check-syntax','--verbose'])18 rc = subprocess.call(['./scripts/check-syntax','--verbose'])
11 if rc != 0:19 if rc != 0:
12 import sys20 import sys
diff --git a/p-l-p/bug-status.py b/p-l-p/bug-status.py
index 16cbfbf..55c0bc9 100755
--- a/p-l-p/bug-status.py
+++ b/p-l-p/bug-status.py
@@ -1,36 +1,43 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Jamie Strandboge <jamie@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Jamie Strandboge <jamie@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5import sys5from __future__ import absolute_import, print_function
6
6import os7import os
8import sys
7import launchpadbugs.connector as Connector9import launchpadbugs.connector as Connector
810
9Bug = Connector.ConnectBug()
10Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
1111
12for num in sys.argv[1:]:12def print_bugs():
13 bug = Bug(int(num))13 Bug = Connector.ConnectBug()
14 Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
15
16 for num in sys.argv[1:]:
17 bug = Bug(int(num))
18
19 print(num + ": " + bug.title)
20 print(" URL: https://bugs.launchpad.net/bugs/" + num)
21 if bug.duplicate_of:
22 print(" Duplicate of " + str(bug.duplicate_of))
23 print(" Status: " + bug.status + "\n")
1424
15 print num + ": " + bug.title25 if bug.private:
16 print " URL: https://bugs.launchpad.net/bugs/" + num26 print(" Private: yes")
17 if bug.duplicate_of:27 else:
18 print " Duplicate of " + str(bug.duplicate_of)28 print(" Private: no")
19 print " Status: " + bug.status + "\n"
2029
21 if bug.private:30 if bug.security:
22 print " Private: yes"31 print(" Security: yes")
23 else:32 else:
24 print " Private: no"33 print(" Security: no")
2534
26 if bug.security:35 print("\n Subscribers:")
27 print " Security: yes"36 for s in bug.subscribers:
28 else:37 print(" " + s)
29 print " Security: no"
3038
31 print "\n Subscribers:"39 print("\n--\n")
32 for s in bug.subscribers:
33 print " " + s
3440
35 print "\n--\n"
3641
42if __name__ == "__main__":
43 print_bugs()
37\ No newline at end of file44\ No newline at end of file
diff --git a/p-l-p/cookies-sql2txt.py b/p-l-p/cookies-sql2txt.py
index cc6347c..304ca01 100755
--- a/p-l-p/cookies-sql2txt.py
+++ b/p-l-p/cookies-sql2txt.py
@@ -1,33 +1,38 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# Extract.cookies.sqlite.txt-like file from FF3 sqlite3 cookies file. e.g.:2# Extract.cookies.sqlite.txt-like file from FF3 sqlite3 cookies file. e.g.:
3# .cookies.sqlite-sql2txt ~/.mozilla/*/cookies.sqlite launchpad3# .cookies.sqlite-sql2txt ~/.mozilla/*/cookies.sqlite launchpad
4#4#
5# Copyright 2008 Kees Cook <kees@outflux.net>5# Copyright 2008 Kees Cook <kees@outflux.net>
6# License: GPLv26# License: GPLv2
7import sys7from __future__ import absolute_import, print_function
8import os8import os
9import sys
10# TODO: Migrate this to sqlite3 + argparse
9from pysqlite2 import dbapi2 as sqlite11from pysqlite2 import dbapi2 as sqlite
1012
11def usage():13def print_usage():
12 print >>sys.stderr, "Usage: %s SQLITE3DB DOMAIN"14 print("Usage: %s SQLITE3DB DOMAIN", file=sys.stderr)
13 sys.exit(1)15 sys.exit(1)
1416
15try:
16 filename = sys.argv[1]
17 match = '%%%s%%' % sys.argv[2]
18except:
19 usage()
2017
21con = sqlite.connect(filename)18def print_cookie_file(filename, match_param):
19 match = '%%%s%%' % match_param
20 con = sqlite.connect(filename)
21
22 cur = con.cursor()
23 cur.execute("select host, path, isSecure, expiry, name, value from moz.cookies.sqlite where host like ?", [match])
2224
23cur = con.cursor()25 ftstr = ["FALSE","TRUE"]
24cur.execute("select host, path, isSecure, expiry, name, value from moz.cookies.sqlite where host like ?", [match])
2526
26ftstr = ["FALSE","TRUE"]27 print('# HTTP Cookie File')
28 for item in cur.fetchall():
29 print("%s\t%s\t%s\t%s\t%s\t%s\t%s" % (
30 item[0], ftstr[item[0].startswith('.')], item[1],
31 ftstr[item[2]], item[3], item[4], item[5]))
2732
28print '# HTTP Cookie File'
29for item in cur.fetchall():
30 print "%s\t%s\t%s\t%s\t%s\t%s\t%s" % (
31 item[0], ftstr[item[0].startswith('.')], item[1],
32 ftstr[item[2]], item[3], item[4], item[5])
3333
34if __name__ == "__main__":
35 try:
36 print_cookie_file(sys.argv[1], sys.argv[2])
37 except Exception:
38 print_usage()
34\ No newline at end of file39\ No newline at end of file
diff --git a/p-l-p/dump-bug.py b/p-l-p/dump-bug.py
index 8b7d8d6..bf2851a 100755
--- a/p-l-p/dump-bug.py
+++ b/p-l-p/dump-bug.py
@@ -1,15 +1,16 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Jamie Strandboge <jamie@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Jamie Strandboge <jamie@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys6import sys
6import os7import os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
910
10def printDict(di, format="%-25s %s"):11def printDict(di, format="%-25s %s"):
11 for (key, val) in di.items():12 for key, val in di.items():
12 print format % (str(key)+':', val)13 print(format % (str(key)+':', val))
1314
14def dumpObj(obj, maxlen=77, lindent=24, maxspew=600):15def dumpObj(obj, maxlen=77, lindent=24, maxspew=600):
15 """Print a nicely formatted overview of an object.16 """Print a nicely formatted overview of an object.
@@ -79,7 +80,7 @@ def dumpObj(obj, maxlen=77, lindent=24, maxspew=600):
79 elif (isinstance(attr, types.MethodType) or80 elif (isinstance(attr, types.MethodType) or
80 isinstance(attr, types.FunctionType)):81 isinstance(attr, types.FunctionType)):
81 methods.append( (slot, attr) )82 methods.append( (slot, attr) )
82 elif isinstance(attr, types.TypeType):83 elif isinstance(attr, type):
83 classes.append( (slot, attr) )84 classes.append( (slot, attr) )
84 else:85 else:
85 attrs.append( (slot, attr) )86 attrs.append( (slot, attr) )
@@ -109,57 +110,57 @@ def dumpObj(obj, maxlen=77, lindent=24, maxspew=600):
109 objclass = type(obj).__name__110 objclass = type(obj).__name__
110 intro = "Instance of class '%s' as defined in module %s with id %d" % \111 intro = "Instance of class '%s' as defined in module %s with id %d" % \
111 (objclass, objmodule, id(obj))112 (objclass, objmodule, id(obj))
112 print '\n'.join(prettyPrint(intro, maxlen))113 print('\n'.join(prettyPrint(intro, maxlen)))
113114
114 # Object's Docstring115 # Object's Docstring
115 if objdoc is None:116 if objdoc is None:
116 objdoc = str(objdoc)117 objdoc = str(objdoc)
117 else:118 else:
118 objdoc = ('"""' + objdoc.strip() + '"""')119 objdoc = ('"""' + objdoc.strip() + '"""')
119 print120 print()
120 print prettyPrintCols( ('Documentation string:',121 print(prettyPrintCols( ('Documentation string:',
121 truncstring(objdoc, maxspew)),122 truncstring(objdoc, maxspew)),
122 normalwidths, ' ')123 normalwidths, ' '))
123124
124 # Built-in methods125 # Built-in methods
125 if builtins:126 if builtins:
126 bi_str = delchars(str(builtins), "[']") or str(None)127 bi_str = delchars(str(builtins), "[']") or str(None)
127 print128 print()
128 print prettyPrintCols( ('Built-in Methods:',129 print(prettyPrintCols( ('Built-in Methods:',
129 truncstring(bi_str, maxspew)),130 truncstring(bi_str, maxspew)),
130 normalwidths, ', ')131 normalwidths, ', '))
131 132
132 # Classes133 # Classes
133 if classes:134 if classes:
134 print135 print()
135 print 'Classes:'136 print('Classes:')
136 for (classname, classtype) in classes:137 for (classname, classtype) in classes:
137 classdoc = getattr(classtype, '__doc__', None) or '<No documentation>'138 classdoc = getattr(classtype, '__doc__', None) or '<No documentation>'
138 print prettyPrintCols( ('',139 print(prettyPrintCols( ('',
139 classname,140 classname,
140 truncstring(classdoc, maxspew)),141 truncstring(classdoc, maxspew)),
141 tabbedwidths, ' ')142 tabbedwidths, ' '))
142143
143 # User methods144 # User methods
144 if methods:145 if methods:
145 print146 print()
146 print 'Methods:'147 print('Methods:')
147 for (methodname, method) in methods:148 for (methodname, method) in methods:
148 methoddoc = getattr(method, '__doc__', None) or '<No documentation>'149 methoddoc = getattr(method, '__doc__', None) or '<No documentation>'
149 print prettyPrintCols( ('',150 print(prettyPrintCols( ('',
150 methodname,151 methodname,
151 truncstring(methoddoc, maxspew)),152 truncstring(methoddoc, maxspew)),
152 tabbedwidths, ' ')153 tabbedwidths, ' '))
153154
154 # Attributes155 # Attributes
155 if attrs:156 if attrs:
156 print157 print()
157 print 'Attributes:'158 print('Attributes:')
158 for (attr, val) in attrs:159 for (attr, val) in attrs:
159 print prettyPrintCols( ('',160 print(prettyPrintCols( ('',
160 attr,161 attr,
161 truncstring(str(val), maxspew)),162 truncstring(str(val), maxspew)),
162 tabbedwidths, ' ')163 tabbedwidths, ' '))
163164
164def prettyPrintCols(strings, widths, split=' '):165def prettyPrintCols(strings, widths, split=' '):
165 """Pretty prints text in colums, with each string breaking at166 """Pretty prints text in colums, with each string breaking at
@@ -168,7 +169,7 @@ def prettyPrintCols(strings, widths, split=' '):
168169
169 assert len(strings) == len(widths)170 assert len(strings) == len(widths)
170171
171 strings = map(nukenewlines, strings)172 strings = list(map(nukenewlines, strings))
172173
173 # pretty print each column174 # pretty print each column
174 cols = [''] * len(strings)175 cols = [''] * len(strings)
@@ -179,7 +180,7 @@ def prettyPrintCols(strings, widths, split=' '):
179 format = ''.join(["%%-%ds" % width for width in widths[0:-1]]) + "%s"180 format = ''.join(["%%-%ds" % width for width in widths[0:-1]]) + "%s"
180181
181 def formatline(*cols):182 def formatline(*cols):
182 return format % tuple(map(lambda s: (s or ''), cols))183 return format % tuple([(s or '') for s in cols])
183184
184 # generate the formatted text185 # generate the formatted text
185 return '\n'.join(map(formatline, *cols))186 return '\n'.join(map(formatline, *cols))
@@ -226,11 +227,17 @@ def delchars(str, chars):
226 return str.translate(identity, chars)227 return str.translate(identity, chars)
227228
228229
229Bug = Connector.ConnectBug()230# TODO: Migrate this to argparse
230Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
231231
232for num in sys.argv[1:]:232def print_bugs(*bugs):
233 bug = Bug(int(num))233 Bug = Connector.ConnectBug()
234 Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
234235
235 dumpObj(bug, 1024, 24, 1024)236 for num in bugs:
237 bug = Bug(int(num))
236238
239 dumpObj(bug, 1024, 24, 1024)
240
241
242if __name__ == "__main__":
243 print_bugs(*sys.argv[1:])
237\ No newline at end of file244\ No newline at end of file
diff --git a/p-l-p/in-english.py b/p-l-p/in-english.py
index 8e56db0..ad75f5e 100755
--- a/p-l-p/in-english.py
+++ b/p-l-p/in-english.py
@@ -1,30 +1,37 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5import sys5from __future__ import absolute_import, print_function
6import os6import os
7import sys
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
9Bug = Connector.ConnectBug()10Bug = Connector.ConnectBug()
10Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')11Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
1112
12for num in sys.argv[1:]:13
13 bug = Bug(num)14def reassign_bugs_to_bugs_queue(*bugs)
1415 for num in bugs:
15 try:16 bug = Bug(num)
16 bug.subscribers.add("ubuntu-bugs")17
17 except:18 try:
18 pass19 bug.subscribers.add("ubuntu-bugs")
1920 except:
20 comment = Bug.NewComment(text='Thanks for taking the time to report this bug and helping to make Ubuntu better. Your bug report is more likely to get attention if it is made in English, since this is the language understood by the majority of Ubuntu developers. Additionally, please only mark a bug as "security" if it shows evidence of allowing attackers to cross privilege boundaries or to directly cause loss of data/privacy. Please feel free to report any other bugs you may find.', subject='')21 pass
21 bug.comments.add(comment)22
22 bug.private = False23 comment = Bug.NewComment(text='Thanks for taking the time to report this bug and helping to make Ubuntu better. Your bug report is more likely to get attention if it is made in English, since this is the language understood by the majority of Ubuntu developers. Additionally, please only mark a bug as "security" if it shows evidence of allowing attackers to cross privilege boundaries or to directly cause loss of data/privacy. Please feel free to report any other bugs you may find.', subject='')
23 bug.security = False24 bug.comments.add(comment)
24 bug.status = 'Incomplete'25 bug.private = False
2526 bug.security = False
26 try:27 bug.status = 'Incomplete'
27 bug.subscribers.remove("ubuntu-security")28
28 except:29 try:
29 pass30 bug.subscribers.remove("ubuntu-security")
30 bug.commit(force_changes=True, ignore_lp_errors=False)31 except:
32 pass
33 bug.commit(force_changes=True, ignore_lp_errors=False)
34
35
36if __name__ == "__main__":
37 reassign_bugs_to_bugs_queue(*sys.argv[1:])
31\ No newline at end of file38\ No newline at end of file
diff --git a/p-l-p/is-cache.py b/p-l-p/is-cache.py
index 5aafacf..da75103 100755
--- a/p-l-p/is-cache.py
+++ b/p-l-p/is-cache.py
@@ -1,29 +1,36 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys, os6import sys, os
6import launchpadbugs.connector as Connector7import launchpadbugs.connector as Connector
78
8Bug = Connector.ConnectBug()
9Bug.authentication = os.path.expanduser('~/.plb_cookies')
10reply = '''Thanks for your report. We appreciate the difficulties you are facing, but this bug has already been reported. Please review the information and solution in bug 124373. We are marking this bug as a duplicate.'''
119
12for num in sys.argv[1:]:10# TODO: Switch to argparse
13 print '%s ...' % (num)11def respond_to_duplicate_bugs(*bugs)
14 bug = Bug(num)12 Bug = Connector.ConnectBug()
13 Bug.authentication = os.path.expanduser('~/.plb_cookies')
14 reply = '''Thanks for your report. We appreciate the difficulties you are facing, but this bug has already been reported. Please review the information and solution in bug 124373. We are marking this bug as a duplicate.'''
15 for bug in bugs:
16 print('%s ...' % (num))
17 bug = Bug(num)
1518
16 comment = Bug.NewComment(text=reply)19 comment = Bug.NewComment(text=reply)
17 bug.comments.add(comment)20 bug.comments.add(comment)
1821
19 bug.status = 'Invalid'22 bug.status = 'Invalid'
20 bug.private = False23 bug.private = False
21 bug.security = False24 bug.security = False
22 if not 'ubuntu-bugs' in bug.subscribers['directly']:25 if not 'ubuntu-bugs' in bug.subscribers['directly']:
23 bug.subscribers.add("ubuntu-bugs")26 bug.subscribers.add("ubuntu-bugs")
24 if 'ubuntu-security' in bug.subscribers['directly']:27 if 'ubuntu-security' in bug.subscribers['directly']:
25 bug.subscribers.remove("ubuntu-security")28 bug.subscribers.remove("ubuntu-security")
2629
27 bug.duplicate_of = 12437330 bug.duplicate_of = 124373
2831
29 bug.commit(force_changes=True, ignore_lp_errors=False)32 bug.commit(force_changes=True, ignore_lp_errors=False)
33
34
35if __name__ == "__main__":
36 respond_to_duplicate_bugs(*sys.argv[1:])
30\ No newline at end of file37\ No newline at end of file
diff --git a/p-l-p/is-private.py b/p-l-p/is-private.py
index d29045b..0333f51 100755
--- a/p-l-p/is-private.py
+++ b/p-l-p/is-private.py
@@ -1,33 +1,61 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5# Change lp_user to self below... (3 times)5# Change lp_user to self below... (3 times)
6import sys6from __future__ import absolute_import, print_function
7import os7import os
8import sys
8import launchpadbugs.connector as Connector9import launchpadbugs.connector as Connector
9import configobj
1010
11config = configobj.ConfigObj(os.path.expanduser('~/.ubuntu-cve-tracker.conf'))11if sys.version_info[0] == 2:
12Bug = Connector.ConnectBug()12 from ConfigParser import SafeConfigParser as ConfigParser
13Bug.authentication = os.path.join(config['plb_authentication'])13 from cStringIO import StringIO
14lp_user = config['plb_user']14else:
15 from configparser import ConfigParser
16 from io import StringIO
1517
16for num in sys.argv[1:]:18UCT_PATH = os.path.expanduser('~/.ubuntu-cve-tracker.conf')
17 print '%s ... ' % (num)
18 bug = Bug(num)
1919
20 if not lp_user in bug.subscriptions:
21 bug.subscribers.add(lp_user)
22 bug.commit(force_changes=True, ignore_lp_errors=False)
2320
24 if bug.security:21def get_config():
25 bug.security = False22 # replace configobj functionality to avoid the extra dependency
23 config_content = StringIO()
24 config_content.write("[dummy_section]\n")
25 with open(UCT_PATH, "r") as fh:
26 config_content.write(fh.read())
27 config_content.seek(0)
28 parser = ConfigParser()
29 read_file_func = getattr(parser, "read_file", getattr(parser, "readfp", None))
30 if read_file_func is not None:
31 read_file_func(config_content)
32 return {k: v for k, v in parser.items("dummy_section")}
33
34
35def make_bugs_private(*bugs):
36 for num in bugs:
37 config = get_config()
38 Bug = Connector.ConnectBug()
39 Bug.authentication = os.path.join(config['plb_authentication'])
40 lp_user = config['plb_user']
41 print('%s ... ' % (num))
42 bug = Bug(num)
43
44 if not lp_user in bug.subscriptions:
45 bug.subscribers.add(lp_user)
46 bug.commit(force_changes=True, ignore_lp_errors=False)
47
48 if bug.security:
49 bug.security = False
50 bug.commit(force_changes=True, ignore_lp_errors=False)
51
52 bug = Bug(num)
53 if 'ubuntu-security' in bug.subscriptions:
54 bug.subscribers.remove("ubuntu-security")
55
56 bug.subscribers.remove(lp_user)
26 bug.commit(force_changes=True, ignore_lp_errors=False)57 bug.commit(force_changes=True, ignore_lp_errors=False)
2758
28 bug = Bug(num)
29 if 'ubuntu-security' in bug.subscriptions:
30 bug.subscribers.remove("ubuntu-security")
3159
32 bug.subscribers.remove(lp_user)60if __name__ == "__main__":
33 bug.commit(force_changes=True, ignore_lp_errors=False)61 make_bugs_private(*sys.argv[1:])
34\ No newline at end of file62\ No newline at end of file
diff --git a/p-l-p/is-support.py b/p-l-p/is-support.py
index 0dd199f..e2b9eee 100755
--- a/p-l-p/is-support.py
+++ b/p-l-p/is-support.py
@@ -1,25 +1,31 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5import sys5from __future__ import absolute_import, print_function
6import os6import os
7import sys
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
9Bug = Connector.ConnectBug()10def close_non_bug_reports(*bugs):
10Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')11 Bug = Connector.ConnectBug()
12 Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
13
14 for num in bugs:
15 bug = Bug(num)
16
17 if 'ubuntu-bugs' not in bug.subscriptions:
18 bug.subscribers.add("ubuntu-bugs")
1119
12for num in sys.argv[1:]:20 comment = Bug.NewComment(text='Thanks for your comments. This does not appear to be a bug report and we are closing it. We appreciate the difficulties you are facing, but it would make more sense to raise your question in the support tracker. Please visit https://answers.launchpad.net/ubuntu/+addquestion', subject='')
13 bug = Bug(num)21 bug.comments.add(comment)
22 bug.status = 'Invalid'
23 bug.private = False
24 bug.security = False
1425
15 if 'ubuntu-bugs' not in bug.subscriptions:26 bug.subscribers.remove("ubuntu-security")
16 bug.subscribers.add("ubuntu-bugs")27 bug.commit(force_changes=True, ignore_lp_errors=False)
1728
18 comment = Bug.NewComment(text='Thanks for your comments. This does not appear to be a bug report and we are closing it. We appreciate the difficulties you are facing, but it would make more sense to raise your question in the support tracker. Please visit https://answers.launchpad.net/ubuntu/+addquestion', subject='')
19 bug.comments.add(comment)
20 bug.status = 'Invalid'
21 bug.private = False
22 bug.security = False
2329
24 bug.subscribers.remove("ubuntu-security")30if __name__ == "__main__":
25 bug.commit(force_changes=True, ignore_lp_errors=False)31 close_non_bug_reports(*sys.argv[1:])
26\ No newline at end of file32\ No newline at end of file
diff --git a/p-l-p/not-a-bug.py b/p-l-p/not-a-bug.py
index ad185ff..a7a30f9 100755
--- a/p-l-p/not-a-bug.py
+++ b/p-l-p/not-a-bug.py
@@ -1,41 +1,69 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5import sys5from __future__ import absolute_import, print_function
6import os6import os
7import sys
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
8import configobj
99
10config = configobj.ConfigObj(os.path.expanduser('~/.ubuntu-cve-tracker.conf'))10if sys.version_info[0] == 2:
11Bug = Connector.ConnectBug()11 from ConfigParser import SafeConfigParser as ConfigParser
12Bug.authentication = os.path.join(config['plb_authentication'])12 from cStringIO import StringIO
13else:
14 from configparser import ConfigParser
15 from io import StringIO
16
17UCT_PATH = os.path.expanduser('~/.ubuntu-cve-tracker.conf')
18
19
20def get_config():
21 # Replace configobj functionality to avoid the extra dependency
22 config_content = StringIO()
23 config_content.write("[dummy_section]\n")
24 with open(UCT_PATH, "r") as fh:
25 config_content.write(fh.read())
26 config_content.seek(0)
27 parser = ConfigParser()
28 read_file_func = getattr(parser, "read_file", getattr(parser, "readfp", None))
29 if read_file_func is not None:
30 read_file_func(config_content)
31 return {k: v for k, v in parser.items("dummy_section")}
32
33
34def flag_non_bugs(*bugs):
35 Bug = Connector.ConnectBug()
36 Bug.authentication = os.path.join(get_config()['plb_authentication'])
37
38 for num in bugs:
39 bug = Bug(num)
40
41 try:
42 bug.subscribers.add("ubuntu-bugs")
43 changed = True
44 except:
45 pass
1346
14for num in sys.argv[1:]:47 comment = Bug.NewComment(text='''Thank you for using Ubuntu and taking the time to report a bug. Your report should contain, at a minimum, the following information so we can better find the source of the bug and work to resolve it.
15 bug = Bug(num)
1648
17 try:49 Submitting the bug about the proper source package is essential. For help see https://wiki.ubuntu.com/Bugs/FindRightPackage . Additionally, in the report please include:
18 bug.subscribers.add("ubuntu-bugs")
19 changed = True
20 except:
21 pass
2250
23 comment = Bug.NewComment(text='''Thank you for using Ubuntu and taking the time to report a bug. Your report should contain, at a minimum, the following information so we can better find the source of the bug and work to resolve it.51 1) The release of Ubuntu you are using, via 'cat /etc/lsb-release' or System -> About Ubuntu.
52 2) The version of the package you are using, via 'dpkg -l PKGNAME | cat' or by checking in Synaptic.
53 3) What happened and what you expected to happen.
2454
25Submitting the bug about the proper source package is essential. For help see https://wiki.ubuntu.com/Bugs/FindRightPackage . Additionally, in the report please include:55 The Ubuntu community has also created debugging procedures for a wide variety of packages at https://wiki.ubuntu.com/DebuggingProcedures . Following the debugging instructions for the affected package will make your bug report much more complete. Thanks!''', subject='')
56 bug.comments.add(comment)
57 bug.status = 'Invalid'
58 bug.private = False
59 bug.security = False
2660
271) The release of Ubuntu you are using, via 'cat /etc/lsb-release' or System -> About Ubuntu.61 try:
282) The version of the package you are using, via 'dpkg -l PKGNAME | cat' or by checking in Synaptic.62 bug.subscribers.remove("ubuntu-security")
293) What happened and what you expected to happen.63 except:
64 pass
65 bug.commit(force_changes=True, ignore_lp_errors=False)
3066
31The Ubuntu community has also created debugging procedures for a wide variety of packages at https://wiki.ubuntu.com/DebuggingProcedures . Following the debugging instructions for the affected package will make your bug report much more complete. Thanks!''', subject='')
32 bug.comments.add(comment)
33 bug.status = 'Invalid'
34 bug.private = False
35 bug.security = False
3667
37 try:68if __name__ == "__main__":
38 bug.subscribers.remove("ubuntu-security")69 flag_non_bugs(*sys.argv[1:])
39 except:
40 pass
41 bug.commit(force_changes=True, ignore_lp_errors=False)
42\ No newline at end of file70\ No newline at end of file
diff --git a/p-l-p/not-private.py b/p-l-p/not-private.py
index 289052f..4abc231 100755
--- a/p-l-p/not-private.py
+++ b/p-l-p/not-private.py
@@ -1,13 +1,14 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys6import sys
6import os7import os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
9print "This script is obsoleted by launchpadlib/not-private. Please use it instead."10print("This script is obsoleted by launchpadlib/not-private. Please use it instead.")
10print "Continuing..."11print("Continuing...")
1112
12Bug = Connector.ConnectBug()13Bug = Connector.ConnectBug()
13Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')14Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
diff --git a/p-l-p/not-security-in-dups.py b/p-l-p/not-security-in-dups.py
index 4046c74..e9a1ced 100755
--- a/p-l-p/not-security-in-dups.py
+++ b/p-l-p/not-security-in-dups.py
@@ -1,7 +1,8 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys6import sys
6import os7import os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
@@ -10,7 +11,7 @@ Bug = Connector.ConnectBug()
10Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')11Bug.authentication = os.path.join(os.environ['HOME'], '.cookies.sqlite')
1112
12def not_security(num):13def not_security(num):
13 print '%s ...' % (num),14 print('%s ...' % (num), end=' ')
14 bug = Bug(num)15 bug = Bug(num)
1516
16 changed = False17 changed = False
@@ -28,13 +29,15 @@ def not_security(num):
28 changed = True29 changed = True
29 if changed:30 if changed:
30 bug.commit(force_changes=True, ignore_lp_errors=False)31 bug.commit(force_changes=True, ignore_lp_errors=False)
31 print 'updated'32 print('updated')
32 else:33 else:
33 print 'skipped'34 print('skipped')
34 return bug35 return bug
3536
36for num in sys.argv[1:]:
37 bug = not_security(num)
3837
39 for num in bug.duplicates:38if __name__ == "__main__":
40 not_security(num)39 for num in sys.argv[1:]:
40 bug = not_security(num)
41
42 for num in bug.duplicates:
43 not_security(num)
diff --git a/p-l-p/not-security-without-comment.py b/p-l-p/not-security-without-comment.py
index e890308..3dad01b 100755
--- a/p-l-p/not-security-without-comment.py
+++ b/p-l-p/not-security-without-comment.py
@@ -1,29 +1,57 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv33# License: GPLv3
4import sys4from __future__ import absolute_import, print_function
5import os5import os
6import sys
6import launchpadbugs.connector as Connector7import launchpadbugs.connector as Connector
7import configobj
88
9config = configobj.ConfigObj(os.path.expanduser('~/.ubuntu-cve-tracker.conf'))9if sys.version_info[0] == 2:
10Bug = Connector.ConnectBug()10 from ConfigParser import SafeConfigParser as ConfigParser
11Bug.authentication = os.path.join(config['plb_authentication'])11 from cStringIO import StringIO
12else:
13 from configparser import ConfigParser
14 from io import StringIO
15
16UCT_PATH = os.path.expanduser('~/.ubuntu-cve-tracker.conf')
17
18
19def get_config():
20 config_content = StringIO()
21 config_content.write("[dummy_section]\n")
22 with open(UCT_PATH, "r") as fh:
23 config_content.write(fh.read())
24 config_content.seek(0)
25 parser = ConfigParser()
26 read_file_func = getattr(parser, "read_file", getattr(parser, "readfp", None))
27 if read_file_func is not None:
28 read_file_func(config_content)
29 return {k: v for k, v in parser.items("dummy_section")}
30
31
32def remove_security_without_comment(*bugs):
33 Bug = Connector.ConnectBug()
34 config = get_config()
35 Bug.authentication = os.path.join(config['plb_authentication'])
36
37 for num in bugs:
38 print('%s ...' % (num))
39 bug = Bug(num)
40
41 bug.private = False
42 bug.security = False
1243
13for num in sys.argv[1:]:44 try:
14 print '%s ...' % (num)45 bug.subscribers.add("ubuntu-bugs")
15 bug = Bug(num)46 except:
47 print("ubuntu-bugs already subscribed", file=sys.stderr)
1648
17 bug.private = False49 try:
18 bug.security = False50 bug.subscribers.remove("ubuntu-security")
51 except:
52 pass
53 bug.commit(force_changes=True, ignore_lp_errors=False)
1954
20 try:
21 bug.subscribers.add("ubuntu-bugs")
22 except:
23 print >>sys.stderr, "ubuntu-bugs already subscribed"
2455
25 try:56if __name__ == "__main__":
26 bug.subscribers.remove("ubuntu-security")57 remove_security_without_comment(*sys.argv[1:])
27 except:
28 pass
29 bug.commit(force_changes=True, ignore_lp_errors=False)
30\ No newline at end of file58\ No newline at end of file
diff --git a/p-l-p/not-security.py b/p-l-p/not-security.py
index 4108e82..c909518 100755
--- a/p-l-p/not-security.py
+++ b/p-l-p/not-security.py
@@ -1,31 +1,60 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv33# License: GPLv3
4from __future__ import absolute_import, print_function
4import sys5import sys
5import os6import os
6import launchpadbugs.connector as Connector7import launchpadbugs.connector as Connector
7import configobj
88
9config = configobj.ConfigObj(os.path.expanduser('~/.ubuntu-cve-tracker.conf'))9if sys.version_info[0] == 2:
10Bug = Connector.ConnectBug()10 from ConfigParser import SafeConfigParser as ConfigParser
11Bug.authentication = os.path.join(config['plb_authentication'])11 from cStringIO import StringIO
12else:
13 from configparser import ConfigParser
14 from io import StringIO
1215
13for num in sys.argv[1:]:16UCT_PATH = os.path.expanduser('~/.ubuntu-cve-tracker.conf')
14 bug = Bug(num)
1517
16 comment = Bug.NewComment(text='Thanks for taking the time to report this bug and helping to make Ubuntu better. We appreciate the difficulties you are facing, but this appears to be a "regular" (non-security) bug. I have unmarked it as a security issue since this bug does not show evidence of allowing attackers to cross privilege boundaries nor directly cause loss of data/privacy. Please feel free to report any other bugs you may find.', subject='')
17 bug.comments.add(comment)
18 bug.private = False
19 bug.security = False
2018
21 try:19def get_config():
22 bug.subscribers.add("ubuntu-bugs")20 # replace configobj functionality to avoid extra dependency
23 except:21 config_content = StringIO()
24 pass22 config_content.write("[dummy_section]\n")
23 with open(UCT_PATH, "r") as fh:
24 config_content.write(fh.read())
25 config_content.seek(0)
26 parser = ConfigParser()
27 read_file_func = getattr(parser, "read_file", getattr(parser, "readfp", None))
28 if read_file_func is not None:
29 read_file_func(config_content)
30 return {k: v for k, v in parser.items("dummy_section")}
2531
26 try:
27 bug.subscribtions.remove("ubuntu-security")
28 except:
29 pass
3032
31 bug.commit(force_changes=True, ignore_lp_errors=False)33def remove_security(*bugs):
34 Bug = Connector.ConnectBug()
35 config = get_config()
36 Bug.authentication = os.path.join(config['plb_authentication'])
37
38 for num in bugs:
39 bug = Bug(num)
40
41 comment = Bug.NewComment(text='Thanks for taking the time to report this bug and helping to make Ubuntu better. We appreciate the difficulties you are facing, but this appears to be a "regular" (non-security) bug. I have unmarked it as a security issue since this bug does not show evidence of allowing attackers to cross privilege boundaries nor directly cause loss of data/privacy. Please feel free to report any other bugs you may find.', subject='')
42 bug.comments.add(comment)
43 bug.private = False
44 bug.security = False
45
46 try:
47 bug.subscribers.add("ubuntu-bugs")
48 except:
49 pass
50
51 try:
52 bug.subscribtions.remove("ubuntu-security")
53 except:
54 pass
55
56 bug.commit(force_changes=True, ignore_lp_errors=False)
57
58
59if __name__ == "__main__":
60 remove_security(*sys.argv[1:])
32\ No newline at end of file61\ No newline at end of file
diff --git a/p-l-p/reassign.py b/p-l-p/reassign.py
index d2d18f3..6690cec 100755
--- a/p-l-p/reassign.py
+++ b/p-l-p/reassign.py
@@ -1,7 +1,8 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys6import sys
6import os, os7import os, os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
@@ -22,26 +23,27 @@ if assignee == 'None':
22 assignee = None23 assignee = None
2324
24for num in sys.argv[5:]:25for num in sys.argv[5:]:
25 bug = Bug(num)26 bug = Bug(num)
2627
27 for info in bug.get_infotable():28 for info in bug.get_infotable():
28 if info.target and info.target.lower() != 'ubuntu':29 if info.target and info.target.lower() != 'ubuntu':
29 print 'skipping target "%s"' % (info.target)30 print('skipping target "%s"' % (info.target))
30 continue31 continue
31 if info.targeted_to == 'Intrepid' or info.targeted_to == None or info.status == 'Fix Released' or info.status == 'Incomplete' or info.status == 'Invalid':32 if info.targeted_to == 'Intrepid' or info.targeted_to == None or info.status == 'Fix Released' or info.status == 'Incomplete' or info.status == 'Invalid':
32 print 'skipping (targeted_to:%s status:%s)' % (info.targeted_to,info.status)33 print('skipping (targeted_to:%s status:%s)' % (info.targeted_to,info.status))
33 continue34 continue
34 if info.affects == pkg:35 if info.affects == pkg:
35 if status != "-" and info.status != status:36 if status != "-" and info.status != status:
36 print '%s: status => %s' % (info.targeted_to,status)37 print('%s: status => %s' % (info.targeted_to,status))
37 info.status = status38 info.status = status
38 if importance != "-" and info.importance != importance:39 if importance != "-" and info.importance != importance:
39 print '%s: status => %s' % (info.targeted_to,importance)40 print('%s: status => %s' % (info.targeted_to,importance))
40 info.importance = importance41 info.importance = importance
41 if assignee != "-" and info.assignee != assignee:42 if assignee != "-" and info.assignee != assignee:
42 print '%s: assignee => %s' % (info.targeted_to,assignee)43 print('%s: assignee => %s' % (info.targeted_to,assignee))
43 info.assignee = assignee44 info.assignee = assignee
44 else:45 else:
45 print 'skipping affects "%s"' % (info.affects)46 print('skipping affects "%s"' % (info.affects))
47
48 bug.commit(force_changes=True, ignore_lp_errors=False)
4649
47 bug.commit(force_changes=True, ignore_lp_errors=False)
diff --git a/p-l-p/requires-trojaned-account.py b/p-l-p/requires-trojaned-account.py
index 3619b04..0970eee 100755
--- a/p-l-p/requires-trojaned-account.py
+++ b/p-l-p/requires-trojaned-account.py
@@ -1,7 +1,8 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys, os6import sys, os
6import launchpadbugs.connector as Connector7import launchpadbugs.connector as Connector
78
diff --git a/p-l-p/set-package.py b/p-l-p/set-package.py
index def815c..1a62e14 100755
--- a/p-l-p/set-package.py
+++ b/p-l-p/set-package.py
@@ -1,4 +1,5 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2from __future__ import absolute_import, print_function
2import sys, os3import sys, os
3import launchpadbugs.connector as Connector4import launchpadbugs.connector as Connector
45
@@ -6,7 +7,7 @@ Bug = Connector.ConnectBug()
6Bug.authentication = os.path.expanduser('~/.plb_cookies')7Bug.authentication = os.path.expanduser('~/.plb_cookies')
78
8if len(sys.argv) < 2:9if len(sys.argv) < 2:
9 print 'Usage: set-package.py PKG bug [bug ...]'10 print('Usage: set-package.py PKG bug [bug ...]')
10 sys.exit(1)11 sys.exit(1)
1112
12pkg = sys.argv[1]13pkg = sys.argv[1]
diff --git a/p-l-p/sub-security.py b/p-l-p/sub-security.py
index decca39..5259438 100755
--- a/p-l-p/sub-security.py
+++ b/p-l-p/sub-security.py
@@ -1,26 +1,33 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5# Change 'keescook' to self below... (3 times)5# Change 'keescook' to self below... (3 times)
6from __future__ import absolute_import, print_function
6import sys, os7import sys, os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
9Bug = Connector.ConnectBug()10Bug = Connector.ConnectBug()
10Bug.authentication = os.path.expanduser('~/.plb_cookies')11Bug.authentication = os.path.expanduser('~/.plb_cookies')
1112
12for num in sys.argv[1:]:
13 print '%s ... ' % (num)
14 try:
15 bug = Bug(num)
16 except:
17 print 'private'
18 continue
1913
20 if not bug.security:14def subscribe_ubuntu_security(*bugs)
21 continue15 for num in bugs:
16 print('%s ... ' % (num))
17 try:
18 bug = Bug(num)
19 except:
20 print('private')
21 continue
2222
23 if not 'ubuntu-security' in bug.subscriptions['directly']:23 if not bug.security:
24 bug.subscribers.add("ubuntu-security")24 continue
2525
26 bug.commit(force_changes=True, ignore_lp_errors=False)26 if not 'ubuntu-security' in bug.subscriptions['directly']:
27 bug.subscribers.add("ubuntu-security")
28
29 bug.commit(force_changes=True, ignore_lp_errors=False)
30
31
32if __name__ == "__main__":
33 subscribe_ubuntu_security(*sys.argv[1:])
27\ No newline at end of file34\ No newline at end of file
diff --git a/p-l-p/tag.py b/p-l-p/tag.py
index 466e46b..2a59136 100755
--- a/p-l-p/tag.py
+++ b/p-l-p/tag.py
@@ -2,6 +2,7 @@
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5from __future__ import absolute_import, print_function
5import sys, os6import sys, os
6import launchpadbugs.connector as Connector7import launchpadbugs.connector as Connector
78
@@ -9,14 +10,14 @@ Bug = Connector.ConnectBug()
9Bug.authentication = os.path.expanduser('~/.plb_cookies')10Bug.authentication = os.path.expanduser('~/.plb_cookies')
1011
11if len(sys.argv) < 3:12if len(sys.argv) < 3:
12 print 'Usage: tag.py [+|-]TAG bug [bug ...]'13 print('Usage: tag.py [+|-]TAG bug [bug ...]')
13 sys.exit(1)14 sys.exit(1)
1415
15tag = sys.argv[1]16tag = sys.argv[1]
16state = tag[0]17state = tag[0]
17tag = tag[1:]18tag = tag[1:]
18if state not in ['-','+']:19if state not in ['-','+']:
19 print 'Tag must start with - or +'20 print('Tag must start with - or +')
20 sys.exit(1)21 sys.exit(1)
2122
22for num in sys.argv[2:]:23for num in sys.argv[2:]:
diff --git a/p-l-p/unsub-in-dups.py b/p-l-p/unsub-in-dups.py
index 24a2d97..cc6eb4c 100755
--- a/p-l-p/unsub-in-dups.py
+++ b/p-l-p/unsub-in-dups.py
@@ -1,8 +1,9 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>2# Copyright (C) 2007 Canonical, Ltd. Kees Cook <kees@ubuntu.com>
3# License: GPLv23# License: GPLv2
4# Change the cookie path below...4# Change the cookie path below...
5# Change 'keescook' below... (twice)5# Change 'keescook' below... (twice)
6from __future__ import absolute_import, print_function
6import sys, os7import sys, os
7import launchpadbugs.connector as Connector8import launchpadbugs.connector as Connector
89
@@ -12,7 +13,7 @@ Bug = Connector.ConnectBug()
12Bug.authentication = os.path.expanduser('~/.plb_cookies')13Bug.authentication = os.path.expanduser('~/.plb_cookies')
1314
14def not_security(num):15def not_security(num):
15 print '%s ...' % (num),16 print('%s ...' % (num), end=' ')
16 bug = Bug(num)17 bug = Bug(num)
1718
18 changed = False19 changed = False
@@ -22,9 +23,9 @@ def not_security(num):
2223
23 if changed:24 if changed:
24 bug.commit(force_changes=True, ignore_lp_errors=False)25 bug.commit(force_changes=True, ignore_lp_errors=False)
25 print 'updated'26 print('updated')
26 else:27 else:
27 print 'skipped'28 print('skipped')
28 return bug29 return bug
2930
30for num in sys.argv[2:]:31for num in sys.argv[2:]:
diff --git a/package-tools/debcompare b/package-tools/debcompare
index 5a3eac7..21e5538 100755
--- a/package-tools/debcompare
+++ b/package-tools/debcompare
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# Name: debcompare3# Name: debcompare
4# Description: Compares different versions of binary packages4# Description: Compares different versions of binary packages
@@ -16,7 +16,7 @@
16#16#
17# License: GPLv317# License: GPLv3
18#18#
19from __future__ import print_function19from __future__ import absolute_import, print_function
2020
21import difflib21import difflib
22import os22import os
@@ -82,10 +82,9 @@ class DebFile:
82 '''Gets the symbols of the file specified'''82 '''Gets the symbols of the file specified'''
8383
84 symbols = []84 symbols = []
85 report = subprocess.check_output(["nm", "-DC", filename])85 report = subprocess.check_output(["nm", "-DC", filename], universal_newlines=True)
8686
87 for line in report.splitlines():87 for line in report.splitlines():
88 line = line.decode()
89 if line[0] == ' ':88 if line[0] == ' ':
90 # no address prefix, just take everything89 # no address prefix, just take everything
91 symbol_entry = line.strip().split(maxsplit=2)[0:]90 symbol_entry = line.strip().split(maxsplit=2)[0:]
@@ -652,29 +651,35 @@ def compare_debs(old_deb, new_deb):
652 new_deb.jarfiles, new_deb.files_dir)651 new_deb.jarfiles, new_deb.files_dir)
653652
654653
655if len(sys.argv) < 3:654if __name__ == "__main__":
656 print_usage()655 # * Code that is unguarded by this check will run if the file is ever
657 sys.exit(1)656 # * used in an import statement, even if we only plan to use or import
657 # * one function from this file. Guarding code behind this check means
658 # * it only runs when the file is invoked directly (i.e. ./myfile.py)
659 # * or via the interpreter, i.e. python myfile.py
660 if len(sys.argv) < 3:
661 print_usage()
662 sys.exit(1)
658663
659oldfile = os.path.abspath(sys.argv[1])664 oldfile = os.path.abspath(sys.argv[1])
660newfile = os.path.abspath(sys.argv[2])665 newfile = os.path.abspath(sys.argv[2])
661666
662if not os.path.isfile(oldfile) or not os.path.isfile(newfile):667 if not os.path.isfile(oldfile) or not os.path.isfile(newfile):
663 print_usage()668 print_usage()
664 sys.exit(1)669 sys.exit(1)
665670
666check_required_tools()671 check_required_tools()
667672
668old_deb = DebFile(oldfile)673 old_deb = DebFile(oldfile)
669new_deb = DebFile(newfile)674 new_deb = DebFile(newfile)
670675
671compare_debs(old_deb, new_deb)676 compare_debs(old_deb, new_deb)
672677
673# Clean up temp dirs678 # Clean up temp dirs
674if old_deb.temp_dir and os.path.exists(old_deb.temp_dir):679 if old_deb.temp_dir and os.path.exists(old_deb.temp_dir):
675 shutil.rmtree(old_deb.temp_dir, ignore_errors=True)680 shutil.rmtree(old_deb.temp_dir, ignore_errors=True)
676if new_deb.temp_dir and os.path.exists(new_deb.temp_dir):681 if new_deb.temp_dir and os.path.exists(new_deb.temp_dir):
677 shutil.rmtree(new_deb.temp_dir, ignore_errors=True)682 shutil.rmtree(new_deb.temp_dir, ignore_errors=True)
678683
679print("\n\n--------------")684 print("\n\n--------------")
680print("End of report.")685 print("End of report.")
diff --git a/repo-tools/count-hardened-pkgs b/repo-tools/count-hardened-pkgs
index 60d860a..f5b75cf 100755
--- a/repo-tools/count-hardened-pkgs
+++ b/repo-tools/count-hardened-pkgs
@@ -1,9 +1,13 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# 2012, Kees Cook <kees@debian.org>2# 2012, Kees Cook <kees@debian.org>
33
4from __future__ import absolute_import, print_function
4import time, tempfile, shutil, sys, os, stat, glob5import time, tempfile, shutil, sys, os, stat, glob
5import cPickle as pickle6import subprocess
6from subprocess import *7if sys.version_info[0] == 2:
8 import cPickle as pickle
9else:
10 import pickle
711
8count_names = ['elf', 'fortify', 'stackprotector', 'relro', 'bindnow', 'pie']12count_names = ['elf', 'fortify', 'stackprotector', 'relro', 'bindnow', 'pie']
9run_time = time.strftime("%Y%m%d")13run_time = time.strftime("%Y%m%d")
@@ -23,26 +27,26 @@ class Archive():
23 else:27 else:
24 components = [component]28 components = [component]
2529
26 print "Loading %s ..." % (release)30 print("Loading %s ..." % (release))
27 for component in components:31 for component in components:
28 print "\t%s ..." % (component)32 print("\t%s ..." % (component))
29 packages = os.path.join(base, 'dists', release, component,33 packages = os.path.join(base, 'dists', release, component,
30 'binary-%s' % (arch), 'Packages')34 'binary-%s' % (arch), 'Packages')
31 packages_xz = packages + ".xz"35 packages_xz = packages + ".xz"
32 packages_bz2 = packages + ".bz2"36 packages_bz2 = packages + ".bz2"
33 packages_gz = packages + ".gz"37 packages_gz = packages + ".gz"
34 if os.path.exists(packages):38 if os.path.exists(packages):
35 cat = Popen(["cat", packages], stdout=PIPE)39 cat = subprocess.Popen(["cat", packages], stdout=subprocess.PIPE)
36 elif os.path.exists(packages_xz):40 elif os.path.exists(packages_xz):
37 cat = Popen(["xzcat", packages_xz], stdout=PIPE)41 cat = subprocess.Popen(["xzcat", packages_xz], stdout=subprocess.PIPE)
38 elif os.path.exists(packages_bz2):42 elif os.path.exists(packages_bz2):
39 cat = Popen(["bzcat", packages_bz2], stdout=PIPE)43 cat = subprocess.Popen(["bzcat", packages_bz2], stdout=subprocess.PIPE)
40 elif os.path.exists(packages_gz):44 elif os.path.exists(packages_gz):
41 cat = Popen(["zcat", packages_gz], stdout=PIPE)45 cat = subprocess.Popen(["zcat", packages_gz], stdout=subprocess.PIPE)
42 else:46 else:
43 raise ValueError, "Missing %s*" % (packages)47 raise ValueError("Missing %s*" % (packages))
44 p = Popen(["grep-dctrl", "-s", "Package,Source,Filename", "."],48 p = subprocess.Popen(["grep-dctrl", "-s", "Package,Source,Filename", "."],
45 stdin=cat.stdout, stdout=PIPE)49 stdin=cat.stdout, stdout=subprocess.PIPE)
4650
47 pkg = ""51 pkg = ""
48 src = ""52 src = ""
@@ -62,7 +66,7 @@ class Archive():
62 self.srcs[src].setdefault(pkg, line.split(' ')[1])66 self.srcs[src].setdefault(pkg, line.split(' ')[1])
63 cat.wait()67 cat.wait()
64 if cat.returncode != 0:68 if cat.returncode != 0:
65 raise ValueError, "cat %s: %d" % (packges, cat.returncode)69 raise ValueError("cat %s: %d" % (packges, cat.returncode))
6670
67 def sources(self):71 def sources(self):
68 return sorted(self.srcs)72 return sorted(self.srcs)
@@ -77,7 +81,7 @@ class HardeningReporter():
77 def __init__(self, cachedir):81 def __init__(self, cachedir):
78 # Load version cache.82 # Load version cache.
79 self.pickle = os.path.join(cachedir, 'cache.pickle')83 self.pickle = os.path.join(cachedir, 'cache.pickle')
80 print "Loading package cache ..."84 print("Loading package cache ...")
81 try:85 try:
82 self.seen = pickle.load(open(self.pickle, "rb"))86 self.seen = pickle.load(open(self.pickle, "rb"))
83 except:87 except:
@@ -132,9 +136,15 @@ class HardeningReporter():
132 tmpdir = tempfile.mkdtemp(prefix='unpack-%s-%s-' % (src, pkg))136 tmpdir = tempfile.mkdtemp(prefix='unpack-%s-%s-' % (src, pkg))
133137
134 # Unpack.138 # Unpack.
135 print "\t\tUnpacking into %s ..." % (tmpdir)139 print("\t\tUnpacking into %s ..." % (tmpdir))
136 if call(['dpkg-deb', '-x', deb, tmpdir]) != 0:140 try:
137 print >> sys.stderr, "Could not unpack '%s'!?" % (deb)141 # XXX: subprocess.call is less preferable compared with check_call
142 # XXX: when we are only interested in handling failure cases and
143 # XXX: not specific outputs and return codes -- by default we can
144 # XXX: do nothing, this does relevant checks for us
145 subprocess.check_call(['dpkg-deb', '-x', deb, tmpdir])
146 except subprocess.CalledProcessError:
147 print("Could not unpack '%s'!?" % (deb), file=sys.stderr)
138 # Force this package to be ignored.148 # Force this package to be ignored.
139 seen[src][pkg]['counts']['elf'] = 0149 seen[src][pkg]['counts']['elf'] = 0
140 return seen[src][pkg]['counts']150 return seen[src][pkg]['counts']
@@ -164,7 +174,7 @@ class HardeningReporter():
164 if len(elfs) > 0:174 if len(elfs) > 0:
165 #print elfs175 #print elfs
166 badpie = 0176 badpie = 0
167 p = Popen(['hardening-check'] + elfs, stdout=PIPE)177 p = subprocess.Popen(['hardening-check'] + elfs, stdout=subprocess.PIPE)
168 for line in p.stdout:178 for line in p.stdout:
169 if 'Position Independent Executable: ' in line:179 if 'Position Independent Executable: ' in line:
170 if ': yes' in line:180 if ': yes' in line:
@@ -194,7 +204,7 @@ class HardeningReporter():
194 shutil.rmtree(tmpdir, ignore_errors=False)204 shutil.rmtree(tmpdir, ignore_errors=False)
195 except:205 except:
196 # Fix insane unpacks.206 # Fix insane unpacks.
197 call(['chmod', '-R', 'u+rwx', tmpdir])207 subprocess.check_call(['chmod', '-R', 'u+rwx', tmpdir])
198 shutil.rmtree(tmpdir, ignore_errors=True)208 shutil.rmtree(tmpdir, ignore_errors=True)
199209
200 # Finished scanning this src/pkg combo, store it.210 # Finished scanning this src/pkg combo, store it.
@@ -207,7 +217,7 @@ class HardeningReporter():
207class CacheArchive():217class CacheArchive():
208 def __init__(self, srcs, reporter):218 def __init__(self, srcs, reporter):
209 self.cache, self.mapping = reporter.cache()219 self.cache, self.mapping = reporter.cache()
210 print "Mapping source packages ..."220 print("Mapping source packages ...")
211 self.bins = [x.strip() for x in open(srcs, "r").readlines()]221 self.bins = [x.strip() for x in open(srcs, "r").readlines()]
212 self.srcs = dict()222 self.srcs = dict()
213 for pkg in self.bins:223 for pkg in self.bins:
@@ -225,22 +235,6 @@ class CacheArchive():
225 return self.cache[src][pkg]['filename']235 return self.cache[src][pkg]['filename']
226236
227237
228release = None
229arch = None
230component = None
231try:
232 output = sys.argv[1]
233 mirror = sys.argv[2]
234 if len(sys.argv) > 3:
235 release = sys.argv[3]
236 arch = sys.argv[4]
237 if len(sys.argv) > 5:
238 component = sys.argv[5]
239except:
240 print 'Usage: %s OUTDIR [BINPKGLIST|MIRROR RELEASE ARCH [COMPONENT]]' % (sys.argv[0])
241 print 'Example: %s /tmp/info /var/cache/mirrors/debian unstable amd64 main' % (sys.argv[0])
242 sys.exit(1)
243
244def scan_archive(reporter, archive):238def scan_archive(reporter, archive):
245 # The master package feature counts239 # The master package feature counts
246 counts = dict()240 counts = dict()
@@ -252,15 +246,15 @@ def scan_archive(reporter, archive):
252 src_counts.setdefault('elf', 0)246 src_counts.setdefault('elf', 0)
253 badpie = 0247 badpie = 0
254248
255 print "Source: %s ..." % (src)249 print("Source: %s ..." % (src))
256 for pkg in archive.binary_packages(src):250 for pkg in archive.binary_packages(src):
257 deb = archive.package_path(src, pkg)251 deb = archive.package_path(src, pkg)
258 print "\t%s (%s) ..." % (pkg, deb)252 print("\t%s (%s) ..." % (pkg, deb))
259 bin_counts = reporter.examine(src, pkg, deb)253 bin_counts = reporter.examine(src, pkg, deb)
260 if bin_counts['elf'] == 0:254 if bin_counts['elf'] == 0:
261 # Ignore this deb.255 # Ignore this deb.
262 continue256 continue
263 print "\t\t%s" % (repr(bin_counts))257 print("\t\t%s" % (repr(bin_counts)))
264258
265 # If we have a binary package with ELF and no PIE,259 # If we have a binary package with ELF and no PIE,
266 # this means a non-PIE executable was found.260 # this means a non-PIE executable was found.
@@ -278,7 +272,7 @@ def scan_archive(reporter, archive):
278 src_counts.setdefault('pie', 0)272 src_counts.setdefault('pie', 0)
279 src_counts['pie'] = 0273 src_counts['pie'] = 0
280274
281 print "\t%s" % (repr(src_counts))275 print("\t%s" % (repr(src_counts)))
282276
283 # If at least 1 binary's ELF has the option, count it as in source,277 # If at least 1 binary's ELF has the option, count it as in source,
284 # except for PIE, which is handled above as lacking non-PIE.278 # except for PIE, which is handled above as lacking non-PIE.
@@ -286,23 +280,47 @@ def scan_archive(reporter, archive):
286 for name in count_names:280 for name in count_names:
287 if src_counts[name] > 0:281 if src_counts[name] > 0:
288 counts[name] += 1282 counts[name] += 1
289 print "%s\n" % (repr(counts))283 print("%s\n" % (repr(counts)))
290284
291 return counts285 return counts
292286
293287
294reporter = HardeningReporter(output)288if __name__ == "__main__":
295289 # * Code that is unguarded by this check will run if the file is ever
296if release == None:290 # * used in an import statement, even if we only plan to use or import
297 archive = CacheArchive(mirror, reporter)291 # * one function from this file. Guarding code behind this check means
298else:292 # * it only runs when the file is invoked directly (i.e. ./myfile.py)
299 print "Loading archive ..."293 # * or via the interpreter, i.e. python myfile.py
300 archive = Archive(mirror, release, arch, component)294 release = None
301295 arch = None
302counts = scan_archive(reporter, archive)296 component = None
303297 # TODO: switch to argparse
304# Append graph data.298 try:
305for name in counts:299 output = sys.argv[1]
306 report = open(os.path.join(output, '%s.data' % (name)), "a")300 mirror = sys.argv[2]
307 report.write('%s %d\n' % (run_time, counts[name]))301 if len(sys.argv) > 3:
308 report.close()302 release = sys.argv[3]
303 arch = sys.argv[4]
304 if len(sys.argv) > 5:
305 component = sys.argv[5]
306 except:
307 print('Usage: %s OUTDIR [BINPKGLIST|MIRROR RELEASE ARCH [COMPONENT]]' % (sys.argv[0]))
308 print('Example: %s /tmp/info /var/cache/mirrors/debian unstable amd64 main' % (sys.argv[0]))
309 sys.exit(1)
310
311 reporter = HardeningReporter(output)
312
313 if release == None:
314 archive = CacheArchive(mirror, reporter)
315 else:
316 print("Loading archive ...")
317 archive = Archive(mirror, release, arch, component)
318
319 counts = scan_archive(reporter, archive)
320
321 # Append graph data.
322 for name in counts:
323 # * Open files in context managers to make sure file handles are
324 # * closed properly before the process is cleaned up
325 with open(os.path.join(output, '%s.data' % (name)), "a") as report:
326 report.write('%s %d\n' % (run_time, counts[name]))
diff --git a/repo-tools/count-hash-sources b/repo-tools/count-hash-sources
index 48e6c2d..de5fbf4 100755
--- a/repo-tools/count-hash-sources
+++ b/repo-tools/count-hash-sources
@@ -1,12 +1,20 @@
1#!/usr/bin/python1#!/usr/bin/env python3
22
3from __future__ import absolute_import, print_function
3import deb822 # from python-debian4import deb822 # from python-debian
4import gzip
5import argparse5import argparse
6import contextlib
7import gzip
8import io
6import os9import os
7import re10import re
8import sys11import sys
9import urllib212
13if sys.version_info[0] == 2:
14 from urllib2 import urlopen
15else:
16 from urllib.request import urlopen
17
1018
11components = ['main', 'multiverse', 'restricted', 'universe']19components = ['main', 'multiverse', 'restricted', 'universe']
12default_releases = ['precise', 'trusty', 'xenial', 'bionic', 'cosmic', 'disco']20default_releases = ['precise', 'trusty', 'xenial', 'bionic', 'cosmic', 'disco']
@@ -16,22 +24,23 @@ def count_md5only_sources(sources_list):
16 md5only = 024 md5only = 0
17 sha1only = 025 sha1only = 0
18 langpack = 026 langpack = 0
19 for src in deb822.Sources.iter_paragraphs(file(sources_list)):27 with open(sources_list, "r") as sources_handle:
20 count += 128 for src in deb822.Sources.iter_paragraphs(sources_handle):
21 if not src.has_key('Checksums-Sha256'):29 count += 1
22 sha1only += 130 if 'Checksums-Sha256' not in src:
23 if not src.has_key('Checksums-Sha1'):31 sha1only += 1
24 if re.match("language-pack-.*", src['Package']):32 if 'Checksums-Sha1' not in src:
25 langpack += 133 if re.match("language-pack-.*", src['Package']):
26 else:34 langpack += 1
27 md5only += 135 else:
28 #print src['Package']36 md5only += 1
29 if not src.has_key('Files'):37 #print src['Package']
30 print "Bizarre, src package '%s' has no Files section" %(src['Package'])38 if 'Files' not in src:
39 print("Bizarre, src package '%s' has no Files section" %(src['Package']))
31 return (count, md5only, sha1only, langpack)40 return (count, md5only, sha1only, langpack)
3241
33def download_release_files(release):42def download_release_files(release):
34 print "Downloading release files for %s" % release43 print("Downloading release files for %s" % release)
3544
36 for component in components:45 for component in components:
3746
@@ -42,39 +51,43 @@ def download_release_files(release):
42 continue51 continue
4352
44 url= "http://archive.ubuntu.com/ubuntu/dists/%s/%s/source/Sources.gz" % (release, component)53 url= "http://archive.ubuntu.com/ubuntu/dists/%s/%s/source/Sources.gz" % (release, component)
45 print "Downloading %s..." % url54 print("Downloading %s..." % url)
4655
47 # Download it56 # * Download compressed contents and write it to a buffer
48 open_url = urllib2.urlopen(url)57 compressed_contents = io.BytesIO()
49 output = open('Sources.gz','wb')58 with contextlib.closing(urlopen(url)) as response:
50 output.write(open_url.read())59 compressed_contents.write(response.read())
51 output.close()60 compressed_contents.seek(0)
5261
53 # Now uncompress it62 # * Now lets unzip the buffer, decode it, clean up line endings and
54 f_in = gzip.open('Sources.gz', 'rb')63 # * write to a target file
55 f_out = open(file_name, 'wb')64 with gzip.GzipFile(fileobj=compressed_contents, mode="rb") as f_in:
56 f_out.writelines(f_in)65 with open(file_name, "w") as f_out:
57 f_out.close()66 f_out.write(f_in.read().decode("utf-8").replace(r"\r\n", r"\n"))
58 f_in.close()67
5968 print("Download completed.")
60 os.unlink('Sources.gz')69
6170
62 print "Download completed."71if __name__ == "__main__":
6372 # * Code that is unguarded by this check will run if the file is ever
64parser = argparse.ArgumentParser(description='Finds source packages with md5 only hash sums')73 # * used in an import statement, even if we only plan to use or import
65parser.add_argument('-r', '--release', action='append', help="find sources in a specific release")74 # * one function from this file. Guarding code behind this check means
66args = parser.parse_args()75 # * it only runs when the file is invoked directly (i.e. ./myfile.py)
6776 # * or via the interpreter, i.e. python myfile.py
68if args.release:77 parser = argparse.ArgumentParser(description='Finds source packages with md5 only hash sums')
69 releases = args.release78 parser.add_argument('-r', '--release', action='append', help="find sources in a specific release")
70else:79 args = parser.parse_args()
71 releases = default_releases80
7281 if args.release:
73for release in releases:82 releases = args.release
74 download_release_files(release)83 else:
7584 releases = default_releases
76for release in releases:85
77 for component in components:86 for release in releases:
78 (total, md5only, sha1only, langpack) = count_md5only_sources("%s-sources-%s" %(release, component))87 download_release_files(release)
79 print "%s %s: \ttotal: %d \tmd5only: %d\tsha1only: %d\tlangpacks: %d" %(release, component, total, md5only, sha1only, langpack)88
80 print89 for release in releases:
90 for component in components:
91 total, md5only, sha1only, langpack = count_md5only_sources("%s-sources-%s" %(release, component))
92 print("%s %s: \ttotal: %d \tmd5only: %d\tsha1only: %d\tlangpacks: %d" %(release, component, total, md5only, sha1only, langpack))
93 print()
diff --git a/repo-tools/for-archive-tools/has-execstack b/repo-tools/for-archive-tools/has-execstack
index 4d53338..8453f2b 100755
--- a/repo-tools/for-archive-tools/has-execstack
+++ b/repo-tools/for-archive-tools/has-execstack
@@ -1,27 +1,42 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# Copyright 2009 Canonical, Ltd2# Copyright 2009 Canonical, Ltd
3# Author: Kees Cook <kees@ubuntu.com>3# Author: Kees Cook <kees@ubuntu.com>
4# License: GPLv34# License: GPLv3
5#5#
6# Expects to be run via "unpack-search" within "for-archive"6# Expects to be run via "unpack-search" within "for-archive"
7# Checks only ELF files for execstack, and reports anything non-exec or unknown7# Checks only ELF files for execstack, and reports anything non-exec or unknown
8import sys, subprocess8from __future__ import absolute_import, print_function
9import os
10import subprocess
11import sys
9files = sys.argv[1:]12files = sys.argv[1:]
10if files[0] == '--':13if files[0] == '--':
11 files.pop(0)14 files.pop(0)
12if files[0] == '--':15if files[0] == '--':
13 files.pop(0)16 files.pop(0)
14devnull = open('/dev/null','w')17# * Here we use a context manager again to make sure the handle is closed
15for f in files:18with open('/dev/null','w') as devnull:
16 #print >>sys.stderr, f19 for f in files:
17 try:20 if not os.path.exists(f) and os.path.isfile(f):
18 ok = (open(f).read(4) == '\x7fELF')21 continue
19 except:22 with open(f, "rb") as fh:
20 continue23 try:
21 if ok:24 ok = f.read(4) == b"\x7fELF"
22 out = subprocess.Popen(['execstack','-q',f],stdout=subprocess.PIPE,stderr=devnull).communicate()[0]25 except Exception:
23 for line in out.splitlines():
24 line = line.strip()
25 if line.startswith('- '):
26 continue26 continue
27 print line27 if ok:
28 # * the .communicate() call returns a 2-tuple (stdout, stderr), so
29 # * we are implicitly throwing away stderr by assigning it to _
30 # * which is ignored in python
31 # * Note that we are using 'universal_newlines=True' which actually
32 # * tells the interpreter to give back unicode output rather than
33 # * bytes, so we will be equipped for moving back and forth between
34 # * python 2 and python 3
35 out, _ = subprocess.Popen(
36 ['execstack','-q',f], stdout=subprocess.PIPE, stderr=devnull,
37 universal_newlines=True
38 ).communicate()
39 for line in out.splitlines():
40 line = line.strip()
41 if not line.startswith('- '):
42 print(line)
diff --git a/repo-tools/for-archive-tools/has-symbols b/repo-tools/for-archive-tools/has-symbols
index a48402c..a62af89 100755
--- a/repo-tools/for-archive-tools/has-symbols
+++ b/repo-tools/for-archive-tools/has-symbols
@@ -1,12 +1,15 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# Copyright 2009 Canonical, Ltd2# Copyright 2009 Canonical, Ltd
3# Author: Kees Cook <kees@ubuntu.com>3# Author: Kees Cook <kees@ubuntu.com>
4# License: GPLv34# License: GPLv3
5#5#
6# Expects to be run via "unpack-search" within "for-archive"6# Expects to be run via "unpack-search" within "for-archive"
7# Checks only ELF files for symbols, and reports anything referencing these symbols7# Checks only ELF files for symbols, and reports anything referencing these symbols
8import sys, subprocess8from __future__ import absolute_import, print_function
9import os
9import re10import re
11import subprocess
12import sys
1013
11symrx = re.compile(r'\*UND\*.*(_ZNSt6chrono12system_clock3nowEv|_ZNSt6chrono12steady_clock3nowEv)')14symrx = re.compile(r'\*UND\*.*(_ZNSt6chrono12system_clock3nowEv|_ZNSt6chrono12steady_clock3nowEv)')
12#symrx = re.compile(r'\*UND\*.*(__fprintf_chk|__progname_full)')15#symrx = re.compile(r'\*UND\*.*(__fprintf_chk|__progname_full)')
@@ -16,17 +19,29 @@ if files[0] == '--':
16 files.pop(0)19 files.pop(0)
17if files[0] == '--':20if files[0] == '--':
18 files.pop(0)21 files.pop(0)
19devnull = open('/dev/null','w')22# * Here we use a context manager again to make sure the handle is closed
20for f in files:23with open('/dev/null','w') as devnull:
21 #print >>sys.stderr, f24 for f in files:
22 try:25 if not os.path.exists(f) and os.path.isfile(f):
23 ok = (open(f).read(4) == '\x7fELF')26 continue
24 except:27 with open(f, "rb") as fh:
25 continue28 try:
26 if ok:29 ok = f.read(4) == b"\x7fELF"
27 out = subprocess.Popen(['objdump','-T',f],stdout=subprocess.PIPE,stderr=devnull).communicate()[0]30 except Exception:
28 for line in out.splitlines():
29 line = line.strip()
30 if not symrx.search(line):
31 continue31 continue
32 print line32 if ok:
33 # * the .communicate() call returns a 2-tuple (stdout, stderr), so
34 # * we are implicitly throwing away stderr by assigning it to _
35 # * which is ignored in python
36 # * Note that we are using 'universal_newlines=True' which actually
37 # * tells the interpreter to give back unicode output rather than
38 # * bytes, so we will be equipped for moving back and forth between
39 # * python 2 and python 3
40 out, _ = subprocess.Popen(
41 ['objdump', '-T' ,f], stdout=subprocess.PIPE, stderr=devnull,
42 universal_newlines=True
43 ).communicate()
44 for line in out.splitlines():
45 line = line.strip()
46 if symrx.search(line):
47 print(line)
33\ No newline at end of file48\ No newline at end of file
diff --git a/repo-tools/packages-support-status b/repo-tools/packages-support-status
index 9817a80..c0082f6 100755
--- a/repo-tools/packages-support-status
+++ b/repo-tools/packages-support-status
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>3# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>
4# Copyright (C) 2012 Canonical Ltd.4# Copyright (C) 2012 Canonical Ltd.
@@ -12,17 +12,23 @@
12#12#
13# You can download the Release files for i386 with the --download command.13# You can download the Release files for i386 with the --download command.
14#14#
15from __future__ import print_function15from __future__ import absolute_import, print_function
1616
17import contextlib
18import io
17import gzip19import gzip
18import os20import os
19import re21import re
20import sys22import sys
21import urllib.error
22import urllib.parse
23import urllib.request
24from optparse import OptionParser23from optparse import OptionParser
2524
25if sys.version_info[0] == 2:
26 from urllib2 import urlopen
27else:
28 from urllib.request import urlopen
29
30# TODO: Switch to argparse
31
26components = ['main', 'multiverse', 'restricted', 'universe']32components = ['main', 'multiverse', 'restricted', 'universe']
2733
28def parse_package_files():34def parse_package_files():
@@ -84,56 +90,59 @@ def download_release_files(release):
84 url= "http://archive.ubuntu.com/ubuntu/dists/%s/%s/binary-i386/Packages.gz" % (release, component)90 url= "http://archive.ubuntu.com/ubuntu/dists/%s/%s/binary-i386/Packages.gz" % (release, component)
85 print("Downloading %s..." % url)91 print("Downloading %s..." % url)
8692
87 # Download it93 # * Download compressed contents and write it to a buffer
88 open_url = urllib.request.urlopen(url)94 compressed_contents = io.BytesIO()
89 output = open('Packages.gz', 'wb')95 with contextlib.closing(urlopen(url)) as response:
90 output.write(open_url.read())96 compressed_contents.write(response.read())
91 output.close()97 compressed_contents.seek(0)
9298
93 # Now uncompress it99 # * Now lets unzip the buffer, decode it, clean up line endings and
94 f_in = gzip.open('Packages.gz', 'rb')100 # * write to a target file
95 f_out = open(file_name, 'wb')101 with gzip.GzipFile(fileobj=compressed_contents, mode="rb") as f_in:
96 f_out.writelines(f_in)102 with open(file_name, "w") as f_out:
97 f_out.close()103 f_out.write(f_in.read().decode("utf-8").replace(r"\r\n", r"\n"))
98 f_in.close()
99
100 os.unlink('Packages.gz')
101
102 print("Download completed.")104 print("Download completed.")
103105
104def print_package(package, component, supported):106def print_package(package, component, supported):
105 print("%-50s %-12s %s" % (package, component, supported))107 print("%-50s %-12s %s" % (package, component, supported))
106108
107parser = OptionParser()109
108parser.add_option("", "--show-unsupported",110if __name__ == "__main__":
109 action="append_const", dest="filter",111 # * Code that is unguarded by this check will run if the file is ever
110 const="Unsupported", help="Show unsupported packages")112 # * used in an import statement, even if we only plan to use or import
111parser.add_option("", "--show-18m",113 # * one function from this file. Guarding code behind this check means
112 action="append_const", dest="filter",114 # * it only runs when the file is invoked directly (i.e. ./myfile.py)
113 const="18m", help="Show 18m supported packages")115 # * or via the interpreter, i.e. python myfile.py
114parser.add_option("", "--show-3y",116 parser = OptionParser()
115 action="append_const", dest="filter",117 parser.add_option("", "--show-unsupported",
116 const="3y", help="Show 3y supported packages")118 action="append_const", dest="filter",
117parser.add_option("", "--show-5y",119 const="Unsupported", help="Show unsupported packages")
118 action="append_const", dest="filter",120 parser.add_option("", "--show-18m",
119 const="5y", help="Show 5y supported packages")121 action="append_const", dest="filter",
120parser.add_option("", "--download", metavar="RELEASE",122 const="18m", help="Show 18m supported packages")
121 action="store", dest="download",123 parser.add_option("", "--show-3y",
122 help="Download release files for RELEASE in current directory")124 action="append_const", dest="filter",
123125 const="3y", help="Show 3y supported packages")
124(options, args) = parser.parse_args()126 parser.add_option("", "--show-5y",
125127 action="append_const", dest="filter",
126if options.download:128 const="5y", help="Show 5y supported packages")
127 download_release_files(options.download)129 parser.add_option("", "--download", metavar="RELEASE",
128 sys.exit(0)130 action="store", dest="download",
129131 help="Download release files for RELEASE in current directory")
130packages = parse_package_files()132
131all_packages = sorted(packages.keys())133 (options, args) = parser.parse_args()
132for package in all_packages:134
133135 if options.download:
134 if options.filter:136 download_release_files(options.download)
135 if packages[package]['supported'] not in options.filter:137 sys.exit(0)
136 continue138
137139 packages = parse_package_files()
138 print_package(package, packages[package]['component'], packages[package]['supported'])140 all_packages = sorted(packages.keys())
141 for package in all_packages:
142
143 if options.filter:
144 if packages[package]['supported'] not in options.filter:
145 continue
146
147 print_package(package, packages[package]['component'], packages[package]['supported'])
139148
diff --git a/repo-tools/universe-binaries-with-sources-in-main.py b/repo-tools/universe-binaries-with-sources-in-main.py
index 8c76793..ccd1a03 100755
--- a/repo-tools/universe-binaries-with-sources-in-main.py
+++ b/repo-tools/universe-binaries-with-sources-in-main.py
@@ -1,10 +1,12 @@
1#!/usr/bin/python1#!/usr/bin/env python3
22
3from __future__ import absolute_import, print_function
3packages = "./universe/binary-i386/Packages"4packages = "./universe/binary-i386/Packages"
4sources = "./main/source/Sources"5sources = "./main/source/Sources"
56
6# Get all the binaries in universe7# Get all the binaries in universe
7lines = open(packages).readlines()8with open(packages, "r") as fh:
9 lines = fh.readlines()
8bins = {}10bins = {}
9for line in lines:11for line in lines:
10 line = line.strip()12 line = line.strip()
@@ -12,6 +14,8 @@ for line in lines:
12 bins[line.split()[1]] = True14 bins[line.split()[1]] = True
1315
14# then see if one of these binaries matches the Binary line in sources from main16# then see if one of these binaries matches the Binary line in sources from main
17with open(sources, "r") as fh:
18 lines = fh.readlines()
15lines = open(sources).readlines()19lines = open(sources).readlines()
16srcs = {}20srcs = {}
17src = None21src = None
@@ -23,4 +27,4 @@ for line in lines:
23 for b in line.partition(' ')[2].split(','):27 for b in line.partition(' ')[2].split(','):
24 b = b.strip()28 b = b.strip()
25 if b in bins:29 if b in bins:
26 print "%s (src: %s)" % (b, src)30 print("%s (src: %s)" % (b, src))
diff --git a/snaps/coverity-ubuntu-security/files/bin/refresh-auth-key b/snaps/coverity-ubuntu-security/files/bin/refresh-auth-key
index 88ac51a..9f6cf3c 100755
--- a/snaps/coverity-ubuntu-security/files/bin/refresh-auth-key
+++ b/snaps/coverity-ubuntu-security/files/bin/refresh-auth-key
@@ -1,5 +1,6 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3from __future__ import absolute_import, print_function
3import json4import json
4import os5import os
5import subprocess6import subprocess
diff --git a/utilities/build_failures.py b/utilities/build_failures.py
index 18a2896..d4df8cc 100755
--- a/utilities/build_failures.py
+++ b/utilities/build_failures.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python31#!/usr/bin/env python3
22
3# This is a start of a script that looks for build failures on the3# This is a start of a script that looks for build failures on the
4# yaml version of the excuses page from4# yaml version of the excuses page from
@@ -8,20 +8,26 @@
8# In particular, we're looking for failures due to gcc -pie by default8# In particular, we're looking for failures due to gcc -pie by default
9# on amd64, where a build will succeed on i386 but fail on amd649# on amd64, where a build will succeed on i386 but fail on amd64
1010
11from yaml import load, dump11from __future__ import absolute_import, print_function
12from yaml import safe_load, safe_dump
1213
13with open("update_excuses.yaml") as f:
14 data = load(f)
1514
16source_entries = data['sources']15def check_builds():
16 with open("update_excuses.yaml", "r") as f:
17 data = safe_load(f)
1718
18for s in source_entries:19 source_entries = data['sources']
19 if 'missing-builds' in s.keys():
20 arches = s['missing-builds']['on-architectures']
21 if 'amd64' in arches and not 'i386' in arches:
22 for excuse in s['excuses']:
23 if excuse.startswith("missing build on") and '>amd64<' in excuse:
24 url = excuse.split('"')[1]
25 print('%s: %s' % (s['source'], url))
26 #print('%s' %s)
2720
21 for s in source_entries:
22 if 'missing-builds' in s:
23 arches = s['missing-builds']['on-architectures']
24 if 'amd64' in arches and 'i386' not in arches:
25 for excuse in s['excuses']:
26 if excuse.startswith("missing build on") and '>amd64<' in excuse:
27 url = excuse.split('"')[1]
28 print('%s: %s' % (s['source'], url))
29 #print('%s' %s)
30
31
32if __name__ == "__main__":
33 check_builds()
28\ No newline at end of file34\ No newline at end of file
diff --git a/utilities/ceviche b/utilities/ceviche
index 546482b..4f7e3c5 100755
--- a/utilities/ceviche
+++ b/utilities/ceviche
@@ -1,4 +1,4 @@
1#!/usr/bin/env python1#!/usr/bin/env python3
22
3# Author: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>3# Author: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
4# Copyright (C) 2020 Canonical Ltd.4# Copyright (C) 2020 Canonical Ltd.
@@ -7,17 +7,26 @@
7# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html7# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html
8# for details.8# for details.
99
10from __future__ import absolute_import, print_function
11import contextlib
10import curses12import curses
13import glob
11import json14import json
12import optparse15import optparse
13import os16import os
14import pickle
15import re17import re
16import subprocess18import subprocess
17import sys19import sys
18import time20import time
19import urllib221
20import glob22if sys.version_info[0] == 2:
23 from urllib2 import urlopen
24 import cPickle as pickle
25 raw_input = raw_input
26else:
27 from urllib.request import urlopen
28 import pickle
29 raw_input = input
2130
22# cve_lib may not be in PYTHONPATH so try harder to find it31# cve_lib may not be in PYTHONPATH so try harder to find it
23try:32try:
@@ -155,8 +164,11 @@ def main_screen(stdscr, opt, args):
155 colors.append(["high", 197, -1])164 colors.append(["high", 197, -1])
156 colors.append(["critical", 197, -1])165 colors.append(["critical", 197, -1])
157166
158 for i in range(0, len(colors)):167 for i, color_triplet in enumerate(colors, start=1):
159 curses.init_pair(i + 1, colors[i][1], colors[i][2])168 # * Range operations are slightly different between python 2 and 3
169 # * so should be avoided wherever possible
170 _, fg_color, bg_color = color_triplet
171 curses.init_pair(i, fg_color, bg_color)
160172
161 downloaded = []173 downloaded = []
162 if os.path.isdir(DOWNLOAD_PATH):174 if os.path.isdir(DOWNLOAD_PATH):
@@ -519,6 +531,7 @@ def main_screen(stdscr, opt, args):
519 stdscr.addstr(x, columns_start - 7, "%6d" % item[COL_POP])531 stdscr.addstr(x, columns_start - 7, "%6d" % item[COL_POP])
520532
521 y = columns_start533 y = columns_start
534 # check the status on each supported release
522 for i in range(COL_REL, len(RELEASES) + COL_REL):535 for i in range(COL_REL, len(RELEASES) + COL_REL):
523 release_status = item[i]536 release_status = item[i]
524 if release_status == "needed" \537 if release_status == "needed" \
@@ -706,7 +719,7 @@ def run_command(stdscr, command, pause = False):
706 os.system("bash -c \"%s\"" % command)719 os.system("bash -c \"%s\"" % command)
707 if pause:720 if pause:
708 try:721 try:
709 input("\nPress Enter to continue...")722 raw_input("\nPress Enter to continue...")
710 except:723 except:
711 pass724 pass
712 curses.reset_prog_mode()725 curses.reset_prog_mode()
@@ -755,7 +768,7 @@ def reload_persistent_data(stdscr, opt):
755768
756 column = COL_REL769 column = COL_REL
757 for release in RELEASES:770 for release in RELEASES:
758 if release in table[cve][package].keys():771 if release in table[cve][package]
759 item[column] = table[cve][package][release]772 item[column] = table[cve][package][release]
760 else:773 else:
761 item[column] = "---"774 item[column] = "---"
@@ -782,13 +795,13 @@ def load_persistent_data(stdscr, opt):
782 return reload_persistent_data(stdscr, opt)795 return reload_persistent_data(stdscr, opt)
783796
784def get_links(filename):797def get_links(filename):
785 list = []798 match_list = []
786 with open(filename) as fh:799 with open(filename) as fh:
787 for line in fh:800 for line in fh:
788 match = re.search("(http|https|ftp)://[\w\-]+(\.[\w\-]+)+\S*", line)801 match = re.search("(http|https|ftp)://[\w\-]+(\.[\w\-]+)+\S*", line)
789 if match:802 if match:
790 list.insert(len(list), match.group())803 match_list.append(match.group())
791 return list804 return match_list
792805
793def is_patch(url):806def is_patch(url):
794 if re.search("(http|https|ftp)://.*\/(commit|hg\/rev)\/.*", url):807 if re.search("(http|https|ftp)://.*\/(commit|hg\/rev)\/.*", url):
@@ -798,12 +811,10 @@ def is_patch(url):
798811
799def save_patches(filename):812def save_patches(filename):
800 cve = os.path.basename(filename)813 cve = os.path.basename(filename)
801 links = []814 # * Use set comprehension to eliminate duplicates - creates a set which
802 for link in get_links(filename):815 # * by definition only contains unique elements, duplicates are discarded
803 if is_patch(link):816 # * then we just convert back to a list
804 links.insert(len(links), link)817 links = list({link for link in get_links(filename) if is_patch(link)})
805
806 links = list(dict.fromkeys(links)) # Remove duplicates
807818
808 try:819 try:
809 message = "Saved:"820 message = "Saved:"
@@ -811,19 +822,22 @@ def save_patches(filename):
811 link = links[0]822 link = links[0]
812 link += ".patch" if link[-6:] != ".patch" else ""823 link += ".patch" if link[-6:] != ".patch" else ""
813824
814 filedata = urllib2.urlopen(link)825 with contextlib.closing(urlopen(link)) as response:
815 datatowrite = filedata.read()826 filedata = response.read()
827 # FIXME: Don't write full absolute paths directly to the filesystem
828 # XXX : Use NamedTemporaryFile / mkstemp to generate names
816 tmpfile = '%s.patch' % cve829 tmpfile = '%s.patch' % cve
817 message += " %s" % tmpfile830 message += " %s" % tmpfile
818 with open('/tmp/' + tmpfile, 'wb') as f:831 with open('/tmp/' + tmpfile, 'wb') as f:
819 f.write(datatowrite)832 f.write(filedata)
820 elif len(links) > 1:833 elif len(links) > 1:
821 for i in range(0, len(links)):834 for i, link in enumerate(links):
822 filedata = urllib2.urlopen("%s.patch" % links[i])835 url = "%s.patch" % link
823 datatowrite = filedata.read()836 with contextlib.closing(urlopen(url)) as response:
837 filedata = response.read()
824 tmpfile = '%s-%d.patch' % (cve, i + 1)838 tmpfile = '%s-%d.patch' % (cve, i + 1)
825 with open('/tmp/' + tmpfile, 'wb') as f:839 with open('/tmp/' + tmpfile, 'wb') as f:
826 f.write(datatowrite)840 f.write(filedata)
827 message += " %s" % tmpfile841 message += " %s" % tmpfile
828 return message842 return message
829 except:843 except:
@@ -832,7 +846,7 @@ def save_patches(filename):
832def git_filter(filter):846def git_filter(filter):
833 returnlist = []847 returnlist = []
834 p = subprocess.Popen(['git', '-C', PATH, 'status', '-s', '.'],848 p = subprocess.Popen(['git', '-C', PATH, 'status', '-s', '.'],
835 stdout=subprocess.PIPE, stderr=subprocess.PIPE)849 stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
836 out, err = p.communicate()850 out, err = p.communicate()
837 for line in out.splitlines():851 for line in out.splitlines():
838 l = line.split()852 l = line.split()
@@ -964,6 +978,7 @@ def parse_opts():
964 return (opt, args)978 return (opt, args)
965979
966def main():980def main():
981 # TODO: Migrate to argparse
967 (opt, args) = parse_opts()982 (opt, args) = parse_opts()
968 if not os.path.isdir(PATH):983 if not os.path.isdir(PATH):
969 print("CVEs directory not found (%s)!" % PATH)984 print("CVEs directory not found (%s)!" % PATH)
diff --git a/utilities/maildir2mbox.py b/utilities/maildir2mbox.py
index ef75c99..9abe155 100755
--- a/utilities/maildir2mbox.py
+++ b/utilities/maildir2mbox.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2#2#
3# Author: Jamie Strandboge <jamie@ubuntu.com>3# Author: Jamie Strandboge <jamie@ubuntu.com>
4# Copyright (C) 2005-2011 Canonical Ltd.4# Copyright (C) 2005-2011 Canonical Ltd.
@@ -11,6 +11,7 @@
11# directories.11# directories.
12#12#
1313
14from __future__ import absolute_import, print_function
14import datetime15import datetime
15import email16import email
16import email.utils17import email.utils
@@ -25,20 +26,20 @@ import tempfile
25def debug(s):26def debug(s):
26 '''Print debug message'''27 '''Print debug message'''
27 if opt.debug:28 if opt.debug:
28 print >>sys.stderr, "DEBUG: %s" % (s)29 print("DEBUG: %s" % (s), file=sys.stderr)
2930
30def get_date(s):31def get_date(s):
31 '''Return a datetime.date object from string'''32 '''Return a datetime.date object from string'''
32 pat = re.compile(r'^\d\d\d\d-\d\d-\d\d$')33 pat = re.compile(r'^\d\d\d\d-\d\d-\d\d$')
33 d = None34 d = None
34 if not pat.match(s):35 if not pat.match(s):
35 print >>sys.stderr, "date '%s' should be YYYY-MM-DD" % (s)36 print("date '%s' should be YYYY-MM-DD" % (s), file=sys.stderr)
36 return None37 return None
37 t = s.split('-')38 t = s.split('-')
38 try:39 try:
39 d = datetime.date(int(t[0]), int(t[1]), int(t[2]))40 d = datetime.date(int(t[0]), int(t[1]), int(t[2]))
40 except:41 except:
41 print >>sys.stderr, "Invalid date '%s'" % (s)42 print("Invalid date '%s'" % (s), file=sys.stderr)
42 raise43 raise
4344
44 return d45 return d
@@ -64,16 +65,16 @@ parser.add_option("--end-date",
64(opt, args) = parser.parse_args()65(opt, args) = parser.parse_args()
6566
66if not opt.folder:67if not opt.folder:
67 print >>sys.stderr, "Must specify --folder"68 print("Must specify --folder", file=sys.stderr)
68 sys.exit(1)69 sys.exit(1)
69elif not opt.mbox:70elif not opt.mbox:
70 print >>sys.stderr, "Must specify --mbox"71 print("Must specify --mbox", file=sys.stderr)
71 sys.exit(1)72 sys.exit(1)
72elif not os.path.isdir(opt.folder):73elif not os.path.isdir(opt.folder):
73 print >>sys.stderr, "'%s' does not exist" % opt.folder74 print("'%s' does not exist" % opt.folder, file=sys.stderr)
74 sys.exit(1)75 sys.exit(1)
75elif os.path.exists(opt.mbox):76elif os.path.exists(opt.mbox):
76 print >>sys.stderr, "'%s' already exists" % opt.mbox77 print("'%s' already exists" % opt.mbox, file=sys.stderr)
77 sys.exit(1)78 sys.exit(1)
7879
79start = None80start = None
@@ -114,7 +115,7 @@ for message in src_maildir:
114 debug("Skipping: 'Subject: %s' (%s is after %s)" % (message['subject'], msg_date, start))115 debug("Skipping: 'Subject: %s' (%s is after %s)" % (message['subject'], msg_date, start))
115 continue116 continue
116117
117 if message.has_key('subject') and message.has_key('date'):118 if 'subject' in message and 'date' in message:
118 debug("Processing '%s: Subject: %s'" % (message['date'], message['subject']))119 debug("Processing '%s: Subject: %s'" % (message['date'], message['subject']))
119120
120 try:121 try:
diff --git a/utilities/mugshot b/utilities/mugshot
index 9f063ea..55dc6ff 100755
--- a/utilities/mugshot
+++ b/utilities/mugshot
@@ -1,9 +1,9 @@
1#!/usr/bin/python1#!/usr/bin/env python3
2# Author: Kees Cook <kees@ubuntu.com>2# Author: Kees Cook <kees@ubuntu.com>
3# Copyright (C) 2010 Canonical, Ltd.3# Copyright (C) 2010 Canonical, Ltd.
4# License: GPLv34# License: GPLv3
55
6from __future__ import print_function6from __future__ import absolute_import, print_function
7import sys7import sys
8import optparse8import optparse
9import httplib29import httplib2

Subscribers

People subscribed via source and target branches