Replace DataForm implementation by Form implementation from PyXMPP

darcs-hash:20070213174122-86b55-54dc9d8ae9c4f354af0b46e597779744fbd97900.gz
This commit is contained in:
David Rousselie
2007-02-13 18:41:22 +01:00
parent b4ae16acc6
commit 826d045b41
8 changed files with 128 additions and 507 deletions

View File

@@ -46,9 +46,9 @@ from pyxmpp.jabberd.component import Component
from pyxmpp.jabber.disco import DiscoInfo, DiscoItems, DiscoItem, DiscoIdentity
from pyxmpp.message import Message
from pyxmpp.presence import Presence
from pyxmpp.jabber.dataforms import Form, Field, Option
import jcl
from jcl.jabber.x import DataForm
from jcl.jabber.error import FieldError
from jcl.model import account
from jcl.model.account import Account
@@ -129,6 +129,7 @@ class JCLComponent(Component, object):
self.queue.put(exception)
raise
finally:
# self.running = False
if self.stream and not self.stream.eof \
and self.stream.socket is not None:
current_user_jid = None
@@ -277,8 +278,8 @@ class JCLComponent(Component, object):
self._list_accounts(disco_items, self.account_classes[0], \
base_from_jid, account_type)
else:
print >>sys.stderr, self.account_classes[0].__name__ + \
" name not well formed"
self.__logger.error(self.account_classes[0].__name__ + \
" name not well formed")
else: # list account types (when multiples accounts types)
for account_class in self.account_classes:
regexp_type = re.compile("(.*)Account$")
@@ -291,8 +292,8 @@ class JCLComponent(Component, object):
account_type, \
account_type)
else:
print >>sys.stderr, account_class.__name__ + \
" name not well formed"
self.__logger.error(account_class.__name__ + \
" name not well formed")
else: # second level
nodes = node.split("/");
if len(nodes) == 1 \
@@ -305,8 +306,8 @@ class JCLComponent(Component, object):
base_from_jid,
account_type = nodes[0])
else:
print >> sys.stderr, "Error: " + account_class.__name__ \
+ " class not in account_classes"
self.__logger.error("Error: " + account_class.__name__ \
+ " class not in account_classes")
return disco_items
def handle_get_version(self, info_query):
@@ -331,7 +332,7 @@ class JCLComponent(Component, object):
AND(_account_class.q.name == name, \
_account_class.q.user_jid == base_from_jid)):
self.get_reg_form_init(lang_class, \
_account).attach_xml(query)
_account).as_xml(query)
self.db_disconnect()
self.__logger.debug("GET_REGISTER")
@@ -355,7 +356,7 @@ class JCLComponent(Component, object):
else: # get_register new account of type node_list[0] + "Account"
_account_class = self._get_account_class(account_type + "Account")
self.get_reg_form(lang_class, \
_account_class).attach_xml(query)
_account_class).as_xml(query)
self.stream.send(info_query)
return 1
@@ -403,12 +404,8 @@ class JCLComponent(Component, object):
{"jir" : "jabber:iq:register", \
"jxd" : "jabber:x:data"})[0]
x_data = DataForm()
x_data.from_xml(x_node)
name = x_data.get_field_value("name")
self.__logger.debug("Account name received = " + str(name))
if name is None or name == "":
x_data = Form(x_node)
if not "name" in x_data or x_data["name"].value == "":
iq_error = info_query.make_error_response("not-acceptable")
text = iq_error.get_error().xmlnode.newTextChild(None, \
"text", \
@@ -416,6 +413,8 @@ class JCLComponent(Component, object):
text.setNs(text.newNs(error.STANZA_ERROR_NS, None))
self.stream.send(iq_error)
return
name = x_data["name"].value
self.__logger.debug("Account name received = " + str(name))
self.db_connect()
accounts = Account.select(\
AND(Account.q.name == name, \
@@ -426,14 +425,14 @@ class JCLComponent(Component, object):
all_accounts_count = all_accounts.count()
if accounts_count > 1:
# Just print a warning, only the first account will be use
print >> sys.stderr, "There might not exist 2 accounts for " + \
base_from_jid + " and named " + name
self.__logger.error("There might not exist 2 accounts for " + \
base_from_jid + " and named " + name)
if accounts_count >= 1:
_account = list(accounts)[0]
else:
if info_query.get_to().node is None:
if len(self.account_classes) > 1:
print >>sys.stderr, "There should be only one account class declared"
self.__logger.error("There should be only one account class declared")
new_account_class = self.account_classes[0]
else:
new_account_class = self._get_account_class(info_query.get_to().node + "Account")
@@ -445,13 +444,15 @@ class JCLComponent(Component, object):
for (field, field_type, field_options, field_post_func, \
field_default_func) in _account.get_register_fields():
if field is not None:
setattr(_account, field, \
x_data.get_field_value(field, \
field_post_func, \
field_default_func))
if field in x_data:
setattr(_account, field, \
field_post_func(x_data[field].value))
else:
setattr(_account, field, \
field_default_func(field))
except FieldError, exception:
_account.destroySelf()
print >>sys.stderr, str(exception)
self.__logger.error(str(exception))
iq_error = info_query.make_error_response("not-acceptable")
text = iq_error.get_error().xmlnode.newTextChild(None, \
"text", \
@@ -726,16 +727,12 @@ class JCLComponent(Component, object):
def get_reg_form(self, lang_class, _account_class):
"""Return register form based on language and account class
"""
reg_form = DataForm()
reg_form.xmlns = "jabber:x:data"
reg_form.title = lang_class.register_title
reg_form.instructions = lang_class.register_instructions
reg_form.type = "form"
reg_form = Form(title = lang_class.register_title, \
instructions = lang_class.register_instructions)
# "name" field is mandatory
reg_form.add_field(field_type = "text-single", \
label = lang_class.account_name, \
var = "name", \
name = "name", \
required = True)
for (field_name, field_type, field_options, post_func, default_func) in \
@@ -752,7 +749,7 @@ class JCLComponent(Component, object):
label = field_name
field = reg_form.add_field(field_type = field_type, \
label = label, \
var = field_name)
name = field_name)
if field_options is not None:
for option_value in field_options:
lang_label_attr = _account_class.__name__.lower() \
@@ -762,7 +759,7 @@ class JCLComponent(Component, object):
else:
label = option_value
field.add_option(label = label, \
value = option_value)
values = [option_value])
if default_func == account.mandatory_field:
field.required = True
## TODO : get default value if any
@@ -772,11 +769,11 @@ class JCLComponent(Component, object):
"""Return register form for an existing account (update)
"""
reg_form = self.get_reg_form(lang_class, _account.__class__)
reg_form.fields["name"].value = _account.name
reg_form.fields["name"].type = "hidden"
for (field_name, field) in reg_form.fields.items():
if hasattr(_account, field_name):
field.value = str(getattr(_account, field_name))
reg_form["name"].value = _account.name
reg_form["name"].type = "hidden"
for field in reg_form.fields: # TODO
if hasattr(_account, field.name):
field.value = getattr(_account, field.name)
return reg_form
###########################################################################

View File

@@ -1,172 +0,0 @@
##
## x.py
## Login : David Rousselie <dax@happycoders.org>
## Started on Fri Jan 7 11:06:42 2005
## $Id: x.py,v 1.3 2005/09/18 20:24:07 dax Exp $
##
## Copyright (C) 2005
## 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
##
"""X -- Data Form handling
"""
__revision__ = "$Id: x.py,v 1.3 2005/09/18 20:24:07 dax Exp $"
from pyxmpp.stanza import common_doc
class Option(object):
"""Option value for list field
"""
def __init__(self, label, value):
self.label = label
self.value = value
def get_xml(self, parent):
"""Return XML Option representation from
self.label and self.value and attach it to parent
"""
if parent is None:
option = common_doc.newChild(None, "option", None)
else:
option = parent.newChild(None, "option", None)
option.setProp("label", self.label)
option.newChild(None, "value", self.value)
return option
class Field(object):
"""Jabber Xdata form Field
"""
def __init__(self, field_type, label, var, value, required = False):
self.type = field_type
self.label = label
self.var = var
self.value = value
self.options = []
self.required = required
def add_option(self, label, value):
"""Add an Option to this field
"""
option = Option(label, value)
self.options.append(option)
return option
def get_xml(self, parent):
"""Return XML Field representation
and attach it to parent
"""
if parent is None:
raise Exception, "parent field should not be None"
else:
field = parent.newChild(None, "field", None)
field.setProp("type", self.type)
if not self.label is None:
field.setProp("label", self.label)
if not self.var is None:
field.setProp("var", self.var)
if self.value:
field.newChild(None, "value", self.value)
if self.required:
field.newChild(None, "required", None)
for option in self.options:
option.get_xml(field)
return field
class DataForm(object):
"""Jabber Data Form
"""
def __init__(self):
self.fields = {}
self.fields_tab = []
self.title = None
self.instructions = None
self.x_type = None
self.xmlns = None
def add_field(self, \
field_type = "fixed", \
label = None, \
var = None, \
value = "", \
required = False):
"""Add a Field to this Xdata form
"""
field = Field(field_type, label, var, value, required)
self.fields[var] = field
# fields_tab exist to keep added fields order
self.fields_tab.append(field)
return field
def get_field_value(self, field_name, \
post_func = (lambda value: value), \
default_func = (lambda field_name: None)):
"""Return field value processed by post_func
or return default func processing if field does not exist"""
if self.fields.has_key(field_name):
return post_func(self.fields[field_name].value)
return default_func(field_name)
def attach_xml(self, info_query):
"""Attach this Xdata form to iq node
"""
node = info_query.newChild(None, "x", None)
_ns = node.newNs(self.xmlns, None)
node.setNs(_ns)
if not self.title is None:
node.newTextChild(None, "title", self.title)
if not self.instructions is None:
node.newTextChild(None, "instructions", self.instructions)
for field in self.fields_tab:
field.get_xml(node)
return node
def from_xml(self, node):
"""Populate this X object from an XML representation
"""
context = common_doc.xpathNewContext()
context.setContextNode(node)
context.xpathRegisterNs("jxd", "jabber:x:data")
fields_node = context.xpathEval("jxd:field")
for field_node in fields_node:
if field_node.hasProp("type"):
field_type = field_node.prop("type")
else:
field_type = ""
if field_node.hasProp("label"):
label = field_node.prop("label")
else:
label = ""
if field_node.hasProp("var"):
var = field_node.prop("var")
else:
var = ""
field_context = common_doc.xpathNewContext()
field_context.setContextNode(field_node)
field_context.xpathRegisterNs("jxd", "jabber:x:data")
fields_value_node = field_context.xpathEval("jxd:value")
if len(fields_value_node) > 0:
value = fields_value_node[0].content
else:
value = ""
self.add_field(field_type = field_type, \
label = label, \
var = var, \
value = value)
field_context.xpathFreeContext()
context.xpathFreeContext()

View File

@@ -41,10 +41,6 @@ def default_post_func(field_value):
"""Default post process function: do nothing"""
return field_value
def boolean_post_func(field_value):
"""Return a boolean from boolean field value"""
return (field_value == "1" or field_value.lower() == "true")
def int_post_func(field_value):
"""Return an integer from integer field value"""
return int(field_value)