From 2d3009ccb123bb34bf0d8b8b516a15c05240bf03 Mon Sep 17 00:00:00 2001 From: "Sean B. Palmer" Date: Mon, 5 Sep 2011 17:46:17 +0100 Subject: Attempt to patch a possible message injection hole. --- bot.py | 2 ++ irc.py | 8 ++++- modules/head.py | 12 +++++++ modules/oblique.py | 2 +- modules/reload.py | 2 ++ modules/search.py | 96 +++++++++++++++++++++++++++++++++++++++------------- modules/tell.py | 1 + modules/wikipedia.py | 2 +- phenny | 4 ++- 9 files changed, 101 insertions(+), 28 deletions(-) diff --git a/bot.py b/bot.py index 3886a87..453dbc4 100755 --- a/bot.py +++ b/bot.py @@ -55,6 +55,8 @@ class Phenny(irc.Bot): for filename in filenames: name = os.path.basename(filename)[:-3] if name in excluded_modules: continue + # if name in sys.modules: + # del sys.modules[name] try: module = imp.load_source(name, filename) except Exception, e: print >> sys.stderr, "Error loading %s: %s (in bot.py)" % (name, e) diff --git a/irc.py b/irc.py index a16c61b..7a4bed4 100755 --- a/irc.py +++ b/irc.py @@ -42,6 +42,9 @@ class Bot(asynchat.async_chat): import threading self.sending = threading.RLock() + # def push(self, *args, **kargs): + # asynchat.async_chat.push(self, *args, **kargs) + def __write(self, args, text=None): # print '%r %r %r' % (self, args, text) try: @@ -148,7 +151,10 @@ class Bot(asynchat.async_chat): self.sending.release() return - self.__write(('PRIVMSG', recipient), text) + def safe(input): + input = input.replace('\n', '') + return input.replace('\r', '') + self.__write(('PRIVMSG', safe(recipient)), safe(text)) self.stack.append((time.time(), text)) self.stack = self.stack[-10:] diff --git a/modules/head.py b/modules/head.py index 1008628..66e9eef 100755 --- a/modules/head.py +++ b/modules/head.py @@ -83,6 +83,18 @@ def f_title(self, origin, match, args): uri = 'http://' + uri uri = uri.replace('#!', '?_escaped_fragment_=') + localhost = [ + 'http://localhost/', 'http://localhost:80/', + 'http://localhost:8080/', 'http://127.0.0.1/', + 'http://127.0.0.1:80/', 'http://127.0.0.1:8080/', + 'https://localhost/', 'https://localhost:80/', + 'https://localhost:8080/', 'https://127.0.0.1/', + 'https://127.0.0.1:80/', 'https://127.0.0.1:8080/', + ] + for s in localhost: + if uri.startswith(s): + return phenny.reply('Sorry, access forbidden.') + try: redirects = 0 while True: diff --git a/modules/oblique.py b/modules/oblique.py index 6d6156c..7bd6718 100755 --- a/modules/oblique.py +++ b/modules/oblique.py @@ -81,7 +81,7 @@ def o(phenny, input): return phenny.reply(msg) if not o.services.has_key(command): - return phenny.reply('Sorry, no such service. See %s' % o.serviceURI) + return phenny.reply('Service not found in %s' % o.serviceURI) if hasattr(phenny.config, 'external'): default = phenny.config.external.get('*') diff --git a/modules/reload.py b/modules/reload.py index 32e6796..dfd0e8e 100755 --- a/modules/reload.py +++ b/modules/reload.py @@ -19,6 +19,8 @@ def f_reload(phenny, input): return phenny.reply('What?') if (not name) or (name == '*'): + phenny.variables = None + phenny.commands = None phenny.setup() return phenny.reply('done') diff --git a/modules/search.py b/modules/search.py index c8f9a6a..bfc50bd 100755 --- a/modules/search.py +++ b/modules/search.py @@ -18,26 +18,26 @@ class Grab(web.urllib.URLopener): def http_error_default(self, url, fp, errcode, errmsg, headers): return web.urllib.addinfourl(fp, [headers, errcode], "http:" + url) -def search(query): +def google_ajax(query): """Search using AjaxSearch, and return its JSON.""" uri = 'http://ajax.googleapis.com/ajax/services/search/web' - args = '?v=1.0&safe=off&q=' + web.urllib.quote(query.encode('utf-8')) + args = '?v=1.0&safe=off&q=' + web.urllib.quote(query) handler = web.urllib._urlopener web.urllib._urlopener = Grab() bytes = web.get(uri + args) web.urllib._urlopener = handler return web.json(bytes) -def result(query): - results = search(query) +def google_search(query): + results = google_ajax(query) try: return results['responseData']['results'][0]['unescapedUrl'] except IndexError: return None except TypeError: print results return False -def count(query): - results = search(query) +def google_count(query): + results = google_ajax(query) if not results.has_key('responseData'): return '0' if not results['responseData'].has_key('cursor'): return '0' if not results['responseData']['cursor'].has_key('estimatedResultCount'): @@ -56,7 +56,8 @@ def g(phenny, input): query = input.group(2) if not query: return phenny.reply('.g what?') - uri = result(query) + query = query.encode('utf-8') + uri = google_search(query) if uri: phenny.reply(uri) if not hasattr(phenny.bot, 'last_seen_uri'): @@ -73,7 +74,8 @@ def gc(phenny, input): query = input.group(2) if not query: return phenny.reply('.gc what?') - num = formatnumber(count(query)) + query = query.encode('utf-8') + num = formatnumber(google_count(query)) phenny.say(query + ': ' + num) gc.commands = ['gc'] gc.priority = 'high' @@ -93,7 +95,8 @@ def gcs(phenny, input): results = [] for i, query in enumerate(queries): query = query.strip('[]') - n = int((formatnumber(count(query)) or '0').replace(',', '')) + query = query.encode('utf-8') + n = int((formatnumber(google_count(query)) or '0').replace(',', '')) results.append((n, query)) if i >= 2: __import__('time').sleep(0.25) if i >= 4: __import__('time').sleep(0.25) @@ -105,6 +108,13 @@ gcs.commands = ['gcs', 'comp'] r_bing = re.compile(r'

') +r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">') -def ddg(phenny, input): +def duck_search(query): + query = query.replace('!', '') + query = web.urllib.quote(query) + uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query + bytes = web.get(uri) + m = r_duck.search(bytes) + if m: return web.decode(m.group(1)) + +def duck(phenny, input): query = input.group(2) if not query: return phenny.reply('.ddg what?') - query = web.urllib.quote(query.encode('utf-8')) - uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query - bytes = web.get(uri) - m = r_ddg.search(bytes) - if m: - uri = m.group(1) + query = query.encode('utf-8') + uri = duck_search(query) + if uri: phenny.reply(uri) if not hasattr(phenny.bot, 'last_seen_uri'): phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri[input.sender] = uri else: phenny.reply("No results found for '%s'." % query) -ddg.commands = ['ddg'] +duck.commands = ['duck', 'ddg'] + +def search(phenny, input): + if not input.group(2): + return phenny.reply('.search for what?') + query = input.group(2).encode('utf-8') + gu = google_search(query) or '-' + bu = bing_search(query) or '-' + du = duck_search(query) or '-' + + if (gu == bu) and (bu == du): + result = '%s (g, b, d)' % gu + elif (gu == bu): + result = '%s (g, b), %s (d)' % (gu, du) + elif (bu == du): + result = '%s (b, d), %s (g)' % (bu, gu) + elif (gu == du): + result = '%s (g, d), %s (b)' % (gu, bu) + else: + if len(gu) > 250: gu = '(extremely long link)' + if len(bu) > 150: bu = '(extremely long link)' + if len(du) > 150: du = '(extremely long link)' + result = '%s (g), %s (b), %s (d)' % (gu, bu, du) + + phenny.reply(result) +search.commands = ['search'] + +def suggest(phenny, input): + if not input.group(2): + return phenny.reply("No query term.") + query = input.group(2).encode('utf-8') + uri = 'http://websitedev.de/temp-bin/suggest.pl?q=' + answer = web.get(uri + web.urllib.quote(query).replace('+', '%2B')) + if answer: + phenny.say(answer) + else: phenny.reply('Sorry, no result.') +suggest.commands = ['suggest'] if __name__ == '__main__': print __doc__.strip() diff --git a/modules/tell.py b/modules/tell.py index 5e61007..d3ee609 100755 --- a/modules/tell.py +++ b/modules/tell.py @@ -122,6 +122,7 @@ def message(phenny, input): tellee = input.nick channel = input.sender + if not os: return if not os.path.exists(phenny.tell_filename): return diff --git a/modules/wikipedia.py b/modules/wikipedia.py index ba9ce0b..1a406b3 100755 --- a/modules/wikipedia.py +++ b/modules/wikipedia.py @@ -53,7 +53,7 @@ def search(term): else: term = term.decode('utf-8') term = term.replace('_', ' ') - try: uri = search.result('site:en.wikipedia.org %s' % term) + try: uri = search.google_search('site:en.wikipedia.org %s' % term) except IndexError: return term if uri: return uri[len('http://en.wikipedia.org/wiki/'):] diff --git a/phenny b/phenny index 3153f33..6cb0961 100755 --- a/phenny +++ b/phenny @@ -30,7 +30,9 @@ def create_default_config(fn): channels = ['#example', '#test'] owner = 'yournickname' - # password = 'yourserverpassword' + # password is the NickServ password, serverpass is the server password + # password = 'example' + # serverpass = 'serverpass' # These are people who will be able to use admin.py's functions... admins = [owner, 'someoneyoutrust'] -- cgit v1.2.3-1-g7c22