Initial version of blocklist for 0.6

This commit is contained in:
Mark Stahler 2008-03-09 06:05:00 +00:00
parent 74cd111513
commit e0c5820bf0
10 changed files with 1163 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,56 @@
#
# blocklist/__init__.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# 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 2 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
from deluge.plugins.init import PluginBase
class CorePlugin(PluginBase):
def __init__(self, plugin_api, plugin_name):
# Load the Core portion of the plugin
try:
from core import Core
self.plugin = Core(plugin_api, plugin_name)
except Exception, e:
log.debug("Did not load a Core plugin: %s", e)
class GtkUIPlugin(PluginBase):
def __init__(self, plugin_api, plugin_name):
# Load the GtkUI portion of the plugin
try:
from gtkui import GtkUI
self.plugin = GtkUI(plugin_api, plugin_name)
except Exception, e:
log.debug("Did not load a GtkUI plugin: %s", e)

View File

@ -0,0 +1,119 @@
#
# blocklist/core.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# 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 2 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 torrentblocklist import TorrentBlockList
from deluge.log import LOG as log
from deluge.plugins.corepluginbase import CorePluginBase
class Core(CorePluginBase):
def enable(self):
self.blocklist = TorrentBlockList(self.plugin)
self.plugin.register_hook("post_session_load", self._post_session_load)
log.debug('Blocklist: Plugin enabled..')
def disable(self):
log.debug('Blocklist: Plugin disabled')
self.plugin.deregister_hook("post_session_load", self._post_session_load)
self.plugin.reset_ip_filter()
# Delete the blocklist object
del self.blocklist
self.blocklist = None
def update(self):
pass
## Hooks for core ##
def _post_session_load(self):
log.info('Blocklist: Session load hook caught')
if self.blocklist.load_on_start == True or self.blocklist.load_on_start == 'True':
# Wait until an idle time to load block list
import gobject
gobject.idle_add(self.blocklist.import_list)
## Callbacks
def register_import_hook(self):
self.plugin.register_hook("post_session_load", self._post_session_load)
return False
# Exported functions for ui
def export_critical_setting(self):
if self.blocklist.old_url != self.blocklist.url or self.blocklist.old_listtype != self.blocklist.listtype:
log.info('Blocklist: Critical setting changed')
self.blocklist.download()
self.blocklist.import_list()
self.blocklist.return_count() # Return count after import
# New settings are now old settings
self.blocklist.old_url = self.blocklist.url
self.blocklist.old_listtype = self.blocklist.listtype
def export_count_ips(self):
log.debug('Blocklist: Count IPs imported into blocklist')
return self.blocklist.return_count()
def export_import_list(self):
log.debug('Blocklist: Import started from GTK UI')
self.blocklist.import_list()
def export_set_options(self, settings):
log.debug("Blocklist: Set Options")
self.blocklist.set_options(settings)
def export_get_options(self):
log.debug("Blocklist: Get Options")
settings_dict = {
"url": self.blocklist.url,
"listtype": self.blocklist.listtype,
"check_after_days": self.blocklist.check_after_days,
"load_on_start":self.blocklist.load_on_start,
"try_times": self.blocklist.try_times,
"timeout": self.blocklist.timeout
}
log.info(settings_dict)
return settings_dict
def export_get_config_value(self, key):
log.debug("Blocklist: Get configuration setting")
return self.blocklist.get_config_value(key)
def export_set_config_value(self, key):
log.debug("Blocklist: Set configuration setting")
return self.blocklist.set_config_value(key)
def export_get_formats(self):
log.debug('Blocklist: Get Reader Formats')
return self.blocklist.return_formats()

View File

@ -0,0 +1,306 @@
#
# blocklist/gtkui.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# 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 2 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 pkg_resources # remove possibly, double check
from deluge.log import LOG as log
import deluge.common # for pixmap
import deluge.component # for systray
import ui
import gtk, gobject
FORMATS = {
'gzmule': ["Emule IP list (GZip)", None],
'spzip': ["SafePeer Text (Zipped)", None],
'pgtext': ["PeerGuardian Text (Uncompressed)", None],
'p2bgz': ["PeerGuardian P2B (GZip)", None]
}
class GtkUI(ui.UI):
def __init__(self, plugin_api, plugin_name):
log.debug("Calling UI init")
# Call UI constructor
ui.UI.__init__(self, plugin_api, plugin_name)
log.debug("Blocklist GtkUI plugin initalized..")
def enable(self):
self.plugin.register_hook("on_apply_prefs", self.apply_prefs)
# Import File Format Readers from TorrentBlocklist
#ui.client.block_list_get_formats(self.callback_load_formats) # cant marshal classobj objects - wtf
# Update Blocked IP status bar number - BETTER METHOD TO FOLLOW
# emit a blocklsit import signal
gobject.timeout_add(5000, self.get_ip_count)
gobject.timeout_add(10000, self.get_ip_count)
gobject.timeout_add(20000, self.get_ip_count)
self.load_interface()
def disable(self):
deluge.component.get("StatusBar").remove_item(self.blocklist_status)
self.plugin.deregister_hook("on_apply_prefs", self.apply_prefs)
def add_status_icon(self, ip_count):
try:
deluge.component.get("StatusBar").remove_item(self.blocklist_status)
except:
pass
# self, image=None, stock=None, text=None, callback=None
self.blocklist_status = deluge.component.get("StatusBar").add_item(deluge.common.get_pixmap("blocklist16.png"), None, str(ip_count) + " Blocked IP Ranges ", None)
def get_ip_count(self):
ui.client.block_list_count_ips(self.add_status_icon)
return False
def start_import(self, widget, data=None):
ui.client.block_list_import_list(None)
log.debug('Blocklist: Import button')
gobject.timeout_add(20000, self.get_ip_count)
def unload_interface(self):
self.plugin.remove_preferences_page("Blocklist")
# def get_active_text(combobox):
# model = combobox.get_model()
# active = combobox.get_active()
# if active < 0:
# return None
# return model[active][0]
def load_interface(self):
log.debug("Beginning gtk pane initialization")
self.blocklist_pref_page = gtk.VBox(False, 3)
self.blocklist_pref_page.set_spacing(6)
label = gtk.Label()
label.set_markup('<b>' + 'General' + '</b>')
frame = gtk.Frame()
frame.set_shadow_type(gtk.SHADOW_NONE)
alignment = gtk.Alignment(0.5, 0.5, 1, 1)
alignment.set_padding(8, 5, 5, 5)
table = gtk.Table(7, 2, False)
table.set_col_spacings(8)
table.set_row_spacings(10)
# First row
label0 = gtk.Label()
label0.set_text('Blocklist Type')
ls = gtk.ListStore(gobject.TYPE_STRING, # Long name
gobject.TYPE_STRING) # Short name
self.listtype = gtk.ComboBox(model=ls)
cell = gtk.CellRendererText()
cell.set_property('xpad', 5) # padding for status text
self.listtype.pack_start(cell, False)
self.listtype.add_attribute(cell, 'text', 0)
for k in FORMATS.keys():
i = ls.append([FORMATS[k][0], k])
FORMATS[k][1] = ls.get_path(i)
self.listtype.set_active(0)
table.attach(label0, 0, 1, 0 , 1)
table.attach(self.listtype, 1, 2, 0, 1)
# Second row
label1 = gtk.Label()
label1.set_text('Blocklist URL')
self.url = gtk.Entry()
table.attach(label1, 0, 1, 1, 2)
table.attach(self.url, 1, 2, 1, 2)
# Third row
label2 = gtk.Label()
label2.set_text('Check for a new blocklist every')
self.check_after_days = gtk.SpinButton(None, 1.0, 0)
self.check_after_days.set_increments(1, 3)
self.check_after_days.set_range(-1, 14)
label3 = gtk.Label()
label3.set_text('days')
hbox = gtk.HBox(False, 3)
hbox.pack_start(label2, False, True)
hbox.pack_start(self.check_after_days, False, False, 4)
hbox.pack_start(label3)
alignment.add(table)
table.attach(hbox, 0, 2, 2, 3)
# Fourth row
label4 = gtk.Label()
label4.set_text('Timeout to download new blocklist')
self.timeout = gtk.SpinButton(None, 5.0, 0)
self.timeout.set_increments(5, 20)
self.timeout.set_range(15, 360)
label5 = gtk.Label()
label5.set_text('seconds')
hbox1 = gtk.HBox(False, 3)
hbox1.pack_start(label4, False, True)
hbox1.pack_start(self.timeout)
hbox1.pack_start(label5, False, True)
table.attach(hbox1, 0, 2, 3, 4)
# Fifth row
label5 = gtk.Label()
label5.set_text('Times to attempt download of new list')
self.try_times = gtk.SpinButton(None, 1.0, 0)
self.try_times.set_increments(1, 2)
self.try_times.set_range(1, 5)
hbox2 = gtk.HBox(False, 3)
hbox2.pack_start(label5, False, True)
hbox2.pack_start(self.try_times)
table.attach(hbox2, 0, 2, 4, 5)
# sixth row
self.load_on_start = gtk.CheckButton('Import blocklist on daemon startup')
table.attach(self.load_on_start, 0, 2, 5, 6)
# DO I NEED THIS STILL I DONT KNOW THINK ABOUT IT AND ASK MYSELF AGAIN LATER K THX BYE
# # import button (Check and possibly download)
import_button = gtk.Button("_Import Blocklist", None, True)
import_button.connect("clicked", self.start_import, None)
pixbuf = gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap("blocklist_import24.png"))
image = gtk.image_new_from_pixbuf(pixbuf)
import_button.set_image(image)
table.attach(import_button, 0, 2, 6, 7)
# finish frame
frame.set_label_widget(label)
frame.add(alignment)
self.blocklist_pref_page.pack_start(frame)
# Add preferences page to preferences page
log.debug('Adding Blocklist Preferences page')
self.plugin.add_preferences_page("Blocklist", self.blocklist_pref_page)
# Load settings from config and fill widgets with settings
log.debug('Starting to load blocklist preferences')
self.fetch_prefs()
log.debug('Finished loading blocklist preferences')
def fetch_prefs(self): # Fetch settings dictionary from plugin core and pass it to GTK ui settings
log.info('Blocklist: Fetching and loading Preferences via GTK ui')
ui.client.block_list_get_options(self.callback_load_prefs)
def apply_prefs(self):
log.info('Blocklist: Preferences saved via Gtk ui')
settings_dict = {
"url": self.url.get_text(),
"listtype": self.get_ltype(),
"check_after_days": self.check_after_days.get_value_as_int(),
"load_on_start":self.load_on_start.get_active(),
"try_times": self.try_times.get_value_as_int(),
"timeout": self.timeout.get_value_as_int()
}
ui.client.block_list_set_options(None, settings_dict)
# Needs to go in another thread or wait until window is closed
gobject.idle_add(self.call_critical_setting)
def call_critical_setting(self):
ui.client.block_list_critical_setting(None) # This checks to see if url or listtype changed, if so download & import
self.get_ip_count()
# GTK Gui Callback functions
def callback_load_prefs(self, dict):
log.info('Blocklist: Callback Load Prefs GTK ui')
self.settings_url(dict['url'])
self.settings_listtype(dict['listtype'])
self.settings_load(dict['load_on_start'])
self.settings_check_after_days(dict['check_after_days'])
self.settings_timeout(dict['timeout'])
self.settings_try_times(dict['try_times'])
# Specific function to return proper listtype so we can save and open it again
def get_ltype(self):
ls = self.listtype.get_model()
log.debug(ls)
ltype = ls[self.listtype.get_active()][1]
log.debug(ltype)
return ltype
# Settings functions
def settings_listtype(self, setting):
log.debug('Blocklist: listtype')
path = FORMATS[setting][1]
i = self.listtype.get_model().get_iter(path)
self.listtype.set_active_iter(i)
def settings_url(self, setting):
log.debug('Blocklist: url')
self.url.set_text(setting)
def settings_check_after_days(self, setting):
log.debug('Blocklist: days')
self.check_after_days.set_value(setting)
def settings_load(self, setting):
log.debug('Blocklist: load_on_start')
log.info(setting)
if setting == True or setting == "True":
setting = 1
else:
setting = 0
self.load_on_start.set_active(setting)
def settings_timeout(self, setting):
log.debug('Blocklist: timeout')
self.timeout.set_value(setting)
def settings_try_times(self, setting):
log.debug('Blocklist: try times')
self.try_times.set_value(setting)

View File

@ -0,0 +1,61 @@
##
# Copyright 2007 Steve 'Tarka' Smith (tarka@internode.on.net)
# Distributed under the same terms as Deluge
##
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
try:
self.fd = gzip.open(filename, "rb")
except IOError, e:
print 'Blocklist: PGReader: Incorrect file type or list is corrupt'
# 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()

View File

@ -0,0 +1,142 @@
##
# 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
class TextException(Exception):
pass
class FormatException(TextException):
pass
class TextBase:
def __init__(self, fd, regexp):
print "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:
print '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):
print "PGTextReader loading"
regexp = ':(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$'
TextBase.__init__(self, fd, regexp)
# This reads uncompressed PG text list
class TextReader(PGTextReader):
def __init__(self, filename):
print "TextReader loading",filename
try:
PGTextReader.__init__(self, open(filename, 'r'))
except:
print 'Wrong file type or corrupted blocklist file.'
# Reads Emule style blocklists (aka nipfilter)
class MuleReader(TextBase):
def __init__(self, fd):
print "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):
print "GZMuleReader loading",filename
try:
MuleReader.__init__(self, gzip.open(filename, "r"))
except:
print '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:
print '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()
print "Loading file",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 ret == False:
# 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:
print '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

View File

@ -0,0 +1,372 @@
#
# blocklist/blocklist.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
# a snip or two used from johhnyg
#
# 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 2 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.
# TODO:
# - ZERO connections until after import
# - download timeouts / retries
import urllib2, httplib, socket, os, datetime, sys
import deluge.common
import deluge.component # for libtorrent session reference to change connection number
from deluge.log import LOG as log
import ui # added by Mark for pausing torrents
from peerguardian import PGReader, PGException
from text import TextReader, GZMuleReader, PGZip
BLOCKLIST_PREFS = {
"url": "http://www.bluetack.co.uk/config/pipfilter.dat.gz",
"load_on_start": "True",
"check_after_days": 2,
"listtype": "gzmule",
"timeout": 180,
"try_times": 3
}
BACKUP_PREFS = {
"url": "http://www.bluetack.co.uk/config/pipfilter.dat.gz",
"listtype": "gzmule",
}
FORMATS = {
'gzmule': ["Emule IP list (GZip)", GZMuleReader, None],
'spzip': ["SafePeer Text (Zipped)", PGZip, None],
'pgtext': ["PeerGuardian Text (Uncompressed)", TextReader, None],
'p2bgz': ["PeerGuardian P2B (GZip)", PGReader, None]
}
class HTTPConnection(httplib.HTTPConnection):
"""A customized HTTPConnection allowing a per-connection timeout, specified at construction."""
def __init__(self, host, port=None, strict=None, timeout=None):
httplib.HTTPConnection.__init__(self, host, port, strict)
self.timeout = timeout
def connect(self):
"""Override HTTPConnection.connect to connect to
host/port specified in __init__."""
msg = "getaddrinfo returns an empty list"
for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
self.sock = socket.socket(af, socktype, proto)
if self.timeout:
self.sock.settimeout(self.timeout)
self.sock.connect(sa)
except socket.error, msg:
if self.sock:
self.sock.close()
self.sock = None
continue
break
if not self.sock:
raise socket.error, msg
class HTTPHandler(urllib2.HTTPHandler):
"""A customized HTTPHandler which times out connection after the duration specified at construction."""
def __init__(self, timeout=None):
urllib2.HTTPHandler.__init__(self)
self.timeout = timeout
def http_open(self, req):
"""Override http_open."""
def makeConnection(host, port=None, strict=None):
return HTTPConnection(host, port, strict, timeout = self.timeout)
#print "HTTPHandler opening", req.get_full_url()
return self.do_open(makeConnection, req)
class TorrentBlockList:
def __init__(self, coreplugin):
self.plugin = coreplugin # reference from plugin core
log.info('Blocklist: TorrentBlockList instantiated')
deluge.component.get("Core").session.set_max_connections(0)
self.config = deluge.configmanager.ConfigManager("blocklist.conf", BLOCKLIST_PREFS)
self.curr = 0
self.load_options()
# Make sure we have a current block list file locally
self.fetch = False
self.local_blocklist = deluge.common.get_config_dir("blocklist.cache")
# Check list for modifications from online version
self.check_update()
# Initialize download attempt
self.attempt = 0
if self.fetch == True:
self.download()
log.debug('Blocklist: TorrentBlockList Constructor finished')
def load_options(self):
#self.config.load()
# Fill variables with settings from block list configuration file
self.url = self.config['url']
self.listtype = self.config['listtype']
self.check_after_days = self.config['check_after_days']
self.load_on_start = self.config['load_on_start']
self.timeout = self.config['timeout']
self.try_times = self.config['try_times']
self.old_url = self.url
self.old_listtype = self.listtype
socket.setdefaulttimeout(self.timeout)
def set_options(self, options):
log.info('Blocklist: Options saved...')
self.config.set('url', options['url'])
self.config.set('check_after_days', options['check_after_days'])
self.config.set('load_on_start', options['load_on_start'])
self.config.set('listtype', options['listtype'])
self.config.set('timeout', options['timeout'])
self.config.set('try_times', options['try_times'])
# Save settings to disk
self.config.save()
# Load newly set options to core plugin
self.load_options()
def check_update(self):
log.info('Blocklist: Checking for updates')
try:
# Check current block lists time stamp and decide if it needs to be replaced
list_stats = os.stat(self.local_blocklist)
list_time = datetime.datetime.fromtimestamp(list_stats.st_mtime)
list_size = list_stats.st_size
current_time = datetime.datetime.today()
except:
self.fetch = True
return
# If local blocklist file exists but nothing is in it
if list_size == 0:
self.fetch = True
return
if current_time >= (list_time + datetime.timedelta(self.check_after_days)):
check_newer = True
log.debug('Blocklist: List may need to be replaced')
else:
check_newer = False
# If the program decides it is time to get a new list
if check_newer == True:
log.debug('Blocklist: Attempting check')
j = 0 # counter for loop
while j < self.try_times:
# Get current online block lists time stamp and compare it with current
try:
http_handler = HTTPHandler(timeout = 15)
opener = urllib2.build_opener(http_handler)
request = urllib2.Request(self.url)
try:
new_listinfo = opener.open(request) # Can Raise URLError
header = new_listinfo.info()
remote_size = int(header['content-length'])
remote_time = datetime.datetime.strptime(header['last-modified'],"%a, %d %b %Y %H:%M:%S GMT")
remote_type = header['content-type']
except Exception, e:
log.warning(e)
# HANDLE EXCEPTOIN
log.debug(self.listtype)
# check expected list type
if self.listtype == "spzip":
list_type = "application/zip"
elif self.listtype == "gzmule" or self.listtype == "p2bgz":
list_type = "application/x-gzip"
else:
list_type = "text/html"
# Print remote file information and local
log.debug('Blocklist: remote')
log.debug(remote_type)
log.debug(remote_time)
log.debug(remote_size)
log.debug('Blocklist: local')
log.debug(list_type)
log.debug(list_time)
log.debug(list_size)
# Compare MIME types of local and remote list
if list_type == remote_type:
log.info('Blocklist: Remote and Local have the same list type')
# Compare last modified times and decide to download a new list or not
if list_time < remote_time or list_size != remote_size:
self.fetch = True
log.info('Blocklist: Local blocklist list is out of date')
else:
self.fetch = False
log.info('Blocklist: Local block list is up to date')
return
j+=1
log.debug('Blocklist: 6 TRY AGAIN FOO')
# Connection can't be made to check remote time stamps
except: # && urllib2.URLError
log.debug('Blocklist: Connection to remote server timed out')
self.fetch = False
j+=1
else:
log.info('Blocklist: Not enough time has passed to check for a new list')
return
def download(self):
log.info('Blocklist: Beginning download')
self.attempt += 1
i = 0
while i < self.try_times:
# Download a new block list
try:
log.info('Blocklist: Downloading new list...')
http_handler = HTTPHandler(timeout = 15)
opener = urllib2.build_opener(http_handler)
request = urllib2.Request(self.url)
new_list = opener.open(request)
file = open(deluge.common.get_config_dir("blocklist.cache"), 'w')
while 1:
data = new_list.read()
if not len(data):
break
file.write(data)
file.close()
except OSError, e:
log.debug('Blocklist: Unable to write blocklist file')
return
except:
if self.attempt > self.try_times:
log.warning('Blocklist: All download attempts failed')
return
else:
log.warning('Blocklist: Try list download again')
i += 1
# CHECKSUM
log.info('Blocklist: List downloaded sucessfully')
def import_list(self):
log.info('Blocklist: Importing list...')
try:
self.plugin.reset_ip_filter()
self.curr = 0
log.info('Blocklist: IP Filter reset')
except:
log.debug('Blocklist: Reset filter failed')
pass
# Instantiate format class that will read the lists file format
try:
log.info('Blocklist: ' + str(self.listtype))
read_list = FORMATS[self.listtype][1](self.local_blocklist)
except:
log.warning('Blocklist: Error: Format read error')
self.reset_critical_settings()
try:
ips = read_list.next()
print ips
while ips:
self.plugin.block_ip_range(ips)
ips = read_list.next()
self.curr += 1
# Progress measurement here
log.info(self.curr)
except IOError, e:
log.debug('Blocklist: Problem with list, re-download')
return
# Throw exception if curr = 0 reset critical settings
if self.curr == 0:
log.warning("Blocklist: Improper list read")
self.reset_critical_settings()
else:
deluge.component.get("Core").session.set_max_connections(deluge.configmanager.ConfigManager("core.conf")["max_connections_global"])
log.info('Blocklist: Import completed sucessfully')
def reset_critical_settings(self):
log.info('Blocklist: URL and List type reset')
reset_url = BACKUP_PREFS["url"]
reset_listtype = BACKUP_PREFS["listtype"]
log.info(reset_url)
log.info(reset_listtype)
self.config.set('url', reset_url)
self.config.set('listtype', reset_listtype)
self.config.save()
self.load_options()
log.info(self.url)
log.info(self.listtype)
self.download()
self.import_list()
def return_count(self):
return self.curr
def get_config_value(self, key): # url, check_after_days, listtype
val = self.config[key]
log.debug('Blocklist: Get_config_val')
return val

View File

@ -0,0 +1,53 @@
#
# blocklist/ui.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# 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 2 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 gettext
import locale
import pkg_resources
import deluge.component
from deluge.ui.client import aclient as client
from deluge.log import LOG as log
class UI:
def __init__(self, plugin_api, plugin_name):
self.plugin = plugin_api
def enable(self):
pass
def disable(self):
pass

View File

@ -0,0 +1,54 @@
# setup.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program 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 this program. 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.
"""
Download and import IP Blocklists
"""
from setuptools import setup
__author__ = "Mark Stahler"
setup(
name="Block List",
version="1.0",
description=__doc__,
author=__author__,
packages=["blocklist"],
package_data = {"blocklist": ["glade/*.glade"]},
entry_points="""
[deluge.plugin.core]
Blocklist = blocklist:CorePlugin
[deluge.plugin.gtkui]
Blocklist = blocklist:GtkUIPlugin
"""
)