Package pyxmpp :: Package jabber :: Module register
[hide private]

Source Code for Module pyxmpp.jabber.register

  1  # 
  2  # (C) Copyright 2005-2006 Jacek Konieczny <jajcus@jajcus.net> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU Lesser General Public License Version 
  6  # 2.1 as published by the Free Software Foundation. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU Lesser General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU Lesser General Public 
 14  # License along with this program; if not, write to the Free Software 
 15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 16  # 
 17   
 18  """In-band registration (jabber:iq:register) handling. 
 19   
 20  Normative reference: 
 21    - `JEP 77 <http://www.jabber.org/jeps/jep-0077.html>`__ 
 22  """ 
 23   
 24  __revision__="$Id: delay.py 567 2005-03-29 20:08:55Z jajcus $" 
 25  __docformat__="restructuredtext en" 
 26   
 27  import libxml2 
 28  import logging 
 29   
 30  from pyxmpp.utils import to_utf8,from_utf8 
 31  from pyxmpp.xmlextra import get_node_ns_uri 
 32  from pyxmpp.objects import StanzaPayloadObject 
 33  from pyxmpp.xmlextra import xml_element_iter 
 34   
 35  from pyxmpp.jabber.dataforms import DATAFORM_NS, Form 
 36   
 37  REGISTER_NS="jabber:iq:register" 
 38   
 39  legacy_fields = { 
 40          "username": ("text-single", u"Account name associated with the user"), 
 41          "nick": ("text-single", u"Familiar name of the user"), 
 42          "password": ("text-private", u"Password or secret for the user"), 
 43          "name": ("text-single", u"Full name of the user"), 
 44          "first": ("text-single", u"First name or given name of the user"), 
 45          "last": ("text-single", u"Last name, surname, or family name of the user"), 
 46          "email": ("text-single", u"Email address of the user"), 
 47          "address": ("text-single", u"Street portion of a physical or mailing address"), 
 48          "city": ("text-single", u"Locality portion of a physical or mailing address"), 
 49          "state": ("text-single", u"Region portion of a physical or mailing address"), 
 50          "zip": ("text-single", u"Postal code portion of a physical or mailing address"), 
 51          "phone": ("text-single", u"Telephone number of the user"), 
 52          "url": ("text-single", u"URL to web page describing the user"), 
 53          "date": ("text-single", u"Some date (e.g., birth date, hire date, sign-up date)"), 
 54          "misc": ("text-single", u"Free-form text field (obsolete)"), 
 55          "text": ("text-single", u"Free-form text field (obsolete)"), 
 56          "key": ("text-single", u"Session key for transaction (obsolete)"), 
 57          } 
 58   
59 -class Register(StanzaPayloadObject):
60 """ 61 Delayed delivery tag. 62 63 Represents 'jabber:iq:register' (JEP-0077) element of a Jabber <iq/> stanza. 64 65 Please note that it is recommended to use `get_form` and `submit_form` records 66 instead of accessing the `form` and legacy fields directly. This way both 67 legacy and Data Forms registration would work transparently to the application. 68 69 :Ivariables: 70 - `form`: registration form (when available) 71 - `registered`: `True` if entity is already registered 72 - `instrutions`: Registration instructions (legacy protocol) 73 - `username`: Username field (legacy protocol) 74 - `nick`: Nickname (legacy protocol) 75 - `password`: Password (legacy protocol) 76 - `name`: Name field (legacy protocol) 77 - `first`: First name field (legacy protocol) 78 - `last`: Last name field (legacy protocol) 79 - `email`: E-mail field (legacy protocol) 80 - `address`: Address field (legacy protocol) 81 - `city`: City field (legacy protocol) 82 - `state`: State field (legacy protocol) 83 - `zip`: ZIP code field (legacy protocol) 84 - `phone`: Phone field (legacy protocol) 85 - `url`: URL field (legacy protocol) 86 - `date`: Date field (legacy protocol) 87 - `misc`: Misc field (legacy protocol, obsolete) 88 - `text`: Text field (legacy protocol, obsolete) 89 - `key`: Key field (legacy protocol, obsolete) 90 - `remove`: `True` when the account should be removed 91 :Types: 92 - `form`: `pyxmpp.jabber.dataforms.Form` 93 - `registered`: `bool` 94 - `instrutions`: `unicode` 95 - `username`: `unicode` 96 - `nick`: `unicode` 97 - `password`: `unicode` 98 - `name`: `unicode` 99 - `first`: `unicode` 100 - `last`: `unicode` 101 - `email`: `unicode` 102 - `address`: `unicode` 103 - `city`: `unicode` 104 - `state`: `unicode` 105 - `zip`: `unicode` 106 - `phone`: `unicode` 107 - `url`: `unicode` 108 - `date`: `unicode` 109 - `misc`: `unicode` 110 - `text`: `unicode` 111 - `key`: `unicode` 112 - `remove`: `True` when the account should be removed 113 """ 114 115 xml_element_name = "query" 116 xml_element_namespace = REGISTER_NS 117
118 - def __init__(self, xmlnode = None):
119 """ 120 Initialize the `Register` object. 121 122 :Parameters: 123 - `xmlnode`: an optional XML node to parse. 124 :Types: 125 - `xmlnode`: `libxml2.xmlNode` 126 """ 127 self.__logger=logging.getLogger("pyxmpp.jabber.Register") 128 self.form = None 129 self.registered = False 130 self.instructions = None 131 self.remove = False 132 for f in legacy_fields: 133 setattr(self, f, None) 134 if isinstance(xmlnode,libxml2.xmlNode): 135 self.__from_xml(xmlnode)
136
137 - def __from_xml(self, xmlnode):
138 """Initialize `Register` from an XML node. 139 140 :Parameters: 141 - `xmlnode`: the jabber:x:register XML element. 142 :Types: 143 - `xmlnode`: `libxml2.xmlNode`""" 144 145 self.__logger.debug("Converting jabber:iq:register element from XML") 146 if xmlnode.type!="element": 147 raise ValueError,"XML node is not a jabber:iq:register element (not an element)" 148 ns=get_node_ns_uri(xmlnode) 149 if ns and ns!=REGISTER_NS or xmlnode.name!="query": 150 raise ValueError,"XML node is not a jabber:iq:register element" 151 152 for element in xml_element_iter(xmlnode.children): 153 ns = get_node_ns_uri(element) 154 if ns == DATAFORM_NS and element.name == "x" and not self.form: 155 self.form = Form(element) 156 elif ns != REGISTER_NS: 157 continue 158 name = element.name 159 if name == "instructions" and not self.instructions: 160 self.instructions = from_utf8(element.getContent()) 161 elif name == "registered": 162 self.registered = True 163 elif name == "remove": 164 self.remove = True 165 elif name in legacy_fields and not getattr(self, name): 166 value = from_utf8(element.getContent()) 167 if value is None: 168 value = u"" 169 self.__logger.debug(u"Setting legacy field %r to %r" % (name, value)) 170 setattr(self, name, value)
171
172 - def complete_xml_element(self, xmlnode, doc):
173 """Complete the XML node with `self` content. 174 175 :Parameters: 176 - `xmlnode`: XML node with the element being built. It has already 177 right name and namespace, but no attributes or content. 178 - `doc`: document to which the element belongs. 179 :Types: 180 - `xmlnode`: `libxml2.xmlNode` 181 - `doc`: `libxml2.xmlDoc`""" 182 ns = xmlnode.ns() 183 if self.instructions is not None: 184 xmlnode.newTextChild(ns, "instructions", to_utf8(self.instructions)) 185 if self.form: 186 self.form.as_xml(xmlnode, doc) 187 if self.remove: 188 xmlnode.newChild(ns, "remove", None) 189 else: 190 if self.registered: 191 xmlnode.newChild(ns, "registered", None) 192 for field in legacy_fields: 193 value = getattr(self, field) 194 if value is not None: 195 xmlnode.newTextChild(ns, field, to_utf8(value))
196
197 - def get_form(self, form_type = "form"):
198 """Return Data Form for the `Register` object. 199 200 Convert legacy fields to a data form if `self.form` is `None`, return `self.form` otherwise. 201 202 :Parameters: 203 - `form_type`: If "form", then a form to fill-in should be 204 returned. If "sumbit", then a form with submitted data. 205 :Types: 206 - `form_type`: `unicode` 207 208 :return: `self.form` or a form created from the legacy fields 209 :returntype: `pyxmpp.jabber.dataforms.Form`""" 210 211 if self.form: 212 if self.form.type != form_type: 213 raise ValueError, "Bad form type in the jabber:iq:register element" 214 return self.form 215 216 form = Form(form_type, instructions = self.instructions) 217 form.add_field("FORM_TYPE", [u"jabber:iq:register"], "hidden") 218 for field in legacy_fields: 219 field_type, field_label = legacy_fields[field] 220 value = getattr(self, field) 221 if value is None: 222 continue 223 if form_type == "form": 224 if not value: 225 value = None 226 form.add_field(name = field, field_type = field_type, label = field_label, 227 value = value, required = True) 228 else: 229 form.add_field(name = field, value = value) 230 return form
231
232 - def submit_form(self, form):
233 """Make `Register` object for submitting the registration form. 234 235 Convert form data to legacy fields if `self.form` is `None`. 236 237 :Parameters: 238 - `form`: The form to submit. Its type doesn't have to be "submit" 239 (a "submit" form will be created here), so it could be the form 240 obtained from `get_form` just with the data entered. 241 242 :return: new registration element 243 :returntype: `Register`""" 244 245 result = Register() 246 if self.form: 247 result.form = form.make_submit() 248 return result 249 250 if "FORM_TYPE" not in form or "jabber:iq:register" not in form["FORM_TYPE"].values: 251 raise ValueError, "FORM_TYPE is not jabber:iq:register" 252 253 for field in legacy_fields: 254 self.__logger.debug(u"submitted field %r" % (field, )) 255 value = getattr(self, field) 256 try: 257 form_value = form[field].value 258 except KeyError: 259 if value: 260 raise ValueError, "Required field with no value!" 261 continue 262 setattr(result, field, form_value) 263 264 return result
265 266 267 # vi: sts=4 et sw=4 268