# -*- coding: utf-8 -*- # # Copyright (c) 2010 by FlashCode # # 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 3 of the License, 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, see . # # # Antispam for DCC file/chat requests. # (this script requires WeeChat 0.3.0 or newer) # # History: # # 2010-02-08, FlashCode : # version 0.1: initial release # import_ok = True try: import weechat except: print "This script must be run under WeeChat." print "Get WeeChat now at: http://www.weechat.org/" import_ok = False import re SCRIPT_NAME = "dcc_antispam" SCRIPT_AUTHOR = "FlashCode " SCRIPT_VERSION = "0.1" SCRIPT_LICENSE = "GPL3" SCRIPT_DESC = "Antispam for DCC file/chat requests" # script options dcc_settings = { "display" : "on", # display blocked dcc on core buffer? # comma separated lists: "server" : "", # restricts anti-spam on these servers (internal names) "name" : "", # list of names (regex) to block "ip" : "^0.0.0.0", # list of IPs (regex) to block "port" : "^0$,^\D+$", # list of ports (regex) to block "size" : "0", # list of sizes to block (should be "0" or empty string) } dcc_settings_regex_allowed = [ "name", "ip", "port" ] dcc_settings_regex = {} # DCC message looks like: # SEND: # :nick!user@host.com PRIVMSG mynick :\01DCC SEND filename.txt 2130706433 40017 123456\01 # \----------/ \--------/ \---/ \----/ # name ip port size # CHAT: # :nick!user@host.com PRIVMSG mynick :\01DCC CHAT chat 2130706433 40017\01 # \--------/ \---/ # ip port dcc_regex_dcc_send = re.compile(r"\S+ PRIVMSG \S+ :\01DCC (SEND|CHAT) ([^\01]+)\01") def dcc_is_blocked(dcc): """ Return True if dcc is blocked, False if dcc is not blocked. """ global dcc_settings_regex for key, value in dcc.iteritems(): if key in dcc_settings_regex: if weechat.config_get_plugin(key) != "": for regex in dcc_settings_regex[key]: if regex.search(value): return True else: for str in weechat.config_get_plugin(key).split(","): if value == str: return True # dcc NOT blocked return False def dcc_parse(type, message): """ Parse dcc request, return dict with values. """ dcc = {} for arg in [ "size", "port", "ip" ]: if type == "CHAT" and arg == "size": continue; pos = message.rfind(" ") if pos < 0: # problem with parsing, dcc is not blocked return False dcc[arg] = message[pos+1:] message = message[:pos] if type == "SEND": if message.startswith("\"") and message.endswith("\""): message = message[1:len(message)-1] dcc["name"] = message ip = int(dcc["ip"]) dcc["ip"] = "%d.%d.%d.%d" % (ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff) return dcc def dcc_privmsg_modifier_cb(data, modifier, modifier_data, string): """ Modifier callback for IRC PRIVMSG messages. """ match = dcc_regex_dcc_send.match(string) if match: server = weechat.config_get_plugin("server") if server == "" or modifier_data in server.split(","): dcctype = match.group(1) dcc = dcc_parse(dcctype, match.group(2)) if dcc_is_blocked(dcc): if weechat.config_get_plugin("display") == "on": if dcctype == "CHAT": weechat.prnt("", "%s: dcc blocked (chat from %s, port %s)" % (SCRIPT_NAME, dcc["ip"], dcc["port"])) else: weechat.prnt("", "%s: dcc blocked (file: '%s', size %s, from %s, port %s)" % (SCRIPT_NAME, dcc["name"], dcc["size"], dcc["ip"], dcc["port"])) return "" return string def dcc_build_regex(): """ Build regex for all options. """ global dcc_settings_regex_allowed, dcc_settings_regex for key in dcc_settings_regex_allowed: dcc_settings_regex[key] = [] for string in weechat.config_get_plugin(key).split(","): dcc_settings_regex[key].append(re.compile(string, re.I)) def dcc_config_cb(data, option, value): """ Callback called when a script option is changed. """ dcc_build_regex() return weechat.WEECHAT_RC_OK if __name__ == "__main__" and import_ok: if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""): # set default settings for option, default_value in dcc_settings.iteritems(): if not weechat.config_is_set_plugin(option): weechat.config_set_plugin(option, default_value) dcc_build_regex() # modifier for privmsg messages weechat.hook_modifier("irc_in_privmsg", "dcc_privmsg_modifier_cb", "") # config weechat.hook_config("plugins.var.python." + SCRIPT_NAME + ".*", "dcc_config_cb", "")