core, setup: huge cleaning:
- moved directories from src and frontends/src to sat and sat_frontends, which is the recommanded naming convention - move twisted directory to root - removed all hacks from setup.py, and added missing dependencies, it is now clean - use https URL for website in setup.py - removed "Environment :: X11 Applications :: GTK", as wix is deprecated and removed - renamed sat.sh to sat and fixed its installation - added python_requires to specify Python version needed - replaced glib2reactor which use deprecated code by gtk3reactor sat can now be installed directly from virtualenv without using --system-site-packages anymore \o/
This commit is contained in:
parent
4afd2ff26f
commit
80ef13612b
1 changed files with 42 additions and 269 deletions
|
|
@ -1,209 +0,0 @@
|
|||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# SAT plugin for managing gateways (xep-0100)
|
||||
# Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core.i18n import _, D_
|
||||
from sat.core.constants import Const as C
|
||||
from sat.core import exceptions
|
||||
from sat.tools import xml_tools
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from twisted.words.protocols.jabber import jid
|
||||
from twisted.internet import reactor, defer
|
||||
|
||||
PLUGIN_INFO = {
|
||||
C.PI_NAME: "Gateways Plugin",
|
||||
C.PI_IMPORT_NAME: "XEP-0100",
|
||||
C.PI_TYPE: "XEP",
|
||||
C.PI_PROTOCOLS: ["XEP-0100"],
|
||||
C.PI_DEPENDENCIES: ["XEP-0077"],
|
||||
C.PI_MAIN: "XEP_0100",
|
||||
C.PI_DESCRIPTION: _("""Implementation of Gateways protocol""")
|
||||
}
|
||||
|
||||
WARNING_MSG = D_(u"""Be careful ! Gateways allow you to use an external IM (legacy IM), so you can see your contact as XMPP contacts.
|
||||
But when you do this, all your messages go throught the external legacy IM server, it is a huge privacy issue (i.e.: all your messages throught the gateway can be monitored, recorded, analysed by the external server, most of time a private company).""")
|
||||
|
||||
GATEWAY_TIMEOUT = 10 # time to wait before cancelling a gateway disco info, in seconds
|
||||
|
||||
TYPE_DESCRIPTIONS = {'irc': D_("Internet Relay Chat"),
|
||||
'xmpp': D_("XMPP"),
|
||||
'qq': D_("Tencent QQ"),
|
||||
'simple': D_("SIP/SIMPLE"),
|
||||
'icq': D_("ICQ"),
|
||||
'yahoo': D_("Yahoo! Messenger"),
|
||||
'gadu-gadu': D_("Gadu-Gadu"),
|
||||
'aim': D_("AOL Instant Messenger"),
|
||||
'msn': D_("Windows Live Messenger"),
|
||||
}
|
||||
|
||||
|
||||
class XEP_0100(object):
|
||||
|
||||
def __init__(self, host):
|
||||
log.info(_("Gateways plugin initialization"))
|
||||
self.host = host
|
||||
self.__gateways = {} # dict used to construct the answer to findGateways. Key = target jid
|
||||
host.bridge.addMethod("findGateways", ".plugin", in_sign='ss', out_sign='s', method=self._findGateways)
|
||||
host.bridge.addMethod("gatewayRegister", ".plugin", in_sign='ss', out_sign='s', method=self._gatewayRegister)
|
||||
self.__menu_id = host.registerCallback(self._gatewaysMenu, with_data=True)
|
||||
self.__selected_id = host.registerCallback(self._gatewaySelectedCb, with_data=True)
|
||||
host.importMenu((D_("Service"), D_("Gateways")), self._gatewaysMenu, security_limit=1, help_string=D_("Find gateways"))
|
||||
|
||||
def _gatewaysMenu(self, data, profile):
|
||||
""" XMLUI activated by menu: return Gateways UI
|
||||
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
jid_ = jid.JID(data.get(xml_tools.formEscape('external_jid'), client.jid.host))
|
||||
except RuntimeError:
|
||||
raise exceptions.DataError(_("Invalid JID"))
|
||||
d = self.findGateways(jid_, profile)
|
||||
d.addCallback(self._gatewaysResult2XMLUI, jid_)
|
||||
d.addCallback(lambda xmlui: {'xmlui': xmlui.toXml()})
|
||||
return d
|
||||
|
||||
def _gatewaysResult2XMLUI(self, result, entity):
|
||||
xmlui = xml_tools.XMLUI(title=_('Gateways manager (%s)') % entity.full())
|
||||
xmlui.addText(_(WARNING_MSG))
|
||||
xmlui.addDivider('dash')
|
||||
adv_list = xmlui.changeContainer('advanced_list', columns=3, selectable='single', callback_id=self.__selected_id)
|
||||
for success, gateway_data in result:
|
||||
if not success:
|
||||
fail_cond, disco_item = gateway_data
|
||||
xmlui.addJid(disco_item.entity)
|
||||
xmlui.addText(_('Failed (%s)') % fail_cond)
|
||||
xmlui.addEmpty()
|
||||
else:
|
||||
jid_, data = gateway_data
|
||||
for datum in data:
|
||||
identity, name = datum
|
||||
adv_list.setRowIndex(jid_.full())
|
||||
xmlui.addJid(jid_)
|
||||
xmlui.addText(name)
|
||||
xmlui.addText(self._getIdentityDesc(identity))
|
||||
adv_list.end()
|
||||
xmlui.addDivider('blank')
|
||||
xmlui.changeContainer('advanced_list', columns=3)
|
||||
xmlui.addLabel(_('Use external XMPP server'))
|
||||
xmlui.addString('external_jid')
|
||||
xmlui.addButton(self.__menu_id, _(u'Go !'), fields_back=('external_jid',))
|
||||
return xmlui
|
||||
|
||||
def _gatewaySelectedCb(self, data, profile):
|
||||
try:
|
||||
target_jid = jid.JID(data['index'])
|
||||
except (KeyError, RuntimeError):
|
||||
log.warning(_("No gateway index selected"))
|
||||
return {}
|
||||
|
||||
d = self.gatewayRegister(target_jid, profile)
|
||||
d.addCallback(lambda xmlui: {'xmlui': xmlui.toXml()})
|
||||
return d
|
||||
|
||||
def _getIdentityDesc(self, identity):
|
||||
""" Return a human readable description of identity
|
||||
@param identity: tuple as returned by Disco identities (category, type)
|
||||
|
||||
"""
|
||||
category, type_ = identity
|
||||
if category != 'gateway':
|
||||
log.error(_(u'INTERNAL ERROR: identity category should always be "gateway" in _getTypeString, got "%s"') % category)
|
||||
try:
|
||||
return _(TYPE_DESCRIPTIONS[type_])
|
||||
except KeyError:
|
||||
return _("Unknown IM")
|
||||
|
||||
def _registrationSuccessful(self, jid_, profile):
|
||||
"""Called when in_band registration is ok, we must now follow the rest of procedure"""
|
||||
log.debug(_("Registration successful, doing the rest"))
|
||||
self.host.addContact(jid_, profile_key=profile)
|
||||
self.host.setPresence(jid_, profile_key=profile)
|
||||
|
||||
def _gatewayRegister(self, target_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
d = self.gatewayRegister(jid.JID(target_jid_s), profile_key)
|
||||
d.addCallback(lambda xmlui: xmlui.toXml())
|
||||
return d
|
||||
|
||||
def gatewayRegister(self, target_jid, profile_key=C.PROF_KEY_NONE):
|
||||
"""Register gateway using in-band registration, then log-in to gateway"""
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
assert(profile)
|
||||
d = self.host.plugins["XEP-0077"].inBandRegister(target_jid, self._registrationSuccessful, profile)
|
||||
return d
|
||||
|
||||
def _infosReceived(self, dl_result, items, target, client):
|
||||
"""Find disco infos about entity, to check if it is a gateway"""
|
||||
|
||||
ret = []
|
||||
for idx, (success, result) in enumerate(dl_result):
|
||||
if not success:
|
||||
if isinstance(result.value, defer.CancelledError):
|
||||
msg = _("Timeout")
|
||||
else:
|
||||
try:
|
||||
msg = result.value.condition
|
||||
except AttributeError:
|
||||
msg = str(result)
|
||||
ret.append((success, (msg, items[idx])))
|
||||
else:
|
||||
entity = items[idx].entity
|
||||
gateways = [(identity, result.identities[identity]) for identity in result.identities if identity[0] == 'gateway']
|
||||
if gateways:
|
||||
log.info(_(u"Found gateway [%(jid)s]: %(identity_name)s") % {'jid': entity.full(), 'identity_name': ' - '.join([gateway[1] for gateway in gateways])})
|
||||
ret.append((success, (entity, gateways)))
|
||||
else:
|
||||
log.info(_(u"Skipping [%(jid)s] which is not a gateway") % {'jid': entity.full()})
|
||||
return ret
|
||||
|
||||
def _itemsReceived(self, disco, target, client):
|
||||
"""Look for items with disco protocol, and ask infos for each one"""
|
||||
|
||||
if len(disco._items) == 0:
|
||||
log.debug(_("No gateway found"))
|
||||
return []
|
||||
|
||||
_defers = []
|
||||
for item in disco._items:
|
||||
log.debug(_(u"item found: %s") % item.entity)
|
||||
_defers.append(client.disco.requestInfo(item.entity))
|
||||
dl = defer.DeferredList(_defers)
|
||||
dl.addCallback(self._infosReceived, items=disco._items, target=target, client=client)
|
||||
reactor.callLater(GATEWAY_TIMEOUT, dl.cancel)
|
||||
return dl
|
||||
|
||||
def _findGateways(self, target_jid_s, profile_key):
|
||||
target_jid = jid.JID(target_jid_s)
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if not profile:
|
||||
raise exceptions.ProfileUnknownError
|
||||
d = self.findGateways(target_jid, profile)
|
||||
d.addCallback(self._gatewaysResult2XMLUI, target_jid)
|
||||
d.addCallback(lambda xmlui: xmlui.toXml())
|
||||
return d
|
||||
|
||||
def findGateways(self, target, profile):
|
||||
"""Find gateways in the target JID, using discovery protocol
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
log.debug(_(u"find gateways (target = %(target)s, profile = %(profile)s)") % {'target': target.full(), 'profile': profile})
|
||||
d = client.disco.requestItems(target)
|
||||
d.addCallback(self._itemsReceived, target=target, client=client)
|
||||
return d
|
||||
Loading…
Reference in a new issue