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"""
|
||||
__revision__ = ""
|
||||
|
||||
import jcl.model.account as account
|
||||
from jcl.model.account import Account
|
||||
|
||||
class Handler(object):
|
||||
"""handling class"""
|
||||
|
||||
def __init__(self, component):
|
||||
"""Default Handler constructor"""
|
||||
self.component = component
|
||||
|
||||
def filter(self, stanza, lang_class):
|
||||
"""
|
||||
Filter account to be processed by the handler
|
||||
@@ -21,13 +26,41 @@ class Handler(object):
|
||||
"""
|
||||
return []
|
||||
|
||||
class DiscoHandler(object):
|
||||
"""Handle disco get items requests"""
|
||||
|
||||
def filter(self, node, info_query):
|
||||
"""Filter requests to be handled"""
|
||||
return False
|
||||
|
||||
def handle(self, node, info_query, lang_class, disco_items, data):
|
||||
"""Handle disco get items request"""
|
||||
def 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 True
|
||||
else:
|
||||
return None
|
||||
|
||||
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
|
||||
|
||||
@@ -27,7 +27,8 @@ from pyxmpp.jabber.dataforms import Form, Field
|
||||
|
||||
import jcl
|
||||
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
|
||||
|
||||
COMMAND_NS = "http://jabber.org/protocol/commands"
|
||||
@@ -146,47 +147,60 @@ class JCLCommandManager(CommandManager):
|
||||
field_type="fixed",
|
||||
label="Account name")) # TODO: add to Lang
|
||||
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)
|
||||
for _account in accounts:
|
||||
fields = [Field(name="name",
|
||||
field_type="fixed",
|
||||
value=_account.name)]
|
||||
result_form.add_item(fields)
|
||||
self.account_manager.db_disconnect()
|
||||
model.db_disconnect()
|
||||
result_form.as_xml(command_node)
|
||||
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):
|
||||
"""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
|
||||
"""
|
||||
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
|
||||
"""
|
||||
if not disco_info:
|
||||
disco_info = DiscoInfo()
|
||||
return command_manager.get_command_info(disco_info, node, lang_class)
|
||||
if not disco_obj:
|
||||
disco_obj = DiscoInfo()
|
||||
return [command_manager.get_command_info(disco_info=disco_obj,
|
||||
command_name=node,
|
||||
lang_class=lang_class)]
|
||||
|
||||
class CommandDiscoGetItemsHandler(DiscoHandler):
|
||||
"""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.
|
||||
"""
|
||||
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:
|
||||
disco_items = DiscoItems()
|
||||
return command_manager.list_commands(disco_items, lang_class)
|
||||
if not disco_obj:
|
||||
disco_obj = DiscoItems()
|
||||
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.sqlbuilder import AND
|
||||
from sqlobject.dbconnection import connectionForURI
|
||||
|
||||
import pyxmpp.error as error
|
||||
from pyxmpp.jid import JID
|
||||
@@ -53,10 +52,19 @@ from pyxmpp.jabber.dataforms import Form, Field, Option
|
||||
import jcl
|
||||
from jcl.error import FieldError
|
||||
from jcl.jabber import Handler
|
||||
from jcl.jabber.disco import AccountDiscoGetInfoHandler, \
|
||||
AccountTypeDiscoGetInfoHandler, RootDiscoGetItemsHandler, \
|
||||
AccountTypeDiscoGetItemsHandler
|
||||
from jcl.jabber.message import PasswordMessageHandler
|
||||
import jcl.jabber.command as command
|
||||
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.account import Account, LegacyJID
|
||||
from jcl.lang import Lang
|
||||
@@ -67,10 +75,12 @@ VERSION = "0.1"
|
||||
# JCL implementation
|
||||
###############################################################################
|
||||
class JCLComponent(Component, object):
|
||||
"""Implement default JCL component behavior:
|
||||
"""
|
||||
Implement default JCL component behavior:
|
||||
- Jabber register process (add, delete, update accounts)
|
||||
- Jabber presence handling
|
||||
- passwork request at login
|
||||
- Service Administration (XEP-0133)
|
||||
"""
|
||||
|
||||
timeout = 1
|
||||
@@ -80,7 +90,6 @@ class JCLComponent(Component, object):
|
||||
secret,
|
||||
server,
|
||||
port,
|
||||
db_connection_str,
|
||||
disco_category="headline",
|
||||
disco_type="x-unknown",
|
||||
lang=Lang()):
|
||||
@@ -94,21 +103,28 @@ class JCLComponent(Component, object):
|
||||
# default values
|
||||
self.name = lang.get_default_lang_class().component_name
|
||||
self.spool_dir = "."
|
||||
self.db_connection_str = db_connection_str
|
||||
self.version = VERSION
|
||||
self.time_unit = 60
|
||||
self.queue = Queue(100)
|
||||
self.account_manager = AccountManager(self)
|
||||
self.msg_handlers = []
|
||||
self.subscribe_handlers = []
|
||||
self.unsubscribe_handlers = []
|
||||
self.available_handlers = []
|
||||
self.unavailable_handlers = []
|
||||
self.presence_subscribe_handlers = [[AccountPresenceSubscribeHandler(self),
|
||||
RootPresenceSubscribeHandler(self)]]
|
||||
self.presence_unsubscribe_handlers = [[AccountPresenceUnsubscribeHandler(self)]]
|
||||
self.presence_available_handlers = [[AccountPresenceAvailableHandler(self),
|
||||
RootPresenceAvailableHandler(self)]]
|
||||
self.presence_unavailable_handlers = [[AccountPresenceUnavailableHandler(self),
|
||||
RootPresenceUnavailableHandler(self)]]
|
||||
command.command_manager = JCLCommandManager()
|
||||
command.command_manager.component = self
|
||||
command.command_manager.account_manager = self.account_manager
|
||||
self.disco_get_items_handlers = [CommandDiscoGetItemsHandler()]
|
||||
self.disco_get_info_handlers = [CommandDiscoGetInfoHandler()]
|
||||
self.disco_get_items_handlers = [[RootDiscoGetItemsHandler(self),
|
||||
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.lang = lang
|
||||
@@ -119,7 +135,8 @@ class JCLComponent(Component, object):
|
||||
signal.signal(signal.SIGTERM, self.signal_handler)
|
||||
|
||||
def run(self):
|
||||
"""Main loop
|
||||
"""
|
||||
Main loop
|
||||
Connect to Jabber server
|
||||
Start timer thread
|
||||
Call Component main loop
|
||||
@@ -149,27 +166,12 @@ class JCLComponent(Component, object):
|
||||
self.disconnect()
|
||||
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
|
||||
###########################################################################
|
||||
def time_handler(self):
|
||||
"""Timer thread handler
|
||||
"""
|
||||
Timer thread handler
|
||||
"""
|
||||
self.__logger.info("Timer thread started...")
|
||||
try:
|
||||
@@ -179,13 +181,17 @@ class JCLComponent(Component, object):
|
||||
self.wait_event.wait(self.time_unit)
|
||||
self.handle_tick()
|
||||
self.__logger.debug("Resetting alarm signal")
|
||||
##time.sleep(self.time_unit)
|
||||
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.__logger.info("Timer thread terminated...")
|
||||
|
||||
def authenticated(self):
|
||||
"""Override authenticated Component event handler
|
||||
"""
|
||||
Override authenticated Component event handler
|
||||
Register event handlers
|
||||
Probe for every accounts registered
|
||||
"""
|
||||
@@ -227,7 +233,7 @@ class JCLComponent(Component, object):
|
||||
self.handle_message)
|
||||
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):
|
||||
"""Stop method handler
|
||||
@@ -277,19 +283,33 @@ class JCLComponent(Component, object):
|
||||
self.send_stanzas(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"""
|
||||
result = []
|
||||
self.db_connect()
|
||||
lang = self.lang.get_lang_class_from_node(stanza.get_node())
|
||||
for handler in handlers:
|
||||
lang_class = self.lang.get_lang_class_from_node(stanza.get_node())
|
||||
for handler_group in handlers:
|
||||
for handler in handler_group:
|
||||
try:
|
||||
self.__logger.debug("Applying filter " + repr(handler))
|
||||
data = handler.filter(stanza, lang)
|
||||
if data:
|
||||
if apply_filter_func is not None:
|
||||
data = apply_filter_func(handler.filter, stanza, lang_class)
|
||||
else:
|
||||
data = handler.filter(stanza, lang_class)
|
||||
if data is not None and data != False:
|
||||
self.__logger.debug("Applying handler " + repr(handler))
|
||||
result += handler.handle(stanza, lang, data)
|
||||
if not apply_all:
|
||||
if apply_handle_func is not None:
|
||||
handler_result = apply_handle_func(handler.handle,
|
||||
stanza,
|
||||
lang_class,
|
||||
data,
|
||||
result)
|
||||
else:
|
||||
handler_result = handler.handle(stanza, lang_class,
|
||||
data)
|
||||
if handler_result is not None:
|
||||
result += handler_result
|
||||
break
|
||||
except Exception, e:
|
||||
type, value, stack = sys.exc_info()
|
||||
@@ -300,9 +320,8 @@ class JCLComponent(Component, object):
|
||||
result += [Message(from_jid=stanza.get_to(),
|
||||
to_jid=stanza.get_from(),
|
||||
stanza_type="error",
|
||||
subject=lang.error_subject,
|
||||
body=lang.error_body % (e.message))]
|
||||
self.db_disconnect()
|
||||
subject=lang_class.error_subject,
|
||||
body=lang_class.error_body % (e.message))]
|
||||
self.send_stanzas(result)
|
||||
return result
|
||||
|
||||
@@ -337,50 +356,29 @@ class JCLComponent(Component, object):
|
||||
return 1
|
||||
|
||||
def disco_get_info(self, node, info_query):
|
||||
"""Discovery get info handler
|
||||
"""
|
||||
result = self.apply_behavior(\
|
||||
Discovery get info handler
|
||||
"""
|
||||
result = self.apply_registered_behavior(\
|
||||
self.disco_get_info_handlers,
|
||||
info_query,
|
||||
lambda name, from_jid, account_type, lang_class: \
|
||||
self.account_manager.account_disco_get_info(),
|
||||
lambda name, from_jid, account_type, lang_class: \
|
||||
self.account_manager.account_type_disco_get_info(),
|
||||
lambda name, from_jid, account_type, lang_class: \
|
||||
self.account_manager.root_disco_get_info(\
|
||||
node,
|
||||
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)
|
||||
lambda filter_func, stanza, lang_class: \
|
||||
filter_func(stanza, lang_class, node),
|
||||
lambda handle_func, stanza, lang_class, data, result: \
|
||||
handle_func(stanza, lang_class, node, result, data))
|
||||
return result
|
||||
|
||||
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,
|
||||
lambda name, from_jid, account_type, lang_class: \
|
||||
None,
|
||||
lambda name, from_jid, account_type, lang_class: \
|
||||
self.account_manager.account_type_disco_get_items(from_jid,
|
||||
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)
|
||||
lambda filter_func, stanza, lang_class: \
|
||||
filter_func(stanza, lang_class, node),
|
||||
lambda handle_func, stanza, lang_class, data, result: \
|
||||
handle_func(stanza, lang_class, node, result, data))
|
||||
return result
|
||||
|
||||
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
|
||||
all accounts for current user. Otherwise, send presence from current account.
|
||||
"""
|
||||
result = self.apply_registered_behavior(self.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)
|
||||
result = self.apply_registered_behavior(self.presence_available_handlers, stanza)
|
||||
return result
|
||||
|
||||
|
||||
@@ -497,38 +480,16 @@ class JCLComponent(Component, object):
|
||||
"""Handle presence unavailability
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_UNAVAILABLE")
|
||||
result = self.apply_registered_behavior(self.unavailable_handlers, stanza)
|
||||
if result == []:
|
||||
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)
|
||||
result = self.apply_registered_behavior(self.presence_unavailable_handlers,
|
||||
stanza)
|
||||
return result
|
||||
|
||||
def handle_presence_subscribe(self, stanza):
|
||||
"""Handle subscribe presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_SUBSCRIBE")
|
||||
result = self.apply_registered_behavior(self.subscribe_handlers, stanza)
|
||||
if result == []:
|
||||
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)
|
||||
result = self.apply_registered_behavior(self.presence_subscribe_handlers,
|
||||
stanza)
|
||||
return result
|
||||
|
||||
def handle_presence_subscribed(self, stanza):
|
||||
@@ -541,18 +502,8 @@ class JCLComponent(Component, object):
|
||||
"""Handle unsubscribe presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_UNSUBSCRIBE")
|
||||
result = self.apply_registered_behavior(self.unsubscribe_handlers, stanza)
|
||||
if result == []:
|
||||
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)
|
||||
result = self.apply_registered_behavior(self.presence_unsubscribe_handlers,
|
||||
stanza)
|
||||
return result
|
||||
|
||||
def handle_presence_unsubscribed(self, stanza):
|
||||
@@ -570,7 +521,7 @@ class JCLComponent(Component, object):
|
||||
Handle password response message
|
||||
"""
|
||||
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
|
||||
|
||||
def handle_command(self, info_query):
|
||||
@@ -593,7 +544,7 @@ class JCLComponent(Component, object):
|
||||
###########################################################################
|
||||
# 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))
|
||||
type, value, stack = sys.exc_info()
|
||||
@@ -643,72 +594,6 @@ class AccountManager(object):
|
||||
|
||||
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 ######
|
||||
def account_get_register(self, info_query,
|
||||
name,
|
||||
@@ -718,19 +603,19 @@ class AccountManager(object):
|
||||
"""Handle get_register on an account.
|
||||
Return a preinitialized form"""
|
||||
info_query = info_query.make_result_response()
|
||||
account_class = self._get_account_class(account_type + "Account")
|
||||
self.db_connect()
|
||||
account_class = self.get_account_class(account_type + "Account")
|
||||
model.db_connect()
|
||||
accounts = account_class.select(\
|
||||
AND(account_class.q.name == name,
|
||||
account_class.q.user_jid == unicode(from_jid.bare())))
|
||||
if accounts is not None:
|
||||
query = info_query.new_query("jabber:iq:register")
|
||||
_account = accounts[0]
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
self.get_reg_form_init(lang_class,
|
||||
_account).as_xml(query)
|
||||
else:
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return [info_query]
|
||||
|
||||
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"""
|
||||
return self._account_type_get_register(\
|
||||
info_query,
|
||||
self._get_account_class(account_type + "Account"),
|
||||
self.get_account_class(account_type + "Account"),
|
||||
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):
|
||||
"""Unsubscribe all accounts associated to 'user_jid' then delete
|
||||
those accounts from the DataBase"""
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
result = []
|
||||
for _account in Account.select(Account.q.user_jid == unicode(user_jid)):
|
||||
self.__logger.debug("Deleting " + _account.name
|
||||
@@ -781,7 +666,7 @@ class AccountManager(object):
|
||||
result.append(Presence(from_jid=self.component.jid,
|
||||
to_jid=user_jid,
|
||||
stanza_type="unsubscribed"))
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return result
|
||||
|
||||
def _populate_account(self, _account, lang_class, x_data,
|
||||
@@ -791,7 +676,7 @@ class AccountManager(object):
|
||||
result = []
|
||||
from_jid = info_query.get_from()
|
||||
bare_from_jid = unicode(from_jid.bare())
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
try:
|
||||
for (field, field_type, field_options, field_post_func,
|
||||
field_default_func) in _account.get_register_fields():
|
||||
@@ -816,7 +701,7 @@ class AccountManager(object):
|
||||
lang_class.mandatory_field % (field))
|
||||
text.setNs(text.newNs(error.STANZA_ERROR_NS, None))
|
||||
result.append(iq_error)
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return result
|
||||
result.append(info_query.make_result_response())
|
||||
|
||||
@@ -840,7 +725,7 @@ class AccountManager(object):
|
||||
to_jid=_account.user_jid,
|
||||
subject=_account.get_update_message_subject(lang_class),
|
||||
body=_account.get_update_message_body(lang_class)))
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return result
|
||||
|
||||
def account_set_register(self, name, from_jid, lang_class,
|
||||
@@ -848,13 +733,13 @@ class AccountManager(object):
|
||||
"""Update account"""
|
||||
self.__logger.debug("Updating account " + name)
|
||||
bare_from_jid = from_jid.bare()
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
accounts = Account.select(\
|
||||
AND(Account.q.name == name,
|
||||
Account.q.user_jid == unicode(bare_from_jid)))
|
||||
accounts_count = accounts.count()
|
||||
_account = list(accounts)[0]
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
if accounts_count > 1:
|
||||
# Just print a warning, only the first account will be use
|
||||
self.__logger.error("There might not exist 2 accounts for " +
|
||||
@@ -874,7 +759,7 @@ class AccountManager(object):
|
||||
x_data,
|
||||
info_query):
|
||||
"""Create new account from account_class"""
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
bare_from_jid = from_jid.bare()
|
||||
_account = account_class(user_jid=unicode(bare_from_jid),
|
||||
name=name,
|
||||
@@ -882,7 +767,7 @@ class AccountManager(object):
|
||||
all_accounts = Account.select(\
|
||||
Account.q.user_jid == unicode(bare_from_jid))
|
||||
first_account = (all_accounts.count() > 0)
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return self._populate_account(_account, lang_class, x_data,
|
||||
info_query, True, first_account)
|
||||
|
||||
@@ -895,7 +780,7 @@ class AccountManager(object):
|
||||
"""Create new typed account"""
|
||||
return self._account_type_set_register(\
|
||||
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)
|
||||
|
||||
def root_set_register(self, name, from_jid, lang_class,
|
||||
@@ -911,39 +796,12 @@ class AccountManager(object):
|
||||
|
||||
|
||||
###### 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):
|
||||
"""Send presence to all account. Optimized to use only one sql
|
||||
request"""
|
||||
current_user_jid = None
|
||||
result = []
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
# Explicit reference to account table (clauseTables) to use
|
||||
# "user_jid" column with Account subclasses
|
||||
for _account in \
|
||||
@@ -951,146 +809,50 @@ class AccountManager(object):
|
||||
orderBy="user_jid"):
|
||||
if 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,
|
||||
presence))
|
||||
result.extend(getattr(self, "_send_presence_" +
|
||||
result.extend(getattr(self, "send_presence_" +
|
||||
presence)(_account))
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
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):
|
||||
"""Send presence probe to all registered accounts"""
|
||||
return self.send_presence_all("probe")
|
||||
|
||||
###### Utils methods ######
|
||||
def _has_account(self, from_jid, name=None):
|
||||
"""Check if user with \"from_jid\" JID has an account.
|
||||
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,
|
||||
def list_accounts(self, bare_from_jid, account_class=None,
|
||||
account_type=""):
|
||||
"""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 != "":
|
||||
resource = "/" + account_type
|
||||
account_type = account_type + "/"
|
||||
else:
|
||||
resource = ""
|
||||
self.db_connect()
|
||||
accounts = _account_class.select(_account_class.q.user_jid == \
|
||||
model.db_connect()
|
||||
accounts = account_class.select(account_class.q.user_jid == \
|
||||
unicode(bare_from_jid))
|
||||
if accounts.count() == 0:
|
||||
return None
|
||||
disco_items = DiscoItems()
|
||||
return
|
||||
for _account in accounts:
|
||||
self.__logger.debug(str(_account))
|
||||
DiscoItem(disco_items,
|
||||
JID(unicode(_account.jid) + resource),
|
||||
account_type + _account.name,
|
||||
_account.long_name)
|
||||
self.db_disconnect()
|
||||
return disco_items
|
||||
yield (_account, resource, account_type)
|
||||
model.db_disconnect()
|
||||
|
||||
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
|
||||
account_classes from its 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")
|
||||
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):
|
||||
"""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,
|
||||
instructions=lang_class.register_instructions)
|
||||
@@ -1123,7 +875,7 @@ class AccountManager(object):
|
||||
name="name",
|
||||
required=True)
|
||||
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
for (field_name,
|
||||
field_type,
|
||||
field_options,
|
||||
@@ -1158,11 +910,12 @@ class AccountManager(object):
|
||||
except:
|
||||
self.__logger.debug("Setting field " + field_name + " required")
|
||||
field.required = True
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
return reg_form
|
||||
|
||||
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__,
|
||||
_account.user_jid)
|
||||
@@ -1177,31 +930,34 @@ class AccountManager(object):
|
||||
"""Compose account jid from account name"""
|
||||
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"""
|
||||
return [Presence(from_jid=_account.jid,
|
||||
to_jid=_account.user_jid,
|
||||
stanza_type="probe")]
|
||||
|
||||
def _send_presence_unavailable(self, _account):
|
||||
def send_presence_unavailable(self, _account):
|
||||
"""Send unavailable presence to account's user"""
|
||||
model.db_connect()
|
||||
_account.status = account.OFFLINE
|
||||
return [Presence(from_jid=_account.jid,
|
||||
result = [Presence(from_jid=_account.jid,
|
||||
to_jid=_account.user_jid,
|
||||
stanza_type="unavailable")]
|
||||
model.db_disconnect()
|
||||
return result
|
||||
|
||||
def _send_root_presence(self, to_jid, presence_type,
|
||||
def send_root_presence(self, to_jid, presence_type,
|
||||
show=None, status=None):
|
||||
result = self._send_presence(self.component.jid, to_jid,
|
||||
result = self.send_presence(self.component.jid, to_jid,
|
||||
presence_type, show=show,
|
||||
status=status)
|
||||
result.extend(self._send_root_presence_legacy(to_jid,
|
||||
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):
|
||||
def send_presence(self, from_jid, to_jid, presence_type, status=None, show=None):
|
||||
"""Send presence stanza"""
|
||||
return [Presence(from_jid=from_jid,
|
||||
to_jid=to_jid,
|
||||
@@ -1209,10 +965,11 @@ class AccountManager(object):
|
||||
show=show,
|
||||
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
|
||||
if necessary"""
|
||||
result = []
|
||||
model.db_connect()
|
||||
_account.default_lang_class = lang_class
|
||||
old_status = _account.status
|
||||
if show is None:
|
||||
@@ -1230,23 +987,19 @@ class AccountManager(object):
|
||||
and old_status == account.OFFLINE \
|
||||
and _account.password == None :
|
||||
result.extend(self.ask_password(_account, lang_class))
|
||||
model.db_disconnect()
|
||||
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):
|
||||
"""Send presence from legacy JID"""
|
||||
result = []
|
||||
self.db_connect()
|
||||
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:
|
||||
for legacy_jid in account.get_legacy_jids(unicode(to_jid.bare())):
|
||||
result.append(Presence(from_jid=legacy_jid.jid,
|
||||
to_jid=to_jid,
|
||||
show=show,
|
||||
status=status,
|
||||
stanza_type=presence_type))
|
||||
self.db_disconnect()
|
||||
return result
|
||||
|
||||
def ask_password(self, _account, lang_class):
|
||||
@@ -1265,6 +1018,20 @@ class AccountManager(object):
|
||||
(_account.name)))
|
||||
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):
|
||||
"""Send an error message only one time until _account.in_error
|
||||
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.component import JCLComponent
|
||||
from jcl.lang import Lang
|
||||
import jcl.model as model
|
||||
from jcl.model.account import Account
|
||||
|
||||
from pyxmpp.message import Message
|
||||
@@ -48,14 +49,12 @@ class FeederComponent(JCLComponent):
|
||||
secret,
|
||||
server,
|
||||
port,
|
||||
db_connection_str,
|
||||
lang = Lang()):
|
||||
JCLComponent.__init__(self,
|
||||
jid,
|
||||
secret,
|
||||
server,
|
||||
port,
|
||||
db_connection_str,
|
||||
lang=lang)
|
||||
# Define default feeder and sender, can be override
|
||||
self.handler = FeederHandler(Feeder(self), Sender(self))
|
||||
@@ -65,12 +64,12 @@ class FeederComponent(JCLComponent):
|
||||
|
||||
def handle_tick(self):
|
||||
"""Implement main feed/send behavior"""
|
||||
self.db_connect()
|
||||
model.db_connect()
|
||||
self.handler.handle(\
|
||||
None, self.lang.get_default_lang_class(),
|
||||
self.handler.filter(None,
|
||||
self.lang.get_default_lang_class()))
|
||||
self.db_disconnect()
|
||||
model.db_disconnect()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,16 +22,19 @@
|
||||
|
||||
import re
|
||||
|
||||
from sqlobject.sqlbuilder import AND
|
||||
from pyxmpp.message import Message
|
||||
|
||||
from jcl.jabber import Handler
|
||||
import jcl.model.account as account
|
||||
from jcl.model.account import Account
|
||||
|
||||
class PasswordMessageHandler(Handler):
|
||||
"""Handle password message"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, component):
|
||||
"""handler constructor"""
|
||||
Handler.__init__(self, component)
|
||||
self.password_regexp = re.compile("\[PASSWORD\]")
|
||||
|
||||
def filter(self, stanza, lang_class):
|
||||
@@ -39,23 +42,14 @@ class PasswordMessageHandler(Handler):
|
||||
Return the uniq account associated with a name and user JID.
|
||||
DB connection might already be opened.
|
||||
"""
|
||||
name = stanza.get_to().node
|
||||
bare_from_jid = unicode(stanza.get_from().bare())
|
||||
accounts = Account.select(\
|
||||
AND(Account.q.name == name,
|
||||
Account.q.user_jid == bare_from_jid))
|
||||
if accounts.count() > 1:
|
||||
print >>sys.stderr, "Account " + name + " for user " + \
|
||||
bare_from_jid + " must be uniq"
|
||||
elif accounts.count() == 0:
|
||||
return None
|
||||
_account = accounts[0]
|
||||
_account = account.get_account(stanza.get_to().node,
|
||||
stanza.get_from().bare())
|
||||
if hasattr(_account, 'password') \
|
||||
and hasattr(_account, 'waiting_password_reply') \
|
||||
and (getattr(_account, 'waiting_password_reply') == True) \
|
||||
and self.password_regexp.search(stanza.get_subject()) \
|
||||
is not None:
|
||||
return accounts
|
||||
return _account
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -63,10 +57,6 @@ class PasswordMessageHandler(Handler):
|
||||
"""
|
||||
Receive password in stanza (must be a Message) for given account.
|
||||
"""
|
||||
_account = data[0]
|
||||
_account.password = stanza.get_body()
|
||||
_account.waiting_password_reply = False
|
||||
return [Message(from_jid=_account.jid,
|
||||
to_jid=stanza.get_from(),
|
||||
subject=lang_class.password_saved_for_session,
|
||||
body=lang_class.password_saved_for_session)]
|
||||
return self.component.account_manager.set_password(data, stanza.get_from(),
|
||||
stanza.get_body(),
|
||||
lang_class)
|
||||
|
||||
@@ -24,17 +24,19 @@
|
||||
from pyxmpp.presence import Presence
|
||||
|
||||
from jcl.jabber import Handler
|
||||
import jcl.jabber as jabber
|
||||
import jcl.model as model
|
||||
|
||||
class DefaultPresenceHandler(Handler):
|
||||
"""Handle presence"""
|
||||
|
||||
def handle(self, presence, lang_class, data):
|
||||
def handle(self, stanza, lang_class, data):
|
||||
"""Return same presence as receive one"""
|
||||
to_jid = presence.get_to()
|
||||
from_jid = presence.get_from()
|
||||
presence.set_to(from_jid)
|
||||
presence.set_from(to_jid)
|
||||
return [presence]
|
||||
to_jid = stanza.get_to()
|
||||
from_jid = stanza.get_from()
|
||||
stanza.set_to(from_jid)
|
||||
stanza.set_from(to_jid)
|
||||
return [stanza]
|
||||
|
||||
class DefaultSubscribeHandler(Handler):
|
||||
"""Return default response to subscribe queries"""
|
||||
@@ -64,3 +66,94 @@ class DefaultUnsubscribeHandler(Handler):
|
||||
stanza_type="unsubscribed"))
|
||||
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
|
||||
|
||||
from jcl.jabber.tests import component, feeder, command
|
||||
from jcl.jabber.tests import component, feeder, command, message, presence
|
||||
|
||||
def suite():
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(component.suite())
|
||||
suite.addTest(feeder.suite())
|
||||
suite.addTest(command.suite())
|
||||
suite.addTest(message.suite())
|
||||
suite.addTest(presence.suite())
|
||||
return suite
|
||||
|
||||
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, \
|
||||
HeadlineSender, FeederHandler
|
||||
from jcl.model.account import Account, LegacyJID
|
||||
import jcl.model as model
|
||||
from jcl.model import account
|
||||
|
||||
from jcl.model.tests.account import ExampleAccount, Example2Account
|
||||
@@ -65,24 +66,24 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
||||
self.comp = FeederComponent("jcl.test.com",
|
||||
"password",
|
||||
"localhost",
|
||||
"5347",
|
||||
'sqlite://' + DB_URL)
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
"5347")
|
||||
model.db_connection_str = 'sqlite://' + DB_URL
|
||||
model.db_connect()
|
||||
Account.createTable(ifNotExists = True)
|
||||
LegacyJID.createTable(ifNotExists=True)
|
||||
ExampleAccount.createTable(ifNotExists = True)
|
||||
Example2Account.createTable(ifNotExists = True)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
def tearDown(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
Account.dropTable(ifExists = True)
|
||||
LegacyJID.dropTable(ifExists=True)
|
||||
ExampleAccount.dropTable(ifExists = True)
|
||||
Example2Account.dropTable(ifExists = True)
|
||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||
account.hub.threadConnection.close()
|
||||
del account.hub.threadConnection
|
||||
model.hub.threadConnection.close()
|
||||
model.db_disconnect()
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
|
||||
@@ -90,7 +91,7 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
||||
self.comp.time_unit = 1
|
||||
self.comp.stream = 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")
|
||||
run_thread.start()
|
||||
time.sleep(1)
|
||||
@@ -118,7 +119,7 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
|
||||
|
||||
self.comp.stream = MockStream()
|
||||
self.comp.stream_class = MockStream
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
account11 = Account(user_jid = "user1@test.com", \
|
||||
name = "account11", \
|
||||
jid = "account11@jcl.test.com")
|
||||
@@ -190,29 +191,29 @@ class MessageSender_TestCase(unittest.TestCase):
|
||||
self.comp = FeederComponent("jcl.test.com",
|
||||
"password",
|
||||
"localhost",
|
||||
"5347",
|
||||
'sqlite://' + DB_URL)
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
"5347")
|
||||
model.db_connection_str = 'sqlite://' + DB_URL
|
||||
model.db_connect()
|
||||
Account.createTable(ifNotExists = True)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
self.sender = MessageSender(self.comp)
|
||||
self.message_type = None
|
||||
|
||||
def tearDown(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
Account.dropTable(ifExists = True)
|
||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||
account.hub.threadConnection.close()
|
||||
del account.hub.threadConnection
|
||||
model.hub.threadConnection.close()
|
||||
model.db_disconnect()
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
|
||||
def test_send(self):
|
||||
self.comp.stream = MockStream()
|
||||
self.comp.stream_class = MockStream
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
account11 = Account(user_jid = "user1@test.com", \
|
||||
name = "account11", \
|
||||
model.db_connect()
|
||||
account11 = Account(user_jid="user1@test.com",
|
||||
name="account11",
|
||||
jid="account11@jcl.test.com")
|
||||
self.sender.send(account11, ("subject", "Body message"))
|
||||
self.assertEquals(len(self.comp.stream.sent), 1)
|
||||
@@ -222,7 +223,7 @@ class MessageSender_TestCase(unittest.TestCase):
|
||||
self.assertEquals(message.get_subject(), "subject")
|
||||
self.assertEquals(message.get_body(), "Body message")
|
||||
self.assertEquals(message.get_type(), self.message_type)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
class HeadlineSender_TestCase(MessageSender_TestCase):
|
||||
def setUp(self):
|
||||
@@ -235,24 +236,25 @@ class FeederHandler_TestCase(unittest.TestCase):
|
||||
self.handler = FeederHandler(FeederMock(), SenderMock())
|
||||
if os.path.exists(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)
|
||||
ExampleAccount.createTable(ifNotExists = True)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
def tearDown(self):
|
||||
self.handler = None
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
ExampleAccount.dropTable(ifExists = True)
|
||||
Account.dropTable(ifExists = True)
|
||||
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
|
||||
account.hub.threadConnection.close()
|
||||
del account.hub.threadConnection
|
||||
model.hub.threadConnection.close()
|
||||
model.db_disconnect()
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
|
||||
def test_filter(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
account12 = ExampleAccount(user_jid="user2@test.com",
|
||||
name="account12",
|
||||
jid="account12@jcl.test.com")
|
||||
@@ -264,10 +266,10 @@ class FeederHandler_TestCase(unittest.TestCase):
|
||||
# accounts must be ordered by user_jid
|
||||
self.assertEquals(accounts[0].name, "account11")
|
||||
self.assertEquals(accounts[1].name, "account12")
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
def test_handle(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
|
||||
model.db_connect()
|
||||
account11 = ExampleAccount(user_jid="user1@test.com",
|
||||
name="account11",
|
||||
jid="account11@jcl.test.com")
|
||||
@@ -279,7 +281,7 @@ class FeederHandler_TestCase(unittest.TestCase):
|
||||
self.assertEquals(len(sent), 2)
|
||||
self.assertEquals(sent[0], (account11, ("subject", "body")))
|
||||
self.assertEquals(sent[1], (account12, ("subject", "body")))
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
def suite():
|
||||
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"""
|
||||
__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.col import StringCol, EnumCol, IntCol, BoolCol, ForeignKey
|
||||
from sqlobject.dbconnection import ConnectionHub
|
||||
from sqlobject.joins import MultipleJoin
|
||||
from sqlobject.sqlbuilder import AND
|
||||
|
||||
from jcl.lang import Lang
|
||||
from jcl.error import FieldError
|
||||
import jcl.model as model
|
||||
|
||||
OFFLINE = "offline"
|
||||
ONLINE = "online"
|
||||
|
||||
|
||||
def default_post_func(field_value, default_func, bare_from_jid):
|
||||
"""Default post process function: do nothing"""
|
||||
if field_value is None or str(field_value) == "":
|
||||
@@ -57,13 +57,32 @@ def mandatory_field(field_value):
|
||||
raise FieldError # TODO : add translated message
|
||||
return field_value
|
||||
|
||||
# create a hub to attach a per thread connection
|
||||
hub = ConnectionHub()
|
||||
def get_account(name, bare_user_jid):
|
||||
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):
|
||||
"""Base Account class"""
|
||||
_cacheValue = False
|
||||
_connection = hub
|
||||
_connection = model.hub
|
||||
user_jid = StringCol()
|
||||
name = StringCol()
|
||||
jid = StringCol()
|
||||
@@ -268,8 +287,17 @@ class PresenceAccount(Account):
|
||||
|
||||
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):
|
||||
_connection = hub
|
||||
_connection = model.hub
|
||||
|
||||
legacy_address = StringCol()
|
||||
jid = StringCol()
|
||||
|
||||
@@ -28,6 +28,7 @@ from sqlobject import *
|
||||
from sqlobject.dbconnection import TheURIOpener
|
||||
|
||||
from jcl.error import FieldError
|
||||
import jcl.model as model
|
||||
from jcl.model import account
|
||||
from jcl.model.account import Account, PresenceAccount
|
||||
|
||||
@@ -165,13 +166,15 @@ class AccountModule_TestCase(unittest.TestCase):
|
||||
class InheritableAccount_TestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.db_url = DB_URL
|
||||
model.db_connection_str = 'sqlite://' + self.db_url
|
||||
|
||||
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
|
||||
exception.
|
||||
"""
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
||||
model.db_connect()
|
||||
for (field_name,
|
||||
field_type,
|
||||
field_options,
|
||||
@@ -184,41 +187,42 @@ class InheritableAccount_TestCase(unittest.TestCase):
|
||||
except FieldError, error:
|
||||
# this type of error is OK
|
||||
pass
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
class Account_TestCase(InheritableAccount_TestCase):
|
||||
def setUp(self):
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
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)
|
||||
ExampleAccount.createTable(ifNotExists = True)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
self.account_class = Account
|
||||
|
||||
def tearDown(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
||||
model.db_connect()
|
||||
ExampleAccount.dropTable(ifExists = True)
|
||||
Account.dropTable(ifExists = True)
|
||||
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
||||
account.hub.threadConnection.close()
|
||||
del account.hub.threadConnection
|
||||
model.hub.threadConnection.close()
|
||||
model.db_disconnect()
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
|
||||
def test_set_status(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
||||
model.db_connect()
|
||||
account11 = Account(user_jid="test1@test.com",
|
||||
name="account11",
|
||||
jid="account11@jcl.test.com")
|
||||
account11.status = account.OFFLINE
|
||||
self.assertEquals(account11.status, account.OFFLINE)
|
||||
# TODO : test first_check attribute
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
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",
|
||||
name="account11",
|
||||
jid="account11@jcl.test.com",
|
||||
@@ -232,32 +236,33 @@ class Account_TestCase(InheritableAccount_TestCase):
|
||||
self.assertEquals(account11.status, account.OFFLINE)
|
||||
self.assertEquals(account11.waiting_password_reply, False)
|
||||
self.assertEquals(account11.password, None)
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
|
||||
class PresenceAccount_TestCase(InheritableAccount_TestCase):
|
||||
def setUp(self):
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
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)
|
||||
PresenceAccount.createTable(ifNotExists = True)
|
||||
PresenceAccountExample.createTable(ifNotExists = True)
|
||||
self.account = PresenceAccountExample(\
|
||||
user_jid = "test1@test.com", \
|
||||
name = "account11", \
|
||||
user_jid="test1@test.com",
|
||||
name="account11",
|
||||
jid="account11@jcl.test.com")
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
self.account_class = PresenceAccount
|
||||
|
||||
def tearDown(self):
|
||||
account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url)
|
||||
model.db_connect()
|
||||
PresenceAccountExample.dropTable(ifExists = True)
|
||||
PresenceAccount.dropTable(ifExists = True)
|
||||
Account.dropTable(ifExists = True)
|
||||
del TheURIOpener.cachedURIs['sqlite://' + self.db_url]
|
||||
account.hub.threadConnection.close()
|
||||
del account.hub.threadConnection
|
||||
model.hub.threadConnection.close()
|
||||
model.db_disconnect()
|
||||
if os.path.exists(DB_PATH):
|
||||
os.unlink(DB_PATH)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ from getopt import gnu_getopt
|
||||
|
||||
from sqlobject import *
|
||||
|
||||
import jcl.model as model
|
||||
from jcl.model import account
|
||||
from jcl.model.account import Account, PresenceAccount
|
||||
|
||||
@@ -48,35 +49,35 @@ class JCLRunner(object):
|
||||
self.language = "en"
|
||||
self.db_url = "sqlite:///var/spool/jabber/jcl.db"
|
||||
self.pid_file = "/var/run/jabber/jcl.pid"
|
||||
self.options = [("c:", "config-file=", None, \
|
||||
" FILE\t\t\t\tConfiguration file to use", \
|
||||
lambda arg: self.set_attr("config_file", arg)), \
|
||||
("S:", "server=", "jabber", \
|
||||
" SERVER_ADDRESS\t\t\tAddress of the Jabber server", \
|
||||
lambda arg: self.set_attr("server", arg)), \
|
||||
("P:", "port=", "jabber", \
|
||||
" PORT\t\t\t\t\tPort of the Jabber server to connect the component", \
|
||||
lambda arg: self.set_attr("port", int(arg))), \
|
||||
("s:", "secret=", "jabber", \
|
||||
" SECRET\t\t\t\tComponent password to connect to the Jabber server", \
|
||||
lambda arg: self.set_attr("secret", arg)), \
|
||||
("j:", "service-jid=", "jabber", \
|
||||
" JID\t\t\t\tJID of the component", \
|
||||
lambda arg: self.set_attr("service_jid", arg)), \
|
||||
("l:", "language=", "jabber", \
|
||||
" LANG\t\t\t\tDefault Language of the component", \
|
||||
lambda arg: self.set_attr("language", arg)), \
|
||||
("u:", "db-url=", "db", \
|
||||
" URL\t\t\t\tDatabase URL", \
|
||||
lambda arg: self.set_attr("db_url", arg)), \
|
||||
("p:", "pid-file=", "component", \
|
||||
" FILE\t\t\t\tPath of the PID file", \
|
||||
lambda arg: self.set_attr("pid_file", arg)), \
|
||||
("d", "debug", None, \
|
||||
"\t\t\t\t\tEnable debug traces", \
|
||||
lambda arg: self.set_attr("debug", True)), \
|
||||
("h", "help", None, \
|
||||
"\t\t\t\t\tThis help", \
|
||||
self.options = [("c:", "config-file=", None,
|
||||
" FILE\t\t\t\tConfiguration file to use",
|
||||
lambda arg: self.set_attr("config_file", arg)),
|
||||
("S:", "server=", "jabber",
|
||||
" SERVER_ADDRESS\t\t\tAddress of the Jabber server",
|
||||
lambda arg: self.set_attr("server", arg)),
|
||||
("P:", "port=", "jabber",
|
||||
" PORT\t\t\t\t\tPort of the Jabber server to connect the component",
|
||||
lambda arg: self.set_attr("port", int(arg))),
|
||||
("s:", "secret=", "jabber",
|
||||
" SECRET\t\t\t\tComponent password to connect to the Jabber server",
|
||||
lambda arg: self.set_attr("secret", arg)),
|
||||
("j:", "service-jid=", "jabber",
|
||||
" JID\t\t\t\tJID of the component",
|
||||
lambda arg: self.set_attr("service_jid", arg)),
|
||||
("l:", "language=", "jabber",
|
||||
" LANG\t\t\t\tDefault Language of the component",
|
||||
lambda arg: self.set_attr("language", arg)),
|
||||
("u:", "db-url=", "db",
|
||||
" URL\t\t\t\tDatabase URL",
|
||||
lambda arg: self.set_attr("db_url", arg)),
|
||||
("p:", "pid-file=", "component",
|
||||
" FILE\t\t\t\tPath of the PID file",
|
||||
lambda arg: self.set_attr("pid_file", arg)),
|
||||
("d", "debug", None,
|
||||
"\t\t\t\t\tEnable debug traces",
|
||||
lambda arg: self.set_attr("debug", True)),
|
||||
("h", "help", None,
|
||||
"\t\t\t\t\tThis help",
|
||||
lambda arg: self.print_help())]
|
||||
self.logger = logging.getLogger()
|
||||
self.logger.addHandler(logging.StreamHandler())
|
||||
@@ -97,7 +98,7 @@ class JCLRunner(object):
|
||||
def __apply_commandline_args(self, commandline_args, cleanopts):
|
||||
for arg in commandline_args:
|
||||
value = commandline_args[arg]
|
||||
self.logger.debug("Applying argument " + arg + " = " + \
|
||||
self.logger.debug("Applying argument " + arg + " = " +
|
||||
value)
|
||||
cleanopts[arg][1](value)
|
||||
|
||||
@@ -118,9 +119,9 @@ class JCLRunner(object):
|
||||
if section is not None:
|
||||
attr = opt.replace("-", "_")
|
||||
config_property = self.config.get(section, attr)
|
||||
self.logger.debug("Setting " + attr + " = " + \
|
||||
config_property + \
|
||||
" from configuration file " + \
|
||||
self.logger.debug("Setting " + attr + " = " +
|
||||
config_property +
|
||||
" from configuration file " +
|
||||
self.config_file)
|
||||
set_func(config_property)
|
||||
|
||||
@@ -186,10 +187,11 @@ class JCLRunner(object):
|
||||
def _run(self, run_func):
|
||||
try:
|
||||
self.setup_pidfile()
|
||||
account.hub.threadConnection = connectionForURI(self.db_url)
|
||||
model.db_connection_str = self.db_url
|
||||
model.db_connect()
|
||||
self.setup_db()
|
||||
del account.hub.threadConnection
|
||||
self.logger.debug(self.component_name + " v" + \
|
||||
model.db_disconnect()
|
||||
self.logger.debug(self.component_name + " v" +
|
||||
self.component_version + " is starting ...")
|
||||
run_func()
|
||||
self.logger.debug(self.component_name + " is exiting")
|
||||
@@ -199,11 +201,10 @@ class JCLRunner(object):
|
||||
|
||||
def run(self):
|
||||
def run_func():
|
||||
component = JCLComponent(jid = self.service_jid, \
|
||||
secret = self.secret, \
|
||||
server = self.server, \
|
||||
port = self.port, \
|
||||
db_connection_str = self.db_url, \
|
||||
component = JCLComponent(jid=self.service_jid,
|
||||
secret=self.secret,
|
||||
server=self.server,
|
||||
port=self.port,
|
||||
lang=Lang(self.language))
|
||||
component.run()
|
||||
self._run(run_func)
|
||||
|
||||
@@ -29,6 +29,7 @@ from sqlobject import *
|
||||
import jcl
|
||||
from jcl.runner import JCLRunner
|
||||
|
||||
import jcl.model as model
|
||||
from jcl.model import account
|
||||
from jcl.model.account import Account, PresenceAccount
|
||||
|
||||
@@ -125,11 +126,11 @@ class JCLRunner_TestCase(unittest.TestCase):
|
||||
def do_nothing():
|
||||
pass
|
||||
self.runner._run(do_nothing)
|
||||
account.hub.threadConnection = connectionForURI(self.runner.db_url)
|
||||
model.db_connect()
|
||||
# dropTable should succeed because tables should exist
|
||||
Account.dropTable()
|
||||
PresenceAccount.dropTable()
|
||||
del account.hub.threadConnection
|
||||
model.db_disconnect()
|
||||
os.unlink(DB_PATH)
|
||||
self.assertFalse(os.access("/tmp/jcl.pid", os.F_OK))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user