Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
-
a161f7fa
by Philipp Hörist at 2019-04-03T16:54:07Z
-
79330a50
by Philipp Hörist at 2019-04-03T19:30:17Z
4 changed files:
Changes:
| ... | ... | @@ -66,6 +66,7 @@ from nbxmpp.modules.openpgp import OpenPGP |
| 66 | 66 |
from nbxmpp.modules.omemo import OMEMO
|
| 67 | 67 |
from nbxmpp.modules.annotations import Annotations
|
| 68 | 68 |
from nbxmpp.modules.muclumbus import Muclumbus
|
| 69 |
+from nbxmpp.modules.software_version import SoftwareVersion
|
|
| 69 | 70 |
from nbxmpp.modules.misc import unwrap_carbon
|
| 70 | 71 |
from nbxmpp.modules.misc import unwrap_mam
|
| 71 | 72 |
from nbxmpp.util import get_properties_struct
|
| ... | ... | @@ -200,6 +201,7 @@ class XMPPDispatcher(PlugIn): |
| 200 | 201 |
self._modules['OMEMO'] = OMEMO(self._owner)
|
| 201 | 202 |
self._modules['Annotations'] = Annotations(self._owner)
|
| 202 | 203 |
self._modules['Muclumbus'] = Muclumbus(self._owner)
|
| 204 |
+ self._modules['SoftwareVersion'] = SoftwareVersion(self._owner)
|
|
| 203 | 205 |
|
| 204 | 206 |
for instance in self._modules.values():
|
| 205 | 207 |
for handler in instance.handlers:
|
| ... | ... | @@ -82,7 +82,7 @@ class MUC: |
| 82 | 82 |
callback=self._process_direct_invite,
|
| 83 | 83 |
typ='normal',
|
| 84 | 84 |
ns=NS_CONFERENCE,
|
| 85 |
- priority=11),
|
|
| 85 |
+ priority=12),
|
|
| 86 | 86 |
StanzaHandler(name='message',
|
| 87 | 87 |
callback=self._process_voice_request,
|
| 88 | 88 |
ns=NS_DATA,
|
| ... | ... | @@ -90,7 +90,7 @@ class MUC: |
| 90 | 90 |
StanzaHandler(name='message',
|
| 91 | 91 |
callback=self._process_message,
|
| 92 | 92 |
ns=NS_MUC_USER,
|
| 93 |
- priority=12),
|
|
| 93 |
+ priority=13),
|
|
| 94 | 94 |
]
|
| 95 | 95 |
|
| 96 | 96 |
@staticmethod
|
| ... | ... | @@ -225,15 +225,14 @@ class MUC: |
| 225 | 225 |
if direct is None:
|
| 226 | 226 |
return
|
| 227 | 227 |
|
| 228 |
- muc_jid = direct.getAttr('jid')
|
|
| 229 |
- if muc_jid is None:
|
|
| 230 |
- # Not a direct invite
|
|
| 228 |
+ if stanza.getTag('x', namespace=NS_MUC_USER) is not None:
|
|
| 229 |
+ # not a direct invite
|
|
| 231 | 230 |
# See https://xmpp.org/extensions/xep-0045.html#example-57
|
| 232 | 231 |
# read implementation notes
|
| 233 | 232 |
return
|
| 234 | 233 |
|
| 235 | 234 |
data = {}
|
| 236 |
- data['muc'] = JID(muc_jid)
|
|
| 235 |
+ data['muc'] = JID(direct.getAttr('jid'))
|
|
| 237 | 236 |
data['from_'] = properties.jid
|
| 238 | 237 |
data['reason'] = direct.getAttr('reason')
|
| 239 | 238 |
data['password'] = direct.getAttr('password')
|
| 1 |
+# Copyright (C) 2019 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 |
+import logging
|
|
| 19 |
+ |
|
| 20 |
+from nbxmpp.protocol import NS_VERSION
|
|
| 21 |
+from nbxmpp.protocol import Iq
|
|
| 22 |
+from nbxmpp.protocol import isResultNode
|
|
| 23 |
+from nbxmpp.protocol import ErrorNode
|
|
| 24 |
+from nbxmpp.protocol import NodeProcessed
|
|
| 25 |
+from nbxmpp.protocol import ERR_SERVICE_UNAVAILABLE
|
|
| 26 |
+from nbxmpp.structs import SoftwareVersionResult
|
|
| 27 |
+from nbxmpp.structs import StanzaHandler
|
|
| 28 |
+from nbxmpp.util import call_on_response
|
|
| 29 |
+from nbxmpp.util import callback
|
|
| 30 |
+from nbxmpp.util import raise_error
|
|
| 31 |
+ |
|
| 32 |
+log = logging.getLogger('nbxmpp.m.software_version')
|
|
| 33 |
+ |
|
| 34 |
+ |
|
| 35 |
+class SoftwareVersion:
|
|
| 36 |
+ def __init__(self, client):
|
|
| 37 |
+ self._client = client
|
|
| 38 |
+ self.handlers = [
|
|
| 39 |
+ StanzaHandler(name='iq',
|
|
| 40 |
+ callback=self._answer_request,
|
|
| 41 |
+ typ='get',
|
|
| 42 |
+ ns=NS_VERSION),
|
|
| 43 |
+ ]
|
|
| 44 |
+ |
|
| 45 |
+ self._name = None
|
|
| 46 |
+ self._version = None
|
|
| 47 |
+ self._os = None
|
|
| 48 |
+ |
|
| 49 |
+ self._enabled = False
|
|
| 50 |
+ |
|
| 51 |
+ def disable(self):
|
|
| 52 |
+ self._enabled = False
|
|
| 53 |
+ |
|
| 54 |
+ @call_on_response('_software_version_received')
|
|
| 55 |
+ def request_software_version(self, jid):
|
|
| 56 |
+ log.info('Request software version for %s', jid)
|
|
| 57 |
+ return Iq(typ='get', to=jid, queryNS=NS_VERSION)
|
|
| 58 |
+ |
|
| 59 |
+ @callback
|
|
| 60 |
+ def _software_version_received(self, stanza):
|
|
| 61 |
+ if not isResultNode(stanza):
|
|
| 62 |
+ return raise_error(log.info, stanza)
|
|
| 63 |
+ |
|
| 64 |
+ try:
|
|
| 65 |
+ return SoftwareVersionResult(*self._parse_info(stanza))
|
|
| 66 |
+ except Exception as error:
|
|
| 67 |
+ log.warning(error)
|
|
| 68 |
+ return raise_error(log.warning, stanza, 'stanza-malformed')
|
|
| 69 |
+ |
|
| 70 |
+ @staticmethod
|
|
| 71 |
+ def _parse_info(stanza):
|
|
| 72 |
+ name = stanza.getQueryChild('name').getData()
|
|
| 73 |
+ version = stanza.getQueryChild('version').getData()
|
|
| 74 |
+ |
|
| 75 |
+ os_info = stanza.getQueryChild('os')
|
|
| 76 |
+ if os_info is not None:
|
|
| 77 |
+ os_info = os_info.getData()
|
|
| 78 |
+ |
|
| 79 |
+ return name, version, os_info
|
|
| 80 |
+ |
|
| 81 |
+ def set_software_version(self, name, version, os=None):
|
|
| 82 |
+ self._name, self._version, self._os = name, version, os
|
|
| 83 |
+ self._enabled = True
|
|
| 84 |
+ |
|
| 85 |
+ def _answer_request(self, _con, stanza, _properties):
|
|
| 86 |
+ log.info('Request received from %s', stanza.getFrom())
|
|
| 87 |
+ if (not self._enabled or
|
|
| 88 |
+ self._name is None or
|
|
| 89 |
+ self._version is None):
|
|
| 90 |
+ iq = stanza.buildReply('error')
|
|
| 91 |
+ iq.addChild(node=ErrorNode(ERR_SERVICE_UNAVAILABLE))
|
|
| 92 |
+ log.info('Send service-unavailable')
|
|
| 93 |
+ |
|
| 94 |
+ else:
|
|
| 95 |
+ iq = stanza.buildReply('result')
|
|
| 96 |
+ query = iq.getQuery()
|
|
| 97 |
+ query.setTagData('name', self._name)
|
|
| 98 |
+ query.setTagData('version', self._version)
|
|
| 99 |
+ if self._os is not None:
|
|
| 100 |
+ query.setTagData('os', self._os)
|
|
| 101 |
+ log.info('Send software version: %s %s %s',
|
|
| 102 |
+ self._name, self._version, self._os)
|
|
| 103 |
+ |
|
| 104 |
+ self._client.send(iq)
|
|
| 105 |
+ raise NodeProcessed
|
| ... | ... | @@ -104,6 +104,8 @@ MuclumbusResult = namedtuple('MuclumbusResult', 'first last max end items') |
| 104 | 104 |
|
| 105 | 105 |
MuclumbusItem = namedtuple('MuclumbusItem', 'jid name nusers description language is_open anonymity_mode')
|
| 106 | 106 |
|
| 107 |
+SoftwareVersionResult = namedtuple('SoftwareVersionResult', 'name version os')
|
|
| 108 |
+ |
|
| 107 | 109 |
|
| 108 | 110 |
class OMEMOBundle(namedtuple('OMEMOBundle', 'spk spk_signature ik otpks')):
|
| 109 | 111 |
def pick_prekey(self):
|