diff --git a/src/jcl/jabber/__init__.py b/src/jcl/jabber/__init__.py index 4dc5978..100e47d 100644 --- a/src/jcl/jabber/__init__.py +++ b/src/jcl/jabber/__init__.py @@ -7,14 +7,18 @@ class Handler(object): """handling class""" def filter(self, stanza, lang_class): - """Filter account to be processed by the handler - return all accounts. DB connection might already be opened.""" + """ + Filter account to be processed by the handler + return all accounts. DB connection might already be opened. + """ accounts = Account.select() return accounts - def handle(self, stanza, lang_class, accounts): - """Apply actions to do on given accounts - Do nothing by default""" + def handle(self, stanza, lang_class, data): + """ + Apply actions to do on given accounts + Do nothing by default. + """ return [] class DiscoHandler(object): @@ -24,6 +28,6 @@ class DiscoHandler(object): """Filter requests to be handled""" return False - def handle(self, disco_items, node, info_query, data, lang_class): + def handle(self, node, info_query, lang_class, disco_items, data): """Handle disco get items request""" return None diff --git a/src/jcl/jabber/component.py b/src/jcl/jabber/component.py index 4bb44cf..3597166 100644 --- a/src/jcl/jabber/component.py +++ b/src/jcl/jabber/component.py @@ -21,7 +21,8 @@ ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## -"""JCL base component +""" +JCL base component """ __revision__ = "$Id: component.py,v 1.3 2005/09/18 20:24:07 dax Exp $" @@ -50,8 +51,9 @@ from pyxmpp.presence import Presence from pyxmpp.jabber.dataforms import Form, Field, Option import jcl -from jcl.jabber import Handler from jcl.error import FieldError +from jcl.jabber import Handler +from jcl.jabber.message import PasswordMessageHandler import jcl.jabber.command as command from jcl.jabber.command import CommandDiscoGetItemsHandler, \ CommandDiscoGetInfoHandler, CommandManager, JCLCommandManager @@ -283,10 +285,10 @@ class JCLComponent(Component, object): for handler in handlers: try: self.__logger.debug("Applying filter " + repr(handler)) - accounts = handler.filter(stanza, lang) - if accounts is not None: + data = handler.filter(stanza, lang) + if data: self.__logger.debug("Applying handler " + repr(handler)) - result += handler.handle(stanza, lang, accounts) + result += handler.handle(stanza, lang, data) if not apply_all: break except Exception, e: @@ -1276,82 +1278,3 @@ class AccountManager(object): body=_account.default_lang_class.error_body \ % (exception))) return result - -class DefaultPresenceHandler(Handler): - """Handle presence""" - - def handle(self, presence, lang_class, accounts): - """Return same presence as receive one""" - to_jid = presence.get_to() - from_jid = presence.get_from() - presence.set_to(from_jid) - presence.set_from(to_jid) - return [presence] - -class DefaultSubscribeHandler(Handler): - """Return default response to subscribe queries""" - - def handle(self, stanza, lang_class, accounts): - """Create subscribe response""" - result = [] - result.append(Presence(from_jid=stanza.get_to(), - to_jid=stanza.get_from(), - stanza_type="subscribe")) - result.append(Presence(from_jid=stanza.get_to(), - to_jid=stanza.get_from(), - stanza_type="subscribed")) - return result - -class DefaultUnsubscribeHandler(Handler): - """Return default response to subscribe queries""" - - def handle(self, stanza, lang_class, accounts): - """Create subscribe response""" - result = [] - result.append(Presence(from_jid=stanza.get_to(), - to_jid=stanza.get_from(), - stanza_type="unsubscribe")) - result.append(Presence(from_jid=stanza.get_to(), - to_jid=stanza.get_from(), - stanza_type="unsubscribed")) - return result - -class PasswordMessageHandler(Handler): - """Handle password message""" - - def __init__(self): - """handler constructor""" - self.password_regexp = re.compile("\[PASSWORD\]") - - def filter(self, stanza, lang_class): - """Return the uniq account associated with a name and user JID. - DB connection might already be opened.""" - name = stanza.get_to().node - bare_from_jid = unicode(stanza.get_from().bare()) - accounts = Account.select(\ - AND(Account.q.name == name, - Account.q.user_jid == bare_from_jid)) - if accounts.count() > 1: - print >>sys.stderr, "Account " + name + " for user " + \ - bare_from_jid + " must be uniq" - elif accounts.count() == 0: - return None - _account = accounts[0] - if hasattr(_account, 'password') \ - and hasattr(_account, 'waiting_password_reply') \ - and (getattr(_account, 'waiting_password_reply') == True) \ - and self.password_regexp.search(stanza.get_subject()) \ - is not None: - return accounts - else: - return None - - def handle(self, stanza, lang_class, accounts): - """Receive password in stanza (must be a Message) for given account""" - _account = accounts[0] - _account.password = stanza.get_body() - _account.waiting_password_reply = False - return [Message(from_jid=_account.jid, - to_jid=stanza.get_from(), - subject=lang_class.password_saved_for_session, - body=lang_class.password_saved_for_session)] diff --git a/src/jcl/jabber/feeder.py b/src/jcl/jabber/feeder.py index 4986151..7455543 100644 --- a/src/jcl/jabber/feeder.py +++ b/src/jcl/jabber/feeder.py @@ -36,10 +36,13 @@ from jcl.model.account import Account from pyxmpp.message import Message class FeederComponent(JCLComponent): - """Implement a feeder sender behavior based on the + """ + Implement a feeder sender behavior based on the regular interval behavior of JCLComponent feed data from given Feeder and send it to user - through the given Sender.""" + through the given Sender. + """ + def __init__(self, jid, secret, @@ -121,7 +124,8 @@ class HeadlineSender(MessageSender): body=body) class FeederHandler(Handler): - """Filter (nothing by default) and call sender for each message from + """ + Filter (nothing by default) and call sender for each message from Feeder. """ @@ -131,18 +135,20 @@ class FeederHandler(Handler): self.sender = sender def filter(self, stanza, lang_class): - """Filter account to be processed by the handler + """ + Filter account to be processed by the handler return all accounts. """ accounts = Account.select(clauseTables=["account"], orderBy="user_jid") return accounts - def handle(self, stanza, lang_class, accounts): - """Apply actions to do on given accounts + def handle(self, stanza, lang_class, data): + """ + Apply actions to do on given accounts Do nothing by default. """ - for _account in accounts: + for _account in data: for data in self.feeder.feed(_account): self.sender.send(_account, data) return [] diff --git a/src/jcl/jabber/message.py b/src/jcl/jabber/message.py new file mode 100644 index 0000000..5d60c4c --- /dev/null +++ b/src/jcl/jabber/message.py @@ -0,0 +1,72 @@ +## +## message.py +## Login : David Rousselie +## Started on Wed Jun 27 21:43:57 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## 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 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import re + +from pyxmpp.message import Message + +from jcl.jabber import Handler +from jcl.model.account import Account + +class PasswordMessageHandler(Handler): + """Handle password message""" + + def __init__(self): + """handler constructor""" + self.password_regexp = re.compile("\[PASSWORD\]") + + def filter(self, stanza, lang_class): + """ + Return the uniq account associated with a name and user JID. + DB connection might already be opened. + """ + name = stanza.get_to().node + bare_from_jid = unicode(stanza.get_from().bare()) + accounts = Account.select(\ + AND(Account.q.name == name, + Account.q.user_jid == bare_from_jid)) + if accounts.count() > 1: + print >>sys.stderr, "Account " + name + " for user " + \ + bare_from_jid + " must be uniq" + elif accounts.count() == 0: + return None + _account = accounts[0] + if hasattr(_account, 'password') \ + and hasattr(_account, 'waiting_password_reply') \ + and (getattr(_account, 'waiting_password_reply') == True) \ + and self.password_regexp.search(stanza.get_subject()) \ + is not None: + return accounts + else: + return None + + def handle(self, stanza, lang_class, data): + """ + Receive password in stanza (must be a Message) for given account. + """ + _account = data[0] + _account.password = stanza.get_body() + _account.waiting_password_reply = False + return [Message(from_jid=_account.jid, + to_jid=stanza.get_from(), + subject=lang_class.password_saved_for_session, + body=lang_class.password_saved_for_session)] diff --git a/src/jcl/jabber/presence.py b/src/jcl/jabber/presence.py new file mode 100644 index 0000000..c498485 --- /dev/null +++ b/src/jcl/jabber/presence.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +## +## component.py +## Login : David Rousselie +## Started on Wed Jun 27 21:42:47 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2006 David Rousselie +## 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 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +from pyxmpp.presence import Presence + +from jcl.jabber import Handler + +class DefaultPresenceHandler(Handler): + """Handle presence""" + + def handle(self, presence, lang_class, data): + """Return same presence as receive one""" + to_jid = presence.get_to() + from_jid = presence.get_from() + presence.set_to(from_jid) + presence.set_from(to_jid) + return [presence] + +class DefaultSubscribeHandler(Handler): + """Return default response to subscribe queries""" + + def handle(self, stanza, lang_class, data): + """Create subscribe response""" + result = [] + result.append(Presence(from_jid=stanza.get_to(), + to_jid=stanza.get_from(), + stanza_type="subscribe")) + result.append(Presence(from_jid=stanza.get_to(), + to_jid=stanza.get_from(), + stanza_type="subscribed")) + return result + +class DefaultUnsubscribeHandler(Handler): + """Return default response to subscribe queries""" + + def handle(self, stanza, lang_class, data): + """Create subscribe response""" + result = [] + result.append(Presence(from_jid=stanza.get_to(), + to_jid=stanza.get_from(), + stanza_type="unsubscribe")) + result.append(Presence(from_jid=stanza.get_to(), + to_jid=stanza.get_from(), + stanza_type="unsubscribed")) + return result + diff --git a/src/jcl/jabber/tests/component.py b/src/jcl/jabber/tests/component.py index bc50fb4..1872f84 100644 --- a/src/jcl/jabber/tests/component.py +++ b/src/jcl/jabber/tests/component.py @@ -41,8 +41,9 @@ from pyxmpp.presence import Presence from pyxmpp.message import Message from pyxmpp.jabber.dataforms import Form, Field, Option -from jcl.jabber.component import JCLComponent, Handler, \ - PasswordMessageHandler, DefaultSubscribeHandler, \ +from jcl.jabber.component import JCLComponent, Handler +from jcl.jabber.message import PasswordMessageHandler +from jcl.jabber.presence import DefaultSubscribeHandler, \ DefaultUnsubscribeHandler, DefaultPresenceHandler from jcl.model import account from jcl.model.account import Account, LegacyJID @@ -154,12 +155,12 @@ class HandlerMock(object): def __init__(self): self.handled = [] - def filter(self, message, lang_class): + def filter(self, stanza, lang_class): return [] - def handle(self, stanza, lang_class, accounts): - self.handled.append((stanza, lang_class, accounts)) - return [(stanza, lang_class, accounts)] + def handle(self, stanza, lang_class, data): + self.handled.append((stanza, lang_class, data)) + return [(stanza, lang_class, data)] class JCLComponent_TestCase(unittest.TestCase): ########################################################################### @@ -1688,24 +1689,25 @@ class JCLComponent_TestCase(unittest.TestCase): self.comp.stream_class = MockStream self.comp.available_handlers += [DefaultPresenceHandler()] account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) - account11 = Account(user_jid = "user1@test.com", \ - name = "account11", \ - jid = "account11@jcl.test.com") - account12 = Account(user_jid = "user1@test.com", \ - name = "account12", \ - jid = "account12@jcl.test.com") - account2 = Account(user_jid = "user2@test.com", \ - name = "account2", \ - jid = "account2@jcl.test.com") + account11 = Account(user_jid="user1@test.com", + name="account11", + jid="account11@jcl.test.com") + account12 = Account(user_jid="user1@test.com", + name="account12", + jid="account12@jcl.test.com") + account2 = Account(user_jid="user2@test.com", + name="account2", + jid="account2@jcl.test.com") del account.hub.threadConnection self.comp.handle_presence_available(Presence(\ - stanza_type = "available", \ - from_jid = "user1@test.com",\ - to_jid = "user1%test.com@jcl.test.com")) + stanza_type="available", + from_jid="user1@test.com", + to_jid="user1%test.com@jcl.test.com")) presence_sent = self.comp.stream.sent self.assertEqual(len(presence_sent), 1) self.assertEqual(presence_sent[0].get_to(), "user1@test.com") - self.assertEqual(presence_sent[0].get_from(), "user1%test.com@jcl.test.com") + self.assertEqual(presence_sent[0].get_from(), + "user1%test.com@jcl.test.com") self.assertTrue(isinstance(presence_sent[0], Presence)) self.assertEqual(presence_sent[0].get_type(), None)