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 18from nbxmpp.namespaces import Namespace 19from nbxmpp.protocol import Iq 20from nbxmpp.protocol import ErrorNode 21from nbxmpp.protocol import NodeProcessed 22from nbxmpp.protocol import ERR_SERVICE_UNAVAILABLE 23from nbxmpp.structs import SoftwareVersionResult 24from nbxmpp.structs import StanzaHandler 25from nbxmpp.modules.base import BaseModule 26from nbxmpp.task import iq_request_task 27from nbxmpp.errors import MalformedStanzaError 28from nbxmpp.errors import StanzaError 29 30 31class SoftwareVersion(BaseModule): 32 def __init__(self, client): 33 BaseModule.__init__(self, client) 34 35 self._client = client 36 self.handlers = [ 37 StanzaHandler(name='iq', 38 callback=self._answer_request, 39 typ='get', 40 ns=Namespace.VERSION), 41 ] 42 43 self._name = None 44 self._version = None 45 self._os = None 46 47 self._enabled = False 48 49 def disable(self): 50 self._enabled = False 51 52 @iq_request_task 53 def request_software_version(self, jid): 54 _task = yield 55 56 self._log.info('Request software version for %s', jid) 57 58 response = yield Iq(typ='get', to=jid, queryNS=Namespace.VERSION) 59 if response.isError(): 60 raise StanzaError(response) 61 62 yield _parse_info(response) 63 64 def set_software_version(self, name, version, os=None): 65 self._name, self._version, self._os = name, version, os 66 self._enabled = True 67 68 def _answer_request(self, _con, stanza, _properties): 69 self._log.info('Request received from %s', stanza.getFrom()) 70 if (not self._enabled or 71 self._name is None or 72 self._version is None): 73 iq = stanza.buildReply('error') 74 iq.addChild(node=ErrorNode(ERR_SERVICE_UNAVAILABLE)) 75 self._log.info('Send service-unavailable') 76 77 else: 78 iq = stanza.buildReply('result') 79 query = iq.getQuery() 80 query.setTagData('name', self._name) 81 query.setTagData('version', self._version) 82 if self._os is not None: 83 query.setTagData('os', self._os) 84 self._log.info('Send software version: %s %s %s', 85 self._name, self._version, self._os) 86 87 self._client.send_stanza(iq) 88 raise NodeProcessed 89 90 91def _parse_info(stanza): 92 try: 93 name = stanza.getQueryChild('name').getData() 94 except Exception: 95 raise MalformedStanzaError('name node missing', stanza) 96 97 try: 98 version = stanza.getQueryChild('version').getData() 99 except Exception: 100 raise MalformedStanzaError('version node missing', stanza) 101 102 os_info = stanza.getQueryChild('os') 103 if os_info is not None: 104 os_info = os_info.getData() 105 106 return SoftwareVersionResult(name, version, os_info) 107