Philipp Hörist pushed to branch nbxmpp_2.0 at gajim / python-nbxmpp
Commits:
3b9e6ea3 by lovetox at 2021-07-24T21:45:22+02:00
AdHoc: Improve XEP-0050 Compliance
- - - - -
a808009a by lovetox at 2021-07-24T21:45:22+02:00
AdHoc: Cancel action is always possible
- - - - -
d3735912 by lovetox at 2021-07-24T21:45:22+02:00
GSSAPI: Catch OSError
Error is thrown when Kerberos for Windows is not installed
- - - - -
4efc81e4 by lovetox at 2021-07-24T21:45:22+02:00
Update README.md
- - - - -
61bff9bd by lovetox at 2021-07-24T21:45:22+02:00
AdHoc: Don’t expect session id for one stage commands
- - - - -
afaf927d by lovetox at 2021-07-24T21:45:22+02:00
Correctly handle RSM count request
Fixes #120
- - - - -
4 changed files:
- README.md
- nbxmpp/auth.py
- nbxmpp/modules/adhoc.py
- nbxmpp/modules/mam.py
Changes:
=====================================
README.md
=====================================
@@ -13,7 +13,7 @@
## Optional Runtime Requirements
-- python-gssapi (for GSSAPI authentication)
+- python-gssapi (for GSSAPI authentication https://pypi.org/project/gssapi/)
## Features
=====================================
nbxmpp/auth.py
=====================================
@@ -37,7 +37,8 @@ log = logging.getLogger('nbxmpp.auth')
try:
gssapi = __import__('gssapi')
GSSAPI_AVAILABLE = True
-except ImportError:
+except (ImportError, OSError) as error:
+ log.warning('GSSAPI not available: %s', error)
GSSAPI_AVAILABLE = False
=====================================
nbxmpp/modules/adhoc.py
=====================================
@@ -66,18 +66,18 @@ class AdHoc(BaseModule):
yield command_list
@iq_request_task
- def execute_command(self, command, action=None, dataform=None):
+ def execute_command(self, cmd, action=None, dataform=None):
_task = yield
if action is None:
action = AdHocAction.EXECUTE
- attrs = {'node': command.node,
+ attrs = {'node': cmd.node,
'xmlns': Namespace.COMMANDS,
'action': action.value}
- if command.sessionid is not None:
- attrs['sessionid'] = command.sessionid
+ if cmd.sessionid is not None:
+ attrs['sessionid'] = cmd.sessionid
- response = yield _make_command(command, attrs, dataform)
+ response = yield _make_command(cmd, attrs, dataform)
if response.isError():
raise StanzaError(response)
@@ -85,41 +85,44 @@ class AdHoc(BaseModule):
if command is None:
raise MalformedStanzaError('command node missing', response)
- attrs = command.getAttrs()
- notes = []
- actions = []
+ node = command.getAttr('node')
+ if node is None:
+ raise MalformedStanzaError('node attribute missing', response)
+
+ status = command.getAttr('status')
+ if status is None:
+ raise MalformedStanzaError('status attribute missing', response)
+
+ if status not in ('executing', 'completed', 'canceled'):
+ raise MalformedStanzaError('invalid status attribute %s' % status,
+ response)
+
+ status = AdHocStatus(status)
+
+ sessionid = command.getAttr('sessionid')
+ if sessionid is None and _expect_sessionid(status, cmd.sessionid):
+ raise MalformedStanzaError('sessionid attribute missing', response)
+
+ try:
+ notes = _parse_notes(command)
+ except ValueError as error:
+ raise MalformedStanzaError(error, response)
+
try:
- for note in command.getTags('note'):
- type_ = note.getAttr('type')
- if type_ is not None:
- type_ = AdHocNoteType(note.getAttr('type'))
- notes.append(AdHocCommandNote(text=note.getData(),
- type=type_))
-
- default = None
- actions_ = command.getTag('actions')
- if actions_ is not None:
- for action_ in actions_.getChildren():
- actions.append(AdHocAction(action_.getName()))
-
- default = actions_.getAttr('execute')
- if default is not None:
- default = AdHocAction(default)
- if default not in actions:
- default = None
-
- yield AdHocCommand(
- jid=str(response.getFrom()),
- name=None,
- node=attrs['node'],
- sessionid=attrs.get('sessionid'),
- status=AdHocStatus(attrs['status']),
- data=command.getTag('x', namespace=Namespace.DATA),
- actions=actions,
- default=default,
- notes=notes)
- except Exception as error:
- raise MalformedStanzaError(str(error), response)
+ actions, default = _parse_actions(command)
+ except ValueError as error:
+ raise MalformedStanzaError(error, response)
+
+ yield AdHocCommand(
+ jid=response.getFrom(),
+ name=None,
+ node=node,
+ sessionid=sessionid,
+ status=status,
+ data=command.getTag('x', namespace=Namespace.DATA),
+ actions=actions,
+ default=default,
+ notes=notes)
def _make_command(command, attrs, dataform):
@@ -129,3 +132,69 @@ def _make_command(command, attrs, dataform):
iq = Iq('set', to=command.jid)
iq.addChild(node=command_node)
return iq
+
+
+def _parse_notes(command):
+ notes = []
+ for note in command.getTags('note'):
+ type_ = note.getAttr('type')
+ if type_ is None:
+ type_ = 'info'
+
+ if type_ not in ('info', 'warn', 'error'):
+ raise ValueError('invalid note type %s' % type_)
+
+ notes.append(AdHocCommandNote(text=note.getData(),
+ type=AdHocNoteType(type_)))
+ return notes
+
+
+def _parse_actions(command):
+ if command.getAttr('status') != 'executing':
+ return [], None
+
+ actions_node = command.getTag('actions')
+ if actions_node is None:
+ # If there is no <actions/> element,
+ # the user-agent can use a single-stage dialog or view.
+ # The action "execute" is equivalent to the action "complete".
+ return [AdHocAction.CANCEL, AdHocAction.COMPLETE], AdHocAction.COMPLETE
+
+ actions = []
+ for action in actions_node.getChildren():
+ name = action.getName()
+ if name not in ('prev', 'next', 'complete'):
+ raise ValueError('invalid action name: %s' % name)
+ actions.append(AdHocAction(name))
+
+ if not actions:
+ raise ValueError('actions element without actions')
+
+ # The action "cancel" is always allowed.
+ actions.append(AdHocAction.CANCEL)
+
+ default = actions_node.getAttr('execute')
+ if default is None:
+ # If the "execute" attribute is absent, it defaults to "next".
+ default = 'next'
+
+ if default not in ('prev', 'next', 'complete'):
+ raise ValueError('invalid execute attribute %s' % default)
+
+ default = AdHocAction(default)
+
+ # A form which has an <actions/> element and an "execute" attribute
+ # which evaluates (taking the default into account if absent) to an
+ # action which is not allowed is therefore invalid.
+ if default not in actions:
+ # Some implementations don’t respect this rule.
+ # Take the first action so we don’t fail here.
+ default = actions[0]
+
+ return actions, default
+
+
+def _expect_sessionid(status, sent_sessionid):
+ # Session id should only be expected for multiple stage commands
+ # or when we initialize the session (set the session attribute)
+ return status != status.COMPLETED or sent_sessionid is not None
=====================================
nbxmpp/modules/mam.py
=====================================
@@ -66,7 +66,10 @@ class MAM(BaseModule):
raise MalformedStanzaError('rsm set missing', response)
complete = fin.getAttr('complete') == 'true'
- if not complete:
+ if max_ != 0 and not complete:
+ # max_ == 0 is a request for count of the items in a result set
+ # in this case first and last will be absent
+ # See: https://xmpp.org/extensions/xep-0059.html#count
if rsm.first is None or rsm.last is None:
raise MalformedStanzaError('first or last element missing',
response)
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/-/compare/99530609dcf9022fccf2a0a…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/-/compare/99530609dcf9022fccf2a0a…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
f532ff35 by lovetox at 2021-07-24T21:09:34+02:00
Correctly handle RSM count request
Fixes #120
- - - - -
1 changed file:
- nbxmpp/modules/mam.py
Changes:
=====================================
nbxmpp/modules/mam.py
=====================================
@@ -66,7 +66,10 @@ class MAM(BaseModule):
raise MalformedStanzaError('rsm set missing', response)
complete = fin.getAttr('complete') == 'true'
- if not complete:
+ if max_ != 0 and not complete:
+ # max_ == 0 is a request for count of the items in a result set
+ # in this case first and last will be absent
+ # See: https://xmpp.org/extensions/xep-0059.html#count
if rsm.first is None or rsm.last is None:
raise MalformedStanzaError('first or last element missing',
response)
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/-/commit/f532ff354c461e6606162489…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/-/commit/f532ff354c461e6606162489…
You're receiving this email because of your account on dev.gajim.org.