Some refactoring
Put disco and presence handlers in configurable Handler classes darcs-hash:20070708140132-86b55-48a41b751c68fb60620fe883f38b7c3104fdf796.gz
This commit is contained in:
@@ -1,11 +1,16 @@
|
|||||||
"""Jabber related classes"""
|
"""Jabber related classes"""
|
||||||
__revision__ = ""
|
__revision__ = ""
|
||||||
|
|
||||||
|
import jcl.model.account as account
|
||||||
from jcl.model.account import Account
|
from jcl.model.account import Account
|
||||||
|
|
||||||
class Handler(object):
|
class Handler(object):
|
||||||
"""handling class"""
|
"""handling class"""
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
"""Default Handler constructor"""
|
||||||
|
self.component = component
|
||||||
|
|
||||||
def filter(self, stanza, lang_class):
|
def filter(self, stanza, lang_class):
|
||||||
"""
|
"""
|
||||||
Filter account to be processed by the handler
|
Filter account to be processed by the handler
|
||||||
@@ -21,13 +26,41 @@ class Handler(object):
|
|||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
class DiscoHandler(object):
|
def root_filter(self, stanza, lang_class, node=None):
|
||||||
"""Handle disco get items requests"""
|
"""Filter stanza sent to root node"""
|
||||||
|
to_jid = stanza.get_to()
|
||||||
def filter(self, node, info_query):
|
if to_jid.resource is None and to_jid.node is None and node is None:
|
||||||
"""Filter requests to be handled"""
|
return True
|
||||||
return False
|
else:
|
||||||
|
return None
|
||||||
def handle(self, node, info_query, lang_class, disco_items, data):
|
|
||||||
"""Handle disco get items request"""
|
def account_type_filter(self, stanza, lang_class, node=None):
|
||||||
|
"""Filter stanzas sent to account type node"""
|
||||||
|
to_jid = stanza.get_to()
|
||||||
|
account_type = to_jid.resource
|
||||||
|
if account_type is not None and to_jid.node is None:
|
||||||
|
return account_type
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def account_filter(self, stanza, lang_class, node=None):
|
||||||
|
"""Filter stanzas sent to account jid"""
|
||||||
|
name = stanza.get_to().node
|
||||||
|
return name
|
||||||
|
|
||||||
|
def get_account_filter(self, stanza, lang_class, node=None):
|
||||||
|
"""Filter stanzas sent to account jid, only if account exists"""
|
||||||
|
name = stanza.get_to().node
|
||||||
|
if name is not None:
|
||||||
|
return account.get_account(name,
|
||||||
|
stanza.get_from().bare())
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_accounts_root_filter(self, stanza, lang_class, node=None):
|
||||||
|
"""Filter stanza sent to root node"""
|
||||||
|
to_jid = stanza.get_to()
|
||||||
|
if to_jid.resource is None and to_jid.node is None and node is None:
|
||||||
|
return account.get_accounts(stanza.get_from().bare())
|
||||||
|
else:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ from pyxmpp.jabber.dataforms import Form, Field
|
|||||||
|
|
||||||
import jcl
|
import jcl
|
||||||
from jcl.lang import Lang
|
from jcl.lang import Lang
|
||||||
from jcl.jabber import DiscoHandler
|
from jcl.jabber.disco import DiscoHandler, RootDiscoGetInfoHandler
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model.account import Account
|
from jcl.model.account import Account
|
||||||
|
|
||||||
COMMAND_NS = "http://jabber.org/protocol/commands"
|
COMMAND_NS = "http://jabber.org/protocol/commands"
|
||||||
@@ -146,47 +147,60 @@ class JCLCommandManager(CommandManager):
|
|||||||
field_type="fixed",
|
field_type="fixed",
|
||||||
label="Account name")) # TODO: add to Lang
|
label="Account name")) # TODO: add to Lang
|
||||||
bare_from_jid = unicode(info_query.get_from().bare())
|
bare_from_jid = unicode(info_query.get_from().bare())
|
||||||
self.account_manager.db_connect()
|
model.db_connect()
|
||||||
accounts = Account.select(Account.q.user_jid == bare_from_jid)
|
accounts = Account.select(Account.q.user_jid == bare_from_jid)
|
||||||
for _account in accounts:
|
for _account in accounts:
|
||||||
fields = [Field(name="name",
|
fields = [Field(name="name",
|
||||||
field_type="fixed",
|
field_type="fixed",
|
||||||
value=_account.name)]
|
value=_account.name)]
|
||||||
result_form.add_item(fields)
|
result_form.add_item(fields)
|
||||||
self.account_manager.db_disconnect()
|
model.db_disconnect()
|
||||||
result_form.as_xml(command_node)
|
result_form.as_xml(command_node)
|
||||||
return [response]
|
return [response]
|
||||||
|
|
||||||
|
class CommandRootDiscoGetInfoHandler(RootDiscoGetInfoHandler):
|
||||||
|
|
||||||
|
def handle(self, info_query, lang_class, node, disco_obj, data):
|
||||||
|
"""Add command feature to DiscoInfo"""
|
||||||
|
disco_infos = RootDiscoGetInfoHandler.handle(self, info_query,
|
||||||
|
lang_class, node,
|
||||||
|
disco_obj, data)
|
||||||
|
disco_infos[0].add_feature(COMMAND_NS)
|
||||||
|
return disco_infos
|
||||||
|
|
||||||
class CommandDiscoGetInfoHandler(DiscoHandler):
|
class CommandDiscoGetInfoHandler(DiscoHandler):
|
||||||
"""Handle Ad-Hoc command disco get info requests"""
|
"""Handle Ad-Hoc command disco get info requests"""
|
||||||
|
|
||||||
def filter(self, node, info_query):
|
def filter(self, info_query, lang_class, node):
|
||||||
"""
|
"""
|
||||||
Filter requests to be handled. Only known commands
|
Filter requests to be handled. Only known commands
|
||||||
"""
|
"""
|
||||||
return (node in command_manager.commands)
|
return (node in command_manager.commands)
|
||||||
|
|
||||||
def handle(self, disco_info, node, info_query, data, lang_class):
|
def handle(self, info_query, lang_class, node, disco_obj, data):
|
||||||
"""
|
"""
|
||||||
Return infos for given command
|
Return infos for given command
|
||||||
"""
|
"""
|
||||||
if not disco_info:
|
if not disco_obj:
|
||||||
disco_info = DiscoInfo()
|
disco_obj = DiscoInfo()
|
||||||
return command_manager.get_command_info(disco_info, node, lang_class)
|
return [command_manager.get_command_info(disco_info=disco_obj,
|
||||||
|
command_name=node,
|
||||||
|
lang_class=lang_class)]
|
||||||
|
|
||||||
class CommandDiscoGetItemsHandler(DiscoHandler):
|
class CommandDiscoGetItemsHandler(DiscoHandler):
|
||||||
"""Handle Ad-Hoc command disco get items requests"""
|
"""Handle Ad-Hoc command disco get items requests"""
|
||||||
|
|
||||||
def filter(self, node, info_query):
|
def filter(self, info_query, lang_class, node):
|
||||||
"""
|
"""
|
||||||
Filter requests to be handled.
|
Filter requests to be handled.
|
||||||
"""
|
"""
|
||||||
return (node == 'http://jabber.org/protocol/commands')
|
return (node == 'http://jabber.org/protocol/commands')
|
||||||
|
|
||||||
def handle(self, disco_items, node, info_query, data, lang_class):
|
def handle(self, info_query, lang_class, node, disco_obj, data):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
if not disco_items:
|
if not disco_obj:
|
||||||
disco_items = DiscoItems()
|
disco_obj = DiscoItems()
|
||||||
return command_manager.list_commands(disco_items, lang_class)
|
return [command_manager.list_commands(disco_items=disco_obj,
|
||||||
|
lang_class=lang_class)]
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ from Queue import Queue
|
|||||||
|
|
||||||
from sqlobject.inheritance import InheritableSQLObject
|
from sqlobject.inheritance import InheritableSQLObject
|
||||||
from sqlobject.sqlbuilder import AND
|
from sqlobject.sqlbuilder import AND
|
||||||
from sqlobject.dbconnection import connectionForURI
|
|
||||||
|
|
||||||
import pyxmpp.error as error
|
import pyxmpp.error as error
|
||||||
from pyxmpp.jid import JID
|
from pyxmpp.jid import JID
|
||||||
@@ -53,10 +52,19 @@ from pyxmpp.jabber.dataforms import Form, Field, Option
|
|||||||
import jcl
|
import jcl
|
||||||
from jcl.error import FieldError
|
from jcl.error import FieldError
|
||||||
from jcl.jabber import Handler
|
from jcl.jabber import Handler
|
||||||
|
from jcl.jabber.disco import AccountDiscoGetInfoHandler, \
|
||||||
|
AccountTypeDiscoGetInfoHandler, RootDiscoGetItemsHandler, \
|
||||||
|
AccountTypeDiscoGetItemsHandler
|
||||||
from jcl.jabber.message import PasswordMessageHandler
|
from jcl.jabber.message import PasswordMessageHandler
|
||||||
import jcl.jabber.command as command
|
import jcl.jabber.command as command
|
||||||
from jcl.jabber.command import CommandDiscoGetItemsHandler, \
|
from jcl.jabber.command import CommandDiscoGetItemsHandler, \
|
||||||
CommandDiscoGetInfoHandler, CommandManager, JCLCommandManager
|
CommandDiscoGetInfoHandler, CommandManager, JCLCommandManager, \
|
||||||
|
CommandRootDiscoGetInfoHandler
|
||||||
|
from jcl.jabber.presence import AccountPresenceAvailableHandler, \
|
||||||
|
RootPresenceAvailableHandler, AccountPresenceUnavailableHandler, \
|
||||||
|
RootPresenceUnavailableHandler, AccountPresenceSubscribeHandler, \
|
||||||
|
RootPresenceSubscribeHandler, AccountPresenceUnsubscribeHandler
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model import account
|
from jcl.model import account
|
||||||
from jcl.model.account import Account, LegacyJID
|
from jcl.model.account import Account, LegacyJID
|
||||||
from jcl.lang import Lang
|
from jcl.lang import Lang
|
||||||
@@ -67,10 +75,12 @@ VERSION = "0.1"
|
|||||||
# JCL implementation
|
# JCL implementation
|
||||||
###############################################################################
|
###############################################################################
|
||||||
class JCLComponent(Component, object):
|
class JCLComponent(Component, object):
|
||||||
"""Implement default JCL component behavior:
|
"""
|
||||||
|
Implement default JCL component behavior:
|
||||||
- Jabber register process (add, delete, update accounts)
|
- Jabber register process (add, delete, update accounts)
|
||||||
- Jabber presence handling
|
- Jabber presence handling
|
||||||
- passwork request at login
|
- passwork request at login
|
||||||
|
- Service Administration (XEP-0133)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
timeout = 1
|
timeout = 1
|
||||||
@@ -80,7 +90,6 @@ class JCLComponent(Component, object):
|
|||||||
secret,
|
secret,
|
||||||
server,
|
server,
|
||||||
port,
|
port,
|
||||||
db_connection_str,
|
|
||||||
disco_category="headline",
|
disco_category="headline",
|
||||||
disco_type="x-unknown",
|
disco_type="x-unknown",
|
||||||
lang=Lang()):
|
lang=Lang()):
|
||||||
@@ -94,21 +103,28 @@ class JCLComponent(Component, object):
|
|||||||
# default values
|
# default values
|
||||||
self.name = lang.get_default_lang_class().component_name
|
self.name = lang.get_default_lang_class().component_name
|
||||||
self.spool_dir = "."
|
self.spool_dir = "."
|
||||||
self.db_connection_str = db_connection_str
|
|
||||||
self.version = VERSION
|
self.version = VERSION
|
||||||
self.time_unit = 60
|
self.time_unit = 60
|
||||||
self.queue = Queue(100)
|
self.queue = Queue(100)
|
||||||
self.account_manager = AccountManager(self)
|
self.account_manager = AccountManager(self)
|
||||||
self.msg_handlers = []
|
self.msg_handlers = []
|
||||||
self.subscribe_handlers = []
|
self.presence_subscribe_handlers = [[AccountPresenceSubscribeHandler(self),
|
||||||
self.unsubscribe_handlers = []
|
RootPresenceSubscribeHandler(self)]]
|
||||||
self.available_handlers = []
|
self.presence_unsubscribe_handlers = [[AccountPresenceUnsubscribeHandler(self)]]
|
||||||
self.unavailable_handlers = []
|
self.presence_available_handlers = [[AccountPresenceAvailableHandler(self),
|
||||||
|
RootPresenceAvailableHandler(self)]]
|
||||||
|
self.presence_unavailable_handlers = [[AccountPresenceUnavailableHandler(self),
|
||||||
|
RootPresenceUnavailableHandler(self)]]
|
||||||
command.command_manager = JCLCommandManager()
|
command.command_manager = JCLCommandManager()
|
||||||
command.command_manager.component = self
|
command.command_manager.component = self
|
||||||
command.command_manager.account_manager = self.account_manager
|
command.command_manager.account_manager = self.account_manager
|
||||||
self.disco_get_items_handlers = [CommandDiscoGetItemsHandler()]
|
self.disco_get_items_handlers = [[RootDiscoGetItemsHandler(self),
|
||||||
self.disco_get_info_handlers = [CommandDiscoGetInfoHandler()]
|
AccountTypeDiscoGetItemsHandler(self)],
|
||||||
|
[CommandDiscoGetItemsHandler(self)]]
|
||||||
|
self.disco_get_info_handlers = [[CommandRootDiscoGetInfoHandler(self),
|
||||||
|
AccountDiscoGetInfoHandler(self),
|
||||||
|
AccountTypeDiscoGetInfoHandler(self)],
|
||||||
|
[CommandDiscoGetInfoHandler(self)]]
|
||||||
|
|
||||||
self.__logger = logging.getLogger("jcl.jabber.JCLComponent")
|
self.__logger = logging.getLogger("jcl.jabber.JCLComponent")
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
@@ -119,7 +135,8 @@ class JCLComponent(Component, object):
|
|||||||
signal.signal(signal.SIGTERM, self.signal_handler)
|
signal.signal(signal.SIGTERM, self.signal_handler)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Main loop
|
"""
|
||||||
|
Main loop
|
||||||
Connect to Jabber server
|
Connect to Jabber server
|
||||||
Start timer thread
|
Start timer thread
|
||||||
Call Component main loop
|
Call Component main loop
|
||||||
@@ -149,27 +166,12 @@ class JCLComponent(Component, object):
|
|||||||
self.disconnect()
|
self.disconnect()
|
||||||
self.__logger.debug("Exitting normally")
|
self.__logger.debug("Exitting normally")
|
||||||
|
|
||||||
#################
|
|
||||||
# SQlite connections are not multi-threaded
|
|
||||||
# Utils workaround methods
|
|
||||||
#################
|
|
||||||
def db_connect(self):
|
|
||||||
"""Create a new connection to the DataBase (SQLObject use connection
|
|
||||||
pool) associated to the current thread"""
|
|
||||||
account.hub.threadConnection = \
|
|
||||||
connectionForURI(self.db_connection_str)
|
|
||||||
# account.hub.threadConnection.debug = True
|
|
||||||
|
|
||||||
def db_disconnect(self):
|
|
||||||
"""Delete connection associated to the current thread"""
|
|
||||||
del account.hub.threadConnection
|
|
||||||
|
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
# Handlers
|
# Handlers
|
||||||
###########################################################################
|
###########################################################################
|
||||||
def time_handler(self):
|
def time_handler(self):
|
||||||
"""Timer thread handler
|
"""
|
||||||
|
Timer thread handler
|
||||||
"""
|
"""
|
||||||
self.__logger.info("Timer thread started...")
|
self.__logger.info("Timer thread started...")
|
||||||
try:
|
try:
|
||||||
@@ -179,13 +181,17 @@ class JCLComponent(Component, object):
|
|||||||
self.wait_event.wait(self.time_unit)
|
self.wait_event.wait(self.time_unit)
|
||||||
self.handle_tick()
|
self.handle_tick()
|
||||||
self.__logger.debug("Resetting alarm signal")
|
self.__logger.debug("Resetting alarm signal")
|
||||||
##time.sleep(self.time_unit)
|
|
||||||
except Exception, exception:
|
except Exception, exception:
|
||||||
|
type, value, stack = sys.exc_info()
|
||||||
|
self.__logger.error("Error in timer thread\n%s\n%s"
|
||||||
|
% (exception, "".join(traceback.format_exception
|
||||||
|
(type, value, stack, 5))))
|
||||||
self.queue.put(exception)
|
self.queue.put(exception)
|
||||||
self.__logger.info("Timer thread terminated...")
|
self.__logger.info("Timer thread terminated...")
|
||||||
|
|
||||||
def authenticated(self):
|
def authenticated(self):
|
||||||
"""Override authenticated Component event handler
|
"""
|
||||||
|
Override authenticated Component event handler
|
||||||
Register event handlers
|
Register event handlers
|
||||||
Probe for every accounts registered
|
Probe for every accounts registered
|
||||||
"""
|
"""
|
||||||
@@ -227,7 +233,7 @@ class JCLComponent(Component, object):
|
|||||||
self.handle_message)
|
self.handle_message)
|
||||||
self.send_stanzas(self.account_manager.probe_all_accounts_presence())
|
self.send_stanzas(self.account_manager.probe_all_accounts_presence())
|
||||||
|
|
||||||
self.msg_handlers += [PasswordMessageHandler()]
|
self.msg_handlers += [[PasswordMessageHandler(self)]]
|
||||||
|
|
||||||
def signal_handler(self, signum, frame):
|
def signal_handler(self, signum, frame):
|
||||||
"""Stop method handler
|
"""Stop method handler
|
||||||
@@ -277,32 +283,45 @@ class JCLComponent(Component, object):
|
|||||||
self.send_stanzas(result)
|
self.send_stanzas(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def apply_registered_behavior(self, handlers, stanza, apply_all=True):
|
def apply_registered_behavior(self, handlers, stanza,
|
||||||
|
apply_filter_func=None,
|
||||||
|
apply_handle_func=None):
|
||||||
"""Execute handler if their filter method does not return None"""
|
"""Execute handler if their filter method does not return None"""
|
||||||
result = []
|
result = []
|
||||||
self.db_connect()
|
lang_class = self.lang.get_lang_class_from_node(stanza.get_node())
|
||||||
lang = self.lang.get_lang_class_from_node(stanza.get_node())
|
for handler_group in handlers:
|
||||||
for handler in handlers:
|
for handler in handler_group:
|
||||||
try:
|
try:
|
||||||
self.__logger.debug("Applying filter " + repr(handler))
|
self.__logger.debug("Applying filter " + repr(handler))
|
||||||
data = handler.filter(stanza, lang)
|
if apply_filter_func is not None:
|
||||||
if data:
|
data = apply_filter_func(handler.filter, stanza, lang_class)
|
||||||
self.__logger.debug("Applying handler " + repr(handler))
|
else:
|
||||||
result += handler.handle(stanza, lang, data)
|
data = handler.filter(stanza, lang_class)
|
||||||
if not apply_all:
|
if data is not None and data != False:
|
||||||
break
|
self.__logger.debug("Applying handler " + repr(handler))
|
||||||
except Exception, e:
|
if apply_handle_func is not None:
|
||||||
type, value, stack = sys.exc_info()
|
handler_result = apply_handle_func(handler.handle,
|
||||||
self.__logger.error("Error with handler " + str(handler) +
|
stanza,
|
||||||
" with " + str(stanza) + "\n%s\n%s"
|
lang_class,
|
||||||
% (e, "".join(traceback.format_exception
|
data,
|
||||||
(type, value, stack, 5))))
|
result)
|
||||||
result += [Message(from_jid=stanza.get_to(),
|
else:
|
||||||
to_jid=stanza.get_from(),
|
handler_result = handler.handle(stanza, lang_class,
|
||||||
stanza_type="error",
|
data)
|
||||||
subject=lang.error_subject,
|
if handler_result is not None:
|
||||||
body=lang.error_body % (e.message))]
|
result += handler_result
|
||||||
self.db_disconnect()
|
break
|
||||||
|
except Exception, e:
|
||||||
|
type, value, stack = sys.exc_info()
|
||||||
|
self.__logger.error("Error with handler " + str(handler) +
|
||||||
|
" with " + str(stanza) + "\n%s\n%s"
|
||||||
|
% (e, "".join(traceback.format_exception
|
||||||
|
(type, value, stack, 5))))
|
||||||
|
result += [Message(from_jid=stanza.get_to(),
|
||||||
|
to_jid=stanza.get_from(),
|
||||||
|
stanza_type="error",
|
||||||
|
subject=lang_class.error_subject,
|
||||||
|
body=lang_class.error_body % (e.message))]
|
||||||
self.send_stanzas(result)
|
self.send_stanzas(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -337,50 +356,29 @@ class JCLComponent(Component, object):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
def disco_get_info(self, node, info_query):
|
def disco_get_info(self, node, info_query):
|
||||||
"""Discovery get info handler
|
|
||||||
"""
|
"""
|
||||||
result = self.apply_behavior(\
|
Discovery get info handler
|
||||||
info_query,
|
"""
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
result = self.apply_registered_behavior(\
|
||||||
self.account_manager.account_disco_get_info(),
|
self.disco_get_info_handlers,
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
info_query,
|
||||||
self.account_manager.account_type_disco_get_info(),
|
lambda filter_func, stanza, lang_class: \
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
filter_func(stanza, lang_class, node),
|
||||||
self.account_manager.root_disco_get_info(\
|
lambda handle_func, stanza, lang_class, data, result: \
|
||||||
node,
|
handle_func(stanza, lang_class, node, result, data))
|
||||||
self.name,
|
|
||||||
self.disco_identity.category,
|
|
||||||
self.disco_identity.type))
|
|
||||||
if result is None:
|
|
||||||
lang_class = self.lang.get_lang_class_from_node(info_query.get_node())
|
|
||||||
for disco_filter in self.disco_get_info_handlers:
|
|
||||||
data = disco_filter.filter(node, info_query)
|
|
||||||
if data:
|
|
||||||
result = disco_filter.handle(result, node, info_query,
|
|
||||||
data, lang_class)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def disco_get_items(self, node, info_query):
|
def disco_get_items(self, node, info_query):
|
||||||
"""Discovery get nested nodes handler
|
|
||||||
"""
|
"""
|
||||||
result = self.apply_behavior(\
|
Discovery get nested nodes handler
|
||||||
|
"""
|
||||||
|
result = self.apply_registered_behavior(\
|
||||||
|
self.disco_get_items_handlers,
|
||||||
info_query,
|
info_query,
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
lambda filter_func, stanza, lang_class: \
|
||||||
None,
|
filter_func(stanza, lang_class, node),
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
lambda handle_func, stanza, lang_class, data, result: \
|
||||||
self.account_manager.account_type_disco_get_items(from_jid,
|
handle_func(stanza, lang_class, node, result, data))
|
||||||
account_type),
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.root_disco_get_items(node,
|
|
||||||
from_jid,
|
|
||||||
lang_class))
|
|
||||||
if result is None:
|
|
||||||
lang_class = self.lang.get_lang_class_from_node(info_query.get_node())
|
|
||||||
for disco_filter in self.disco_get_items_handlers:
|
|
||||||
data = disco_filter.filter(node, info_query)
|
|
||||||
if data:
|
|
||||||
result = disco_filter.handle(result, node, info_query,
|
|
||||||
data, lang_class)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def handle_get_version(self, info_query):
|
def handle_get_version(self, info_query):
|
||||||
@@ -474,22 +472,7 @@ class JCLComponent(Component, object):
|
|||||||
if presence sent to the component ('if not name'), presence is sent to
|
if presence sent to the component ('if not name'), presence is sent to
|
||||||
all accounts for current user. Otherwise, send presence from current account.
|
all accounts for current user. Otherwise, send presence from current account.
|
||||||
"""
|
"""
|
||||||
result = self.apply_registered_behavior(self.available_handlers, stanza)
|
result = self.apply_registered_behavior(self.presence_available_handlers, stanza)
|
||||||
if result == []:
|
|
||||||
result = self.apply_behavior(\
|
|
||||||
stanza,
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.account_handle_presence_available(name,
|
|
||||||
from_jid,
|
|
||||||
lang_class,
|
|
||||||
stanza.get_show()),
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
[],
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.root_handle_presence_available(from_jid,
|
|
||||||
lang_class,
|
|
||||||
stanza.get_show()),
|
|
||||||
send_result=True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@@ -497,38 +480,16 @@ class JCLComponent(Component, object):
|
|||||||
"""Handle presence unavailability
|
"""Handle presence unavailability
|
||||||
"""
|
"""
|
||||||
self.__logger.debug("PRESENCE_UNAVAILABLE")
|
self.__logger.debug("PRESENCE_UNAVAILABLE")
|
||||||
result = self.apply_registered_behavior(self.unavailable_handlers, stanza)
|
result = self.apply_registered_behavior(self.presence_unavailable_handlers,
|
||||||
if result == []:
|
stanza)
|
||||||
result = self.apply_behavior(\
|
|
||||||
stanza,
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.account_handle_presence_unavailable(name,
|
|
||||||
from_jid),
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
[],
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.root_handle_presence_unavailable(from_jid),
|
|
||||||
send_result=True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def handle_presence_subscribe(self, stanza):
|
def handle_presence_subscribe(self, stanza):
|
||||||
"""Handle subscribe presence from user
|
"""Handle subscribe presence from user
|
||||||
"""
|
"""
|
||||||
self.__logger.debug("PRESENCE_SUBSCRIBE")
|
self.__logger.debug("PRESENCE_SUBSCRIBE")
|
||||||
result = self.apply_registered_behavior(self.subscribe_handlers, stanza)
|
result = self.apply_registered_behavior(self.presence_subscribe_handlers,
|
||||||
if result == []:
|
stanza)
|
||||||
result = self.apply_behavior(\
|
|
||||||
stanza,
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.account_handle_presence_subscribe(name,
|
|
||||||
from_jid,
|
|
||||||
stanza),
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
[],
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.root_handle_presence_subscribe(from_jid,
|
|
||||||
stanza),
|
|
||||||
send_result=True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def handle_presence_subscribed(self, stanza):
|
def handle_presence_subscribed(self, stanza):
|
||||||
@@ -541,18 +502,8 @@ class JCLComponent(Component, object):
|
|||||||
"""Handle unsubscribe presence from user
|
"""Handle unsubscribe presence from user
|
||||||
"""
|
"""
|
||||||
self.__logger.debug("PRESENCE_UNSUBSCRIBE")
|
self.__logger.debug("PRESENCE_UNSUBSCRIBE")
|
||||||
result = self.apply_registered_behavior(self.unsubscribe_handlers, stanza)
|
result = self.apply_registered_behavior(self.presence_unsubscribe_handlers,
|
||||||
if result == []:
|
stanza)
|
||||||
result = self.apply_behavior(\
|
|
||||||
stanza,
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
self.account_manager.account_handle_presence_unsubscribe(name,
|
|
||||||
from_jid),
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
[],
|
|
||||||
lambda name, from_jid, account_type, lang_class: \
|
|
||||||
[],
|
|
||||||
send_result=True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def handle_presence_unsubscribed(self, stanza):
|
def handle_presence_unsubscribed(self, stanza):
|
||||||
@@ -570,7 +521,7 @@ class JCLComponent(Component, object):
|
|||||||
Handle password response message
|
Handle password response message
|
||||||
"""
|
"""
|
||||||
self.__logger.debug("MESSAGE: " + message.get_body())
|
self.__logger.debug("MESSAGE: " + message.get_body())
|
||||||
self.apply_registered_behavior(self.msg_handlers, message, False)
|
self.apply_registered_behavior(self.msg_handlers, message)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def handle_command(self, info_query):
|
def handle_command(self, info_query):
|
||||||
@@ -593,7 +544,7 @@ class JCLComponent(Component, object):
|
|||||||
###########################################################################
|
###########################################################################
|
||||||
# Utils
|
# Utils
|
||||||
###########################################################################
|
###########################################################################
|
||||||
def send_error_to_account(self, _account, exception):
|
def send_error(self, _account, exception):
|
||||||
""" """
|
""" """
|
||||||
self.send_stanzas(self.account_manager.send_error_from_account(_account, exception))
|
self.send_stanzas(self.account_manager.send_error_from_account(_account, exception))
|
||||||
type, value, stack = sys.exc_info()
|
type, value, stack = sys.exc_info()
|
||||||
@@ -643,72 +594,6 @@ class AccountManager(object):
|
|||||||
|
|
||||||
account_classes = property(_get_account_classes, _set_account_classes)
|
account_classes = property(_get_account_classes, _set_account_classes)
|
||||||
|
|
||||||
###### disco_get_info handlers ######
|
|
||||||
def account_disco_get_info(self):
|
|
||||||
"""Implement discovery get_info on an account node"""
|
|
||||||
self.__logger.debug("account_disco_get_info")
|
|
||||||
disco_info = DiscoInfo()
|
|
||||||
disco_info.add_feature("jabber:iq:register")
|
|
||||||
return disco_info
|
|
||||||
|
|
||||||
def account_type_disco_get_info(self):
|
|
||||||
"""Implement discovery get_info on an account type node"""
|
|
||||||
self.__logger.debug("account_type_disco_get_info")
|
|
||||||
return self.account_disco_get_info()
|
|
||||||
|
|
||||||
def root_disco_get_info(self, node, name, category, type):
|
|
||||||
"""Implement discovery get_info on main component JID"""
|
|
||||||
self.__logger.debug("root_disco_get_info")
|
|
||||||
if not node:
|
|
||||||
disco_info = DiscoInfo()
|
|
||||||
disco_info.add_feature("jabber:iq:version")
|
|
||||||
disco_info.add_feature(command.COMMAND_NS)
|
|
||||||
if not self.has_multiple_account_type:
|
|
||||||
disco_info.add_feature("jabber:iq:register")
|
|
||||||
DiscoIdentity(disco_info, name,
|
|
||||||
category,
|
|
||||||
type)
|
|
||||||
return disco_info
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
###### disco_get_items handlers ######
|
|
||||||
def account_type_disco_get_items(self, from_jid, account_type):
|
|
||||||
"""Discovery get_items on an account type node"""
|
|
||||||
self.__logger.debug("Listing account for " + account_type)
|
|
||||||
account_class = self._get_account_class(account_type + "Account")
|
|
||||||
if account_class is not None:
|
|
||||||
return self._list_accounts(account_class,
|
|
||||||
from_jid.bare(),
|
|
||||||
account_type=account_type)
|
|
||||||
else:
|
|
||||||
self.__logger.error("Error: " + account_class.__name__
|
|
||||||
+ " class not in account_classes")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def root_disco_get_items(self, node, from_jid, lang_class):
|
|
||||||
"""Discovery get_items on root node"""
|
|
||||||
if node is not None:
|
|
||||||
return None
|
|
||||||
disco_items = None
|
|
||||||
if self.has_multiple_account_type: # list accounts with only one type declared
|
|
||||||
disco_items = DiscoItems()
|
|
||||||
for account_type in self.account_types:
|
|
||||||
type_label_attr = "type_" + account_type.lower() + "_name"
|
|
||||||
if hasattr(lang_class, type_label_attr):
|
|
||||||
type_label = getattr(lang_class, type_label_attr)
|
|
||||||
else:
|
|
||||||
type_label = account_type
|
|
||||||
DiscoItem(disco_items,
|
|
||||||
JID(unicode(self.component.jid) + "/" +
|
|
||||||
account_type),
|
|
||||||
account_type,
|
|
||||||
type_label)
|
|
||||||
else:
|
|
||||||
disco_items = self._list_accounts(self.account_classes[0],
|
|
||||||
from_jid.bare())
|
|
||||||
return disco_items
|
|
||||||
|
|
||||||
###### get_register handlers ######
|
###### get_register handlers ######
|
||||||
def account_get_register(self, info_query,
|
def account_get_register(self, info_query,
|
||||||
name,
|
name,
|
||||||
@@ -718,19 +603,19 @@ class AccountManager(object):
|
|||||||
"""Handle get_register on an account.
|
"""Handle get_register on an account.
|
||||||
Return a preinitialized form"""
|
Return a preinitialized form"""
|
||||||
info_query = info_query.make_result_response()
|
info_query = info_query.make_result_response()
|
||||||
account_class = self._get_account_class(account_type + "Account")
|
account_class = self.get_account_class(account_type + "Account")
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
accounts = account_class.select(\
|
accounts = account_class.select(\
|
||||||
AND(account_class.q.name == name,
|
AND(account_class.q.name == name,
|
||||||
account_class.q.user_jid == unicode(from_jid.bare())))
|
account_class.q.user_jid == unicode(from_jid.bare())))
|
||||||
if accounts is not None:
|
if accounts is not None:
|
||||||
query = info_query.new_query("jabber:iq:register")
|
query = info_query.new_query("jabber:iq:register")
|
||||||
_account = accounts[0]
|
_account = accounts[0]
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
self.get_reg_form_init(lang_class,
|
self.get_reg_form_init(lang_class,
|
||||||
_account).as_xml(query)
|
_account).as_xml(query)
|
||||||
else:
|
else:
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return [info_query]
|
return [info_query]
|
||||||
|
|
||||||
def _account_type_get_register(self, info_query, account_class, lang_class):
|
def _account_type_get_register(self, info_query, account_class, lang_class):
|
||||||
@@ -748,7 +633,7 @@ class AccountManager(object):
|
|||||||
"""Handle get_register on an account_type node"""
|
"""Handle get_register on an account_type node"""
|
||||||
return self._account_type_get_register(\
|
return self._account_type_get_register(\
|
||||||
info_query,
|
info_query,
|
||||||
self._get_account_class(account_type + "Account"),
|
self.get_account_class(account_type + "Account"),
|
||||||
lang_class)
|
lang_class)
|
||||||
|
|
||||||
def root_get_register(self, info_query, lang_class):
|
def root_get_register(self, info_query, lang_class):
|
||||||
@@ -762,7 +647,7 @@ class AccountManager(object):
|
|||||||
def remove_all_accounts(self, user_jid):
|
def remove_all_accounts(self, user_jid):
|
||||||
"""Unsubscribe all accounts associated to 'user_jid' then delete
|
"""Unsubscribe all accounts associated to 'user_jid' then delete
|
||||||
those accounts from the DataBase"""
|
those accounts from the DataBase"""
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
result = []
|
result = []
|
||||||
for _account in Account.select(Account.q.user_jid == unicode(user_jid)):
|
for _account in Account.select(Account.q.user_jid == unicode(user_jid)):
|
||||||
self.__logger.debug("Deleting " + _account.name
|
self.__logger.debug("Deleting " + _account.name
|
||||||
@@ -781,7 +666,7 @@ class AccountManager(object):
|
|||||||
result.append(Presence(from_jid=self.component.jid,
|
result.append(Presence(from_jid=self.component.jid,
|
||||||
to_jid=user_jid,
|
to_jid=user_jid,
|
||||||
stanza_type="unsubscribed"))
|
stanza_type="unsubscribed"))
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _populate_account(self, _account, lang_class, x_data,
|
def _populate_account(self, _account, lang_class, x_data,
|
||||||
@@ -791,7 +676,7 @@ class AccountManager(object):
|
|||||||
result = []
|
result = []
|
||||||
from_jid = info_query.get_from()
|
from_jid = info_query.get_from()
|
||||||
bare_from_jid = unicode(from_jid.bare())
|
bare_from_jid = unicode(from_jid.bare())
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
try:
|
try:
|
||||||
for (field, field_type, field_options, field_post_func,
|
for (field, field_type, field_options, field_post_func,
|
||||||
field_default_func) in _account.get_register_fields():
|
field_default_func) in _account.get_register_fields():
|
||||||
@@ -816,7 +701,7 @@ class AccountManager(object):
|
|||||||
lang_class.mandatory_field % (field))
|
lang_class.mandatory_field % (field))
|
||||||
text.setNs(text.newNs(error.STANZA_ERROR_NS, None))
|
text.setNs(text.newNs(error.STANZA_ERROR_NS, None))
|
||||||
result.append(iq_error)
|
result.append(iq_error)
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return result
|
return result
|
||||||
result.append(info_query.make_result_response())
|
result.append(info_query.make_result_response())
|
||||||
|
|
||||||
@@ -840,7 +725,7 @@ class AccountManager(object):
|
|||||||
to_jid=_account.user_jid,
|
to_jid=_account.user_jid,
|
||||||
subject=_account.get_update_message_subject(lang_class),
|
subject=_account.get_update_message_subject(lang_class),
|
||||||
body=_account.get_update_message_body(lang_class)))
|
body=_account.get_update_message_body(lang_class)))
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def account_set_register(self, name, from_jid, lang_class,
|
def account_set_register(self, name, from_jid, lang_class,
|
||||||
@@ -848,13 +733,13 @@ class AccountManager(object):
|
|||||||
"""Update account"""
|
"""Update account"""
|
||||||
self.__logger.debug("Updating account " + name)
|
self.__logger.debug("Updating account " + name)
|
||||||
bare_from_jid = from_jid.bare()
|
bare_from_jid = from_jid.bare()
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
accounts = Account.select(\
|
accounts = Account.select(\
|
||||||
AND(Account.q.name == name,
|
AND(Account.q.name == name,
|
||||||
Account.q.user_jid == unicode(bare_from_jid)))
|
Account.q.user_jid == unicode(bare_from_jid)))
|
||||||
accounts_count = accounts.count()
|
accounts_count = accounts.count()
|
||||||
_account = list(accounts)[0]
|
_account = list(accounts)[0]
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
if accounts_count > 1:
|
if accounts_count > 1:
|
||||||
# Just print a warning, only the first account will be use
|
# Just print a warning, only the first account will be use
|
||||||
self.__logger.error("There might not exist 2 accounts for " +
|
self.__logger.error("There might not exist 2 accounts for " +
|
||||||
@@ -874,7 +759,7 @@ class AccountManager(object):
|
|||||||
x_data,
|
x_data,
|
||||||
info_query):
|
info_query):
|
||||||
"""Create new account from account_class"""
|
"""Create new account from account_class"""
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
bare_from_jid = from_jid.bare()
|
bare_from_jid = from_jid.bare()
|
||||||
_account = account_class(user_jid=unicode(bare_from_jid),
|
_account = account_class(user_jid=unicode(bare_from_jid),
|
||||||
name=name,
|
name=name,
|
||||||
@@ -882,7 +767,7 @@ class AccountManager(object):
|
|||||||
all_accounts = Account.select(\
|
all_accounts = Account.select(\
|
||||||
Account.q.user_jid == unicode(bare_from_jid))
|
Account.q.user_jid == unicode(bare_from_jid))
|
||||||
first_account = (all_accounts.count() > 0)
|
first_account = (all_accounts.count() > 0)
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return self._populate_account(_account, lang_class, x_data,
|
return self._populate_account(_account, lang_class, x_data,
|
||||||
info_query, True, first_account)
|
info_query, True, first_account)
|
||||||
|
|
||||||
@@ -895,7 +780,7 @@ class AccountManager(object):
|
|||||||
"""Create new typed account"""
|
"""Create new typed account"""
|
||||||
return self._account_type_set_register(\
|
return self._account_type_set_register(\
|
||||||
name, from_jid,
|
name, from_jid,
|
||||||
self._get_account_class(account_type + "Account"), lang_class,
|
self.get_account_class(account_type + "Account"), lang_class,
|
||||||
x_data, info_query)
|
x_data, info_query)
|
||||||
|
|
||||||
def root_set_register(self, name, from_jid, lang_class,
|
def root_set_register(self, name, from_jid, lang_class,
|
||||||
@@ -911,39 +796,12 @@ class AccountManager(object):
|
|||||||
|
|
||||||
|
|
||||||
###### presence generic handlers ######
|
###### presence generic handlers ######
|
||||||
def account_handle_presence(self, name, from_jid, presence_func):
|
|
||||||
"""Handle presence sent to an account JID"""
|
|
||||||
result = []
|
|
||||||
self.db_connect()
|
|
||||||
accounts = Account.select(\
|
|
||||||
AND(Account.q.name == name,
|
|
||||||
Account.q.user_jid == unicode(from_jid.bare())))
|
|
||||||
if accounts.count() > 0:
|
|
||||||
result.extend(presence_func(accounts[0]))
|
|
||||||
self.db_disconnect()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def root_handle_presence(self, from_jid, presence_func, root_presence_func):
|
|
||||||
"""handle presence sent to component JID"""
|
|
||||||
result = []
|
|
||||||
self.db_connect()
|
|
||||||
accounts = Account.select(\
|
|
||||||
Account.q.user_jid == unicode(from_jid.bare()))
|
|
||||||
accounts_length = 0
|
|
||||||
for _account in accounts:
|
|
||||||
accounts_length += 1
|
|
||||||
result.extend(presence_func(_account))
|
|
||||||
self.db_disconnect()
|
|
||||||
if (accounts_length > 0):
|
|
||||||
result.extend(root_presence_func(accounts_length))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def send_presence_all(self, presence):
|
def send_presence_all(self, presence):
|
||||||
"""Send presence to all account. Optimized to use only one sql
|
"""Send presence to all account. Optimized to use only one sql
|
||||||
request"""
|
request"""
|
||||||
current_user_jid = None
|
current_user_jid = None
|
||||||
result = []
|
result = []
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
# Explicit reference to account table (clauseTables) to use
|
# Explicit reference to account table (clauseTables) to use
|
||||||
# "user_jid" column with Account subclasses
|
# "user_jid" column with Account subclasses
|
||||||
for _account in \
|
for _account in \
|
||||||
@@ -951,146 +809,50 @@ class AccountManager(object):
|
|||||||
orderBy="user_jid"):
|
orderBy="user_jid"):
|
||||||
if current_user_jid != _account.user_jid:
|
if current_user_jid != _account.user_jid:
|
||||||
current_user_jid = _account.user_jid
|
current_user_jid = _account.user_jid
|
||||||
result.extend(self._send_presence(self.component.jid,
|
result.extend(self.send_presence(self.component.jid,
|
||||||
_account.user_jid,
|
_account.user_jid,
|
||||||
presence))
|
presence))
|
||||||
result.extend(getattr(self, "_send_presence_" +
|
result.extend(getattr(self, "send_presence_" +
|
||||||
presence)(_account))
|
presence)(_account))
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
###### presence_available handlers ######
|
|
||||||
def account_handle_presence_available(self, name, from_jid, lang_class, show):
|
|
||||||
"""Handle presence \"available\" sent to an account JID"""
|
|
||||||
self.__logger.debug("Account handle presence available")
|
|
||||||
return self.account_handle_presence(\
|
|
||||||
name, from_jid,
|
|
||||||
lambda _account: \
|
|
||||||
self._send_presence_available(_account,
|
|
||||||
show,
|
|
||||||
lang_class))
|
|
||||||
|
|
||||||
def root_handle_presence_available(self, from_jid, lang_class, show):
|
|
||||||
"""Handle presence \"available\" sent to component JID"""
|
|
||||||
self.__logger.debug("Root handle presence available")
|
|
||||||
return self.root_handle_presence(\
|
|
||||||
from_jid,
|
|
||||||
lambda _account: \
|
|
||||||
self._send_presence_available(_account,
|
|
||||||
show,
|
|
||||||
lang_class),
|
|
||||||
lambda nb_accounts: \
|
|
||||||
self._send_root_presence(from_jid, "available", show,
|
|
||||||
str(nb_accounts) +
|
|
||||||
lang_class.message_status))
|
|
||||||
|
|
||||||
###### presence_unavailable handlers ######
|
|
||||||
def account_handle_presence_unavailable(self, name, from_jid):
|
|
||||||
"""Handle presence \"unavailable\" sent to an account JID"""
|
|
||||||
self.__logger.debug("Account handle presence available")
|
|
||||||
return self.account_handle_presence(\
|
|
||||||
name, from_jid,
|
|
||||||
lambda _account: \
|
|
||||||
self._send_presence_unavailable(_account))
|
|
||||||
|
|
||||||
def root_handle_presence_unavailable(self, from_jid):
|
|
||||||
"""Handle presence \"unavailable\" sent to component JID"""
|
|
||||||
self.__logger.debug("Root handle presence available")
|
|
||||||
return self.root_handle_presence(\
|
|
||||||
from_jid,
|
|
||||||
lambda _account: \
|
|
||||||
self._send_presence_unavailable(_account),
|
|
||||||
lambda nb_accounts: \
|
|
||||||
self._send_root_presence(from_jid, "unavailable"))
|
|
||||||
|
|
||||||
###### presence_subscribe handlers ######
|
|
||||||
def account_handle_presence_subscribe(self, name, from_jid, stanza):
|
|
||||||
"""Handle \"subscribe\" iq sent to an account JID"""
|
|
||||||
if self._has_account(from_jid, name):
|
|
||||||
return [stanza.make_accept_response()]
|
|
||||||
else:
|
|
||||||
self.__logger.debug("Account '" + str(name) + "' for user '" +
|
|
||||||
unicode(from_jid.bare()) + "' was not found. " +
|
|
||||||
"Refusing subscription")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def root_handle_presence_subscribe(self, from_jid, stanza):
|
|
||||||
"""Handle \"subscribe\" iq sent to component JID"""
|
|
||||||
if self._has_account(from_jid):
|
|
||||||
return [stanza.make_accept_response()]
|
|
||||||
else:
|
|
||||||
self.__logger.debug("User '" +
|
|
||||||
unicode(from_jid.bare()) +
|
|
||||||
"' doesn't have any account. " +
|
|
||||||
"Refusing subscription")
|
|
||||||
return []
|
|
||||||
|
|
||||||
###### presence_unsubscribe handler (only apply to account) ######
|
|
||||||
def account_handle_presence_unsubscribe(self, name, from_jid):
|
|
||||||
"""Handle \"unsubscribe\" iq sent to account JID"""
|
|
||||||
result = []
|
|
||||||
self.db_connect()
|
|
||||||
accounts = Account.select(\
|
|
||||||
AND(Account.q.name == name,
|
|
||||||
Account.q.user_jid == unicode(from_jid.bare())))
|
|
||||||
for _account in accounts:
|
|
||||||
result.append(Presence(from_jid=_account.jid,
|
|
||||||
to_jid=from_jid,
|
|
||||||
stanza_type="unsubscribe"))
|
|
||||||
result.append(Presence(from_jid=_account.jid,
|
|
||||||
to_jid=from_jid,
|
|
||||||
stanza_type="unsubscribed"))
|
|
||||||
_account.destroySelf()
|
|
||||||
self.db_disconnect()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def probe_all_accounts_presence(self):
|
def probe_all_accounts_presence(self):
|
||||||
"""Send presence probe to all registered accounts"""
|
"""Send presence probe to all registered accounts"""
|
||||||
return self.send_presence_all("probe")
|
return self.send_presence_all("probe")
|
||||||
|
|
||||||
###### Utils methods ######
|
###### Utils methods ######
|
||||||
def _has_account(self, from_jid, name=None):
|
def list_accounts(self, bare_from_jid, account_class=None,
|
||||||
"""Check if user with \"from_jid\" JID has an account.
|
account_type=""):
|
||||||
Check if an account named \"name\" exist if \"name\" given."""
|
|
||||||
self.db_connect()
|
|
||||||
if name is None:
|
|
||||||
accounts = Account.select(\
|
|
||||||
Account.q.user_jid == unicode(from_jid.bare()))
|
|
||||||
else:
|
|
||||||
accounts = Account.select(\
|
|
||||||
AND(Account.q.name == name,
|
|
||||||
Account.q.user_jid == unicode(from_jid.bare())))
|
|
||||||
result = (accounts is not None \
|
|
||||||
and accounts.count() > 0)
|
|
||||||
self.db_disconnect()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _list_accounts(self, _account_class, bare_from_jid,
|
|
||||||
account_type=""):
|
|
||||||
"""List accounts in disco_items for given _account_class and user jid"""
|
"""List accounts in disco_items for given _account_class and user jid"""
|
||||||
|
if account_class is None:
|
||||||
|
account_class = self.account_classes[0]
|
||||||
if account_type is not None and account_type != "":
|
if account_type is not None and account_type != "":
|
||||||
resource = "/" + account_type
|
resource = "/" + account_type
|
||||||
account_type = account_type + "/"
|
account_type = account_type + "/"
|
||||||
else:
|
else:
|
||||||
resource = ""
|
resource = ""
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
accounts = _account_class.select(_account_class.q.user_jid == \
|
accounts = account_class.select(account_class.q.user_jid == \
|
||||||
unicode(bare_from_jid))
|
unicode(bare_from_jid))
|
||||||
if accounts.count() == 0:
|
if accounts.count() == 0:
|
||||||
return None
|
return
|
||||||
disco_items = DiscoItems()
|
|
||||||
for _account in accounts:
|
for _account in accounts:
|
||||||
self.__logger.debug(str(_account))
|
yield (_account, resource, account_type)
|
||||||
DiscoItem(disco_items,
|
model.db_disconnect()
|
||||||
JID(unicode(_account.jid) + resource),
|
|
||||||
account_type + _account.name,
|
|
||||||
_account.long_name)
|
|
||||||
self.db_disconnect()
|
|
||||||
return disco_items
|
|
||||||
|
|
||||||
def _get_account_class(self, account_class_name):
|
def list_account_types(self, lang_class):
|
||||||
|
"""List account supported types"""
|
||||||
|
for account_type in self.account_types:
|
||||||
|
type_label_attr = "type_" + account_type.lower() + "_name"
|
||||||
|
if hasattr(lang_class, type_label_attr):
|
||||||
|
type_label = getattr(lang_class, type_label_attr)
|
||||||
|
else:
|
||||||
|
type_label = account_type
|
||||||
|
yield (account_type, type_label)
|
||||||
|
|
||||||
|
def get_account_class(self, account_class_name):
|
||||||
"""Return account class definition from declared classes in
|
"""Return account class definition from declared classes in
|
||||||
account_classes from its class name"""
|
account_classes from its class name"""
|
||||||
self.__logger.debug("Looking for " + account_class_name)
|
self.__logger.debug("Looking for " + account_class_name)
|
||||||
@@ -1101,19 +863,9 @@ class AccountManager(object):
|
|||||||
self.__logger.debug(account_class_name + " not found")
|
self.__logger.debug(account_class_name + " not found")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def db_connect(self):
|
|
||||||
"""Create a new connection to the DataBase (SQLObject use connection
|
|
||||||
pool) associated to the current thread"""
|
|
||||||
account.hub.threadConnection = \
|
|
||||||
connectionForURI(self.component.db_connection_str) # TODO : move db_connection_str to AccountManager
|
|
||||||
# account.hub.threadConnection.debug = True
|
|
||||||
|
|
||||||
def db_disconnect(self):
|
|
||||||
"""Delete connection associated to the current thread"""
|
|
||||||
del account.hub.threadConnection
|
|
||||||
|
|
||||||
def get_reg_form(self, lang_class, _account_class, bare_from_jid):
|
def get_reg_form(self, lang_class, _account_class, bare_from_jid):
|
||||||
"""Return register form based on language and account class
|
"""
|
||||||
|
Return register form based on language and account class
|
||||||
"""
|
"""
|
||||||
reg_form = Form(title=lang_class.register_title,
|
reg_form = Form(title=lang_class.register_title,
|
||||||
instructions=lang_class.register_instructions)
|
instructions=lang_class.register_instructions)
|
||||||
@@ -1123,7 +875,7 @@ class AccountManager(object):
|
|||||||
name="name",
|
name="name",
|
||||||
required=True)
|
required=True)
|
||||||
|
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
for (field_name,
|
for (field_name,
|
||||||
field_type,
|
field_type,
|
||||||
field_options,
|
field_options,
|
||||||
@@ -1158,11 +910,12 @@ class AccountManager(object):
|
|||||||
except:
|
except:
|
||||||
self.__logger.debug("Setting field " + field_name + " required")
|
self.__logger.debug("Setting field " + field_name + " required")
|
||||||
field.required = True
|
field.required = True
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
return reg_form
|
return reg_form
|
||||||
|
|
||||||
def get_reg_form_init(self, lang_class, _account):
|
def get_reg_form_init(self, lang_class, _account):
|
||||||
"""Return register form for an existing account (update)
|
"""
|
||||||
|
Return register form for an existing account (update)
|
||||||
"""
|
"""
|
||||||
reg_form = self.get_reg_form(lang_class, _account.__class__,
|
reg_form = self.get_reg_form(lang_class, _account.__class__,
|
||||||
_account.user_jid)
|
_account.user_jid)
|
||||||
@@ -1177,31 +930,34 @@ class AccountManager(object):
|
|||||||
"""Compose account jid from account name"""
|
"""Compose account jid from account name"""
|
||||||
return name + u"@" + unicode(self.component.jid)
|
return name + u"@" + unicode(self.component.jid)
|
||||||
|
|
||||||
def _send_presence_probe(self, _account):
|
def send_presence_probe(self, _account):
|
||||||
"""Send presence probe to account's user"""
|
"""Send presence probe to account's user"""
|
||||||
return [Presence(from_jid=_account.jid,
|
return [Presence(from_jid=_account.jid,
|
||||||
to_jid=_account.user_jid,
|
to_jid=_account.user_jid,
|
||||||
stanza_type="probe")]
|
stanza_type="probe")]
|
||||||
|
|
||||||
def _send_presence_unavailable(self, _account):
|
def send_presence_unavailable(self, _account):
|
||||||
"""Send unavailable presence to account's user"""
|
"""Send unavailable presence to account's user"""
|
||||||
|
model.db_connect()
|
||||||
_account.status = account.OFFLINE
|
_account.status = account.OFFLINE
|
||||||
return [Presence(from_jid=_account.jid,
|
result = [Presence(from_jid=_account.jid,
|
||||||
to_jid=_account.user_jid,
|
to_jid=_account.user_jid,
|
||||||
stanza_type="unavailable")]
|
stanza_type="unavailable")]
|
||||||
|
model.db_disconnect()
|
||||||
def _send_root_presence(self, to_jid, presence_type,
|
|
||||||
show=None, status=None):
|
|
||||||
result = self._send_presence(self.component.jid, to_jid,
|
|
||||||
presence_type, show=show,
|
|
||||||
status=status)
|
|
||||||
result.extend(self._send_root_presence_legacy(to_jid,
|
|
||||||
presence_type,
|
|
||||||
show=show,
|
|
||||||
status=status))
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _send_presence(self, from_jid, to_jid, presence_type, status=None, show=None):
|
def send_root_presence(self, to_jid, presence_type,
|
||||||
|
show=None, status=None):
|
||||||
|
result = self.send_presence(self.component.jid, to_jid,
|
||||||
|
presence_type, show=show,
|
||||||
|
status=status)
|
||||||
|
result.extend(self.send_root_presence_legacy(to_jid,
|
||||||
|
presence_type,
|
||||||
|
show=show,
|
||||||
|
status=status))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def send_presence(self, from_jid, to_jid, presence_type, status=None, show=None):
|
||||||
"""Send presence stanza"""
|
"""Send presence stanza"""
|
||||||
return [Presence(from_jid=from_jid,
|
return [Presence(from_jid=from_jid,
|
||||||
to_jid=to_jid,
|
to_jid=to_jid,
|
||||||
@@ -1209,10 +965,11 @@ class AccountManager(object):
|
|||||||
show=show,
|
show=show,
|
||||||
stanza_type=presence_type)]
|
stanza_type=presence_type)]
|
||||||
|
|
||||||
def _send_presence_available(self, _account, show, lang_class):
|
def send_presence_available(self, _account, show, lang_class):
|
||||||
"""Send available presence to account's user and ask for password
|
"""Send available presence to account's user and ask for password
|
||||||
if necessary"""
|
if necessary"""
|
||||||
result = []
|
result = []
|
||||||
|
model.db_connect()
|
||||||
_account.default_lang_class = lang_class
|
_account.default_lang_class = lang_class
|
||||||
old_status = _account.status
|
old_status = _account.status
|
||||||
if show is None:
|
if show is None:
|
||||||
@@ -1225,28 +982,24 @@ class AccountManager(object):
|
|||||||
show=show,
|
show=show,
|
||||||
stanza_type="available"))
|
stanza_type="available"))
|
||||||
if hasattr(_account, 'store_password') \
|
if hasattr(_account, 'store_password') \
|
||||||
and hasattr(_account, 'password') \
|
and hasattr(_account, 'password') \
|
||||||
and _account.store_password == False \
|
and _account.store_password == False \
|
||||||
and old_status == account.OFFLINE \
|
and old_status == account.OFFLINE \
|
||||||
and _account.password == None :
|
and _account.password == None :
|
||||||
result.extend(self.ask_password(_account, lang_class))
|
result.extend(self.ask_password(_account, lang_class))
|
||||||
|
model.db_disconnect()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _send_root_presence_legacy(self, to_jid, presence_type,
|
def send_root_presence_legacy(self, to_jid, presence_type,
|
||||||
status=None, show=None):
|
status=None, show=None):
|
||||||
"""Send presence from legacy JID"""
|
"""Send presence from legacy JID"""
|
||||||
result = []
|
result = []
|
||||||
self.db_connect()
|
for legacy_jid in account.get_legacy_jids(unicode(to_jid.bare())):
|
||||||
legacy_jids = LegacyJID.select(\
|
|
||||||
AND(LegacyJID.q.accountID == Account.q.id,
|
|
||||||
Account.q.user_jid == unicode(to_jid.bare())))
|
|
||||||
for legacy_jid in legacy_jids:
|
|
||||||
result.append(Presence(from_jid=legacy_jid.jid,
|
result.append(Presence(from_jid=legacy_jid.jid,
|
||||||
to_jid=to_jid,
|
to_jid=to_jid,
|
||||||
show=show,
|
show=show,
|
||||||
status=status,
|
status=status,
|
||||||
stanza_type=presence_type))
|
stanza_type=presence_type))
|
||||||
self.db_disconnect()
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def ask_password(self, _account, lang_class):
|
def ask_password(self, _account, lang_class):
|
||||||
@@ -1254,8 +1007,8 @@ class AccountManager(object):
|
|||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
if hasattr(_account, 'waiting_password_reply') \
|
if hasattr(_account, 'waiting_password_reply') \
|
||||||
and not _account.waiting_password_reply \
|
and not _account.waiting_password_reply \
|
||||||
and _account.status != account.OFFLINE:
|
and _account.status != account.OFFLINE:
|
||||||
_account.waiting_password_reply = True
|
_account.waiting_password_reply = True
|
||||||
result.append(Message(from_jid=_account.jid,
|
result.append(Message(from_jid=_account.jid,
|
||||||
to_jid=_account.user_jid,
|
to_jid=_account.user_jid,
|
||||||
@@ -1265,6 +1018,20 @@ class AccountManager(object):
|
|||||||
(_account.name)))
|
(_account.name)))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def set_password(self, _account, from_jid, password, lang_class):
|
||||||
|
"""
|
||||||
|
Set password to given account
|
||||||
|
"""
|
||||||
|
model.db_connect()
|
||||||
|
_account.password = password
|
||||||
|
_account.waiting_password_reply = False
|
||||||
|
result = [Message(from_jid=_account.jid,
|
||||||
|
to_jid=from_jid,
|
||||||
|
subject=lang_class.password_saved_for_session,
|
||||||
|
body=lang_class.password_saved_for_session)]
|
||||||
|
model.db_disconnect()
|
||||||
|
return result
|
||||||
|
|
||||||
def send_error_from_account(self, _account, exception):
|
def send_error_from_account(self, _account, exception):
|
||||||
"""Send an error message only one time until _account.in_error
|
"""Send an error message only one time until _account.in_error
|
||||||
has been reset to False"""
|
has been reset to False"""
|
||||||
|
|||||||
149
src/jcl/jabber/disco.py
Normal file
149
src/jcl/jabber/disco.py
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
##
|
||||||
|
## disco.py
|
||||||
|
## Login : David Rousselie <dax@happycoders.org>
|
||||||
|
## Started on Wed Jun 27 22:27:25 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 logging
|
||||||
|
|
||||||
|
from pyxmpp.jid import JID
|
||||||
|
from pyxmpp.jabber.disco import DiscoInfo, DiscoItems, DiscoItem, DiscoIdentity
|
||||||
|
|
||||||
|
import jcl.jabber as jabber
|
||||||
|
|
||||||
|
class DiscoHandler(object):
|
||||||
|
"""Handle disco get items requests"""
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
def filter(self, stanza, lang_class, node):
|
||||||
|
"""Filter requests to be handled"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, node, disco_obj, data):
|
||||||
|
"""Handle disco get items request"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
class RootDiscoGetInfoHandler(DiscoHandler):
|
||||||
|
|
||||||
|
filter = jabber.root_filter
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
DiscoHandler.__init__(self, component)
|
||||||
|
self.__logger = logging.getLogger("jcl.jabber.RootDiscoGetInfoHandler")
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, node, disco_obj, data):
|
||||||
|
"""Implement discovery get_info on main component JID"""
|
||||||
|
self.__logger.debug("root_disco_get_info")
|
||||||
|
disco_info = DiscoInfo()
|
||||||
|
disco_info.add_feature("jabber:iq:version")
|
||||||
|
if not self.component.account_manager.has_multiple_account_type:
|
||||||
|
disco_info.add_feature("jabber:iq:register")
|
||||||
|
DiscoIdentity(disco_info, self.component.name,
|
||||||
|
self.component.disco_identity.category,
|
||||||
|
self.component.disco_identity.type)
|
||||||
|
return [disco_info]
|
||||||
|
|
||||||
|
class AccountDiscoGetInfoHandler(DiscoHandler):
|
||||||
|
|
||||||
|
filter = jabber.account_filter
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
DiscoHandler.__init__(self, component)
|
||||||
|
self.__logger = logging.getLogger("jcl.jabber.AccountDiscoGetInfoHandler")
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, node, disco_obj, data):
|
||||||
|
"""Implement discovery get_info on an account node"""
|
||||||
|
self.__logger.debug("account_disco_get_info")
|
||||||
|
disco_info = DiscoInfo()
|
||||||
|
disco_info.add_feature("jabber:iq:register")
|
||||||
|
return [disco_info]
|
||||||
|
|
||||||
|
class AccountTypeDiscoGetInfoHandler(AccountDiscoGetInfoHandler):
|
||||||
|
|
||||||
|
filter = jabber.account_type_filter
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
AccountDiscoGetInfoHandler.__init__(self, component)
|
||||||
|
self.__logger = logging.getLogger("jcl.jabber.AccountTypeDiscoGetInfoHandler")
|
||||||
|
|
||||||
|
class RootDiscoGetItemsHandler(DiscoHandler):
|
||||||
|
|
||||||
|
filter = jabber.root_filter
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
DiscoHandler.__init__(self, component)
|
||||||
|
self.__logger = logging.getLogger("jcl.jabber.RootDiscoGetItemsHandler")
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, node, disco_obj, data):
|
||||||
|
"""Discovery get_items on root node"""
|
||||||
|
from_jid = stanza.get_from()
|
||||||
|
if node is not None:
|
||||||
|
return None
|
||||||
|
disco_items = None
|
||||||
|
if self.component.account_manager.has_multiple_account_type: # list accounts with only one type declared
|
||||||
|
disco_items = DiscoItems()
|
||||||
|
for (account_type, type_label) in \
|
||||||
|
self.component.account_manager.list_account_types(lang_class):
|
||||||
|
DiscoItem(disco_items,
|
||||||
|
JID(unicode(self.component.jid) + "/" +
|
||||||
|
account_type),
|
||||||
|
account_type,
|
||||||
|
type_label)
|
||||||
|
|
||||||
|
else:
|
||||||
|
disco_items = DiscoItems()
|
||||||
|
for (_account, resource, account_type) in \
|
||||||
|
self.component.account_manager.list_accounts(from_jid.bare()):
|
||||||
|
DiscoItem(disco_items,
|
||||||
|
JID(unicode(_account.jid) + resource),
|
||||||
|
account_type + _account.name,
|
||||||
|
_account.long_name)
|
||||||
|
return [disco_items]
|
||||||
|
|
||||||
|
class AccountTypeDiscoGetItemsHandler(DiscoHandler):
|
||||||
|
|
||||||
|
filter = jabber.account_type_filter
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
DiscoHandler.__init__(self, component)
|
||||||
|
self.__logger = logging.getLogger("jcl.jabber.AccountTypeDiscoGetItemsHandler")
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, node, disco_obj, data):
|
||||||
|
"""Discovery get_items on an account type node"""
|
||||||
|
account_type = data
|
||||||
|
from_jid = stanza.get_from()
|
||||||
|
self.__logger.debug("Listing account for " + account_type)
|
||||||
|
account_class = self.component.account_manager.get_account_class(account_type + "Account")
|
||||||
|
if account_class is not None:
|
||||||
|
disco_items = DiscoItems()
|
||||||
|
for (_account, resource, account_type) in \
|
||||||
|
self.component.account_manager.list_accounts(from_jid.bare(),
|
||||||
|
account_class,
|
||||||
|
account_type=account_type):
|
||||||
|
DiscoItem(disco_items,
|
||||||
|
JID(unicode(_account.jid) + resource),
|
||||||
|
account_type + _account.name,
|
||||||
|
_account.long_name)
|
||||||
|
return [disco_items]
|
||||||
|
else:
|
||||||
|
self.__logger.error("Error: " + account_class.__name__
|
||||||
|
+ " class not in account_classes")
|
||||||
|
return []
|
||||||
@@ -31,6 +31,7 @@ import logging
|
|||||||
from jcl.jabber import Handler
|
from jcl.jabber import Handler
|
||||||
from jcl.jabber.component import JCLComponent
|
from jcl.jabber.component import JCLComponent
|
||||||
from jcl.lang import Lang
|
from jcl.lang import Lang
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model.account import Account
|
from jcl.model.account import Account
|
||||||
|
|
||||||
from pyxmpp.message import Message
|
from pyxmpp.message import Message
|
||||||
@@ -48,14 +49,12 @@ class FeederComponent(JCLComponent):
|
|||||||
secret,
|
secret,
|
||||||
server,
|
server,
|
||||||
port,
|
port,
|
||||||
db_connection_str,
|
|
||||||
lang = Lang()):
|
lang = Lang()):
|
||||||
JCLComponent.__init__(self,
|
JCLComponent.__init__(self,
|
||||||
jid,
|
jid,
|
||||||
secret,
|
secret,
|
||||||
server,
|
server,
|
||||||
port,
|
port,
|
||||||
db_connection_str,
|
|
||||||
lang=lang)
|
lang=lang)
|
||||||
# Define default feeder and sender, can be override
|
# Define default feeder and sender, can be override
|
||||||
self.handler = FeederHandler(Feeder(self), Sender(self))
|
self.handler = FeederHandler(Feeder(self), Sender(self))
|
||||||
@@ -65,12 +64,12 @@ class FeederComponent(JCLComponent):
|
|||||||
|
|
||||||
def handle_tick(self):
|
def handle_tick(self):
|
||||||
"""Implement main feed/send behavior"""
|
"""Implement main feed/send behavior"""
|
||||||
self.db_connect()
|
model.db_connect()
|
||||||
self.handler.handle(\
|
self.handler.handle(\
|
||||||
None, self.lang.get_default_lang_class(),
|
None, self.lang.get_default_lang_class(),
|
||||||
self.handler.filter(None,
|
self.handler.filter(None,
|
||||||
self.lang.get_default_lang_class()))
|
self.lang.get_default_lang_class()))
|
||||||
self.db_disconnect()
|
model.db_disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,16 +22,19 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from sqlobject.sqlbuilder import AND
|
||||||
from pyxmpp.message import Message
|
from pyxmpp.message import Message
|
||||||
|
|
||||||
from jcl.jabber import Handler
|
from jcl.jabber import Handler
|
||||||
|
import jcl.model.account as account
|
||||||
from jcl.model.account import Account
|
from jcl.model.account import Account
|
||||||
|
|
||||||
class PasswordMessageHandler(Handler):
|
class PasswordMessageHandler(Handler):
|
||||||
"""Handle password message"""
|
"""Handle password message"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, component):
|
||||||
"""handler constructor"""
|
"""handler constructor"""
|
||||||
|
Handler.__init__(self, component)
|
||||||
self.password_regexp = re.compile("\[PASSWORD\]")
|
self.password_regexp = re.compile("\[PASSWORD\]")
|
||||||
|
|
||||||
def filter(self, stanza, lang_class):
|
def filter(self, stanza, lang_class):
|
||||||
@@ -39,23 +42,14 @@ class PasswordMessageHandler(Handler):
|
|||||||
Return the uniq account associated with a name and user JID.
|
Return the uniq account associated with a name and user JID.
|
||||||
DB connection might already be opened.
|
DB connection might already be opened.
|
||||||
"""
|
"""
|
||||||
name = stanza.get_to().node
|
_account = account.get_account(stanza.get_to().node,
|
||||||
bare_from_jid = unicode(stanza.get_from().bare())
|
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') \
|
if hasattr(_account, 'password') \
|
||||||
and hasattr(_account, 'waiting_password_reply') \
|
and hasattr(_account, 'waiting_password_reply') \
|
||||||
and (getattr(_account, 'waiting_password_reply') == True) \
|
and (getattr(_account, 'waiting_password_reply') == True) \
|
||||||
and self.password_regexp.search(stanza.get_subject()) \
|
and self.password_regexp.search(stanza.get_subject()) \
|
||||||
is not None:
|
is not None:
|
||||||
return accounts
|
return _account
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -63,10 +57,6 @@ class PasswordMessageHandler(Handler):
|
|||||||
"""
|
"""
|
||||||
Receive password in stanza (must be a Message) for given account.
|
Receive password in stanza (must be a Message) for given account.
|
||||||
"""
|
"""
|
||||||
_account = data[0]
|
return self.component.account_manager.set_password(data, stanza.get_from(),
|
||||||
_account.password = stanza.get_body()
|
stanza.get_body(),
|
||||||
_account.waiting_password_reply = False
|
lang_class)
|
||||||
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)]
|
|
||||||
|
|||||||
@@ -24,17 +24,19 @@
|
|||||||
from pyxmpp.presence import Presence
|
from pyxmpp.presence import Presence
|
||||||
|
|
||||||
from jcl.jabber import Handler
|
from jcl.jabber import Handler
|
||||||
|
import jcl.jabber as jabber
|
||||||
|
import jcl.model as model
|
||||||
|
|
||||||
class DefaultPresenceHandler(Handler):
|
class DefaultPresenceHandler(Handler):
|
||||||
"""Handle presence"""
|
"""Handle presence"""
|
||||||
|
|
||||||
def handle(self, presence, lang_class, data):
|
def handle(self, stanza, lang_class, data):
|
||||||
"""Return same presence as receive one"""
|
"""Return same presence as receive one"""
|
||||||
to_jid = presence.get_to()
|
to_jid = stanza.get_to()
|
||||||
from_jid = presence.get_from()
|
from_jid = stanza.get_from()
|
||||||
presence.set_to(from_jid)
|
stanza.set_to(from_jid)
|
||||||
presence.set_from(to_jid)
|
stanza.set_from(to_jid)
|
||||||
return [presence]
|
return [stanza]
|
||||||
|
|
||||||
class DefaultSubscribeHandler(Handler):
|
class DefaultSubscribeHandler(Handler):
|
||||||
"""Return default response to subscribe queries"""
|
"""Return default response to subscribe queries"""
|
||||||
@@ -64,3 +66,94 @@ class DefaultUnsubscribeHandler(Handler):
|
|||||||
stanza_type="unsubscribed"))
|
stanza_type="unsubscribed"))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
class AccountPresenceHandler(Handler):
|
||||||
|
filter = jabber.get_account_filter
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, data):
|
||||||
|
"""Handle presence sent to an account JID"""
|
||||||
|
result = []
|
||||||
|
_account = data
|
||||||
|
result.extend(self.get_account_presence(stanza, lang_class, _account))
|
||||||
|
return result
|
||||||
|
|
||||||
|
class AccountPresenceAvailableHandler(AccountPresenceHandler):
|
||||||
|
def get_account_presence(self, stanza, lang_class, _account):
|
||||||
|
return self.component.account_manager.send_presence_available(_account,
|
||||||
|
stanza.get_show(),
|
||||||
|
lang_class)
|
||||||
|
|
||||||
|
class RootPresenceHandler(Handler):
|
||||||
|
filter = jabber.get_accounts_root_filter
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, data):
|
||||||
|
"""handle presence sent to component JID"""
|
||||||
|
result = []
|
||||||
|
accounts_length = 0
|
||||||
|
accounts = data
|
||||||
|
for _account in accounts:
|
||||||
|
accounts_length += 1
|
||||||
|
result.extend(self.get_account_presence(stanza, lang_class, _account))
|
||||||
|
if accounts_length > 0:
|
||||||
|
result.extend(self.get_root_presence(stanza, lang_class, accounts_length))
|
||||||
|
return result
|
||||||
|
|
||||||
|
class RootPresenceAvailableHandler(RootPresenceHandler, AccountPresenceAvailableHandler):
|
||||||
|
def get_root_presence(self, stanza, lang_class, nb_accounts):
|
||||||
|
return self.component.account_manager.send_root_presence(stanza.get_from(),
|
||||||
|
"available",
|
||||||
|
stanza.get_show(),
|
||||||
|
str(nb_accounts) +
|
||||||
|
lang_class.message_status)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountPresenceUnavailableHandler(AccountPresenceHandler):
|
||||||
|
def get_account_presence(self, stanza, lang_class, _account):
|
||||||
|
return self.component.account_manager.send_presence_unavailable(_account)
|
||||||
|
|
||||||
|
class RootPresenceUnavailableHandler(RootPresenceHandler, AccountPresenceUnavailableHandler):
|
||||||
|
def get_root_presence(self, stanza, lang_class, nb_accounts):
|
||||||
|
return self.component.account_manager.send_root_presence(stanza.get_from(),
|
||||||
|
"unavailable")
|
||||||
|
|
||||||
|
class AccountPresenceSubscribeHandler(Handler):
|
||||||
|
""""""
|
||||||
|
|
||||||
|
filter = jabber.get_account_filter
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, data):
|
||||||
|
"""Handle \"subscribe\" iq sent to an account JID"""
|
||||||
|
return [stanza.make_accept_response()]
|
||||||
|
|
||||||
|
class RootPresenceSubscribeHandler(AccountPresenceSubscribeHandler):
|
||||||
|
""""""
|
||||||
|
|
||||||
|
filter = jabber.get_accounts_root_filter
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, data):
|
||||||
|
"""Handle \"subscribe\" iq sent to component JID"""
|
||||||
|
if list(data) != []:
|
||||||
|
return AccountPresenceSubscribeHandler.handle(self, stanza,
|
||||||
|
lang_class, None)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
class AccountPresenceUnsubscribeHandler(Handler):
|
||||||
|
""""""
|
||||||
|
|
||||||
|
filter = jabber.get_account_filter
|
||||||
|
|
||||||
|
def handle(self, stanza, lang_class, data):
|
||||||
|
"""Handle \"unsubscribe\" iq sent to account JID"""
|
||||||
|
result = []
|
||||||
|
from_jid = stanza.get_from()
|
||||||
|
_account = data
|
||||||
|
model.db_connect()
|
||||||
|
result.append(Presence(from_jid=_account.jid,
|
||||||
|
to_jid=from_jid,
|
||||||
|
stanza_type="unsubscribe"))
|
||||||
|
result.append(Presence(from_jid=_account.jid,
|
||||||
|
to_jid=from_jid,
|
||||||
|
stanza_type="unsubscribed"))
|
||||||
|
_account.destroySelf()
|
||||||
|
model.db_disconnect()
|
||||||
|
return result
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ __revision__ = ""
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from jcl.jabber.tests import component, feeder, command
|
from jcl.jabber.tests import component, feeder, command, message, presence
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
suite.addTest(component.suite())
|
suite.addTest(component.suite())
|
||||||
suite.addTest(feeder.suite())
|
suite.addTest(feeder.suite())
|
||||||
suite.addTest(command.suite())
|
suite.addTest(command.suite())
|
||||||
|
suite.addTest(message.suite())
|
||||||
|
suite.addTest(presence.suite())
|
||||||
return suite
|
return suite
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,7 @@ from jcl.jabber.component import JCLComponent
|
|||||||
from jcl.jabber.feeder import FeederComponent, Feeder, Sender, MessageSender, \
|
from jcl.jabber.feeder import FeederComponent, Feeder, Sender, MessageSender, \
|
||||||
HeadlineSender, FeederHandler
|
HeadlineSender, FeederHandler
|
||||||
from jcl.model.account import Account, LegacyJID
|
from jcl.model.account import Account, LegacyJID
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model import account
|
from jcl.model import account
|
||||||
|
|
||||||
from jcl.model.tests.account import ExampleAccount, Example2Account
|
from jcl.model.tests.account import ExampleAccount, Example2Account
|
||||||
@@ -65,24 +66,24 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
|||||||
self.comp = FeederComponent("jcl.test.com",
|
self.comp = FeederComponent("jcl.test.com",
|
||||||
"password",
|
"password",
|
||||||
"localhost",
|
"localhost",
|
||||||
"5347",
|
"5347")
|
||||||
'sqlite://' + DB_URL)
|
model.db_connection_str = 'sqlite://' + DB_URL
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists = True)
|
||||||
LegacyJID.createTable(ifNotExists=True)
|
LegacyJID.createTable(ifNotExists=True)
|
||||||
ExampleAccount.createTable(ifNotExists = True)
|
ExampleAccount.createTable(ifNotExists = True)
|
||||||
Example2Account.createTable(ifNotExists = True)
|
Example2Account.createTable(ifNotExists = True)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
Account.dropTable(ifExists = True)
|
Account.dropTable(ifExists = True)
|
||||||
LegacyJID.dropTable(ifExists=True)
|
LegacyJID.dropTable(ifExists=True)
|
||||||
ExampleAccount.dropTable(ifExists = True)
|
ExampleAccount.dropTable(ifExists = True)
|
||||||
Example2Account.dropTable(ifExists = True)
|
Example2Account.dropTable(ifExists = True)
|
||||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||||
account.hub.threadConnection.close()
|
model.hub.threadConnection.close()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
@@ -90,8 +91,8 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
|||||||
self.comp.time_unit = 1
|
self.comp.time_unit = 1
|
||||||
self.comp.stream = MockStream()
|
self.comp.stream = MockStream()
|
||||||
self.comp.stream_class = MockStream
|
self.comp.stream_class = MockStream
|
||||||
run_thread = threading.Thread(target = self.comp.run, \
|
run_thread = threading.Thread(target=self.comp.run,
|
||||||
name = "run_thread")
|
name="run_thread")
|
||||||
run_thread.start()
|
run_thread.start()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.comp.running = False
|
self.comp.running = False
|
||||||
@@ -118,7 +119,7 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
|||||||
|
|
||||||
self.comp.stream = MockStream()
|
self.comp.stream = MockStream()
|
||||||
self.comp.stream_class = MockStream
|
self.comp.stream_class = MockStream
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
account11 = Account(user_jid = "user1@test.com", \
|
account11 = Account(user_jid = "user1@test.com", \
|
||||||
name = "account11", \
|
name = "account11", \
|
||||||
jid = "account11@jcl.test.com")
|
jid = "account11@jcl.test.com")
|
||||||
@@ -190,30 +191,30 @@ class MessageSender_TestCase(unittest.TestCase):
|
|||||||
self.comp = FeederComponent("jcl.test.com",
|
self.comp = FeederComponent("jcl.test.com",
|
||||||
"password",
|
"password",
|
||||||
"localhost",
|
"localhost",
|
||||||
"5347",
|
"5347")
|
||||||
'sqlite://' + DB_URL)
|
model.db_connection_str = 'sqlite://' + DB_URL
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists = True)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
self.sender = MessageSender(self.comp)
|
self.sender = MessageSender(self.comp)
|
||||||
self.message_type = None
|
self.message_type = None
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
Account.dropTable(ifExists = True)
|
Account.dropTable(ifExists = True)
|
||||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||||
account.hub.threadConnection.close()
|
model.hub.threadConnection.close()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
def test_send(self):
|
def test_send(self):
|
||||||
self.comp.stream = MockStream()
|
self.comp.stream = MockStream()
|
||||||
self.comp.stream_class = MockStream
|
self.comp.stream_class = MockStream
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
account11 = Account(user_jid = "user1@test.com", \
|
account11 = Account(user_jid="user1@test.com",
|
||||||
name = "account11", \
|
name="account11",
|
||||||
jid = "account11@jcl.test.com")
|
jid="account11@jcl.test.com")
|
||||||
self.sender.send(account11, ("subject", "Body message"))
|
self.sender.send(account11, ("subject", "Body message"))
|
||||||
self.assertEquals(len(self.comp.stream.sent), 1)
|
self.assertEquals(len(self.comp.stream.sent), 1)
|
||||||
message = self.comp.stream.sent[0]
|
message = self.comp.stream.sent[0]
|
||||||
@@ -222,7 +223,7 @@ class MessageSender_TestCase(unittest.TestCase):
|
|||||||
self.assertEquals(message.get_subject(), "subject")
|
self.assertEquals(message.get_subject(), "subject")
|
||||||
self.assertEquals(message.get_body(), "Body message")
|
self.assertEquals(message.get_body(), "Body message")
|
||||||
self.assertEquals(message.get_type(), self.message_type)
|
self.assertEquals(message.get_type(), self.message_type)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
class HeadlineSender_TestCase(MessageSender_TestCase):
|
class HeadlineSender_TestCase(MessageSender_TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -235,24 +236,25 @@ class FeederHandler_TestCase(unittest.TestCase):
|
|||||||
self.handler = FeederHandler(FeederMock(), SenderMock())
|
self.handler = FeederHandler(FeederMock(), SenderMock())
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connection_str = 'sqlite://' + DB_URL
|
||||||
|
model.db_connect()
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists = True)
|
||||||
ExampleAccount.createTable(ifNotExists = True)
|
ExampleAccount.createTable(ifNotExists = True)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.handler = None
|
self.handler = None
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
ExampleAccount.dropTable(ifExists = True)
|
ExampleAccount.dropTable(ifExists = True)
|
||||||
Account.dropTable(ifExists = True)
|
Account.dropTable(ifExists = True)
|
||||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||||
account.hub.threadConnection.close()
|
model.hub.threadConnection.close()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
def test_filter(self):
|
def test_filter(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
account12 = ExampleAccount(user_jid="user2@test.com",
|
account12 = ExampleAccount(user_jid="user2@test.com",
|
||||||
name="account12",
|
name="account12",
|
||||||
jid="account12@jcl.test.com")
|
jid="account12@jcl.test.com")
|
||||||
@@ -264,10 +266,10 @@ class FeederHandler_TestCase(unittest.TestCase):
|
|||||||
# accounts must be ordered by user_jid
|
# accounts must be ordered by user_jid
|
||||||
self.assertEquals(accounts[0].name, "account11")
|
self.assertEquals(accounts[0].name, "account11")
|
||||||
self.assertEquals(accounts[1].name, "account12")
|
self.assertEquals(accounts[1].name, "account12")
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
def test_handle(self):
|
def test_handle(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
model.db_connect()
|
||||||
account11 = ExampleAccount(user_jid="user1@test.com",
|
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||||
name="account11",
|
name="account11",
|
||||||
jid="account11@jcl.test.com")
|
jid="account11@jcl.test.com")
|
||||||
@@ -279,7 +281,7 @@ class FeederHandler_TestCase(unittest.TestCase):
|
|||||||
self.assertEquals(len(sent), 2)
|
self.assertEquals(len(sent), 2)
|
||||||
self.assertEquals(sent[0], (account11, ("subject", "body")))
|
self.assertEquals(sent[0], (account11, ("subject", "body")))
|
||||||
self.assertEquals(sent[1], (account12, ("subject", "body")))
|
self.assertEquals(sent[1], (account12, ("subject", "body")))
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
|
|||||||
161
src/jcl/jabber/tests/message.py
Normal file
161
src/jcl/jabber/tests/message.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
##
|
||||||
|
## message.py
|
||||||
|
## Login : David Rousselie <dax@happycoders.org>
|
||||||
|
## Started on Fri Jul 6 21:40:55 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 unittest
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pyxmpp.message import Message
|
||||||
|
from sqlobject.dbconnection import TheURIOpener
|
||||||
|
|
||||||
|
from jcl.lang import Lang
|
||||||
|
from jcl.jabber.component import JCLComponent
|
||||||
|
from jcl.jabber.message import PasswordMessageHandler
|
||||||
|
import jcl.model.account as account
|
||||||
|
import jcl.model as model
|
||||||
|
from jcl.model.account import Account
|
||||||
|
|
||||||
|
from jcl.model.tests.account import ExampleAccount
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
DB_PATH = "/c|/temp/jcl_test.db"
|
||||||
|
else:
|
||||||
|
DB_PATH = "/tmp/jcl_test.db"
|
||||||
|
DB_URL = DB_PATH# + "?debug=1&debugThreading=1"
|
||||||
|
|
||||||
|
class PasswordMessageHandler_TestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.comp = JCLComponent("jcl.test.com",
|
||||||
|
"password",
|
||||||
|
"localhost",
|
||||||
|
"5347",
|
||||||
|
'sqlite://' + DB_URL)
|
||||||
|
self.handler = PasswordMessageHandler(self.comp)
|
||||||
|
if os.path.exists(DB_PATH):
|
||||||
|
os.unlink(DB_PATH)
|
||||||
|
model.db_connection_str = 'sqlite://' + DB_URL
|
||||||
|
model.db_connect()
|
||||||
|
Account.createTable(ifNotExists = True)
|
||||||
|
ExampleAccount.createTable(ifNotExists = True)
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
model.db_connect()
|
||||||
|
ExampleAccount.dropTable(ifExists = True)
|
||||||
|
Account.dropTable(ifExists = True)
|
||||||
|
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||||
|
model.hub.threadConnection.close()
|
||||||
|
model.db_disconnect()
|
||||||
|
if os.path.exists(DB_PATH):
|
||||||
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
|
def test_filter_waiting_password(self):
|
||||||
|
model.db_connect()
|
||||||
|
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account11",
|
||||||
|
jid="account11@jcl.test.com")
|
||||||
|
account11.waiting_password_reply = True
|
||||||
|
account12 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account12",
|
||||||
|
jid="account12@jcl.test.com")
|
||||||
|
message = Message(from_jid="user1@test.com",
|
||||||
|
to_jid="account11@jcl.test.com",
|
||||||
|
subject="[PASSWORD]",
|
||||||
|
body="secret")
|
||||||
|
_account = self.handler.filter(message, None)
|
||||||
|
self.assertEquals(_account.name, "account11")
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def test_filter_not_waiting_password(self):
|
||||||
|
model.db_connect()
|
||||||
|
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account11",
|
||||||
|
jid="account11@jcl.test.com")
|
||||||
|
account11.waiting_password_reply = False
|
||||||
|
account12 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account12",
|
||||||
|
jid="account12@jcl.test.com")
|
||||||
|
message = Message(from_jid="user1@test.com",
|
||||||
|
to_jid="account11@jcl.test.com",
|
||||||
|
subject="[PASSWORD]",
|
||||||
|
body="secret")
|
||||||
|
_account = self.handler.filter(message, None)
|
||||||
|
self.assertEquals(_account, None)
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def test_filter_not_good_message(self):
|
||||||
|
model.db_connect()
|
||||||
|
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account11",
|
||||||
|
jid="account11@jcl.test.com")
|
||||||
|
account11.waiting_password_reply = True
|
||||||
|
account12 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account12",
|
||||||
|
jid="account12@jcl.test.com")
|
||||||
|
message = Message(from_jid="user1@test.com",
|
||||||
|
to_jid="account11@jcl.test.com",
|
||||||
|
subject="[WRONG MESSAGE]",
|
||||||
|
body="secret")
|
||||||
|
_account = self.handler.filter(message, None)
|
||||||
|
self.assertEquals(_account, None)
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def test_filter_not_password_account(self):
|
||||||
|
model.db_connect()
|
||||||
|
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")
|
||||||
|
message = Message(from_jid="user1@test.com",
|
||||||
|
to_jid="account11@jcl.test.com",
|
||||||
|
subject="[PASSWORD]",
|
||||||
|
body="secret")
|
||||||
|
_account = self.handler.filter(message, None)
|
||||||
|
self.assertEquals(_account, None)
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def test_handle(self):
|
||||||
|
model.db_connect()
|
||||||
|
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account11",
|
||||||
|
jid="account11@jcl.test.com")
|
||||||
|
account12 = ExampleAccount(user_jid="user1@test.com",
|
||||||
|
name="account12",
|
||||||
|
jid="account12@jcl.test.com")
|
||||||
|
message = Message(from_jid="user1@test.com",
|
||||||
|
to_jid="account11@jcl.test.com",
|
||||||
|
subject="[PASSWORD]",
|
||||||
|
body="secret")
|
||||||
|
messages = self.handler.handle(message, Lang.en, account11)
|
||||||
|
self.assertEquals(len(messages), 1)
|
||||||
|
self.assertEquals(account11.password, "secret")
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
suite.addTest(unittest.makeSuite(PasswordMessageHandler_TestCase, 'test'))
|
||||||
|
return suite
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
98
src/jcl/jabber/tests/presence.py
Normal file
98
src/jcl/jabber/tests/presence.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
##
|
||||||
|
## presence.py
|
||||||
|
## Login : David Rousselie <dax@happycoders.org>
|
||||||
|
## Started on Fri Jul 6 21:45:43 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 unittest
|
||||||
|
|
||||||
|
from pyxmpp.presence import Presence
|
||||||
|
|
||||||
|
from jcl.jabber.presence import DefaultSubscribeHandler, \
|
||||||
|
DefaultUnsubscribeHandler, DefaultPresenceHandler
|
||||||
|
|
||||||
|
class DefaultSubscribeHandler_TestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.handler = DefaultSubscribeHandler(None)
|
||||||
|
|
||||||
|
def test_handle(self):
|
||||||
|
presence = Presence(from_jid="user1@test.com",
|
||||||
|
to_jid="user1%test.com@jcl.test.com",
|
||||||
|
stanza_type="subscribe")
|
||||||
|
result = self.handler.handle(presence, None, [])
|
||||||
|
self.assertEquals(len(result), 2)
|
||||||
|
self.assertEquals(result[0].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[0].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[0].get_type(), "subscribe")
|
||||||
|
self.assertEquals(result[1].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[1].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[1].get_type(), "subscribed")
|
||||||
|
|
||||||
|
class DefaultUnsubscribeHandler_TestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.handler = DefaultUnsubscribeHandler(None)
|
||||||
|
|
||||||
|
def test_handle(self):
|
||||||
|
presence = Presence(from_jid="user1@test.com",
|
||||||
|
to_jid="user1%test.com@jcl.test.com",
|
||||||
|
stanza_type="unsubscribe")
|
||||||
|
result = self.handler.handle(presence, None, [])
|
||||||
|
self.assertEquals(len(result), 2)
|
||||||
|
self.assertEquals(result[0].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[0].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[0].get_type(), "unsubscribe")
|
||||||
|
self.assertEquals(result[1].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[1].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[1].get_type(), "unsubscribed")
|
||||||
|
|
||||||
|
class DefaultPresenceHandler_TestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.handler = DefaultPresenceHandler(None)
|
||||||
|
|
||||||
|
def test_handle_away(self):
|
||||||
|
presence = Presence(from_jid="user1@test.com",
|
||||||
|
to_jid="user1%test.com@jcl.test.com",
|
||||||
|
stanza_type="available",
|
||||||
|
show="away")
|
||||||
|
result = self.handler.handle(presence, None, [])
|
||||||
|
self.assertEquals(len(result), 1)
|
||||||
|
self.assertEquals(result[0].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[0].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[0].get_type(), None)
|
||||||
|
self.assertEquals(result[0].get_show(), "away")
|
||||||
|
|
||||||
|
def test_handle_offline(self):
|
||||||
|
presence = Presence(from_jid="user1@test.com",
|
||||||
|
to_jid="user1%test.com@jcl.test.com",
|
||||||
|
stanza_type="unavailable")
|
||||||
|
result = self.handler.handle(presence, None, [])
|
||||||
|
self.assertEquals(len(result), 1)
|
||||||
|
self.assertEquals(result[0].get_to(), "user1@test.com")
|
||||||
|
self.assertEquals(result[0].get_from(), "user1%test.com@jcl.test.com")
|
||||||
|
self.assertEquals(result[0].get_type(), "unavailable")
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
suite.addTest(unittest.makeSuite(DefaultSubscribeHandler_TestCase, 'test'))
|
||||||
|
suite.addTest(unittest.makeSuite(DefaultUnsubscribeHandler_TestCase, 'test'))
|
||||||
|
suite.addTest(unittest.makeSuite(DefaultPresenceHandler_TestCase, 'test'))
|
||||||
|
return suite
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
@@ -1,3 +1,32 @@
|
|||||||
"""Contains data model classes"""
|
"""Contains data model classes"""
|
||||||
__revision__ = ""
|
__revision__ = ""
|
||||||
|
|
||||||
|
from sqlobject.dbconnection import ConnectionHub
|
||||||
|
from sqlobject.dbconnection import connectionForURI
|
||||||
|
|
||||||
|
import jcl.model
|
||||||
|
|
||||||
|
db_connected = False
|
||||||
|
db_connection_str = ""
|
||||||
|
|
||||||
|
# create a hub to attach a per thread connection
|
||||||
|
hub = ConnectionHub()
|
||||||
|
|
||||||
|
def db_connect():
|
||||||
|
"""
|
||||||
|
Create a new connection to the DataBase (SQLObject use connection
|
||||||
|
pool) associated to the current thread.
|
||||||
|
"""
|
||||||
|
if not jcl.model.db_connected:
|
||||||
|
jcl.model.hub.threadConnection = \
|
||||||
|
connectionForURI(db_connection_str)
|
||||||
|
# account.hub.threadConnection.debug = True
|
||||||
|
jcl.model.db_connected = True
|
||||||
|
|
||||||
|
def db_disconnect():
|
||||||
|
"""
|
||||||
|
Delete connection associated to the current thread.
|
||||||
|
"""
|
||||||
|
if jcl.model.db_connected:
|
||||||
|
del jcl.model.hub.threadConnection
|
||||||
|
jcl.model.db_connected = False
|
||||||
|
|||||||
@@ -28,16 +28,16 @@ __revision__ = "$Id: account.py,v 1.3 2005/09/18 20:24:07 dax Exp $"
|
|||||||
|
|
||||||
from sqlobject.inheritance import InheritableSQLObject
|
from sqlobject.inheritance import InheritableSQLObject
|
||||||
from sqlobject.col import StringCol, EnumCol, IntCol, BoolCol, ForeignKey
|
from sqlobject.col import StringCol, EnumCol, IntCol, BoolCol, ForeignKey
|
||||||
from sqlobject.dbconnection import ConnectionHub
|
|
||||||
from sqlobject.joins import MultipleJoin
|
from sqlobject.joins import MultipleJoin
|
||||||
|
from sqlobject.sqlbuilder import AND
|
||||||
|
|
||||||
from jcl.lang import Lang
|
from jcl.lang import Lang
|
||||||
from jcl.error import FieldError
|
from jcl.error import FieldError
|
||||||
|
import jcl.model as model
|
||||||
|
|
||||||
OFFLINE = "offline"
|
OFFLINE = "offline"
|
||||||
ONLINE = "online"
|
ONLINE = "online"
|
||||||
|
|
||||||
|
|
||||||
def default_post_func(field_value, default_func, bare_from_jid):
|
def default_post_func(field_value, default_func, bare_from_jid):
|
||||||
"""Default post process function: do nothing"""
|
"""Default post process function: do nothing"""
|
||||||
if field_value is None or str(field_value) == "":
|
if field_value is None or str(field_value) == "":
|
||||||
@@ -57,13 +57,32 @@ def mandatory_field(field_value):
|
|||||||
raise FieldError # TODO : add translated message
|
raise FieldError # TODO : add translated message
|
||||||
return field_value
|
return field_value
|
||||||
|
|
||||||
# create a hub to attach a per thread connection
|
def get_account(name, bare_user_jid):
|
||||||
hub = ConnectionHub()
|
result = None
|
||||||
|
model.db_connect()
|
||||||
|
accounts = Account.select(\
|
||||||
|
AND(Account.q.name == name,
|
||||||
|
Account.q.user_jid == unicode(bare_user_jid)))
|
||||||
|
if accounts.count() > 0:
|
||||||
|
result = accounts[0]
|
||||||
|
model.db_disconnect()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_accounts(bare_user_jid):
|
||||||
|
model.db_connect()
|
||||||
|
accounts = Account.select(\
|
||||||
|
Account.q.user_jid == unicode(bare_user_jid))
|
||||||
|
if accounts.count() == 0:
|
||||||
|
model.db_disconnect()
|
||||||
|
return
|
||||||
|
for _account in accounts:
|
||||||
|
yield _account
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
class Account(InheritableSQLObject):
|
class Account(InheritableSQLObject):
|
||||||
"""Base Account class"""
|
"""Base Account class"""
|
||||||
_cacheValue = False
|
_cacheValue = False
|
||||||
_connection = hub
|
_connection = model.hub
|
||||||
user_jid = StringCol()
|
user_jid = StringCol()
|
||||||
name = StringCol()
|
name = StringCol()
|
||||||
jid = StringCol()
|
jid = StringCol()
|
||||||
@@ -268,8 +287,17 @@ class PresenceAccount(Account):
|
|||||||
|
|
||||||
action = property(get_action)
|
action = property(get_action)
|
||||||
|
|
||||||
|
def get_legacy_jids(bare_to_jid):
|
||||||
|
model.db_connect()
|
||||||
|
legacy_jids = LegacyJID.select(\
|
||||||
|
AND(LegacyJID.q.accountID == Account.q.id,
|
||||||
|
Account.q.user_jid == bare_to_jid))
|
||||||
|
for legacy_jid in legacy_jids:
|
||||||
|
yield legacy_jid
|
||||||
|
model.db_disconnect()
|
||||||
|
|
||||||
class LegacyJID(InheritableSQLObject):
|
class LegacyJID(InheritableSQLObject):
|
||||||
_connection = hub
|
_connection = model.hub
|
||||||
|
|
||||||
legacy_address = StringCol()
|
legacy_address = StringCol()
|
||||||
jid = StringCol()
|
jid = StringCol()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from sqlobject import *
|
|||||||
from sqlobject.dbconnection import TheURIOpener
|
from sqlobject.dbconnection import TheURIOpener
|
||||||
|
|
||||||
from jcl.error import FieldError
|
from jcl.error import FieldError
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model import account
|
from jcl.model import account
|
||||||
from jcl.model.account import Account, PresenceAccount
|
from jcl.model.account import Account, PresenceAccount
|
||||||
|
|
||||||
@@ -165,13 +166,15 @@ class AccountModule_TestCase(unittest.TestCase):
|
|||||||
class InheritableAccount_TestCase(unittest.TestCase):
|
class InheritableAccount_TestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.db_url = DB_URL
|
self.db_url = DB_URL
|
||||||
|
model.db_connection_str = 'sqlite://' + self.db_url
|
||||||
|
|
||||||
def test_get_register_fields(self):
|
def test_get_register_fields(self):
|
||||||
"""Check if post functions and default functions execute correctly.
|
"""
|
||||||
|
Check if post functions and default functions execute correctly.
|
||||||
To be validated this test only need to be executed without any
|
To be validated this test only need to be executed without any
|
||||||
exception.
|
exception.
|
||||||
"""
|
"""
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connect()
|
||||||
for (field_name,
|
for (field_name,
|
||||||
field_type,
|
field_type,
|
||||||
field_options,
|
field_options,
|
||||||
@@ -184,41 +187,42 @@ class InheritableAccount_TestCase(unittest.TestCase):
|
|||||||
except FieldError, error:
|
except FieldError, error:
|
||||||
# this type of error is OK
|
# this type of error is OK
|
||||||
pass
|
pass
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
class Account_TestCase(InheritableAccount_TestCase):
|
class Account_TestCase(InheritableAccount_TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
self.db_url = DB_URL
|
self.db_url = DB_URL
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connection_str = 'sqlite://' + self.db_url
|
||||||
|
model.db_connect()
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists = True)
|
||||||
ExampleAccount.createTable(ifNotExists = True)
|
ExampleAccount.createTable(ifNotExists = True)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
self.account_class = Account
|
self.account_class = Account
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connect()
|
||||||
ExampleAccount.dropTable(ifExists = True)
|
ExampleAccount.dropTable(ifExists = True)
|
||||||
Account.dropTable(ifExists = True)
|
Account.dropTable(ifExists = True)
|
||||||
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
||||||
account.hub.threadConnection.close()
|
model.hub.threadConnection.close()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
def test_set_status(self):
|
def test_set_status(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connect()
|
||||||
account11 = Account(user_jid="test1@test.com",
|
account11 = Account(user_jid="test1@test.com",
|
||||||
name="account11",
|
name="account11",
|
||||||
jid="account11@jcl.test.com")
|
jid="account11@jcl.test.com")
|
||||||
account11.status = account.OFFLINE
|
account11.status = account.OFFLINE
|
||||||
self.assertEquals(account11.status, account.OFFLINE)
|
self.assertEquals(account11.status, account.OFFLINE)
|
||||||
# TODO : test first_check attribute
|
# TODO : test first_check attribute
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
def test_set_status_live_password(self):
|
def test_set_status_live_password(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connect()
|
||||||
account11 = ExampleAccount(user_jid="test1@test.com",
|
account11 = ExampleAccount(user_jid="test1@test.com",
|
||||||
name="account11",
|
name="account11",
|
||||||
jid="account11@jcl.test.com",
|
jid="account11@jcl.test.com",
|
||||||
@@ -232,32 +236,33 @@ class Account_TestCase(InheritableAccount_TestCase):
|
|||||||
self.assertEquals(account11.status, account.OFFLINE)
|
self.assertEquals(account11.status, account.OFFLINE)
|
||||||
self.assertEquals(account11.waiting_password_reply, False)
|
self.assertEquals(account11.waiting_password_reply, False)
|
||||||
self.assertEquals(account11.password, None)
|
self.assertEquals(account11.password, None)
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
|
|
||||||
class PresenceAccount_TestCase(InheritableAccount_TestCase):
|
class PresenceAccount_TestCase(InheritableAccount_TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
self.db_url = DB_URL
|
self.db_url = DB_URL
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connection_str = 'sqlite://' + self.db_url
|
||||||
|
model.db_connect()
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists = True)
|
||||||
PresenceAccount.createTable(ifNotExists = True)
|
PresenceAccount.createTable(ifNotExists = True)
|
||||||
PresenceAccountExample.createTable(ifNotExists = True)
|
PresenceAccountExample.createTable(ifNotExists = True)
|
||||||
self.account = PresenceAccountExample(\
|
self.account = PresenceAccountExample(\
|
||||||
user_jid = "test1@test.com", \
|
user_jid="test1@test.com",
|
||||||
name = "account11", \
|
name="account11",
|
||||||
jid = "account11@jcl.test.com")
|
jid="account11@jcl.test.com")
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
self.account_class = PresenceAccount
|
self.account_class = PresenceAccount
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
model.db_connect()
|
||||||
PresenceAccountExample.dropTable(ifExists = True)
|
PresenceAccountExample.dropTable(ifExists = True)
|
||||||
PresenceAccount.dropTable(ifExists = True)
|
PresenceAccount.dropTable(ifExists = True)
|
||||||
Account.dropTable(ifExists = True)
|
Account.dropTable(ifExists = True)
|
||||||
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
||||||
account.hub.threadConnection.close()
|
model.hub.threadConnection.close()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
if os.path.exists(DB_PATH):
|
if os.path.exists(DB_PATH):
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from getopt import gnu_getopt
|
|||||||
|
|
||||||
from sqlobject import *
|
from sqlobject import *
|
||||||
|
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model import account
|
from jcl.model import account
|
||||||
from jcl.model.account import Account, PresenceAccount
|
from jcl.model.account import Account, PresenceAccount
|
||||||
|
|
||||||
@@ -48,35 +49,35 @@ class JCLRunner(object):
|
|||||||
self.language = "en"
|
self.language = "en"
|
||||||
self.db_url = "sqlite:///var/spool/jabber/jcl.db"
|
self.db_url = "sqlite:///var/spool/jabber/jcl.db"
|
||||||
self.pid_file = "/var/run/jabber/jcl.pid"
|
self.pid_file = "/var/run/jabber/jcl.pid"
|
||||||
self.options = [("c:", "config-file=", None, \
|
self.options = [("c:", "config-file=", None,
|
||||||
" FILE\t\t\t\tConfiguration file to use", \
|
" FILE\t\t\t\tConfiguration file to use",
|
||||||
lambda arg: self.set_attr("config_file", arg)), \
|
lambda arg: self.set_attr("config_file", arg)),
|
||||||
("S:", "server=", "jabber", \
|
("S:", "server=", "jabber",
|
||||||
" SERVER_ADDRESS\t\t\tAddress of the Jabber server", \
|
" SERVER_ADDRESS\t\t\tAddress of the Jabber server",
|
||||||
lambda arg: self.set_attr("server", arg)), \
|
lambda arg: self.set_attr("server", arg)),
|
||||||
("P:", "port=", "jabber", \
|
("P:", "port=", "jabber",
|
||||||
" PORT\t\t\t\t\tPort of the Jabber server to connect the component", \
|
" PORT\t\t\t\t\tPort of the Jabber server to connect the component",
|
||||||
lambda arg: self.set_attr("port", int(arg))), \
|
lambda arg: self.set_attr("port", int(arg))),
|
||||||
("s:", "secret=", "jabber", \
|
("s:", "secret=", "jabber",
|
||||||
" SECRET\t\t\t\tComponent password to connect to the Jabber server", \
|
" SECRET\t\t\t\tComponent password to connect to the Jabber server",
|
||||||
lambda arg: self.set_attr("secret", arg)), \
|
lambda arg: self.set_attr("secret", arg)),
|
||||||
("j:", "service-jid=", "jabber", \
|
("j:", "service-jid=", "jabber",
|
||||||
" JID\t\t\t\tJID of the component", \
|
" JID\t\t\t\tJID of the component",
|
||||||
lambda arg: self.set_attr("service_jid", arg)), \
|
lambda arg: self.set_attr("service_jid", arg)),
|
||||||
("l:", "language=", "jabber", \
|
("l:", "language=", "jabber",
|
||||||
" LANG\t\t\t\tDefault Language of the component", \
|
" LANG\t\t\t\tDefault Language of the component",
|
||||||
lambda arg: self.set_attr("language", arg)), \
|
lambda arg: self.set_attr("language", arg)),
|
||||||
("u:", "db-url=", "db", \
|
("u:", "db-url=", "db",
|
||||||
" URL\t\t\t\tDatabase URL", \
|
" URL\t\t\t\tDatabase URL",
|
||||||
lambda arg: self.set_attr("db_url", arg)), \
|
lambda arg: self.set_attr("db_url", arg)),
|
||||||
("p:", "pid-file=", "component", \
|
("p:", "pid-file=", "component",
|
||||||
" FILE\t\t\t\tPath of the PID file", \
|
" FILE\t\t\t\tPath of the PID file",
|
||||||
lambda arg: self.set_attr("pid_file", arg)), \
|
lambda arg: self.set_attr("pid_file", arg)),
|
||||||
("d", "debug", None, \
|
("d", "debug", None,
|
||||||
"\t\t\t\t\tEnable debug traces", \
|
"\t\t\t\t\tEnable debug traces",
|
||||||
lambda arg: self.set_attr("debug", True)), \
|
lambda arg: self.set_attr("debug", True)),
|
||||||
("h", "help", None, \
|
("h", "help", None,
|
||||||
"\t\t\t\t\tThis help", \
|
"\t\t\t\t\tThis help",
|
||||||
lambda arg: self.print_help())]
|
lambda arg: self.print_help())]
|
||||||
self.logger = logging.getLogger()
|
self.logger = logging.getLogger()
|
||||||
self.logger.addHandler(logging.StreamHandler())
|
self.logger.addHandler(logging.StreamHandler())
|
||||||
@@ -97,7 +98,7 @@ class JCLRunner(object):
|
|||||||
def __apply_commandline_args(self, commandline_args, cleanopts):
|
def __apply_commandline_args(self, commandline_args, cleanopts):
|
||||||
for arg in commandline_args:
|
for arg in commandline_args:
|
||||||
value = commandline_args[arg]
|
value = commandline_args[arg]
|
||||||
self.logger.debug("Applying argument " + arg + " = " + \
|
self.logger.debug("Applying argument " + arg + " = " +
|
||||||
value)
|
value)
|
||||||
cleanopts[arg][1](value)
|
cleanopts[arg][1](value)
|
||||||
|
|
||||||
@@ -118,9 +119,9 @@ class JCLRunner(object):
|
|||||||
if section is not None:
|
if section is not None:
|
||||||
attr = opt.replace("-", "_")
|
attr = opt.replace("-", "_")
|
||||||
config_property = self.config.get(section, attr)
|
config_property = self.config.get(section, attr)
|
||||||
self.logger.debug("Setting " + attr + " = " + \
|
self.logger.debug("Setting " + attr + " = " +
|
||||||
config_property + \
|
config_property +
|
||||||
" from configuration file " + \
|
" from configuration file " +
|
||||||
self.config_file)
|
self.config_file)
|
||||||
set_func(config_property)
|
set_func(config_property)
|
||||||
|
|
||||||
@@ -175,8 +176,8 @@ class JCLRunner(object):
|
|||||||
|
|
||||||
|
|
||||||
def setup_db(self):
|
def setup_db(self):
|
||||||
Account.createTable(ifNotExists = True)
|
Account.createTable(ifNotExists=True)
|
||||||
PresenceAccount.createTable(ifNotExists = True)
|
PresenceAccount.createTable(ifNotExists=True)
|
||||||
|
|
||||||
def setup_pidfile(self):
|
def setup_pidfile(self):
|
||||||
pidfile = open(self.pid_file, "w")
|
pidfile = open(self.pid_file, "w")
|
||||||
@@ -186,10 +187,11 @@ class JCLRunner(object):
|
|||||||
def _run(self, run_func):
|
def _run(self, run_func):
|
||||||
try:
|
try:
|
||||||
self.setup_pidfile()
|
self.setup_pidfile()
|
||||||
account.hub.threadConnection = connectionForURI(self.db_url)
|
model.db_connection_str = self.db_url
|
||||||
|
model.db_connect()
|
||||||
self.setup_db()
|
self.setup_db()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
self.logger.debug(self.component_name + " v" + \
|
self.logger.debug(self.component_name + " v" +
|
||||||
self.component_version + " is starting ...")
|
self.component_version + " is starting ...")
|
||||||
run_func()
|
run_func()
|
||||||
self.logger.debug(self.component_name + " is exiting")
|
self.logger.debug(self.component_name + " is exiting")
|
||||||
@@ -199,12 +201,11 @@ class JCLRunner(object):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
def run_func():
|
def run_func():
|
||||||
component = JCLComponent(jid = self.service_jid, \
|
component = JCLComponent(jid=self.service_jid,
|
||||||
secret = self.secret, \
|
secret=self.secret,
|
||||||
server = self.server, \
|
server=self.server,
|
||||||
port = self.port, \
|
port=self.port,
|
||||||
db_connection_str = self.db_url, \
|
lang=Lang(self.language))
|
||||||
lang = Lang(self.language))
|
|
||||||
component.run()
|
component.run()
|
||||||
self._run(run_func)
|
self._run(run_func)
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ from sqlobject import *
|
|||||||
import jcl
|
import jcl
|
||||||
from jcl.runner import JCLRunner
|
from jcl.runner import JCLRunner
|
||||||
|
|
||||||
|
import jcl.model as model
|
||||||
from jcl.model import account
|
from jcl.model import account
|
||||||
from jcl.model.account import Account, PresenceAccount
|
from jcl.model.account import Account, PresenceAccount
|
||||||
|
|
||||||
@@ -125,11 +126,11 @@ class JCLRunner_TestCase(unittest.TestCase):
|
|||||||
def do_nothing():
|
def do_nothing():
|
||||||
pass
|
pass
|
||||||
self.runner._run(do_nothing)
|
self.runner._run(do_nothing)
|
||||||
account.hub.threadConnection = connectionForURI(self.runner.db_url)
|
model.db_connect()
|
||||||
# dropTable should succeed because tables should exist
|
# dropTable should succeed because tables should exist
|
||||||
Account.dropTable()
|
Account.dropTable()
|
||||||
PresenceAccount.dropTable()
|
PresenceAccount.dropTable()
|
||||||
del account.hub.threadConnection
|
model.db_disconnect()
|
||||||
os.unlink(DB_PATH)
|
os.unlink(DB_PATH)
|
||||||
self.assertFalse(os.access("/tmp/jcl.pid", os.F_OK))
|
self.assertFalse(os.access("/tmp/jcl.pid", os.F_OK))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user