diff --git a/plugins/BlocklistImport/__init__.py b/plugins/BlocklistImport/__init__.py new file mode 100644 index 000000000..d754fbaf6 --- /dev/null +++ b/plugins/BlocklistImport/__init__.py @@ -0,0 +1,95 @@ + + +plugin_name = "Blocklist Importer" +plugin_author = "Steve 'Tarka' Smith" +plugin_version = "0.1" +plugin_description = "Downloads and import PeerGuardian blocklists" + +def deluge_init(deluge_path): + global path + path = deluge_path + +def enable(core, interface): + global path + return BlocklistImport(path, core, interface) + +#################### The plugin itself #################### + +import urllib, deluge.common, deluge.pref +from peerguardian import PGReader, PGException +from ui import GTKConfig, GTKProgress + +class BlocklistImport: + + def __init__(self, path, core, interface): + print "Loading blocklist plugin ..." + # Save the path, interface, and core so they can be used later + self.path = path + self.core = core + self.interface = interface + self.gtkconf = GTKConfig(self) + self.gtkprog = GTKProgress(self) + + self.blockfile = deluge.common.CONFIG_DIR + "/blocklist.p2b.gzip" + + conffile = deluge.common.CONFIG_DIR + "/blocklist.conf" + self.config = deluge.pref.Preferences(filename=conffile, + global_defaults=False) + self.config.load() + + if not self.config.has_key('url'): + self.configure() + else: + self.loadlist(fetch=self.config.get('load_on_start')) + + + def _download_update(self, curr, chunksize, size): + incs = float(size) / float(chunksize) + self.gtkprog.download_prog(curr/incs) + + def loadlist(self, fetch=False): + # FIXME + #self.gtkprog.start() + + # Attempt initial import + # FIXME: Make async + if fetch: + print "Downloading blocklist..." + filename, headers = urllib.urlretrieve(self.config.get('url'), + filename=self.blockfile, + reporthook=self._download_update) + print "Done" + + self.core.reset_ip_filter() + reader = PGReader(self.blockfile) + + ips = reader.next() + while ips: + print "Blocking",ips + self.core.add_range_to_ip_filter(*ips) + ips = reader.next() + + reader.close() + + # FIXME + #self.gtkprog.stop() + + def configure(self): + self.gtkconf.start() + + def setconfig(self, url, load_on_start): + self.config.set('url', url) + self.config.set('load_on_start', load_on_start) + self.config.save() + + self.loadlist(fetch=True) + + def disable(self): + self.core.reset_ip_filter() + + def unload(self): + #self.config.save_to_file(self.config_file) + self.core.reset_ip_filter() + + def update(self): + pass diff --git a/plugins/BlocklistImport/peerguardian.py b/plugins/BlocklistImport/peerguardian.py new file mode 100644 index 000000000..98d2c70d1 --- /dev/null +++ b/plugins/BlocklistImport/peerguardian.py @@ -0,0 +1,55 @@ + +from exceptions import Exception +from struct import unpack +import gzip, socket + +class PGException(Exception): + pass + +# Incrementally reads PeerGuardian blocklists v1 and v2. +# See http://wiki.phoenixlabs.org/wiki/P2B_Format +class PGReader: + + def __init__(self, filename): + print "PGReader loading",filename + + # FIXME: Catch and convert exception? + self.fd = gzip.open(filename, "rb") + + # 4 bytes, should be 0xffffffff + buf = self.fd.read(4) + hdr = unpack("l", buf)[0] + if hdr != -1: + print "LEADER IS",hdr + raise PGException("Invalid leader %d"%hdr) + + magic = self.fd.read(3) + if magic != "P2B": + raise PGException("Invalid magic code") + + buf = self.fd.read(1) + ver = ord(buf) + if ver != 1 and ver != 2: + raise PGException("Invalid version %d" % ver) + + def next(self): + + # Skip over the string + buf = -1 + while buf != 0: + buf = self.fd.read(1) + if buf == "": # EOF + return False + buf = ord(buf) + + buf = self.fd.read(4) + start = socket.inet_ntoa(buf) + + buf = self.fd.read(4) + end = socket.inet_ntoa(buf) + + return (start, end) + + def close(self): + self.fd.close() + diff --git a/plugins/BlocklistImport/ui.py b/plugins/BlocklistImport/ui.py new file mode 100644 index 000000000..e9aecab49 --- /dev/null +++ b/plugins/BlocklistImport/ui.py @@ -0,0 +1,92 @@ + +import gtk + +class GTKConfig(gtk.Dialog): + def __init__(self, plugin): + gtk.Dialog.__init__(self, title="Blocklist Config", + flags=gtk.DIALOG_MODAL, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) + + # Setup + self.set_border_width(12) + self.vbox.set_spacing(6) + + # List source + label = gtk.Label() + label.set_markup('Blocklist URL') + self.url = gtk.Entry() + self.listtype = gtk.combo_box_new_text() + self.listtype.append_text("PeerGuardian (GZip)") + self.listtype.set_active(0) + + hbox = gtk.HBox(False, 6) + hbox.pack_start(label) + hbox.pack_start(self.url) + hbox.pack_start(self.listtype) + + self.vbox.pack_start(hbox) + + # Load on start + self.load_on_start = gtk.CheckButton("Load on start") + self.vbox.pack_start(self.load_on_start) + + self.connect('response', self.ok) + self.connect('close', self.cancel) + + self.hide_all() + + self.plugin = plugin + + + def ok(self, dialog, response): + self.hide_all() + + if response != gtk.RESPONSE_ACCEPT: + self.cancel(dialog) + return + + self.plugin.setconfig(self.url.get_text(), + self.load_on_start.get_active()) + + def cancel(self, dialog, response): + self.hide_all() + + def start(self): + self.show_all() + + +class GTKProgress(gtk.Dialog): + def __init__(self, plugin): + gtk.Dialog.__init__(self, title="Setting-Up Blocklist", + flags=gtk.DIALOG_MODAL, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) + # Setup + self.set_border_width(12) + self.vbox.set_spacing(6) + + label = gtk.Label() + label.set_markup('Loading and installing blocklist') + self.vbox.pack_start(label) + + self.progress = gtk.ProgressBar() + self.vbox.pack_start(self.progress) + + self.connect('close', self.cancel) + + self.hide_all() + + def download_prog(self, fract): + if fract > 1.0: + fract = 1.0 + self.progress.set_fraction(fract) + + def cancel(self, dialog, response): + self.hide_all() + + def start(self): + print "showing all" + self.show_all() + + def stop(self): + self.hide_all()