New project to automatically check feeds.
[FeedLint.git] / feedlint
blob5cc368aa8be9ee4819bd62eaefab028b753976af
1 #!/usr/bin/env python
3 from optparse import OptionParser
4 import sys, shutil, tempfile, urlparse
5 import urllib2, os
6 import logging
7 from logging import info
9 from zeroinstall import SafeException
10 from zeroinstall.injector import model, gpg, reader
12 version = '0.1'
14 parser = OptionParser(usage="usage: %prog [options] feed.xml")
15 parser.add_option("-v", "--verbose", help="more verbose output", action='count')
16 parser.add_option("-V", "--version", help="display version information", action='store_true')
18 (options, args) = parser.parse_args()
20 if options.version:
21 print "FeedLint (zero-install) " + version
22 print "Copyright (C) 2007 Thomas Leonard"
23 print "This program comes with ABSOLUTELY NO WARRANTY,"
24 print "to the extent permitted by law."
25 print "You may redistribute copies of this program"
26 print "under the terms of the GNU General Public License."
27 print "For more information about these matters, see the file named COPYING."
28 sys.exit(0)
30 if options.verbose:
31 logger = logging.getLogger()
32 if options.verbose == 1:
33 logger.setLevel(logging.INFO)
34 else:
35 logger.setLevel(logging.DEBUG)
37 if len(args) < 1:
38 parser.print_help()
39 sys.exit(1)
41 checked = set()
43 try:
44 to_check = [model.canonical_iface_uri(a) for a in args]
45 except SafeException, ex:
46 if options.verbose: raise
47 print >>sys.stderr, ex
48 sys.exit(1)
50 def check_key(feed, fingerprint):
51 for line in os.popen('gpg --with-colons --list-keys %s' % s.fingerprint):
52 if line.startswith('pub:'):
53 key_id = line.split(':')[4]
54 break
55 else:
56 raise SafeException('Failed to find key with fingerprint %s on your keyring' % fingerprint)
58 key_url = urlparse.urljoin(feed, '%s.gpg' % key_id)
59 print "Checking", key_url
61 if key_url in checked:
62 info("(already checked key URL)")
63 else:
64 urllib2.urlopen(key_url).read()
65 checked.add(key_url)
67 n_errors = 0
69 while to_check:
70 feed = to_check.pop()
71 if feed in checked:
72 info("Already checked feed %s", feed)
73 continue
75 checked.add(feed)
77 print "Checking", feed
79 try:
80 tmp = tempfile.TemporaryFile(prefix = 'feedlint-')
81 try:
82 stream = urllib2.urlopen(feed)
83 shutil.copyfileobj(stream, tmp)
84 data, sigs = gpg.check_stream(tmp)
86 for s in sigs:
87 if isinstance(s, gpg.ValidSig):
88 check_key(feed, s.fingerprint)
89 else:
90 raise SafeException("Can't check sig: %s" % s)
92 feed_tmp = tempfile.NamedTemporaryFile(prefix = 'feedlint-')
93 try:
94 shutil.copyfileobj(data, feed_tmp)
95 feed_tmp.seek(0)
96 iface = model.Interface(feed)
97 reader.update(iface, feed_tmp.name)
99 for f in iface.feeds:
100 info("Will check feed %s", f.uri)
101 to_check.append(f.uri)
102 finally:
103 feed_tmp.close()
104 finally:
105 tmp.close()
106 except urllib2.HTTPError, ex:
107 print >>sys.stderr, ex
108 n_errors += 1
109 except SafeException, ex:
110 if options.verbose: raise
111 print >>sys.stderr, ex
112 n_errors += 1
114 if n_errors == 0:
115 print "OK"
116 else:
117 print "\nERRORS FOUND:", n_errors
118 sys.exit(1)