Files
jcl/src/jcl/jabber/command.py
David Rousselie 6e46ad62b5 Handle exception CommandError sent from ad-hoc commands implementations
darcs-hash:20080307071827-86b55-450e960980325a71b51772f3d608f09ae2a2abe8.gz
2008-03-07 08:18:27 +01:00

1323 lines
64 KiB
Python

# -*- coding: utf-8 -*-
##
## command.py
## Login : David Rousselie <dax@happycoders.org>
## Started on Wed Jun 20 08:19:57 2007 David Rousselie
## $Id$
##
## Copyright (C) 2007 David Rousselie
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import re
import datetime
import logging
import threading
from sqlobject.sqlbuilder import AND
from pyxmpp.jid import JID
from pyxmpp.jabber.disco import DiscoInfo, DiscoItems, DiscoItem, DiscoIdentity
from pyxmpp.jabber.dataforms import Form, Field
from pyxmpp.message import Message
from jcl.jabber.disco import DiscoHandler, RootDiscoGetInfoHandler
from jcl.model import account
from jcl.model.account import Account, User
COMMAND_NS = "http://jabber.org/protocol/commands"
ACTION_COMPLETE = "complete"
ACTION_NEXT = "next"
ACTION_PREVIOUS = "prev"
ACTION_CANCEL = "cancel"
STATUS_COMPLETED = "completed"
STATUS_EXECUTING = "executing"
STATUS_CANCELED = "canceled"
root_node_re = re.compile("^[^@/]+$")
account_type_node_re = re.compile("^[^@/]+/.*$")
account_node_re = re.compile("^[^@/]+@[^/]+/?.*$")
class FieldNoType(Field):
"""
Field with no 'type' attribut
"""
def complete_xml_element(self, xmlnode, doc):
"""Remove the 'type' attribut"""
result = Field.complete_xml_element(self, xmlnode, doc)
result.unsetProp("type")
return result
class CommandError(Exception):
"""
Exception use by commands to report errors
"""
def __init__ (self, error_type="service-unavailable"):
"""
CommandError constructor
"""
Exception.__init__(self)
self.type = error_type
class CommandManager(object):
"""Handle Ad-Hoc commands"""
def __init__(self, component=None, account_manager=None):
"""CommandManager constructor"""
self.__logger = logging.getLogger("jcl.jabber.command.CommandManager")
self.component = component
self.account_manager = account_manager
self.commands = {}
self.command_re = re.compile("([^#]*#)?(.*)")
self.sessions = {}
def get_short_command_name(self, command_name):
"""
Return short command name associated to given command name:
'http://jabber.org/protocol/admin#add-user' -> 'add-user'
"""
match = self.command_re.match(command_name)
return match.group(2).replace('-', '_')
def get_command_desc(self, command_name, lang_class):
"""Return localized command description"""
short_command_name = self.get_short_command_name(command_name)
command_desc_attribut = "command_" + short_command_name
if hasattr(lang_class, command_desc_attribut):
command_desc = getattr(lang_class, command_desc_attribut)
else:
command_desc = short_command_name
return command_desc
def list_commands(self, jid, to_jid, disco_items, lang_class):
"""Return DiscoItem for each supported commands"""
for command_name in self.commands.keys():
(must_be_admin, to_jid_re) = self.commands[command_name]
if to_jid_re.match(unicode(to_jid)) and \
(not must_be_admin or
(must_be_admin and self.component.is_admin(jid))):
command_desc = self.get_command_desc(command_name,
lang_class)
DiscoItem(disco_items,
to_jid,
command_name,
command_desc)
return disco_items
def get_command_info(self, disco_info, command_name, lang_class):
"""Return command infos"""
disco_info.add_feature(COMMAND_NS)
DiscoIdentity(disco_info,
self.get_command_desc(command_name, lang_class),
"automation",
"command-node")
return disco_info
def apply_command_action(self, info_query, command_name, action):
"""Apply action on command"""
if self.commands.has_key(command_name):
(must_be_admin, to_jid_re) = self.commands[command_name]
to_jid = info_query.get_to()
if to_jid_re.match(unicode(to_jid)) and \
not must_be_admin or \
(must_be_admin and
self.component.is_admin(info_query.get_from())):
short_command_name = self.get_short_command_name(command_name)
action_command_method = "apply_" + action + "_command"
if hasattr(self, action_command_method):
return getattr(self, action_command_method)(info_query,
short_command_name)
else:
self.__logger.error("Action '" + str(action) + "' unknown")
return [info_query.make_error_response(\
"feature-not-implemented")]
else:
self.__logger.error(unicode(info_query.get_from().bare()) + " must "
+ "be in admin list")
return [info_query.make_error_response(\
"forbidden")]
else:
self.__logger.error("Command " + str(command_name) + " not found")
return [info_query.make_error_response(\
"feature-not-implemented")]
def apply_execute_command(self, info_query, short_command_name):
return self.execute_multi_step_command(\
info_query,
short_command_name,
lambda session_id: (self.sessions[session_id][0] + 1,
self.sessions[session_id][1]))
apply_next_command = apply_execute_command
def apply_prev_command(self, info_query, short_command_name):
return self.execute_multi_step_command(\
info_query,
short_command_name,
lambda session_id: (self.sessions[session_id][0] - 1,
self.sessions[session_id][1]))
def apply_cancel_command(self, info_query, short_command_name):
xml_command = info_query.xpath_eval("c:command",
{"c": "http://jabber.org/protocol/commands"})[0]
if xml_command.hasProp("sessionid"):
session_id = xml_command.prop("sessionid")
response = info_query.make_result_response()
command_node = response.set_new_content(COMMAND_NS, "command")
command_node.setProp("node", xml_command.prop("node"))
command_node.setProp("status", STATUS_CANCELED)
command_node.setProp("sessionid",
session_id)
del self.sessions[session_id]
return [response]
def generate_session_id(self, node):
return self.get_short_command_name(node) + ":" + \
datetime.datetime.now().isoformat()
def _create_response(self, info_query, completed=True):
xml_command = info_query.xpath_eval(\
"c:command",
{"c": "http://jabber.org/protocol/commands"})[0]
node = xml_command.prop("node")
if xml_command.hasProp("sessionid"):
session_id = xml_command.prop("sessionid")
else:
session_id = self.generate_session_id(node)
self.__logger.debug("Creating command execution with session ID "
+ str(session_id))
response = info_query.make_result_response()
command_node = response.set_new_content(COMMAND_NS, "command")
command_node.setProp("node", node)
if completed:
command_node.setProp("status", STATUS_COMPLETED)
else:
command_node.setProp("status", STATUS_EXECUTING)
command_node.setProp("sessionid",
session_id)
return (response, command_node, session_id)
def parse_form(self, info_query, session_id):
fields = info_query.xpath_eval(\
"c:command/data:x/data:field",
{"c": "http://jabber.org/protocol/commands",
"data": "jabber:x:data"})
for field in fields:
field_name = field.prop("var")
values = info_query.xpath_eval(\
"c:command/data:x/data:field[@var='"
+ field_name + "']/data:value",
{"c": "http://jabber.org/protocol/commands",
"data": "jabber:x:data"})
if len(values) > 0:
values = map(lambda value: value.content, values)
self.__logger.debug("Adding to session '" + session_id
+ "': " + field_name + "="
+ str(values))
if field_name in self.sessions[session_id][1]:
self.sessions[session_id][1][field_name] += values
else:
self.sessions[session_id][1][field_name] = values
def execute_multi_step_command(self, info_query, short_node,
update_step_func):
self.__logger.debug("Executing multi-step command " + str(short_node))
(response,
command_node,
session_id) = self._create_response(info_query,
False)
lang_class = self.component.lang.get_lang_class_from_node(\
info_query.get_node())
if not self.sessions.has_key(session_id):
self.sessions[session_id] = (1, {})
else:
self.sessions[session_id] = update_step_func(session_id)
step = self.sessions[session_id][0]
self.parse_form(info_query, session_id)
try:
step_method = "execute_" + short_node + "_" + str(step)
if hasattr(self, step_method):
(form, result) = getattr(self, step_method)(\
info_query,
self.sessions[session_id][1],
command_node,
lang_class)
return [response] + result
else:
# A method that can execute all other step
step_method = "execute_" + short_node
if hasattr(self, step_method):
(form, result) = getattr(self, step_method)(\
info_query,
self.sessions[session_id][1],
command_node,
lang_class)
return [response] + result
else:
return [info_query.make_error_response(\
"feature-not-implemented")]
except CommandError, error:
return [info_query.make_error_response(error.type)]
def add_actions(self, command_node, actions, default_action_idx=0):
actions_node = command_node.newTextChild(None, "actions", None)
actions_node.setProp("execute", actions[default_action_idx])
for action in actions:
actions_node.newTextChild(None, action, None)
return actions_node
command_manager = CommandManager()
class JCLCommandManager(CommandManager):
"""Implement default set of Ad-Hoc commands"""
def __init__(self, component=None, account_manager=None):
"""
JCLCommandManager constructor
commands not implemented:
'http://jabber.org/protocol/admin#user-stats',
'http://jabber.org/protocol/admin#edit-blacklist',
'http://jabber.org/protocol/admin#add-to-blacklist-in',
'http://jabber.org/protocol/admin#add-to-blacklist-out',
'http://jabber.org/protocol/admin#edit-whitelist',
'http://jabber.org/protocol/admin#add-to-whitelist-in',
'http://jabber.org/protocol/admin#add-to-whitelist-out',
'http://jabber.org/protocol/admin#get-active-users-num',
'http://jabber.org/protocol/admin#get-idle-users-num',
'http://jabber.org/protocol/admin#get-active-users',
'http://jabber.org/protocol/admin#get-idle-users',
"""
CommandManager.__init__(self, component, account_manager)
self.__logger = logging.getLogger("jcl.jabber.command.JCLCommandManager")
self.commands["http://jabber.org/protocol/admin#add-user"] = \
(False, root_node_re)
self.commands["http://jabber.org/protocol/admin#delete-user"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#disable-user"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#reenable-user"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#end-user-session"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-user-roster"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-user-lastlogin"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-registered-users-num"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-disabled-users-num"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-online-users-num"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-registered-users-list"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-disabled-users-list"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#get-online-users-list"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#announce"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#set-motd"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#edit-motd"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#delete-motd"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#set-welcome"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#delete-welcome"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#edit-admin"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#restart"] = \
(True, root_node_re)
self.commands["http://jabber.org/protocol/admin#shutdown"] = \
(True, root_node_re)
self.commands["jcl#get-last-error"] = (False, account_node_re)
#self.commands["http://jabber.org/protocol/admin#get-user-password"] = True
#self.commands["http://jabber.org/protocol/admin#change-user-password"] = True
def get_name_and_jid(self, mixed_name_and_jid):
return mixed_name_and_jid.split("/", 1)[:2]
## Reusable steps
def add_form_select_users_jids(self, command_node,
form_title, form_desc,
field_users_jids_label):
result_form = Form(xmlnode_or_type="form",
title=form_title,
instructions=form_desc)
result_form.add_field(name="user_jids",
field_type="jid-multi",
label=field_users_jids_label)
result_form.as_xml(command_node)
return result_form
def add_form_select_user_jid(self, command_node,
form_title, form_desc,
field_user_jid_label):
result_form = Form(xmlnode_or_type="form",
title=form_title,
instructions=form_desc)
result_form.add_field(name="user_jid",
field_type="jid-single",
label=field_user_jid_label)
result_form.as_xml(command_node)
return result_form
def __add_accounts_to_field(self, user_jids, field, lang_class, filter=None,
show_user_jid=True):
for (account_type, type_label) in \
self.account_manager.list_account_types(lang_class):
account_class = self.account_manager.get_account_class(\
account_type=account_type)
for user_jid in user_jids:
self.__logger.debug("Listing " + str(user_jid) + "'s accounts")
for _account in account.get_accounts(user_jid, account_class,
filter):
self.__logger.debug(" - " + _account.name)
if show_user_jid:
label = _account.name + " (" + account_type \
+ ") (" + user_jid + ")"
else:
label = _account.name + " (" + account_type \
+ ")"
field.add_option(label=label,
values=[_account.name + "/" + user_jid])
def add_form_select_accounts(self, session_context,
command_node, lang_class,
form_title, form_desc,
filter=None, format_as_xml=True,
show_user_jid=True):
"""
Add a form to select accounts for user JIDs contained in
session_context[\"user_jids\"]
"""
result_form = Form(xmlnode_or_type="form",
title=form_title,
instructions=form_desc)
field = result_form.add_field(name="account_names",
field_type="list-multi",
label=lang_class.field_accounts)
self.__add_accounts_to_field(session_context["user_jids"],
field, lang_class, filter,
show_user_jid)
if format_as_xml:
result_form.as_xml(command_node)
return result_form
def add_form_select_account(self, session_context,
command_node, lang_class,
form_title, form_desc,
format_as_xml=True):
"""
Add a form to select account for user JIDs contained in
session_context[\"user_jids\"]
"""
result_form = Form(xmlnode_or_type="form",
title=form_title,
instructions=form_desc)
field = result_form.add_field(name="account_name",
field_type="list-single",
label=lang_class.field_account)
self.__add_accounts_to_field(session_context["user_jid"],
field, lang_class)
if format_as_xml:
result_form.as_xml(command_node)
return result_form
def add_form_select_max(self, command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
max_items_field = result_form.add_field(name="max_items",
field_type="list-single",
label=lang_class.field_max_items)
for value in ["25", "50", "75", "100", "150", "200"]:
max_items_field.add_option(label=value,
values=[value])
result_form.as_xml(command_node)
return (result_form, [])
def add_form_list_accounts(self, command_node,
var_name, var_label,
filter=None, limit=None):
result_form = Form(xmlnode_or_type="form")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
accounts = account.get_all_accounts(filter=filter, limit=limit)
accounts_labels = []
for _account in accounts:
accounts_labels += [_account.user.jid + " (" + _account.name
+ " " + str(_account.__class__.__name__) + ")"]
result_form.fields.append(FieldNoType(name=var_name,
label=var_label,
values=accounts_labels))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# Reusable steps
###########################################################################
def select_users_jids_step_1(self, session_context,
command_node, lang_class, form_title,
form_desc):
self.__logger.debug("Executing select_users_jids step 1")
self.add_actions(command_node, [ACTION_NEXT])
return (self.add_form_select_users_jids(\
command_node, form_title, form_desc,
lang_class.field_users_jids), [])
def select_user_jid_step(self, session_context,
command_node, lang_class,
form_title, form_desc,
actions=[ACTION_NEXT],
default_action=0):
self.__logger.debug("Executing select_user_jid step 1")
self.add_actions(command_node, actions, default_action)
return (self.add_form_select_user_jid(\
command_node, form_title, form_desc,
lang_class.field_user_jid), [])
def select_accounts_step_2(self, session_context,
command_node, lang_class,
form_title, form_desc,
format_as_xml=True):
self.__logger.debug("Executing select_accounts step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
return (self.add_form_select_accounts(session_context, command_node,
lang_class, form_title, form_desc,
format_as_xml=format_as_xml),
[])
def select_account_step_2(self, session_context,
command_node, lang_class,
form_title, form_desc,
format_as_xml=True):
self.__logger.debug("Executing select_account step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
return (self.add_form_select_account(session_context, command_node,
lang_class, form_title, form_desc,
format_as_xml=format_as_xml),
[])
###########################################################################
# add-user command
###########################################################################
def execute_add_user_1(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'add-user' step 1")
self.add_actions(command_node, [ACTION_NEXT])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_add_user,
instructions=lang_class.command_add_user_1_description)
field = result_form.add_field(name="account_type",
field_type="list-single",
label=lang_class.field_account_type)
for (account_type, type_label) in \
self.component.account_manager.list_account_types(lang_class):
field.add_option(label=type_label,
values=[account_type])
if self.component.is_admin(info_query.get_from()):
result_form.add_field(name="user_jid",
field_type="jid-single",
label=lang_class.field_user_jid)
result_form.as_xml(command_node)
return (result_form, [])
def execute_add_user_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'add-user' step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
if not self.component.is_admin(info_query.get_from()):
session_context["user_jid"] = [unicode(info_query.get_from().bare())]
user_jid = session_context["user_jid"][0]
account_type = session_context["account_type"][0]
account_class = self.account_manager.get_account_class(account_type)
result_form = self.account_manager.generate_registration_form(lang_class,
account_class,
user_jid)
result_form.as_xml(command_node)
return (result_form, [])
def execute_add_user_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'add-user' step 3")
x_node = info_query.xpath_eval("c:command/jxd:x",
{"c": "http://jabber.org/protocol/commands",
"jxd" : "jabber:x:data"})[0]
x_data = Form(x_node)
to_send = self.component.account_manager.create_account_from_type(\
account_name=session_context["name"][0],
from_jid=JID(session_context["user_jid"][0]),
account_type=session_context["account_type"][0],
lang_class=lang_class,
x_data=x_data)
command_node.setProp("status", STATUS_COMPLETED)
return (None, to_send)
###########################################################################
# delete-user command
###########################################################################
def execute_delete_user_1(self, info_query, session_context,
command_node, lang_class):
return self.select_users_jids_step_1(\
session_context, command_node, lang_class,
lang_class.command_delete_user,
lang_class.command_delete_user_1_description)
def execute_delete_user_2(self, info_query, session_context,
command_node, lang_class):
return self.select_accounts_step_2(\
session_context, command_node, lang_class,
lang_class.command_delete_user,
lang_class.command_delete_user_2_description)
def execute_delete_user_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'delete-user' step 3")
result = []
for account_name in session_context["account_names"]:
name, user_jid = self.get_name_and_jid(account_name)
result += self.account_manager.remove_account_from_name(JID(user_jid),
name)
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# disable-user command
###########################################################################
def execute_disable_user_1(self, info_query, session_context,
command_node, lang_class):
return self.select_users_jids_step_1(\
session_context, command_node, lang_class,
lang_class.command_disable_user,
lang_class.command_disable_user_1_description)
def execute_disable_user_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing 'disable-user' step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
return (self.add_form_select_accounts(\
session_context, command_node, lang_class,
lang_class.command_disable_user,
lang_class.command_disable_user_2_description,
filter=Account.q.enabled==True),
[])
def execute_disable_user_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'disable-user' step 3")
result = []
for account_name in session_context["account_names"]:
name, user_jid = self.get_name_and_jid(account_name)
_account = account.get_account(user_jid, name)
_account.enabled = False
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# reenable-user command
###########################################################################
def execute_reenable_user_1(self, info_query, session_context,
command_node, lang_class):
return self.select_users_jids_step_1(\
session_context, command_node, lang_class,
lang_class.command_reenable_user,
lang_class.command_reenable_user_1_description)
def execute_reenable_user_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing 'reenable-user' step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
return (self.add_form_select_accounts(\
session_context, command_node, lang_class,
lang_class.command_reenable_user,
lang_class.command_reenable_user_2_description,
filter=Account.q.enabled==False),
[])
def execute_reenable_user_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'reenable-user' step 3")
result = []
for account_name in session_context["account_names"]:
name, user_jid = self.get_name_and_jid(account_name)
_account = account.get_account(user_jid, name)
_account.enabled = True
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# end-user-session command
###########################################################################
def execute_end_user_session_1(self, info_query, session_context,
command_node, lang_class):
return self.select_users_jids_step_1(\
session_context, command_node, lang_class,
lang_class.command_end_user_session,
lang_class.command_end_user_session_1_description)
def execute_end_user_session_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing 'end-user-session' step 2")
self.add_actions(command_node, [ACTION_PREVIOUS, ACTION_COMPLETE], 1)
return (self.add_form_select_accounts(\
session_context, command_node, lang_class,
lang_class.command_end_user_session,
lang_class.command_end_user_session_2_description,
filter=Account.q._status != account.OFFLINE),
[])
def execute_end_user_session_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'end-user-session' step 3")
result = []
for account_name in session_context["account_names"]:
name, user_jid = self.get_name_and_jid(account_name)
_account = account.get_account(user_jid, name)
result += self.component.account_manager.send_presence_unavailable(
_account)
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# get-user-password command
###########################################################################
def execute_get_user_password_1(self, info_query, session_context,
command_node, lang_class):
return self.select_user_jid_step(\
session_context, command_node, lang_class,
lang_class.command_get_user_password,
lang_class.command_get_user_password_1_description)
def execute_get_user_password_2(self, info_query, session_context,
command_node, lang_class):
return self.select_account_step_2(\
session_context, command_node, lang_class,
lang_class.command_get_user_password,
lang_class.command_get_user_password_2_description)
def execute_get_user_password_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'get-user-password' step 3")
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
name, user_jid = self.get_name_and_jid(session_context["account_name"][0])
_account = account.get_account(user_jid, name)
result_form.fields.append(FieldNoType(name="accountjids",
value=user_jid))
result_form.fields.append(FieldNoType(name="password",
value=_account.password))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# change-user-password command
###########################################################################
def execute_change_user_password_1(self, info_query, session_context,
command_node, lang_class):
return self.select_user_jid_step(\
session_context, command_node, lang_class,
lang_class.command_change_user_password,
lang_class.command_change_user_password_1_description)
def execute_change_user_password_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'change-user-password' step 2")
(result_form, result) = self.select_account_step_2(\
session_context, command_node, lang_class,
lang_class.command_change_user_password,
lang_class.command_change_user_password_2_description,
False)
result_form.add_field(field_type="text-private",
name="password",
label=lang_class.field_password)
result_form.as_xml(command_node)
return (result_form, result)
def execute_change_user_password_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'change-user-password' step 2")
name, user_jid = self.get_name_and_jid(session_context["account_name"][0])
_account = account.get_account(user_jid, name)
_account.password = session_context["password"][0]
command_node.setProp("status", STATUS_COMPLETED)
return (None, [])
###########################################################################
# get-user-roster command
###########################################################################
def execute_get_user_roster_1(self, info_query, session_context,
command_node, lang_class):
(result_form, result) = self.select_user_jid_step(\
session_context, command_node, lang_class,
lang_class.command_get_user_roster,
lang_class.command_get_user_roster_1_description,
actions=[ACTION_COMPLETE])
return (result_form, result)
def execute_get_user_roster_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'get-user-roster' step 2")
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
user_jid = session_context["user_jid"][0]
result_form.fields.append(FieldNoType(name="user_jid",
value=user_jid,
label=lang_class.field_user_jid))
result_form.as_xml(command_node)
x_form = command_node.children
query = x_form.newChild(None, "query", None)
roster_ns = query.newNs("jabber:iq:roster", None)
query.setNs(roster_ns)
for _account in account.get_accounts(user_jid):
item = query.newChild(None, "item", None)
item.setProp("jid", _account.jid)
item.setProp("name", _account.name)
for legacy_jid in account.get_legacy_jids(user_jid):
item = query.newChild(None, "item", None)
item.setProp("jid", legacy_jid.jid)
item.setProp("name", legacy_jid.legacy_address)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# get-user-lastlogin command
###########################################################################
def execute_get_user_lastlogin_1(self, info_query, session_context,
command_node, lang_class):
return self.select_user_jid_step(\
session_context, command_node, lang_class,
lang_class.command_get_user_lastlogin,
lang_class.command_get_user_lastlogin_1_description)
def execute_get_user_lastlogin_2(self, info_query, session_context,
command_node, lang_class):
return self.select_account_step_2(\
session_context, command_node, lang_class,
lang_class.command_get_user_lastlogin,
lang_class.command_get_user_lastlogin_2_description)
def execute_get_user_lastlogin_3(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'get-user-roster' step 3")
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
name, user_jid = self.get_name_and_jid(session_context["account_name"][0])
_account = account.get_account(user_jid, name)
result_form.fields.append(FieldNoType(name="user_jid",
value=user_jid,
label=lang_class.field_user_jid))
result_form.fields.append(FieldNoType(name="lastlogin",
value=_account.lastlogin))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# get-registered-users-num command
###########################################################################
def execute_get_registered_users_num_1(self, info_query, session_context,
command_node, lang_class):
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
num_accounts = account.get_all_accounts_count()
result_form.fields.append(FieldNoType(name="registeredusersnum",
label=lang_class.field_registered_users_num,
value=num_accounts))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# get-disabled-users-num command
###########################################################################
def execute_get_disabled_users_num_1(self, info_query, session_context,
command_node, lang_class):
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
num_accounts = account.get_all_accounts_count(\
filter=(Account.q.enabled == False))
result_form.fields.append(FieldNoType(name="disabledusersnum",
label=lang_class.field_disabled_users_num,
value=num_accounts))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# get-online-users-num command
###########################################################################
def execute_get_online_users_num_1(self, info_query, session_context,
command_node, lang_class):
result_form = Form(xmlnode_or_type="result")
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
num_accounts = account.get_all_accounts_count(\
filter=(Account.q._status != account.OFFLINE))
result_form.fields.append(FieldNoType(name="onlineusersnum",
label=lang_class.field_online_users_num,
value=num_accounts))
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
###########################################################################
# get-registered-users-list command
###########################################################################
def execute_get_registered_users_list_1(self, info_query, session_context,
command_node, lang_class):
num_accounts = account.get_all_accounts_count()
if num_accounts < 25:
return self.add_form_list_accounts(command_node,
"registeredusers",
lang_class.field_registered_users_list)
else:
return self.add_form_select_max(command_node, lang_class)
def execute_get_registered_users_list_2(self, info_query, session_context,
command_node, lang_class):
limit = int(session_context["max_items"][0])
return self.add_form_list_accounts(command_node,
"registeredusers",
lang_class.field_registered_users_list,
limit=limit)
###########################################################################
# get-disabled-users-list command
###########################################################################
def execute_get_disabled_users_list_1(self, info_query, session_context,
command_node, lang_class):
num_accounts = account.get_all_accounts_count()
if num_accounts < 25:
return self.add_form_list_accounts(command_node,
"disabledusers",
lang_class.field_disabled_users_list,
filter=(Account.q.enabled == False))
else:
return self.add_form_select_max(command_node, lang_class)
def execute_get_disabled_users_list_2(self, info_query, session_context,
command_node, lang_class):
limit = int(session_context["max_items"][0])
return self.add_form_list_accounts(command_node,
"disabledusers",
lang_class.field_disabled_users_list,
limit=limit,
filter=(Account.q.enabled == False))
###########################################################################
# get-online-users-list command
###########################################################################
def execute_get_online_users_list_1(self, info_query, session_context,
command_node, lang_class):
num_accounts = account.get_all_accounts_count()
if num_accounts < 25:
return self.add_form_list_accounts(\
command_node, "onlineusers",
lang_class.field_online_users_list,
filter=(Account.q._status != account.OFFLINE))
else:
return self.add_form_select_max(command_node, lang_class)
def execute_get_online_users_list_2(self, info_query, session_context,
command_node, lang_class):
limit = int(session_context["max_items"][0])
return self.add_form_list_accounts(\
command_node, "onlineusers",
lang_class.field_online_users_list,
limit=limit,
filter=(Account.q._status != account.OFFLINE))
###########################################################################
# announce command
###########################################################################
def execute_announce_1(self, info_query, session_context,
command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_announce,
instructions=lang_class.command_announce_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
result_form.add_field(name="announcement",
field_type="text-multi",
label=lang_class.field_announcement,
required=True)
result_form.as_xml(command_node)
return (result_form, [])
def execute_announce_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'announce' step 2")
result = []
if session_context.has_key("announcement"):
announcement = session_context["announcement"][0]
users = account.get_all_users(\
filter=AND(Account.q.userID == User.q.id,
Account.q._status != account.OFFLINE),
distinct=True)
for user in users:
result.append(Message(from_jid=self.component.jid,
to_jid=user.jid,
body=announcement))
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# set-motd command
###########################################################################
def execute_set_motd_1(self, info_query, session_context,
command_node, lang_class, motd=""):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_set_motd,
instructions=lang_class.command_set_motd_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
result_form.add_field(name="motd",
field_type="text-multi",
label=lang_class.field_motd,
value=[motd],
required=True)
result_form.as_xml(command_node)
return (result_form, [])
def execute_set_motd_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'set motd' step 2")
motd = session_context["motd"][0]
self.component.set_motd(motd)
users = account.get_all_users(\
filter=AND(Account.q.userID == User.q.id),
distinct=True)
result = []
motd = self.component.get_motd()
if motd is not None:
for user in users:
user.has_received_motd = False
for _account in user.accounts:
if _account.status != account.OFFLINE:
user.has_received_motd = True
if user.has_received_motd:
result.append(Message(from_jid=self.component.jid,
to_jid=user.jid,
body=motd))
command_node.setProp("status", STATUS_COMPLETED)
return (None, result)
###########################################################################
# edit-motd command
###########################################################################
def execute_edit_motd_1(self, info_query, session_context,
command_node, lang_class):
return self.execute_set_motd_1(info_query, session_context,
command_node, lang_class,
self.component.get_motd())
execute_edit_motd_2 = execute_set_motd_2
###########################################################################
# delete-motd command
###########################################################################
def execute_delete_motd_1(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'delete motd' step 1")
self.component.del_motd()
command_node.setProp("status", STATUS_COMPLETED)
return (None, [])
###########################################################################
# set-welcome command
###########################################################################
def execute_set_welcome_1(self, info_query, session_context,
command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_set_welcome,
instructions=lang_class.command_set_welcome_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
welcome_message = self.component.get_welcome_message()
result_form.add_field(name="welcome",
field_type="text-multi",
label=lang_class.field_welcome,
value=[welcome_message],
required=True)
result_form.as_xml(command_node)
return (result_form, [])
def execute_set_welcome_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'set welcome' step 2")
welcome_message = session_context["welcome"][0]
self.component.set_welcome_message(welcome_message)
command_node.setProp("status", STATUS_COMPLETED)
return (None, [])
###########################################################################
# delete-welcome command
###########################################################################
def execute_delete_welcome_1(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'delete welcome' step 1")
self.component.del_welcome_message()
command_node.setProp("status", STATUS_COMPLETED)
return (None, [])
###########################################################################
# edit-admin command
###########################################################################
def execute_edit_admin_1(self, info_query, session_context,
command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_edit_admin,
instructions=lang_class.command_edit_admin_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
admins = self.component.get_admins()
result_form.add_field(name="adminjids",
field_type="jid-multi",
label=lang_class.field_admin_jids,
values=admins,
required=True)
result_form.as_xml(command_node)
return (result_form, [])
def execute_edit_admin_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'edit admin' step 2")
admins = session_context["adminjids"]
self.component.set_admins(admins)
command_node.setProp("status", STATUS_COMPLETED)
return (None, [])
###########################################################################
# restart command
###########################################################################
def execute_restart_1(self, info_query, session_context,
command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_restart,
instructions=lang_class.command_restart_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
delay_field = result_form.add_field(name="delay",
field_type="list-single",
label=lang_class.field_restart_delay,
required=True)
delay_field.add_option(label=lang_class.field_30_sec,
values=["30"])
delay_field.add_option(label=lang_class.field_60_sec,
values=["60"])
delay_field.add_option(label=lang_class.field_90_sec,
values=["90"])
delay_field.add_option(label=lang_class.field_120_sec,
values=["120"])
delay_field.add_option(label=lang_class.field_180_sec,
values=["180"])
delay_field.add_option(label=lang_class.field_240_sec,
values=["240"])
delay_field.add_option(label=lang_class.field_300_sec,
values=["300"])
result_form.add_field(name="announcement",
field_type="text-multi",
label=lang_class.field_announcement)
result_form.as_xml(command_node)
return (result_form, [])
def execute_restart_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'restart' step 2")
delay = int(session_context["delay"][0])
result = []
if session_context.has_key("announcement"):
announcement = session_context["announcement"][0]
if announcement is not None and announcement != "":
users = account.get_all_users(\
filter=AND(Account.q.userID == User.q.id,
Account.q._status != account.OFFLINE),
distinct=True)
for user in users:
result.append(Message(from_jid=self.component.jid,
to_jid=user.jid,
body=announcement))
command_node.setProp("status", STATUS_COMPLETED)
def delayed_restart(self, delay):
threading.Event().wait(delay)
self.component.restart = True
restart_thread = threading.Thread(target=lambda : delayed_restart(self, delay),
name="TimerThread")
restart_thread.start()
return (None, result)
###########################################################################
# shutdown command
###########################################################################
def execute_shutdown_1(self, info_query, session_context,
command_node, lang_class):
self.add_actions(command_node, [ACTION_COMPLETE])
result_form = Form(xmlnode_or_type="form",
title=lang_class.command_shutdown,
instructions=lang_class.command_shutdown_1_description)
result_form.add_field(field_type="hidden",
name="FORM_TYPE",
value="http://jabber.org/protocol/admin")
delay_field = result_form.add_field(name="delay",
field_type="list-single",
label=lang_class.field_shutdown_delay,
required=True)
delay_field.add_option(label=lang_class.field_30_sec,
values=["30"])
delay_field.add_option(label=lang_class.field_60_sec,
values=["60"])
delay_field.add_option(label=lang_class.field_90_sec,
values=["90"])
delay_field.add_option(label=lang_class.field_120_sec,
values=["120"])
delay_field.add_option(label=lang_class.field_180_sec,
values=["180"])
delay_field.add_option(label=lang_class.field_240_sec,
values=["240"])
delay_field.add_option(label=lang_class.field_300_sec,
values=["300"])
result_form.add_field(name="announcement",
field_type="text-multi",
label=lang_class.field_announcement)
result_form.as_xml(command_node)
return (result_form, [])
def execute_shutdown_2(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'shutdown' step 2")
delay = int(session_context["delay"][0])
result = []
if session_context.has_key("announcement"):
announcement = session_context["announcement"][0]
if announcement is not None and announcement != "":
users = account.get_all_users(\
filter=AND(Account.q.userID == User.q.id,
Account.q._status != account.OFFLINE),
distinct=True)
for user in users:
result.append(Message(from_jid=self.component.jid,
to_jid=user.jid,
body=announcement))
command_node.setProp("status", STATUS_COMPLETED)
def delayed_restart(self, delay):
threading.Event().wait(delay)
self.component.running = False
restart_thread = threading.Thread(target=lambda : delayed_restart(self, delay),
name="TimerThread")
restart_thread.start()
return (None, result)
def execute_get_last_error_1(self, info_query, session_context,
command_node, lang_class):
self.__logger.debug("Executing command 'get-last-error' step 1")
result_form = Form(xmlnode_or_type="result")
bare_from_jid = info_query.get_from().bare()
account_name = info_query.get_to().node
_account = account.get_account(bare_from_jid, account_name)
if _account is not None and _account.error is not None:
last_error = _account.error
else:
last_error = lang_class.account_no_error
result_form.add_field(field_type="text-single",
label=lang_class.field_last_error,
value=last_error)
result_form.as_xml(command_node)
command_node.setProp("status", STATUS_COMPLETED)
return (result_form, [])
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, info_query, lang_class, node):
"""
Filter requests to be handled. Only known commands
"""
return (node in command_manager.commands)
def handle(self, info_query, lang_class, node, disco_obj, data):
"""
Return infos for given command
"""
if not disco_obj:
disco_obj = DiscoInfo(node)
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, info_query, lang_class, node):
"""
Filter requests to be handled.
"""
return (node == 'http://jabber.org/protocol/commands')
def handle(self, info_query, lang_class, node, disco_obj, data):
"""
"""
if not disco_obj:
disco_obj = DiscoItems(node)
return [command_manager.list_commands(jid=info_query.get_from(),
to_jid=info_query.get_to(),
disco_items=disco_obj,
lang_class=lang_class)]