Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
-
1cb28e12
by lovetox at 2020-10-19T17:07:13+02:00
6 changed files:
- nbxmpp/errors.py
- − nbxmpp/modules/register.py
- + nbxmpp/modules/register/__init__.py
- + nbxmpp/modules/register/register.py
- + nbxmpp/modules/register/util.py
- nbxmpp/structs.py
Changes:
| ... | ... | @@ -135,3 +135,21 @@ class CancelledError(BaseError): |
| 135 | 135 |
def __init__(self):
|
| 136 | 136 |
BaseError.__init__(self, is_fatal=True)
|
| 137 | 137 |
self.text = 'Task has been cancelled'
|
| 138 |
+ |
|
| 139 |
+ |
|
| 140 |
+class RegisterStanzaError(StanzaError):
|
|
| 141 |
+ def __init__(self, stanza, data):
|
|
| 142 |
+ StanzaError.__init__(self, stanza)
|
|
| 143 |
+ self._data = data
|
|
| 144 |
+ |
|
| 145 |
+ def get_data(self):
|
|
| 146 |
+ return self._data
|
|
| 147 |
+ |
|
| 148 |
+ |
|
| 149 |
+class ChangePasswordStanzaError(StanzaError):
|
|
| 150 |
+ def __init__(self, stanza, form):
|
|
| 151 |
+ StanzaError.__init__(self, stanza)
|
|
| 152 |
+ self._form = form
|
|
| 153 |
+ |
|
| 154 |
+ def get_form(self):
|
|
| 155 |
+ return self._form
|
| 1 |
-# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
|
|
| 2 |
-#
|
|
| 3 |
-# This file is part of nbxmpp.
|
|
| 4 |
-#
|
|
| 5 |
-# This program is free software; you can redistribute it and/or
|
|
| 6 |
-# modify it under the terms of the GNU General Public License
|
|
| 7 |
-# as published by the Free Software Foundation; either version 3
|
|
| 8 |
-# of the License, or (at your option) any later version.
|
|
| 9 |
-#
|
|
| 10 |
-# This program is distributed in the hope that it will be useful,
|
|
| 11 |
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 12 |
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 13 |
-# GNU General Public License for more details.
|
|
| 14 |
-#
|
|
| 15 |
-# You should have received a copy of the GNU General Public License
|
|
| 16 |
-# along with this program; If not, see <http://www.gnu.org/licenses/>.
|
|
| 17 |
- |
|
| 18 |
-from nbxmpp.namespaces import Namespace
|
|
| 19 |
-from nbxmpp.protocol import Iq
|
|
| 20 |
-from nbxmpp.protocol import isResultNode
|
|
| 21 |
-from nbxmpp.structs import CommonResult
|
|
| 22 |
-from nbxmpp.structs import CommonError
|
|
| 23 |
-from nbxmpp.structs import RegisterData
|
|
| 24 |
-from nbxmpp.structs import ChangePasswordResult
|
|
| 25 |
-from nbxmpp.util import call_on_response
|
|
| 26 |
-from nbxmpp.util import callback
|
|
| 27 |
-from nbxmpp.util import raise_error
|
|
| 28 |
-from nbxmpp.util import get_form
|
|
| 29 |
-from nbxmpp.const import REGISTER_FIELDS
|
|
| 30 |
-from nbxmpp.modules.bits_of_binary import parse_bob_data
|
|
| 31 |
-from nbxmpp.modules.dataforms import extend_form
|
|
| 32 |
-from nbxmpp.modules.dataforms import create_field
|
|
| 33 |
-from nbxmpp.modules.dataforms import SimpleDataForm
|
|
| 34 |
-from nbxmpp.modules.base import BaseModule
|
|
| 35 |
- |
|
| 36 |
- |
|
| 37 |
-class Register(BaseModule):
|
|
| 38 |
- def __init__(self, client):
|
|
| 39 |
- BaseModule.__init__(self, client)
|
|
| 40 |
- |
|
| 41 |
- self._client = client
|
|
| 42 |
- self.handlers = []
|
|
| 43 |
- |
|
| 44 |
- @call_on_response('_default_response')
|
|
| 45 |
- def unregister(self, jid=None):
|
|
| 46 |
- iq = Iq('set', to=jid)
|
|
| 47 |
- query = iq.setQuery()
|
|
| 48 |
- query.setNamespace(Namespace.REGISTER)
|
|
| 49 |
- query.addChild('remove')
|
|
| 50 |
- return iq
|
|
| 51 |
- |
|
| 52 |
- @call_on_response('_on_register_form')
|
|
| 53 |
- def request_register_form(self, jid=None):
|
|
| 54 |
- if jid is None:
|
|
| 55 |
- jid = self._client.domain
|
|
| 56 |
- return Iq('get', Namespace.REGISTER, to=jid)
|
|
| 57 |
- |
|
| 58 |
- @callback
|
|
| 59 |
- def _on_register_form(self, stanza):
|
|
| 60 |
- if not isResultNode(stanza):
|
|
| 61 |
- return raise_error(self._log.info, stanza)
|
|
| 62 |
- |
|
| 63 |
- query = stanza.getQuery()
|
|
| 64 |
- instructions = query.getTagData('instructions') or None
|
|
| 65 |
- |
|
| 66 |
- data = RegisterData(instructions=instructions,
|
|
| 67 |
- form=self._parse_form(stanza),
|
|
| 68 |
- fields_form=self._parse_fields_form(query),
|
|
| 69 |
- oob_url=self._parse_oob_url(query),
|
|
| 70 |
- bob_data=parse_bob_data(query))
|
|
| 71 |
- |
|
| 72 |
- if (data.form is None and
|
|
| 73 |
- data.fields_form is None and
|
|
| 74 |
- data.oob_url is None):
|
|
| 75 |
- return raise_error(self._log.info, stanza, 'stanza-malformed')
|
|
| 76 |
- return data
|
|
| 77 |
- |
|
| 78 |
- @call_on_response('_on_submit_result')
|
|
| 79 |
- def submit_register_form(self, jid, form):
|
|
| 80 |
- if jid is None:
|
|
| 81 |
- jid = self._client.domain
|
|
| 82 |
- |
|
| 83 |
- iq = Iq('set', Namespace.REGISTER, to=jid)
|
|
| 84 |
- |
|
| 85 |
- if form.is_fake_form():
|
|
| 86 |
- query = iq.getTag('query')
|
|
| 87 |
- for field in form.iter_fields():
|
|
| 88 |
- if field.var == 'fakeform':
|
|
| 89 |
- continue
|
|
| 90 |
- query.addChild(field.var, payload=[field.value])
|
|
| 91 |
- return iq
|
|
| 92 |
- |
|
| 93 |
- iq.setQueryPayload(form)
|
|
| 94 |
- return iq
|
|
| 95 |
- |
|
| 96 |
- @callback
|
|
| 97 |
- def _on_submit_result(self, stanza):
|
|
| 98 |
- if isResultNode(stanza):
|
|
| 99 |
- return CommonResult(jid=stanza.getFrom())
|
|
| 100 |
- |
|
| 101 |
- query = stanza.getTag('query', namespace=Namespace.REGISTER)
|
|
| 102 |
- if query is None:
|
|
| 103 |
- return RegisterError(stanza, None)
|
|
| 104 |
- |
|
| 105 |
- instructions = query.getTagData('instructions') or None
|
|
| 106 |
- |
|
| 107 |
- data = RegisterData(instructions=instructions,
|
|
| 108 |
- form=self._parse_form(stanza),
|
|
| 109 |
- fields_form=self._parse_fields_form(query),
|
|
| 110 |
- oob_url=self._parse_oob_url(query),
|
|
| 111 |
- bob_data=parse_bob_data(query))
|
|
| 112 |
- |
|
| 113 |
- return RegisterError(stanza, data)
|
|
| 114 |
- |
|
| 115 |
- @callback
|
|
| 116 |
- def _default_response(self, stanza):
|
|
| 117 |
- if not isResultNode(stanza):
|
|
| 118 |
- return raise_error(self._log.info, stanza)
|
|
| 119 |
- return CommonResult(jid=stanza.getFrom())
|
|
| 120 |
- |
|
| 121 |
- @staticmethod
|
|
| 122 |
- def _parse_oob_url(query):
|
|
| 123 |
- oob = query.getTag('x', namespace=Namespace.X_OOB)
|
|
| 124 |
- if oob is not None:
|
|
| 125 |
- return oob.getTagData('url') or None
|
|
| 126 |
- return None
|
|
| 127 |
- |
|
| 128 |
- def _parse_form(self, stanza):
|
|
| 129 |
- query = stanza.getTag('query', namespace=Namespace.REGISTER)
|
|
| 130 |
- form = query.getTag('x', namespace=Namespace.DATA)
|
|
| 131 |
- if form is None:
|
|
| 132 |
- return None
|
|
| 133 |
- |
|
| 134 |
- form = extend_form(node=form)
|
|
| 135 |
- field = form.vars.get('FORM_TYPE')
|
|
| 136 |
- if field is None:
|
|
| 137 |
- self._log.warning('No FORM_TYPE found')
|
|
| 138 |
- self._log.warning(stanza)
|
|
| 139 |
- return None
|
|
| 140 |
- |
|
| 141 |
- # Invalid urn:xmpp:captcha used by ejabberd
|
|
| 142 |
- # See https://github.com/processone/ejabberd/issues/3093
|
|
| 143 |
- if field.value in ('jabber:iq:register', 'urn:xmpp:captcha'):
|
|
| 144 |
- return form
|
|
| 145 |
- return None
|
|
| 146 |
- |
|
| 147 |
- @staticmethod
|
|
| 148 |
- def _parse_fields_form(query):
|
|
| 149 |
- fields = []
|
|
| 150 |
- for field in query.getChildren():
|
|
| 151 |
- field_name = field.getName()
|
|
| 152 |
- if field_name not in REGISTER_FIELDS:
|
|
| 153 |
- continue
|
|
| 154 |
- |
|
| 155 |
- required = field_name in ('username', 'password')
|
|
| 156 |
- typ = 'text-single' if field_name != 'password' else 'text-private'
|
|
| 157 |
- fields.append(create_field(typ=typ,
|
|
| 158 |
- var=field_name,
|
|
| 159 |
- required=required))
|
|
| 160 |
- |
|
| 161 |
- if not fields:
|
|
| 162 |
- return None
|
|
| 163 |
- |
|
| 164 |
- fields.append(create_field(typ='hidden', var='fakeform'))
|
|
| 165 |
- return SimpleDataForm(type_='form',
|
|
| 166 |
- instructions=query.getTagData('instructions'),
|
|
| 167 |
- fields=fields)
|
|
| 168 |
- |
|
| 169 |
- @call_on_response('_on_password_change')
|
|
| 170 |
- def change_password(self, password):
|
|
| 171 |
- domain = self._client.get_bound_jid().domain
|
|
| 172 |
- username = self._client.get_bound_jid().localpart
|
|
| 173 |
- iq = Iq('set', Namespace.REGISTER, to=domain)
|
|
| 174 |
- query = iq.getQuery()
|
|
| 175 |
- query.setTagData('username', username)
|
|
| 176 |
- query.setTagData('password', password)
|
|
| 177 |
- return iq
|
|
| 178 |
- |
|
| 179 |
- @callback
|
|
| 180 |
- def _on_password_change(self, stanza):
|
|
| 181 |
- if isResultNode(stanza):
|
|
| 182 |
- return ChangePasswordResult(successful=True)
|
|
| 183 |
- |
|
| 184 |
- if stanza.getQuery() is None:
|
|
| 185 |
- return raise_error(self._log.info, stanza)
|
|
| 186 |
- |
|
| 187 |
- form = get_form(stanza.getQuery(),
|
|
| 188 |
- 'jabber:iq:register:changepassword')
|
|
| 189 |
- if form is None:
|
|
| 190 |
- return raise_error(self._log.info, stanza)
|
|
| 191 |
- return ChangePasswordResult(successful=False, form=form)
|
|
| 192 |
- |
|
| 193 |
- @call_on_response('_default_response')
|
|
| 194 |
- def change_password_with_form(self, form):
|
|
| 195 |
- domain = self._client.get_bound_jid().domain
|
|
| 196 |
- iq = Iq('set', Namespace.REGISTER, to=domain)
|
|
| 197 |
- iq.setQueryPayload(form)
|
|
| 198 |
- return iq
|
|
| 199 |
- |
|
| 200 |
- |
|
| 201 |
-class RegisterError(CommonError):
|
|
| 202 |
- def __init__(self, stanza, data):
|
|
| 203 |
- CommonError.__init__(self, stanza)
|
|
| 204 |
- self._data = data
|
|
| 205 |
- |
|
| 206 |
- def get_data(self):
|
|
| 207 |
- return self._data
|
| 1 |
+from .register import Register
|
| 1 |
+# Copyright (C) 2020 Philipp Hörist <philipp AT hoerist.com>
|
|
| 2 |
+#
|
|
| 3 |
+# This file is part of nbxmpp.
|
|
| 4 |
+#
|
|
| 5 |
+# This program is free software; you can redistribute it and/or
|
|
| 6 |
+# modify it under the terms of the GNU General Public License
|
|
| 7 |
+# as published by the Free Software Foundation; either version 3
|
|
| 8 |
+# of the License, or (at your option) any later version.
|
|
| 9 |
+#
|
|
| 10 |
+# This program is distributed in the hope that it will be useful,
|
|
| 11 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 12 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 13 |
+# GNU General Public License for more details.
|
|
| 14 |
+#
|
|
| 15 |
+# You should have received a copy of the GNU General Public License
|
|
| 16 |
+# along with this program; If not, see <http://www.gnu.org/licenses/>.
|
|
| 17 |
+ |
|
| 18 |
+from nbxmpp.namespaces import Namespace
|
|
| 19 |
+from nbxmpp.protocol import Iq
|
|
| 20 |
+from nbxmpp.util import get_form
|
|
| 21 |
+from nbxmpp.task import iq_request_task
|
|
| 22 |
+from nbxmpp.errors import StanzaError
|
|
| 23 |
+from nbxmpp.errors import RegisterStanzaError
|
|
| 24 |
+from nbxmpp.errors import ChangePasswordStanzaError
|
|
| 25 |
+from nbxmpp.modules.base import BaseModule
|
|
| 26 |
+from nbxmpp.modules.util import process_response
|
|
| 27 |
+from nbxmpp.modules.register.util import _make_unregister_request
|
|
| 28 |
+from nbxmpp.modules.register.util import _make_register_form
|
|
| 29 |
+from nbxmpp.modules.register.util import _make_password_change_request
|
|
| 30 |
+from nbxmpp.modules.register.util import _make_password_change_with_form
|
|
| 31 |
+from nbxmpp.modules.register.util import _parse_register_data
|
|
| 32 |
+ |
|
| 33 |
+ |
|
| 34 |
+class Register(BaseModule):
|
|
| 35 |
+ def __init__(self, client):
|
|
| 36 |
+ BaseModule.__init__(self, client)
|
|
| 37 |
+ |
|
| 38 |
+ self._client = client
|
|
| 39 |
+ self.handlers = []
|
|
| 40 |
+ |
|
| 41 |
+ @iq_request_task
|
|
| 42 |
+ def unregister(self, jid=None):
|
|
| 43 |
+ _task = yield
|
|
| 44 |
+ |
|
| 45 |
+ response = yield _make_unregister_request(jid)
|
|
| 46 |
+ yield process_response(response)
|
|
| 47 |
+ |
|
| 48 |
+ @iq_request_task
|
|
| 49 |
+ def request_register_form(self, jid=None):
|
|
| 50 |
+ _task = yield
|
|
| 51 |
+ |
|
| 52 |
+ if jid is None:
|
|
| 53 |
+ jid = self._client.domain
|
|
| 54 |
+ |
|
| 55 |
+ response = yield Iq('get', Namespace.REGISTER, to=jid)
|
|
| 56 |
+ if response.isError():
|
|
| 57 |
+ raise StanzaError(response)
|
|
| 58 |
+ |
|
| 59 |
+ yield _parse_register_data(response)
|
|
| 60 |
+ |
|
| 61 |
+ @iq_request_task
|
|
| 62 |
+ def submit_register_form(self, form, jid=None):
|
|
| 63 |
+ _task = yield
|
|
| 64 |
+ |
|
| 65 |
+ if jid is None:
|
|
| 66 |
+ jid = self._client.domain
|
|
| 67 |
+ |
|
| 68 |
+ response = yield _make_register_form(jid, form)
|
|
| 69 |
+ if not response.isError():
|
|
| 70 |
+ yield process_response(response)
|
|
| 71 |
+ |
|
| 72 |
+ else:
|
|
| 73 |
+ data = _parse_register_data(response)
|
|
| 74 |
+ raise RegisterStanzaError(response, data)
|
|
| 75 |
+ |
|
| 76 |
+ @iq_request_task
|
|
| 77 |
+ def change_password(self, password):
|
|
| 78 |
+ _task = yield
|
|
| 79 |
+ |
|
| 80 |
+ response = yield _make_password_change_request(
|
|
| 81 |
+ self._client.domain, self._client.username, password)
|
|
| 82 |
+ if not response.isError():
|
|
| 83 |
+ yield process_response(response)
|
|
| 84 |
+ |
|
| 85 |
+ else:
|
|
| 86 |
+ query = response.getQuery()
|
|
| 87 |
+ if query is None:
|
|
| 88 |
+ raise StanzaError(response)
|
|
| 89 |
+ |
|
| 90 |
+ form = get_form(query, 'jabber:iq:register:changepassword')
|
|
| 91 |
+ if form is None or response.getType() != 'modify':
|
|
| 92 |
+ raise StanzaError(response)
|
|
| 93 |
+ |
|
| 94 |
+ raise ChangePasswordStanzaError(response, form)
|
|
| 95 |
+ |
|
| 96 |
+ @iq_request_task
|
|
| 97 |
+ def change_password_with_form(self, form):
|
|
| 98 |
+ _task = yield
|
|
| 99 |
+ |
|
| 100 |
+ response = yield _make_password_change_with_form(self._client.domain,
|
|
| 101 |
+ form)
|
|
| 102 |
+ yield process_response(response)
|
| 1 |
+# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
|
|
| 2 |
+#
|
|
| 3 |
+# This file is part of nbxmpp.
|
|
| 4 |
+#
|
|
| 5 |
+# This program is free software; you can redistribute it and/or
|
|
| 6 |
+# modify it under the terms of the GNU General Public License
|
|
| 7 |
+# as published by the Free Software Foundation; either version 3
|
|
| 8 |
+# of the License, or (at your option) any later version.
|
|
| 9 |
+#
|
|
| 10 |
+# This program is distributed in the hope that it will be useful,
|
|
| 11 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 12 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 13 |
+# GNU General Public License for more details.
|
|
| 14 |
+#
|
|
| 15 |
+# You should have received a copy of the GNU General Public License
|
|
| 16 |
+# along with this program; If not, see <http://www.gnu.org/licenses/>.
|
|
| 17 |
+ |
|
| 18 |
+from nbxmpp.namespaces import Namespace
|
|
| 19 |
+from nbxmpp.protocol import Iq
|
|
| 20 |
+from nbxmpp.const import REGISTER_FIELDS
|
|
| 21 |
+from nbxmpp.structs import RegisterData
|
|
| 22 |
+from nbxmpp.errors import StanzaError
|
|
| 23 |
+from nbxmpp.errors import MalformedStanzaError
|
|
| 24 |
+from nbxmpp.modules.dataforms import create_field
|
|
| 25 |
+from nbxmpp.modules.dataforms import extend_form
|
|
| 26 |
+from nbxmpp.modules.dataforms import SimpleDataForm
|
|
| 27 |
+from nbxmpp.modules.bits_of_binary import parse_bob_data
|
|
| 28 |
+ |
|
| 29 |
+ |
|
| 30 |
+def _make_password_change_request(domain, username, password):
|
|
| 31 |
+ iq = Iq('set', Namespace.REGISTER, to=domain)
|
|
| 32 |
+ query = iq.getQuery()
|
|
| 33 |
+ query.setTagData('username', username)
|
|
| 34 |
+ query.setTagData('password', password)
|
|
| 35 |
+ return iq
|
|
| 36 |
+ |
|
| 37 |
+ |
|
| 38 |
+def _make_password_change_with_form(domain, form):
|
|
| 39 |
+ iq = Iq('set', Namespace.REGISTER, to=domain)
|
|
| 40 |
+ iq.setQueryPayload(form)
|
|
| 41 |
+ return iq
|
|
| 42 |
+ |
|
| 43 |
+ |
|
| 44 |
+def _make_register_form(jid, form):
|
|
| 45 |
+ iq = Iq('set', Namespace.REGISTER, to=jid)
|
|
| 46 |
+ if form.is_fake_form():
|
|
| 47 |
+ query = iq.getTag('query')
|
|
| 48 |
+ for field in form.iter_fields():
|
|
| 49 |
+ if field.var == 'fakeform':
|
|
| 50 |
+ continue
|
|
| 51 |
+ query.addChild(field.var, payload=[field.value])
|
|
| 52 |
+ return iq
|
|
| 53 |
+ |
|
| 54 |
+ iq.setQueryPayload(form)
|
|
| 55 |
+ return iq
|
|
| 56 |
+ |
|
| 57 |
+ |
|
| 58 |
+def _make_unregister_request(jid):
|
|
| 59 |
+ iq = Iq('set', to=jid)
|
|
| 60 |
+ query = iq.setQuery()
|
|
| 61 |
+ query.setNamespace(Namespace.REGISTER)
|
|
| 62 |
+ query.addChild('remove')
|
|
| 63 |
+ return iq
|
|
| 64 |
+ |
|
| 65 |
+ |
|
| 66 |
+def _parse_oob_url(query):
|
|
| 67 |
+ oob = query.getTag('x', namespace=Namespace.X_OOB)
|
|
| 68 |
+ if oob is not None:
|
|
| 69 |
+ return oob.getTagData('url') or None
|
|
| 70 |
+ return None
|
|
| 71 |
+ |
|
| 72 |
+ |
|
| 73 |
+def _parse_form(stanza):
|
|
| 74 |
+ query = stanza.getTag('query', namespace=Namespace.REGISTER)
|
|
| 75 |
+ form = query.getTag('x', namespace=Namespace.DATA)
|
|
| 76 |
+ if form is None:
|
|
| 77 |
+ return None
|
|
| 78 |
+ |
|
| 79 |
+ form = extend_form(node=form)
|
|
| 80 |
+ field = form.vars.get('FORM_TYPE')
|
|
| 81 |
+ if field is None:
|
|
| 82 |
+ return None
|
|
| 83 |
+ |
|
| 84 |
+ # Invalid urn:xmpp:captcha used by ejabberd
|
|
| 85 |
+ # See https://github.com/processone/ejabberd/issues/3045
|
|
| 86 |
+ if field.value in ('jabber:iq:register', 'urn:xmpp:captcha'):
|
|
| 87 |
+ return form
|
|
| 88 |
+ return None
|
|
| 89 |
+ |
|
| 90 |
+ |
|
| 91 |
+def _parse_fields_form(query):
|
|
| 92 |
+ fields = []
|
|
| 93 |
+ for field in query.getChildren():
|
|
| 94 |
+ field_name = field.getName()
|
|
| 95 |
+ if field_name not in REGISTER_FIELDS:
|
|
| 96 |
+ continue
|
|
| 97 |
+ |
|
| 98 |
+ required = field_name in ('username', 'password')
|
|
| 99 |
+ typ = 'text-single' if field_name != 'password' else 'text-private'
|
|
| 100 |
+ fields.append(create_field(typ=typ,
|
|
| 101 |
+ var=field_name,
|
|
| 102 |
+ required=required))
|
|
| 103 |
+ |
|
| 104 |
+ if not fields:
|
|
| 105 |
+ return None
|
|
| 106 |
+ |
|
| 107 |
+ fields.append(create_field(typ='hidden', var='fakeform'))
|
|
| 108 |
+ return SimpleDataForm(type_='form',
|
|
| 109 |
+ instructions=query.getTagData('instructions'),
|
|
| 110 |
+ fields=fields)
|
|
| 111 |
+ |
|
| 112 |
+ |
|
| 113 |
+def _parse_register_data(response):
|
|
| 114 |
+ query = response.getTag('query', namespace=Namespace.REGISTER)
|
|
| 115 |
+ if query is None:
|
|
| 116 |
+ raise StanzaError(response)
|
|
| 117 |
+ |
|
| 118 |
+ instructions = query.getTagData('instructions') or None
|
|
| 119 |
+ |
|
| 120 |
+ data = RegisterData(instructions=instructions,
|
|
| 121 |
+ form=_parse_form(response),
|
|
| 122 |
+ fields_form=_parse_fields_form(query),
|
|
| 123 |
+ oob_url=_parse_oob_url(query),
|
|
| 124 |
+ bob_data=parse_bob_data(query))
|
|
| 125 |
+ |
|
| 126 |
+ if (data.form is None and
|
|
| 127 |
+ data.fields_form is None and
|
|
| 128 |
+ data.oob_url is None):
|
|
| 129 |
+ raise MalformedStanzaError('invalid register response', response)
|
|
| 130 |
+ |
|
| 131 |
+ return data
|
| ... | ... | @@ -120,9 +120,6 @@ SecurityLabel = namedtuple('SecurityLabel', 'displaymarking') |
| 120 | 120 |
|
| 121 | 121 |
RegisterData = namedtuple('RegisterData', 'instructions form fields_form oob_url bob_data')
|
| 122 | 122 |
|
| 123 |
-ChangePasswordResult = namedtuple('ChangePasswordResult', 'successful form')
|
|
| 124 |
-ChangePasswordResult.__new__.__defaults__ = (None,)
|
|
| 125 |
- |
|
| 126 | 123 |
HTTPUploadData = namedtuple('HTTPUploadData', 'put_uri get_uri headers')
|
| 127 | 124 |
HTTPUploadData.__new__.__defaults__ = (None,)
|
| 128 | 125 |
|