From 4c9d01efe8a966b8d77c5aecfb598679db1d00de Mon Sep 17 00:00:00 2001 From: John Garland Date: Mon, 13 Jul 2009 05:12:26 +0000 Subject: [PATCH] Removed type combo box from gtkui (will be auto-detecting type). Removed old format readers. Added new format readers and decompressers. --- deluge/plugins/blocklist/blocklist/core.py | 32 ++-- .../blocklist/data/blocklist_pref.glade | 82 ++++------ .../blocklist/blocklist/decompressers.py | 59 +++++++ deluge/plugins/blocklist/blocklist/gtkui.py | 28 ---- deluge/plugins/blocklist/blocklist/readers.py | 80 ++++++++++ deluge/plugins/blocklist/blocklist/text.py | 151 ------------------ 6 files changed, 183 insertions(+), 249 deletions(-) create mode 100644 deluge/plugins/blocklist/blocklist/decompressers.py create mode 100644 deluge/plugins/blocklist/blocklist/readers.py delete mode 100644 deluge/plugins/blocklist/blocklist/text.py diff --git a/deluge/plugins/blocklist/blocklist/core.py b/deluge/plugins/blocklist/blocklist/core.py index 6a29df5ea..7d4c719bf 100644 --- a/deluge/plugins/blocklist/blocklist/core.py +++ b/deluge/plugins/blocklist/blocklist/core.py @@ -49,28 +49,18 @@ import deluge.configmanager from deluge.core.rpcserver import export from deluge.httpdownloader import download_file -from peerguardian import PGReader, PGException -from text import TextReader, GZMuleReader, PGZip, PGTextReaderGzip - DEFAULT_PREFS = { "url": "http://deluge-torrent.org/blocklist/nipfilter.dat.gz", "load_on_start": False, "check_after_days": 4, - "list_type": "gzmule", + "list_compression": "", + "list_type": "", "last_update": "", "list_size": 0, "timeout": 180, "try_times": 3, } -FORMATS = { - 'gzmule': ["Emule IP list (GZip)", GZMuleReader], - 'spzip': ["SafePeer Text (Zipped)", PGZip], - 'pgtext': ["PeerGuardian Text (Uncompressed)", TextReader], - 'p2bgz': ["PeerGuardian P2B (GZip)", PGReader], - 'pgtextgz': ["PeerGuardian Text (GZip)", PGTextReaderGzip] -} - class Core(CorePluginBase): def enable(self): log.debug('Blocklist: Plugin enabled..') @@ -81,6 +71,7 @@ class Core(CorePluginBase): self.up_to_date = False self.num_blocked = 0 self.file_progress = 0.0 + self.reader = None self.core = component.get("Core") @@ -153,13 +144,19 @@ class Core(CorePluginBase): else: status["state"] = "Idle" + if self.config["list_compression"]: + status["file_type"] = self.config["list_compression"] + " " + + self.config["list_type"] + status["up_to_date"] = self.up_to_date status["num_blocked"] = self.num_blocked status["file_progress"] = self.file_progress - status["file_type"] = self.config["list_type"] status["file_url"] = self.config["url"] status["file_size"] = self.config["list_size"] status["file_date"] = self.config["last_update"] + status["file_type"] = self.config["list_type"] + if self.config["list_compression"]: + status["file_type"] += " (%s)" % self.config["list_compression"] return status @@ -237,6 +234,10 @@ class Core(CorePluginBase): def import_list(self, force=False): """Imports the downloaded blocklist into the session""" + def on_read_ip_range(ip_range): + # TODO: add to lt session + self.num_blocked += 1 + if self.use_cache and self.has_imported: log.debug("Latest blocklist is already imported") return True @@ -244,9 +245,10 @@ class Core(CorePluginBase): self.is_importing = True self.num_blocked = 0 - # TODO: Open blocklist with appropriate reader - # TODO: Import ranges + if not self.reader: + # TODO: auto-detect reader + #return threads.deferToThread(self.reader.read(on_read_ip_range)) return defer.succeed(None) def on_import_complete(self, result): diff --git a/deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade b/deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade index c6d95c695..29eadb6c8 100644 --- a/deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade +++ b/deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade @@ -1,7 +1,7 @@ - - - + + + @@ -11,68 +11,31 @@ True 0 - GTK_SHADOW_NONE + none True 12 - + True 5 - + True - 5 - - - True - Type: - - - False - False - - - - - True - - - False - False - 1 - - + URL: False False + 0 - + True - 5 - - - True - URL: - - - False - False - - - - - True - True - - - 1 - - + True + 1 @@ -96,13 +59,14 @@ False + 0 True 0 - GTK_SHADOW_NONE + none True @@ -158,14 +122,15 @@ False False + 0 + Import blocklist on startup True True - Import blocklist on startup - 0 + False True @@ -199,7 +164,7 @@ True 0 - GTK_SHADOW_NONE + none True @@ -218,7 +183,6 @@ True True Download the blocklist file if necessary and import the file. - 0 @@ -232,6 +196,7 @@ False False + 0 @@ -251,6 +216,7 @@ False False + 0 @@ -259,7 +225,6 @@ True True Download a new blocklist file and import it. - 0 @@ -273,6 +238,7 @@ False False + 0 @@ -296,6 +262,9 @@ + + 0 + @@ -333,7 +302,7 @@ True 0 - GTK_SHADOW_NONE + none True @@ -346,6 +315,9 @@ True + + 0 + diff --git a/deluge/plugins/blocklist/blocklist/decompressers.py b/deluge/plugins/blocklist/blocklist/decompressers.py new file mode 100644 index 000000000..e9903dbca --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/decompressers.py @@ -0,0 +1,59 @@ +# +# decompressers.py +# +# Copyright (C) 2009 John Garland +# +# Deluge is free software. +# +# You may redistribute it and/or modify it under the terms of the +# GNU General Public License, as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) +# any later version. +# +# deluge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with deluge. If not, write to: +# The Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the OpenSSL +# library. +# You must obey the GNU General Public License in all respects for all of +# the code used other than OpenSSL. If you modify file(s) with this +# exception, you may extend this exception to your version of the file(s), +# but you are not obligated to do so. If you do not wish to do so, delete +# this exception statement from your version. If you delete this exception +# statement from all source files in the program, then also delete it here. +# +# + +import gzip, zipfile, bz2 +import new + +def Zip(reader): + """Blocklist reader for zipped blocklists""" + def open(self): + z = zipfile.ZipFile(self.file) + return z.open(z.namelist()[0]) + setattr(reader, "open", new.instancemethod(open, reader)) + return reader + +def GZip(reader): + """Blocklist reader for gzipped blocklists""" + def open(self): + return gzip.open(self.file) + setattr(reader, "open", new.instancemethod(open, reader)) + return reader + +def BZip2(reader): + """Blocklist reader for bzipped2 blocklists""" + def open(self): + return bz2.BZ2File(self.file) + setattr(reader, "open", new.instancemethod(open, reader)) + return reader diff --git a/deluge/plugins/blocklist/blocklist/gtkui.py b/deluge/plugins/blocklist/blocklist/gtkui.py index 8483fd20c..80064b942 100644 --- a/deluge/plugins/blocklist/blocklist/gtkui.py +++ b/deluge/plugins/blocklist/blocklist/gtkui.py @@ -42,8 +42,6 @@ import deluge.common from deluge.plugins.pluginbase import GtkPluginBase import common -from core import FORMATS - class GtkUI(GtkPluginBase): def enable(self): log.debug("Blocklist GtkUI enable..") @@ -118,11 +116,6 @@ class GtkUI(GtkPluginBase): deluge.common.fsize(status["file_size"])) self.glade.get_widget("label_modified").set_text( str(status["file_date"])) - try: - self.glade.get_widget("label_type").set_text( - FORMATS[status["file_type"]][0]) - except KeyError: - self.glade.get_widget("label_type").set_text("") self.glade.get_widget("label_url").set_text( status["file_url"]) @@ -131,11 +124,6 @@ class GtkUI(GtkPluginBase): def _on_show_prefs(self): def _on_get_config(config): - # Update the combo box. It's ugly, get over it. - self.glade.get_widget("combobox_types").set_active_iter( - self.glade.get_widget("combobox_types").get_model().\ - get_iter(FORMATS[config["list_type"]][1])) - self.glade.get_widget("entry_url").set_text( config["url"]) @@ -149,8 +137,6 @@ class GtkUI(GtkPluginBase): def _on_apply_prefs(self): config = {} - config["list_type"] = self.glade.get_widget("combobox_types").\ - get_model()[self.glade.get_widget("combobox_types").get_active()][1] config["url"] = self.glade.get_widget("entry_url").get_text() config["check_after_days"] = self.glade.get_widget("spin_check_days").get_value_as_int() config["load_on_start"] = self.glade.get_widget("chk_import_on_start").get_active() @@ -184,20 +170,6 @@ class GtkUI(GtkPluginBase): "on_button_force_download_clicked": self._on_button_force_download_clicked }) - # Setup types combobox - combo = self.glade.get_widget("combobox_types") - combo_list = gtk.ListStore(str, str) - combo.set_model(combo_list) - cell = gtk.CellRendererText() - combo.pack_start(cell, False) - combo.add_attribute(cell, "text", 0) - - for k in FORMATS.keys(): - i = combo_list.append([FORMATS[k][0], k]) - FORMATS[k][1] = combo_list.get_path(i) - - combo.set_active(0) - # Set button icons self.glade.get_widget("image_download").set_from_file( common.get_resource("blocklist_download24.png")) diff --git a/deluge/plugins/blocklist/blocklist/readers.py b/deluge/plugins/blocklist/blocklist/readers.py new file mode 100644 index 000000000..dc72ada1c --- /dev/null +++ b/deluge/plugins/blocklist/blocklist/readers.py @@ -0,0 +1,80 @@ +# +# readers.py +# +# Copyright (C) 2009 John Garland +# +# Deluge is free software. +# +# You may redistribute it and/or modify it under the terms of the +# GNU General Public License, as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) +# any later version. +# +# deluge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with deluge. If not, write to: +# The Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the OpenSSL +# library. +# You must obey the GNU General Public License in all respects for all of +# the code used other than OpenSSL. If you modify file(s) with this +# exception, you may extend this exception to your version of the file(s), +# but you are not obligated to do so. If you do not wish to do so, delete +# this exception statement from your version. If you delete this exception +# statement from all source files in the program, then also delete it here. +# +# + +from deluge.log import LOG as log + +class BaseReader(object): + """Base reader for blocklist files""" + def __init__(self, file): + """Creates a new BaseReader given a file""" + self.file = file + + def open(self): + """Opens the associated file for reading""" + return open(self.file) + + def parse(self, line): + """Extracts ip range from given line""" + raise NotYetImplemented + + def read(self, callback): + """Calls callback on each ip range in the file""" + for ip_range in self.readranges(): + callback(ip_range) + + def is_valid(self, line): + return not line.startswith('#') and line.strip() != "" + + def readranges(self): + """Yields each ip range from the file""" + blocklist = self.open() + for line in blocklist: + if self.is_valid(line): + yield self.parse(line) + blocklist.close() + +class EmuleReader(BaseReader): + """Blocklist reader for emule style blocklists""" + def parse(self, line): + return line.strip().split(" , ")[0].split(" - ") + +class SafePeerReader(BaseReader): + """Blocklist reader for SafePeer style blocklists""" + def parse(self, line): + return line.strip().split(":")[1].split("-") + +class PeerGuardianReader(SafePeerReader): + """Blocklist reader for PeerGuardian style blocklists""" + pass diff --git a/deluge/plugins/blocklist/blocklist/text.py b/deluge/plugins/blocklist/blocklist/text.py deleted file mode 100644 index 2c29fefc5..000000000 --- a/deluge/plugins/blocklist/blocklist/text.py +++ /dev/null @@ -1,151 +0,0 @@ -## -# Copyright 2007 Steve 'Tarka' Smith (tarka@internode.on.net) -# Distributed under the same terms as Deluge -## - - -from exceptions import Exception -import re, gzip, os -from socket import inet_aton -from struct import unpack -from zipfile import ZipFile - -from deluge.log import LOG as log - -class TextException(Exception): - pass - -class FormatException(TextException): - pass - -class TextBase: - - def __init__(self, fd, regexp): - log.debug("TextBase loading") - self.count = 0 - self.fd = fd - self.re = re.compile(regexp) - - def next(self): - self.count += 1 - - txt = self.fd.readline() - if txt == "": - return False - - match = self.re.search(txt) - if not match: - log.debug("Blocklist: TextBase: Wrong file type or corrupted blocklist file.") - - try: - g = match.groups() - except AttributeError: - pass - else: - start = ".".join(g[0:4]) - end = ".".join(g[4:8]) - - return (start, end) - - def close(self): - self.fd.close() - - -# This reads PeerGuardian text-formatted block-lists -class PGTextReader(TextBase): - - def __init__(self, fd): - log.debug("PGTextReader loading") - regexp = ':(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$' - TextBase.__init__(self, fd, regexp) - -class PGTextReaderGzip(PGTextReader): - def __init__(self, filename): - log.debug("PGTextReaderGzip loading") - try: - PGTextReader.__init__(self, gzip.open(filename, "r")) - except: - log.debug("Wrong file type or corrupted blocklist file.") - -# This reads uncompressed PG text list -class TextReader(PGTextReader): - - def __init__(self, filename): - log.debug("TextReader loading: %s", filename) - try: - PGTextReader.__init__(self, open(filename, 'r')) - except: - log.debug("Wrong file type or corrupted blocklist file.") - - -# Reads Emule style blocklists (aka nipfilter) -class MuleReader(TextBase): - - def __init__(self, fd): - log.debug("MuleReader loading") - regexp = '0*(\d+)\.0*(\d+)\.0*(\d+)\.0*(\d+)\s*-\s*0*(\d+)\.0*(\d+)\.0*(\d+)\.0*(\d+)\s*,' - TextBase.__init__(self, fd, regexp) - -class GZMuleReader(MuleReader): - - def __init__(self, filename): - log.debug("GZMuleReader loading: %s", filename) - try: - MuleReader.__init__(self, gzip.open(filename, "r")) - except: - log.debug("Wrong file type or corrupted blocklist file.") - - -# Reads zip files from SafePeer style files -class PGZip(TextBase): - - def __init__(self, filename): - # Open zip and extract first file - try: - self.zfd = ZipFile(filename, 'r') - except: - log.debug("Blocklist: PGZip: Wrong file type or corrupted blocklist file.") - else: - self.files = self.zfd.namelist() - self.opennext() - - def opennext(self): - self.tmp = os.tmpfile() - f = self.files.pop() - log.debug("Loading file: %s", f) - self.tmp.write(self.zfd.read(f)) - self.tmp.seek(0) - self.reader = PGTextReader(self.tmp) - - def next(self): - try: - ret = self.reader.next() - if not ret: - # This bit is repeated below and could be moved into a - # new procedure. However I'm not clear on how this - # would effect tail recursion, so it remains - # broken-out for now. - if len(self.files) > 0: - self.opennext() - return self.next() - else: - # End of zip - return False - return ret - - except FormatException, e: - log.debug("Blocklist: PGZip: Got format exception for zipfile") - # Just skip - if len(self.files) > 0: - self.opennext() - return self.next() - else: - return False - except AttributeError: - pass - - def close(self): - try: - self.zfd.close() - except AttributeError: - pass