Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
7286f428
by Philipp Hörist at 2018-12-18T21:41:06Z
-
ced387e7
by Philipp Hörist at 2018-12-18T21:49:07Z
-
de4cd80b
by Philipp Hörist at 2018-12-18T21:52:29Z
-
99cfb8f6
by Philipp Hörist at 2018-12-18T23:11:24Z
-
b935ce70
by Philipp Hörist at 2018-12-19T01:18:12Z
-
1fec6681
by Philipp Hörist at 2018-12-19T22:00:09Z
-
e9f4c505
by Philipp Hörist at 2018-12-19T22:00:50Z
-
5f555193
by Philipp Hörist at 2018-12-19T22:00:56Z
-
ce683995
by Philipp Hörist at 2018-12-19T22:00:56Z
-
56d2c6bc
by Philipp Hörist at 2018-12-19T22:24:38Z
-
8b5adb06
by Philipp Hörist at 2018-12-19T22:24:39Z
-
c614ac69
by Philipp Hörist at 2018-12-19T22:24:44Z
-
1f975df8
by Philipp Hörist at 2018-12-19T22:24:49Z
19 changed files:
- gajim/application.py
- gajim/common/app.py
- gajim/common/configpaths.py
- gajim/common/connection.py
- gajim/common/connection_handlers.py
- gajim/common/connection_handlers_events.py
- gajim/common/ged.py
- gajim/common/helpers.py
- gajim/common/modules/chatstates.py
- gajim/common/modules/mam.py
- gajim/common/modules/message.py
- gajim/common/modules/muc.py
- gajim/common/modules/privacylists.py
- gajim/common/modules/vcard_temp.py
- gajim/gajim.py
- gajim/groupchat_control.py
- gajim/gtk/single_message.py
- gajim/remote_control.py
- setup.cfg
Changes:
| ... | ... | @@ -38,10 +38,14 @@ from datetime import datetime |
| 38 | 38 |
from pathlib import Path
|
| 39 | 39 |
from urllib.parse import unquote
|
| 40 | 40 |
|
| 41 |
-from gi.repository import GLib, Gio, Gtk
|
|
| 41 |
+import nbxmpp
|
|
| 42 |
+from gi.repository import Gio
|
|
| 43 |
+from gi.repository import GLib
|
|
| 44 |
+from gi.repository import Gtk
|
|
| 42 | 45 |
|
| 43 | 46 |
import gajim
|
| 44 | 47 |
from gajim.common import app
|
| 48 |
+from gajim.common import ged
|
|
| 45 | 49 |
from gajim.common import configpaths
|
| 46 | 50 |
from gajim.common import logging_helpers
|
| 47 | 51 |
from gajim.common import exceptions
|
| ... | ... | @@ -227,6 +231,10 @@ class GajimApplication(Gtk.Application): |
| 227 | 231 |
from gajim import gui_menu_builder
|
| 228 | 232 |
gui_menu_builder.build_accounts_menu()
|
| 229 | 233 |
|
| 234 |
+ app.ged.register_event_handler('feature-discovered',
|
|
| 235 |
+ ged.CORE,
|
|
| 236 |
+ self._on_feature_discovered)
|
|
| 237 |
+ |
|
| 230 | 238 |
def _open_uris(self, uris):
|
| 231 | 239 |
for uri in uris:
|
| 232 | 240 |
app.log('uri_handler').info('open %s', uri)
|
| ... | ... | @@ -498,3 +506,14 @@ class GajimApplication(Gtk.Application): |
| 498 | 506 |
elif new_state and state == 'online':
|
| 499 | 507 |
# We go online
|
| 500 | 508 |
self.lookup_action(account + action_name).set_enabled(True)
|
| 509 |
+ |
|
| 510 |
+ def _on_feature_discovered(self, event):
|
|
| 511 |
+ if event.feature == nbxmpp.NS_VCARD:
|
|
| 512 |
+ action = '%s-profile' % event.account
|
|
| 513 |
+ self.lookup_action(action).set_enabled(True)
|
|
| 514 |
+ elif event.feature in (nbxmpp.NS_MAM_1, nbxmpp.NS_MAM_2):
|
|
| 515 |
+ action = '%s-archive' % event.account
|
|
| 516 |
+ self.lookup_action(action).set_enabled(True)
|
|
| 517 |
+ elif event.feature == nbxmpp.NS_PRIVACY:
|
|
| 518 |
+ action = '%s-privacylists' % event.account
|
|
| 519 |
+ self.lookup_action(action).set_enabled(True)
|
| ... | ... | @@ -67,13 +67,6 @@ plugin_manager = None # Plugins Manager |
| 67 | 67 |
|
| 68 | 68 |
logger = cast(LoggerT, None)
|
| 69 | 69 |
|
| 70 |
-# For backwards compatibility needed
|
|
| 71 |
-# some plugins use that
|
|
| 72 |
-gajimpaths = configpaths.gajimpaths
|
|
| 73 |
- |
|
| 74 |
- |
|
| 75 |
-RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname'])
|
|
| 76 |
- |
|
| 77 | 70 |
css_config = None
|
| 78 | 71 |
|
| 79 | 72 |
os_info = None # used to cache os information
|
| ... | ... | @@ -149,17 +142,43 @@ socks5queue = None |
| 149 | 142 |
gupnp_igd = None
|
| 150 | 143 |
|
| 151 | 144 |
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
|
| 152 |
-gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
|
|
| 153 |
- nbxmpp.NS_MUC, nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC_ADMIN, nbxmpp.NS_MUC_OWNER,
|
|
| 154 |
- nbxmpp.NS_MUC_CONFIG, nbxmpp.NS_COMMANDS, nbxmpp.NS_DISCO_INFO, 'ipv6',
|
|
| 155 |
- 'jabber:iq:gateway', nbxmpp.NS_LAST, nbxmpp.NS_PRIVACY, nbxmpp.NS_PRIVATE,
|
|
| 156 |
- nbxmpp.NS_REGISTER, nbxmpp.NS_VERSION, nbxmpp.NS_DATA, nbxmpp.NS_ENCRYPTED,
|
|
| 157 |
- 'msglog', 'sslc2s', 'stringprep', nbxmpp.NS_PING, nbxmpp.NS_TIME_REVISED,
|
|
| 158 |
- nbxmpp.NS_SSN, nbxmpp.NS_MOOD, nbxmpp.NS_ACTIVITY, nbxmpp.NS_NICK,
|
|
| 159 |
- nbxmpp.NS_ROSTERX, nbxmpp.NS_SECLABEL, nbxmpp.NS_HASHES_2,
|
|
| 160 |
- nbxmpp.NS_HASHES_MD5, nbxmpp.NS_HASHES_SHA1, nbxmpp.NS_HASHES_SHA256,
|
|
| 161 |
- nbxmpp.NS_HASHES_SHA512, nbxmpp.NS_CONFERENCE, nbxmpp.NS_CORRECT,
|
|
| 162 |
- nbxmpp.NS_EME, 'urn:xmpp:avatar:metadata+notify', 'storage:bookmarks+notify']
|
|
| 145 |
+ |
|
| 146 |
+gajim_common_features = [
|
|
| 147 |
+ nbxmpp.NS_BYTESTREAM,
|
|
| 148 |
+ nbxmpp.NS_SI,
|
|
| 149 |
+ nbxmpp.NS_FILE,
|
|
| 150 |
+ nbxmpp.NS_MUC,
|
|
| 151 |
+ nbxmpp.NS_COMMANDS,
|
|
| 152 |
+ nbxmpp.NS_DISCO_INFO,
|
|
| 153 |
+ nbxmpp.NS_LAST,
|
|
| 154 |
+ nbxmpp.NS_DATA,
|
|
| 155 |
+ nbxmpp.NS_ENCRYPTED,
|
|
| 156 |
+ nbxmpp.NS_PING,
|
|
| 157 |
+ nbxmpp.NS_TIME_REVISED,
|
|
| 158 |
+ nbxmpp.NS_VERSION,
|
|
| 159 |
+ nbxmpp.NS_ROSTERX,
|
|
| 160 |
+ nbxmpp.NS_SECLABEL,
|
|
| 161 |
+ nbxmpp.NS_CONFERENCE,
|
|
| 162 |
+ nbxmpp.NS_CORRECT,
|
|
| 163 |
+ nbxmpp.NS_EME,
|
|
| 164 |
+ nbxmpp.NS_HASHES,
|
|
| 165 |
+ nbxmpp.NS_HASHES_2,
|
|
| 166 |
+ nbxmpp.NS_HASHES_MD5,
|
|
| 167 |
+ nbxmpp.NS_HASHES_SHA1,
|
|
| 168 |
+ nbxmpp.NS_HASHES_SHA256,
|
|
| 169 |
+ nbxmpp.NS_HASHES_SHA512,
|
|
| 170 |
+ nbxmpp.NS_HASHES_SHA3_256,
|
|
| 171 |
+ nbxmpp.NS_HASHES_SHA3_512,
|
|
| 172 |
+ nbxmpp.NS_HASHES_BLAKE2B_256,
|
|
| 173 |
+ nbxmpp.NS_HASHES_BLAKE2B_512,
|
|
| 174 |
+ nbxmpp.NS_JINGLE,
|
|
| 175 |
+ nbxmpp.NS_JINGLE_FILE_TRANSFER_5,
|
|
| 176 |
+ nbxmpp.NS_JINGLE_XTLS,
|
|
| 177 |
+ nbxmpp.NS_JINGLE_BYTESTREAM,
|
|
| 178 |
+ nbxmpp.NS_JINGLE_IBB,
|
|
| 179 |
+ nbxmpp.NS_AVATAR_METADATA + '+notify',
|
|
| 180 |
+ nbxmpp.NS_BOOKMARKS + '+notify',
|
|
| 181 |
+]
|
|
| 163 | 182 |
|
| 164 | 183 |
# Optional features gajim supports per account
|
| 165 | 184 |
gajim_optional_features = {} # type: Dict[str, List[str]]
|
| ... | ... | @@ -580,6 +599,9 @@ def get_recent_groupchats(account): |
| 580 | 599 |
recent_groupchats = config.get_per(
|
| 581 | 600 |
'accounts', account, 'recent_groupchats').split()
|
| 582 | 601 |
|
| 602 |
+ RecentGroupchat = namedtuple('RecentGroupchat',
|
|
| 603 |
+ ['room', 'server', 'nickname'])
|
|
| 604 |
+ |
|
| 583 | 605 |
recent_list = []
|
| 584 | 606 |
for groupchat in recent_groupchats:
|
| 585 | 607 |
jid = nbxmpp.JID(groupchat)
|
| ... | ... | @@ -241,7 +241,3 @@ class ConfigPaths: |
| 241 | 241 |
|
| 242 | 242 |
|
| 243 | 243 |
_paths = ConfigPaths()
|
| 244 |
- |
|
| 245 |
-# For backwards compatibility needed
|
|
| 246 |
-# some plugins use that
|
|
| 247 |
-gajimpaths = _paths
|
| ... | ... | @@ -1684,14 +1684,6 @@ class Connection(CommonConnection, ConnectionHandlers): |
| 1684 | 1684 |
show=show,
|
| 1685 | 1685 |
caps=ptype != 'unavailable')
|
| 1686 | 1686 |
|
| 1687 |
- def send_captcha(self, jid, form_node):
|
|
| 1688 |
- if not app.account_is_connected(self.name):
|
|
| 1689 |
- return
|
|
| 1690 |
- iq = nbxmpp.Iq(typ='set', to=jid)
|
|
| 1691 |
- captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA)
|
|
| 1692 |
- captcha.addChild(node=form_node)
|
|
| 1693 |
- self.connection.send(iq)
|
|
| 1694 |
- |
|
| 1695 | 1687 |
def check_unique_room_id_support(self, server, instance):
|
| 1696 | 1688 |
if not app.account_is_connected(self.name):
|
| 1697 | 1689 |
return
|
| ... | ... | @@ -585,12 +585,18 @@ class ConnectionHandlers(ConnectionSocks5Bytestream, |
| 585 | 585 |
nbxmpp.NS_PUBKEY_PUBKEY)
|
| 586 | 586 |
|
| 587 | 587 |
for handler in modules.get_handlers(self):
|
| 588 |
- con.RegisterHandler(*handler)
|
|
| 588 |
+ if len(handler) == 5:
|
|
| 589 |
+ name, func, typ, ns, priority = handler
|
|
| 590 |
+ con.RegisterHandler(name, func, typ, ns, priority=priority)
|
|
| 591 |
+ else:
|
|
| 592 |
+ con.RegisterHandler(*handler)
|
|
| 589 | 593 |
self.handlers_registered = True
|
| 590 | 594 |
|
| 591 | 595 |
def _unregister_handlers(self):
|
| 592 | 596 |
if not self.connection:
|
| 593 | 597 |
return
|
| 594 | 598 |
for handler in modules.get_handlers(self):
|
| 599 |
+ if len(handler) > 4:
|
|
| 600 |
+ handler = handler[:4]
|
|
| 595 | 601 |
self.connection.UnregisterHandler(*handler)
|
| 596 | 602 |
self.handlers_registered = False
|
| ... | ... | @@ -40,27 +40,6 @@ from gajim.common.file_props import FilesProp |
| 40 | 40 |
|
| 41 | 41 |
log = logging.getLogger('gajim.c.connection_handlers_events')
|
| 42 | 42 |
|
| 43 |
-CONDITION_TO_CODE = {
|
|
| 44 |
- 'realjid-public': 100,
|
|
| 45 |
- 'affiliation-changed': 101,
|
|
| 46 |
- 'unavailable-shown': 102,
|
|
| 47 |
- 'unavailable-not-shown': 103,
|
|
| 48 |
- 'configuration-changed': 104,
|
|
| 49 |
- 'self-presence': 110,
|
|
| 50 |
- 'logging-enabled': 170,
|
|
| 51 |
- 'logging-disabled': 171,
|
|
| 52 |
- 'non-anonymous': 172,
|
|
| 53 |
- 'semi-anonymous': 173,
|
|
| 54 |
- 'fully-anonymous': 174,
|
|
| 55 |
- 'room-created': 201,
|
|
| 56 |
- 'nick-assigned': 210,
|
|
| 57 |
- 'banned': 301,
|
|
| 58 |
- 'new-nick': 303,
|
|
| 59 |
- 'kicked': 307,
|
|
| 60 |
- 'removed-affiliation': 321,
|
|
| 61 |
- 'removed-membership': 322,
|
|
| 62 |
- 'removed-shutdown': 332,
|
|
| 63 |
-}
|
|
| 64 | 43 |
|
| 65 | 44 |
class HelperEvent:
|
| 66 | 45 |
def get_jid_resource(self, check_fake_jid=False):
|
| ... | ... | @@ -378,14 +357,7 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): |
| 378 | 357 |
self.status_code = ['destroyed']
|
| 379 | 358 |
else:
|
| 380 | 359 |
self.reason = self.stanza.getReason()
|
| 381 |
- conditions = self.stanza.getStatusConditions()
|
|
| 382 |
- if conditions:
|
|
| 383 |
- self.status_code = []
|
|
| 384 |
- for condition in conditions:
|
|
| 385 |
- if condition in CONDITION_TO_CODE:
|
|
| 386 |
- self.status_code.append(CONDITION_TO_CODE[condition])
|
|
| 387 |
- else:
|
|
| 388 |
- self.status_code = self.stanza.getStatusCode()
|
|
| 360 |
+ self.status_code = self.stanza.getStatusCode()
|
|
| 389 | 361 |
|
| 390 | 362 |
self.role = self.stanza.getRole()
|
| 391 | 363 |
self.affiliation = self.stanza.getAffiliation()
|
| ... | ... | @@ -429,60 +401,12 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent): |
| 429 | 401 |
# message from server
|
| 430 | 402 |
self.nick = ''
|
| 431 | 403 |
|
| 432 |
- conditions = self.stanza.getStatusConditions()
|
|
| 433 |
- if conditions:
|
|
| 434 |
- self.status_code = []
|
|
| 435 |
- for condition in conditions:
|
|
| 436 |
- if condition in CONDITION_TO_CODE:
|
|
| 437 |
- self.status_code.append(CONDITION_TO_CODE[condition])
|
|
| 438 |
- else:
|
|
| 439 |
- self.status_code = self.stanza.getStatusCode()
|
|
| 440 |
- |
|
| 441 | 404 |
if not self.stanza.getTag('body'): # no <body>
|
| 442 |
- # It could be a config change. See
|
|
| 443 |
- # http://www.xmpp.org/extensions/xep-0045.html#roomconfig-notify
|
|
| 444 |
- if self.stanza.getTag('x'):
|
|
| 445 |
- if self.status_code != []:
|
|
| 446 |
- app.nec.push_incoming_event(GcConfigChangedReceivedEvent(
|
|
| 447 |
- None, conn=self.conn, msg_event=self))
|
|
| 448 |
- if self.msg_obj.form_node:
|
|
| 449 |
- # It could be a voice request. See
|
|
| 450 |
- # http://www.xmpp.org/extensions/xep-0045.html#voiceapprove
|
|
| 451 |
- from gajim.gtk.single_message import SingleMessageWindow
|
|
| 452 |
- SingleMessageWindow(
|
|
| 453 |
- self.conn.name, self.fjid,
|
|
| 454 |
- action='receive', from_whom=self.fjid,
|
|
| 455 |
- subject='', message='', resource='', session=None,
|
|
| 456 |
- form_node=self.msg_obj.form_node)
|
|
| 457 | 405 |
return
|
| 458 | 406 |
|
| 459 | 407 |
from gajim.common.modules.security_labels import parse_securitylabel
|
| 460 | 408 |
self.displaymarking = parse_securitylabel(self.stanza)
|
| 461 | 409 |
|
| 462 |
- self.captcha_form = None
|
|
| 463 |
- captcha_tag = self.stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA)
|
|
| 464 |
- if captcha_tag:
|
|
| 465 |
- self.captcha_form = captcha_tag.getTag('x',
|
|
| 466 |
- namespace=nbxmpp.NS_DATA)
|
|
| 467 |
- for field in self.captcha_form.getTags('field'):
|
|
| 468 |
- for media in field.getTags('media'):
|
|
| 469 |
- for uri in media.getTags('uri'):
|
|
| 470 |
- uri_data = uri.getData()
|
|
| 471 |
- if uri_data.startswith('cid:'):
|
|
| 472 |
- uri_data = uri_data[4:]
|
|
| 473 |
- found = False
|
|
| 474 |
- for data in self.stanza.getTags('data',
|
|
| 475 |
- namespace=nbxmpp.NS_BOB):
|
|
| 476 |
- if data.getAttr('cid') == uri_data:
|
|
| 477 |
- uri.setData(data.getData())
|
|
| 478 |
- found = True
|
|
| 479 |
- if not found:
|
|
| 480 |
- self.conn.get_module('BitsOfBinary').get_bob_data(
|
|
| 481 |
- uri_data, self.fjid,
|
|
| 482 |
- self.conn._dispatch_gc_msg_with_captcha,
|
|
| 483 |
- [self.stanza, self.msg_obj], 0)
|
|
| 484 |
- return
|
|
| 485 |
- |
|
| 486 | 410 |
from gajim.common.modules.misc import parse_correction
|
| 487 | 411 |
self.correct_id = parse_correction(self.stanza)
|
| 488 | 412 |
|
| ... | ... | @@ -24,6 +24,7 @@ Global Events Dispatcher module. |
| 24 | 24 |
|
| 25 | 25 |
import logging
|
| 26 | 26 |
import traceback
|
| 27 |
+import inspect
|
|
| 27 | 28 |
|
| 28 | 29 |
from nbxmpp import NodeProcessed
|
| 29 | 30 |
|
| ... | ... | @@ -84,13 +85,19 @@ class GlobalEventsDispatcher: |
| 84 | 85 |
Error: %s''', handler, priority, event_name, error)
|
| 85 | 86 |
|
| 86 | 87 |
def raise_event(self, event_name, *args, **kwargs):
|
| 87 |
- log.debug('%s Args: %s', event_name, str(args))
|
|
| 88 |
+ log.debug('Raise event: %s', event_name)
|
|
| 88 | 89 |
if event_name in self.handlers:
|
| 89 | 90 |
node_processed = False
|
| 90 | 91 |
# Iterate over a copy of the handlers list, so while iterating
|
| 91 | 92 |
# the original handlers list can be modified
|
| 92 | 93 |
for _priority, handler in list(self.handlers[event_name]):
|
| 93 | 94 |
try:
|
| 95 |
+ if inspect.ismethod(handler):
|
|
| 96 |
+ log.debug('Call handler %s on %s',
|
|
| 97 |
+ handler.__name__,
|
|
| 98 |
+ handler.__self__)
|
|
| 99 |
+ else:
|
|
| 100 |
+ log.debug('Call handler %s', handler.__name__)
|
|
| 94 | 101 |
if handler(*args, **kwargs):
|
| 95 | 102 |
return True
|
| 96 | 103 |
except NodeProcessed:
|
| ... | ... | @@ -1161,56 +1161,47 @@ def prepare_and_validate_gpg_keyID(account, jid, keyID): |
| 1161 | 1161 |
return keyID
|
| 1162 | 1162 |
|
| 1163 | 1163 |
def update_optional_features(account=None):
|
| 1164 |
- if account:
|
|
| 1164 |
+ if account is not None:
|
|
| 1165 | 1165 |
accounts = [account]
|
| 1166 | 1166 |
else:
|
| 1167 |
- accounts = [a for a in app.connections]
|
|
| 1168 |
- for a in accounts:
|
|
| 1169 |
- app.gajim_optional_features[a] = []
|
|
| 1170 |
- if app.config.get_per('accounts', a, 'subscribe_mood'):
|
|
| 1171 |
- app.gajim_optional_features[a].append(nbxmpp.NS_MOOD + '+notify')
|
|
| 1172 |
- if app.config.get_per('accounts', a, 'subscribe_activity'):
|
|
| 1173 |
- app.gajim_optional_features[a].append(nbxmpp.NS_ACTIVITY + \
|
|
| 1174 |
- '+notify')
|
|
| 1175 |
- if app.config.get_per('accounts', a, 'publish_tune'):
|
|
| 1176 |
- app.gajim_optional_features[a].append(nbxmpp.NS_TUNE)
|
|
| 1177 |
- if app.config.get_per('accounts', a, 'publish_location'):
|
|
| 1178 |
- app.gajim_optional_features[a].append(nbxmpp.NS_LOCATION)
|
|
| 1179 |
- if app.config.get_per('accounts', a, 'subscribe_tune'):
|
|
| 1180 |
- app.gajim_optional_features[a].append(nbxmpp.NS_TUNE + '+notify')
|
|
| 1181 |
- if app.config.get_per('accounts', a, 'subscribe_nick'):
|
|
| 1182 |
- app.gajim_optional_features[a].append(nbxmpp.NS_NICK + '+notify')
|
|
| 1183 |
- if app.config.get_per('accounts', a, 'subscribe_location'):
|
|
| 1184 |
- app.gajim_optional_features[a].append(nbxmpp.NS_LOCATION + \
|
|
| 1185 |
- '+notify')
|
|
| 1167 |
+ accounts = app.connections.keys()
|
|
| 1168 |
+ |
|
| 1169 |
+ for account_ in accounts:
|
|
| 1170 |
+ features = []
|
|
| 1171 |
+ app.gajim_optional_features[account_] = features
|
|
| 1172 |
+ if app.config.get_per('accounts', account_, 'subscribe_mood'):
|
|
| 1173 |
+ features.append(nbxmpp.NS_MOOD + '+notify')
|
|
| 1174 |
+ if app.config.get_per('accounts', account_, 'subscribe_activity'):
|
|
| 1175 |
+ features.append(nbxmpp.NS_ACTIVITY + '+notify')
|
|
| 1176 |
+ if app.config.get_per('accounts', account_, 'subscribe_tune'):
|
|
| 1177 |
+ features.append(nbxmpp.NS_TUNE + '+notify')
|
|
| 1178 |
+ if app.config.get_per('accounts', account_, 'subscribe_nick'):
|
|
| 1179 |
+ features.append(nbxmpp.NS_NICK + '+notify')
|
|
| 1180 |
+ if app.config.get_per('accounts', account_, 'subscribe_location'):
|
|
| 1181 |
+ features.append(nbxmpp.NS_LOCATION + '+notify')
|
|
| 1186 | 1182 |
if app.config.get('outgoing_chat_state_notifactions') != 'disabled':
|
| 1187 |
- app.gajim_optional_features[a].append(nbxmpp.NS_CHATSTATES)
|
|
| 1183 |
+ features.append(nbxmpp.NS_CHATSTATES)
|
|
| 1188 | 1184 |
if not app.config.get('ignore_incoming_xhtml'):
|
| 1189 |
- app.gajim_optional_features[a].append(nbxmpp.NS_XHTML_IM)
|
|
| 1190 |
- if app.config.get_per('accounts', a, 'answer_receipts'):
|
|
| 1191 |
- app.gajim_optional_features[a].append(nbxmpp.NS_RECEIPTS)
|
|
| 1192 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE)
|
|
| 1185 |
+ features.append(nbxmpp.NS_XHTML_IM)
|
|
| 1186 |
+ if app.config.get_per('accounts', account_, 'answer_receipts'):
|
|
| 1187 |
+ features.append(nbxmpp.NS_RECEIPTS)
|
|
| 1193 | 1188 |
if app.is_installed('FARSTREAM'):
|
| 1194 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP)
|
|
| 1195 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_AUDIO)
|
|
| 1196 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_VIDEO)
|
|
| 1197 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_ICE_UDP)
|
|
| 1198 |
- app.gajim_optional_features[a].append(
|
|
| 1199 |
- nbxmpp.NS_JINGLE_FILE_TRANSFER_5)
|
|
| 1200 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_XTLS)
|
|
| 1201 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_BYTESTREAM)
|
|
| 1202 |
- app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_IBB)
|
|
| 1189 |
+ features.append(nbxmpp.NS_JINGLE_RTP)
|
|
| 1190 |
+ features.append(nbxmpp.NS_JINGLE_RTP_AUDIO)
|
|
| 1191 |
+ features.append(nbxmpp.NS_JINGLE_RTP_VIDEO)
|
|
| 1192 |
+ features.append(nbxmpp.NS_JINGLE_ICE_UDP)
|
|
| 1203 | 1193 |
|
| 1204 | 1194 |
# Give plugins the possibility to add their features
|
| 1205 |
- app.plugin_manager.extension_point('update_caps', a)
|
|
| 1195 |
+ app.plugin_manager.extension_point('update_caps', account_)
|
|
| 1206 | 1196 |
|
| 1207 |
- app.caps_hash[a] = caps_cache.compute_caps_hash([app.gajim_identity],
|
|
| 1208 |
- app.gajim_common_features + app.gajim_optional_features[a])
|
|
| 1197 |
+ app.caps_hash[account_] = caps_cache.compute_caps_hash(
|
|
| 1198 |
+ [app.gajim_identity],
|
|
| 1199 |
+ app.gajim_common_features + features)
|
|
| 1209 | 1200 |
# re-send presence with new hash
|
| 1210 |
- connected = app.connections[a].connected
|
|
| 1201 |
+ connected = app.connections[account_].connected
|
|
| 1211 | 1202 |
if connected > 1 and app.SHOW_LIST[connected] != 'invisible':
|
| 1212 |
- app.connections[a].change_status(app.SHOW_LIST[connected],
|
|
| 1213 |
- app.connections[a].status)
|
|
| 1203 |
+ app.connections[account_].change_status(
|
|
| 1204 |
+ app.SHOW_LIST[connected], app.connections[account_].status)
|
|
| 1214 | 1205 |
|
| 1215 | 1206 |
def jid_is_blocked(account, jid):
|
| 1216 | 1207 |
con = app.connections[account]
|
| ... | ... | @@ -171,6 +171,11 @@ class Chatstate: |
| 171 | 171 |
if contact is not None:
|
| 172 | 172 |
contact = contact.as_contact()
|
| 173 | 173 |
else:
|
| 174 |
+ # Contact not found, maybe we left the group chat
|
|
| 175 |
+ # or the contact was removed from the roster
|
|
| 176 |
+ log.info(
|
|
| 177 |
+ 'Contact %s not found, reset chatstate', jid)
|
|
| 178 |
+ self._chatstates.pop(jid, None)
|
|
| 174 | 179 |
self._last_mouse_activity.pop(jid, None)
|
| 175 | 180 |
self._last_keyboard_activity.pop(jid, None)
|
| 176 | 181 |
continue
|
| ... | ... | @@ -206,14 +211,21 @@ class Chatstate: |
| 206 | 211 |
current_state = self._chatstates.get(contact.jid)
|
| 207 | 212 |
setting = app.config.get('outgoing_chat_state_notifications')
|
| 208 | 213 |
if setting == 'disabled':
|
| 209 |
- # Send a last 'gone' state after user disabled chatstates
|
|
| 214 |
+ # Send a last 'active' state after user disabled chatstates
|
|
| 210 | 215 |
if current_state is not None:
|
| 211 |
- log.info('Send: %-10s - %s', State.GONE, contact.jid)
|
|
| 212 |
- app.nec.push_outgoing_event(
|
|
| 213 |
- MessageOutgoingEvent(None,
|
|
| 214 |
- account=self._account,
|
|
| 215 |
- jid=contact.jid,
|
|
| 216 |
- chatstate=str(State.GONE)))
|
|
| 216 |
+ log.info('Send: %-10s - %s', State.ACTIVE, contact.jid)
|
|
| 217 |
+ |
|
| 218 |
+ event_attrs = {'account': self._account,
|
|
| 219 |
+ 'jid': contact.jid,
|
|
| 220 |
+ 'chatstate': str(State.ACTIVE)}
|
|
| 221 |
+ |
|
| 222 |
+ if contact.is_groupchat():
|
|
| 223 |
+ app.nec.push_outgoing_event(
|
|
| 224 |
+ GcMessageOutgoingEvent(None, **event_attrs))
|
|
| 225 |
+ else:
|
|
| 226 |
+ app.nec.push_outgoing_event(
|
|
| 227 |
+ MessageOutgoingEvent(None, **event_attrs))
|
|
| 228 |
+ |
|
| 217 | 229 |
self._chatstates.pop(contact.jid, None)
|
| 218 | 230 |
self._last_mouse_activity.pop(contact.jid, None)
|
| 219 | 231 |
self._last_keyboard_activity.pop(contact.jid, None)
|
| ... | ... | @@ -21,6 +21,7 @@ from datetime import datetime, timedelta |
| 21 | 21 |
import nbxmpp
|
| 22 | 22 |
|
| 23 | 23 |
from gajim.common import app
|
| 24 |
+from gajim.common.nec import NetworkEvent
|
|
| 24 | 25 |
from gajim.common.nec import NetworkIncomingEvent
|
| 25 | 26 |
from gajim.common.const import ArchiveState
|
| 26 | 27 |
from gajim.common.const import KindConstant
|
| ... | ... | @@ -65,9 +66,11 @@ class MAM: |
| 65 | 66 |
|
| 66 | 67 |
self.available = True
|
| 67 | 68 |
log.info('Discovered MAM %s: %s', self.archiving_namespace, from_)
|
| 68 |
- # TODO: Move this GUI code out
|
|
| 69 |
- action = app.app.lookup_action('%s-archive' % self._account)
|
|
| 70 |
- action.set_enabled(True)
|
|
| 69 |
+ |
|
| 70 |
+ app.nec.push_incoming_event(
|
|
| 71 |
+ NetworkEvent('feature-discovered',
|
|
| 72 |
+ account=self._account,
|
|
| 73 |
+ feature=self.archiving_namespace))
|
|
| 71 | 74 |
|
| 72 | 75 |
def _from_valid_archive(self, stanza, message, groupchat):
|
| 73 | 76 |
if groupchat:
|
| ... | ... | @@ -28,7 +28,6 @@ from gajim.common.helpers import AdditionalDataDict |
| 28 | 28 |
from gajim.common.modules.security_labels import parse_securitylabel
|
| 29 | 29 |
from gajim.common.modules.user_nickname import parse_nickname
|
| 30 | 30 |
from gajim.common.modules.carbons import parse_carbon
|
| 31 |
-from gajim.common.modules.bits_of_binary import parse_bob_data
|
|
| 32 | 31 |
from gajim.common.modules.misc import parse_delay
|
| 33 | 32 |
from gajim.common.modules.misc import parse_eme
|
| 34 | 33 |
from gajim.common.modules.misc import parse_correction
|
| ... | ... | @@ -58,7 +57,8 @@ class Message: |
| 58 | 57 |
nbxmpp.NS_MAM_1,
|
| 59 | 58 |
nbxmpp.NS_MAM_2,
|
| 60 | 59 |
nbxmpp.NS_CONFERENCE,
|
| 61 |
- nbxmpp.NS_IBB])
|
|
| 60 |
+ nbxmpp.NS_IBB,
|
|
| 61 |
+ nbxmpp.NS_CAPTCHA,])
|
|
| 62 | 62 |
|
| 63 | 63 |
def _message_received(self, _con, stanza):
|
| 64 | 64 |
# https://tools.ietf.org/html/rfc6120#section-8.1.1.1
|
| ... | ... | @@ -259,8 +259,6 @@ class Message: |
| 259 | 259 |
event.additional_data.set_value(
|
| 260 | 260 |
'gajim', 'user_timestamp', user_timestamp)
|
| 261 | 261 |
|
| 262 |
- parse_bob_data(event.stanza)
|
|
| 263 |
- |
|
| 264 | 262 |
event_attr = {
|
| 265 | 263 |
'popup': False,
|
| 266 | 264 |
'msg_log_id': None,
|
| ... | ... | @@ -22,11 +22,13 @@ import weakref |
| 22 | 22 |
import nbxmpp
|
| 23 | 23 |
|
| 24 | 24 |
from gajim.common import i18n
|
| 25 |
-from gajim.common.modules import dataforms
|
|
| 26 | 25 |
from gajim.common import app
|
| 27 | 26 |
from gajim.common import helpers
|
| 28 | 27 |
from gajim.common.caps_cache import muc_caps_cache
|
| 28 |
+from gajim.common.nec import NetworkEvent
|
|
| 29 | 29 |
from gajim.common.nec import NetworkIncomingEvent
|
| 30 |
+from gajim.common.modules import dataforms
|
|
| 31 |
+from gajim.common.modules.bits_of_binary import parse_bob_data
|
|
| 30 | 32 |
|
| 31 | 33 |
log = logging.getLogger('gajim.c.m.muc')
|
| 32 | 34 |
|
| ... | ... | @@ -37,8 +39,11 @@ class MUC: |
| 37 | 39 |
self._account = con.name
|
| 38 | 40 |
|
| 39 | 41 |
self.handlers = [
|
| 40 |
- ('message', self._mediated_invite, '', nbxmpp.NS_MUC_USER),
|
|
| 42 |
+ ('message', self._on_config_change, '', nbxmpp.NS_MUC_USER),
|
|
| 43 |
+ ('message', self._mediated_invite, 'normal', nbxmpp.NS_MUC_USER),
|
|
| 41 | 44 |
('message', self._direct_invite, '', nbxmpp.NS_CONFERENCE),
|
| 45 |
+ ('message', self._on_captcha_challenge, '', nbxmpp.NS_CAPTCHA),
|
|
| 46 |
+ ('message', self._on_voice_request, '', nbxmpp.NS_DATA, 45),
|
|
| 42 | 47 |
]
|
| 43 | 48 |
|
| 44 | 49 |
def pass_disco(self, from_, identities, features, _data, _node):
|
| ... | ... | @@ -110,6 +115,62 @@ class MUC: |
| 110 | 115 |
log.info('Set subject for %s', room_jid)
|
| 111 | 116 |
self._con.connection.send(message)
|
| 112 | 117 |
|
| 118 |
+ def _on_voice_request(self, _con, stanza):
|
|
| 119 |
+ data_form = stanza.getTag('x', namespace=nbxmpp.NS_DATA)
|
|
| 120 |
+ if data_form is None:
|
|
| 121 |
+ return
|
|
| 122 |
+ |
|
| 123 |
+ if stanza.getBody():
|
|
| 124 |
+ return
|
|
| 125 |
+ |
|
| 126 |
+ room_jid = str(stanza.getFrom())
|
|
| 127 |
+ contact = app.contacts.get_groupchat_contact(self._account, room_jid)
|
|
| 128 |
+ if contact is None:
|
|
| 129 |
+ return
|
|
| 130 |
+ |
|
| 131 |
+ data_form = dataforms.extend_form(data_form)
|
|
| 132 |
+ try:
|
|
| 133 |
+ if data_form['FORM_TYPE'].value != nbxmpp.NS_MUC_REQUEST:
|
|
| 134 |
+ return
|
|
| 135 |
+ except KeyError:
|
|
| 136 |
+ return
|
|
| 137 |
+ |
|
| 138 |
+ app.nec.push_incoming_event(
|
|
| 139 |
+ NetworkEvent('voice-approval',
|
|
| 140 |
+ account=self._account,
|
|
| 141 |
+ room_jid=room_jid,
|
|
| 142 |
+ form=data_form))
|
|
| 143 |
+ raise nbxmpp.NodeProcessed
|
|
| 144 |
+ |
|
| 145 |
+ def _on_captcha_challenge(self, _con, stanza):
|
|
| 146 |
+ captcha = stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA)
|
|
| 147 |
+ if captcha is None:
|
|
| 148 |
+ return
|
|
| 149 |
+ |
|
| 150 |
+ parse_bob_data(stanza)
|
|
| 151 |
+ room_jid = str(stanza.getFrom())
|
|
| 152 |
+ contact = app.contacts.get_groupchat_contact(self._account, room_jid)
|
|
| 153 |
+ if contact is None:
|
|
| 154 |
+ return
|
|
| 155 |
+ |
|
| 156 |
+ log.info('Captcha challenge received from %s', room_jid)
|
|
| 157 |
+ data_form = captcha.getTag('x', namespace=nbxmpp.NS_DATA)
|
|
| 158 |
+ data_form = dataforms.extend_form(node=data_form)
|
|
| 159 |
+ app.nec.push_incoming_event(
|
|
| 160 |
+ NetworkEvent('captcha-challenge',
|
|
| 161 |
+ account=self._account,
|
|
| 162 |
+ room_jid=room_jid,
|
|
| 163 |
+ form=data_form))
|
|
| 164 |
+ raise nbxmpp.NodeProcessed
|
|
| 165 |
+ |
|
| 166 |
+ def send_captcha(self, room_jid, form_node):
|
|
| 167 |
+ if not app.account_is_connected(self._account):
|
|
| 168 |
+ return
|
|
| 169 |
+ iq = nbxmpp.Iq(typ='set', to=room_jid)
|
|
| 170 |
+ captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA)
|
|
| 171 |
+ captcha.addChild(node=form_node)
|
|
| 172 |
+ self._con.connection.send(iq)
|
|
| 173 |
+ |
|
| 113 | 174 |
def request_config(self, room_jid):
|
| 114 | 175 |
if not app.account_is_connected(self._account):
|
| 115 | 176 |
return
|
| ... | ... | @@ -154,6 +215,41 @@ class MUC: |
| 154 | 215 |
self._con.connection.SendAndCallForResponse(
|
| 155 | 216 |
iq, self._default_response, {})
|
| 156 | 217 |
|
| 218 |
+ def _on_config_change(self, _con, stanza):
|
|
| 219 |
+ muc_user = stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
|
|
| 220 |
+ if muc_user is None:
|
|
| 221 |
+ return
|
|
| 222 |
+ |
|
| 223 |
+ if stanza.getBody():
|
|
| 224 |
+ return
|
|
| 225 |
+ |
|
| 226 |
+ room_list = app.contacts.get_gc_list(self._account)
|
|
| 227 |
+ room_jid = str(stanza.getFrom())
|
|
| 228 |
+ if room_jid not in room_list:
|
|
| 229 |
+ # Message not from a group chat
|
|
| 230 |
+ return
|
|
| 231 |
+ |
|
| 232 |
+ # https://xmpp.org/extensions/xep-0045.html#registrar-statuscodes
|
|
| 233 |
+ change_codes = ['100', '102', '103', '104',
|
|
| 234 |
+ '170', '171', '172', '173', '174']
|
|
| 235 |
+ |
|
| 236 |
+ codes = set()
|
|
| 237 |
+ for status in muc_user.getTags('status'):
|
|
| 238 |
+ code = status.getAttr('code')
|
|
| 239 |
+ if code in change_codes:
|
|
| 240 |
+ codes.add(code)
|
|
| 241 |
+ |
|
| 242 |
+ if not codes:
|
|
| 243 |
+ return
|
|
| 244 |
+ |
|
| 245 |
+ log.info('Received config change: %s', codes)
|
|
| 246 |
+ app.nec.push_incoming_event(
|
|
| 247 |
+ NetworkEvent('gc-config-changed-received',
|
|
| 248 |
+ account=self._account,
|
|
| 249 |
+ room_jid=room_jid,
|
|
| 250 |
+ status_codes=codes))
|
|
| 251 |
+ raise nbxmpp.NodeProcessed
|
|
| 252 |
+ |
|
| 157 | 253 |
def destroy(self, room_jid, reason='', jid=''):
|
| 158 | 254 |
if not app.account_is_connected(self._account):
|
| 159 | 255 |
return
|
| ... | ... | @@ -272,6 +368,9 @@ class MUC: |
| 272 | 368 |
if stanza.getType() == 'error':
|
| 273 | 369 |
return
|
| 274 | 370 |
|
| 371 |
+ if stanza.getBody():
|
|
| 372 |
+ return
|
|
| 373 |
+ |
|
| 275 | 374 |
decline = muc_user.getTag('decline')
|
| 276 | 375 |
if decline is not None:
|
| 277 | 376 |
|
| ... | ... | @@ -20,6 +20,7 @@ import nbxmpp |
| 20 | 20 |
|
| 21 | 21 |
from gajim.common import app
|
| 22 | 22 |
from gajim.common import helpers
|
| 23 |
+from gajim.common.nec import NetworkEvent
|
|
| 23 | 24 |
from gajim.common.nec import NetworkIncomingEvent
|
| 24 | 25 |
from gajim.common.connection_handlers_events import InformationEvent
|
| 25 | 26 |
|
| ... | ... | @@ -51,9 +52,11 @@ class PrivacyLists: |
| 51 | 52 |
|
| 52 | 53 |
self.supported = True
|
| 53 | 54 |
log.info('Discovered XEP-0016: Privacy Lists: %s', from_)
|
| 54 |
- # TODO: Move this GUI code out
|
|
| 55 |
- action = app.app.lookup_action('%s-privacylists' % self._account)
|
|
| 56 |
- action.set_enabled(True)
|
|
| 55 |
+ |
|
| 56 |
+ app.nec.push_incoming_event(
|
|
| 57 |
+ NetworkEvent('feature-discovered',
|
|
| 58 |
+ account=self._account,
|
|
| 59 |
+ feature=nbxmpp.NS_PRIVACY))
|
|
| 57 | 60 |
|
| 58 | 61 |
def _list_push_received(self, _con, stanza):
|
| 59 | 62 |
result = stanza.buildReply('result')
|
| ... | ... | @@ -23,6 +23,7 @@ import nbxmpp |
| 23 | 23 |
|
| 24 | 24 |
from gajim.common import app
|
| 25 | 25 |
from gajim.common.const import RequestAvatar
|
| 26 |
+from gajim.common.nec import NetworkEvent
|
|
| 26 | 27 |
from gajim.common.nec import NetworkIncomingEvent
|
| 27 | 28 |
from gajim.common.connection_handlers_events import InformationEvent
|
| 28 | 29 |
|
| ... | ... | @@ -47,9 +48,10 @@ class VCardTemp: |
| 47 | 48 |
|
| 48 | 49 |
self.supported = True
|
| 49 | 50 |
log.info('Discovered vcard-temp: %s', from_)
|
| 50 |
- # TODO: Move this GUI code out
|
|
| 51 |
- action = app.app.lookup_action('%s-profile' % self._account)
|
|
| 52 |
- action.set_enabled(True)
|
|
| 51 |
+ |
|
| 52 |
+ app.nec.push_incoming_event(NetworkEvent('feature-discovered',
|
|
| 53 |
+ account=self._account,
|
|
| 54 |
+ feature=nbxmpp.NS_VCARD))
|
|
| 53 | 55 |
|
| 54 | 56 |
@staticmethod
|
| 55 | 57 |
def _node_to_dict(node):
|
| ... | ... | @@ -24,10 +24,9 @@ from ctypes import CDLL, byref, create_string_buffer |
| 24 | 24 |
from ctypes.util import find_library
|
| 25 | 25 |
from distutils.version import LooseVersion as V
|
| 26 | 26 |
|
| 27 |
-# Install _() in namespace
|
|
| 28 | 27 |
from gajim.common import i18n
|
| 29 | 28 |
|
| 30 |
-_MIN_NBXMPP_VER = "0.9.90"
|
|
| 29 |
+_MIN_NBXMPP_VER = "0.9.90.2"
|
|
| 31 | 30 |
_MIN_GTK_VER = "3.22.0"
|
| 32 | 31 |
|
| 33 | 32 |
|
| ... | ... | @@ -44,7 +44,6 @@ from gajim import gtkgui_helpers |
| 44 | 44 |
from gajim import gui_menu_builder
|
| 45 | 45 |
from gajim import message_control
|
| 46 | 46 |
from gajim import vcard
|
| 47 |
-from gajim import dataforms_widget
|
|
| 48 | 47 |
|
| 49 | 48 |
from gajim.common.const import AvatarSize
|
| 50 | 49 |
from gajim.common.caps_cache import muc_caps_cache
|
| ... | ... | @@ -53,7 +52,6 @@ from gajim.common import app |
| 53 | 52 |
from gajim.common import helpers
|
| 54 | 53 |
from gajim.common.helpers import launch_browser_mailer
|
| 55 | 54 |
from gajim.common.helpers import AdditionalDataDict
|
| 56 |
-from gajim.common.modules import dataforms
|
|
| 57 | 55 |
from gajim.common import ged
|
| 58 | 56 |
from gajim.common import i18n
|
| 59 | 57 |
from gajim.common.i18n import _
|
| ... | ... | @@ -72,11 +70,13 @@ from gajim.gtk.dialogs import ConfirmationDialogCheck |
| 72 | 70 |
from gajim.gtk.dialogs import DoubleInputDialog
|
| 73 | 71 |
from gajim.gtk.dialogs import InputDialog
|
| 74 | 72 |
from gajim.gtk.dialogs import ChangeNickDialog
|
| 73 |
+from gajim.gtk.single_message import SingleMessageWindow
|
|
| 75 | 74 |
from gajim.gtk.filechoosers import AvatarChooserDialog
|
| 76 | 75 |
from gajim.gtk.add_contact import AddNewContactWindow
|
| 77 | 76 |
from gajim.gtk.tooltips import GCTooltip
|
| 78 | 77 |
from gajim.gtk.groupchat_config import GroupchatConfig
|
| 79 | 78 |
from gajim.gtk.adhoc_commands import CommandWindow
|
| 79 |
+from gajim.gtk.dataform import DataFormWidget
|
|
| 80 | 80 |
from gajim.gtk.util import NickCompletionGenerator
|
| 81 | 81 |
from gajim.gtk.util import get_icon_name
|
| 82 | 82 |
from gajim.gtk.util import get_affiliation_surface
|
| ... | ... | @@ -330,6 +330,10 @@ class GroupchatControl(ChatControlBase): |
| 330 | 330 |
self._nec_decrypted_message_received)
|
| 331 | 331 |
app.ged.register_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE,
|
| 332 | 332 |
self._message_sent)
|
| 333 |
+ app.ged.register_event_handler('captcha-challenge', ged.GUI1,
|
|
| 334 |
+ self._on_captcha_challenge)
|
|
| 335 |
+ app.ged.register_event_handler('voice-approval', ged.GUI1,
|
|
| 336 |
+ self._on_voice_approval)
|
|
| 333 | 337 |
self.is_connected = False
|
| 334 | 338 |
# disable win, we are not connected yet
|
| 335 | 339 |
ChatControlBase.got_disconnected(self)
|
| ... | ... | @@ -1073,6 +1077,59 @@ class GroupchatControl(ChatControlBase): |
| 1073 | 1077 |
return
|
| 1074 | 1078 |
self._update_banner_state_image()
|
| 1075 | 1079 |
|
| 1080 |
+ def _on_voice_approval(self, event):
|
|
| 1081 |
+ if event.account != self.account:
|
|
| 1082 |
+ return
|
|
| 1083 |
+ if event.room_jid != self.room_jid:
|
|
| 1084 |
+ return
|
|
| 1085 |
+ SingleMessageWindow(self.account,
|
|
| 1086 |
+ self.room_jid,
|
|
| 1087 |
+ action='receive',
|
|
| 1088 |
+ from_whom=self.room_jid,
|
|
| 1089 |
+ form_node=event.form)
|
|
| 1090 |
+ |
|
| 1091 |
+ def _on_captcha_challenge(self, event):
|
|
| 1092 |
+ if event.account != self.account:
|
|
| 1093 |
+ return
|
|
| 1094 |
+ if event.room_jid != self.room_jid:
|
|
| 1095 |
+ return
|
|
| 1096 |
+ |
|
| 1097 |
+ if self.form_widget:
|
|
| 1098 |
+ self.form_widget.hide()
|
|
| 1099 |
+ self.form_widget.destroy()
|
|
| 1100 |
+ self.btn_box.destroy()
|
|
| 1101 |
+ |
|
| 1102 |
+ self.form_widget = DataFormWidget(event.form)
|
|
| 1103 |
+ |
|
| 1104 |
+ def on_send_dataform_clicked(widget):
|
|
| 1105 |
+ if not self.form_widget:
|
|
| 1106 |
+ return
|
|
| 1107 |
+ form_node = self.form_widget.get_submit_form()
|
|
| 1108 |
+ con = app.connections[self.account]
|
|
| 1109 |
+ con.get_module('MUC').send_captcha(self.room_jid, form_node)
|
|
| 1110 |
+ self.form_widget.hide()
|
|
| 1111 |
+ self.form_widget.destroy()
|
|
| 1112 |
+ self.btn_box.destroy()
|
|
| 1113 |
+ self.form_widget = None
|
|
| 1114 |
+ del self.btn_box
|
|
| 1115 |
+ |
|
| 1116 |
+ # self.form_widget.connect('validated', on_send_dataform_clicked)
|
|
| 1117 |
+ self.form_widget.show_all()
|
|
| 1118 |
+ vbox = self.xml.get_object('gc_textviews_vbox')
|
|
| 1119 |
+ vbox.pack_start(self.form_widget, False, True, 0)
|
|
| 1120 |
+ |
|
| 1121 |
+ valid_button = Gtk.Button(stock=Gtk.STOCK_OK)
|
|
| 1122 |
+ valid_button.connect('clicked', on_send_dataform_clicked)
|
|
| 1123 |
+ self.btn_box = Gtk.HButtonBox()
|
|
| 1124 |
+ self.btn_box.set_layout(Gtk.ButtonBoxStyle.END)
|
|
| 1125 |
+ self.btn_box.pack_start(valid_button, True, True, 0)
|
|
| 1126 |
+ self.btn_box.show_all()
|
|
| 1127 |
+ vbox.pack_start(self.btn_box, False, False, 0)
|
|
| 1128 |
+ if self.parent_win:
|
|
| 1129 |
+ self.parent_win.redraw_tab(self, 'attention')
|
|
| 1130 |
+ else:
|
|
| 1131 |
+ self.attention_flag = True
|
|
| 1132 |
+ |
|
| 1076 | 1133 |
def _nec_mam_decrypted_message_received(self, obj):
|
| 1077 | 1134 |
if obj.conn.name != self.account:
|
| 1078 | 1135 |
return
|
| ... | ... | @@ -1090,45 +1147,7 @@ class GroupchatControl(ChatControlBase): |
| 1090 | 1147 |
def _nec_gc_message_received(self, obj):
|
| 1091 | 1148 |
if obj.room_jid != self.room_jid or obj.conn.name != self.account:
|
| 1092 | 1149 |
return
|
| 1093 |
- if obj.captcha_form:
|
|
| 1094 |
- if self.form_widget:
|
|
| 1095 |
- self.form_widget.hide()
|
|
| 1096 |
- self.form_widget.destroy()
|
|
| 1097 |
- self.btn_box.destroy()
|
|
| 1098 |
- dataform = dataforms.extend_form(node=obj.captcha_form)
|
|
| 1099 |
- self.form_widget = dataforms_widget.DataFormWidget(dataform)
|
|
| 1100 |
- |
|
| 1101 |
- def on_send_dataform_clicked(widget):
|
|
| 1102 |
- if not self.form_widget:
|
|
| 1103 |
- return
|
|
| 1104 |
- form_node = self.form_widget.data_form.get_purged()
|
|
| 1105 |
- form_node.type_ = 'submit'
|
|
| 1106 |
- obj.conn.send_captcha(self.room_jid, form_node)
|
|
| 1107 |
- self.form_widget.hide()
|
|
| 1108 |
- self.form_widget.destroy()
|
|
| 1109 |
- self.btn_box.destroy()
|
|
| 1110 |
- self.form_widget = None
|
|
| 1111 |
- del self.btn_box
|
|
| 1112 |
- |
|
| 1113 |
- self.form_widget.connect('validated', on_send_dataform_clicked)
|
|
| 1114 |
- self.form_widget.show_all()
|
|
| 1115 |
- vbox = self.xml.get_object('gc_textviews_vbox')
|
|
| 1116 |
- vbox.pack_start(self.form_widget, False, True, 0)
|
|
| 1117 |
- |
|
| 1118 |
- valid_button = Gtk.Button(stock=Gtk.STOCK_OK)
|
|
| 1119 |
- valid_button.connect('clicked', on_send_dataform_clicked)
|
|
| 1120 |
- self.btn_box = Gtk.HButtonBox()
|
|
| 1121 |
- self.btn_box.set_layout(Gtk.ButtonBoxStyle.END)
|
|
| 1122 |
- self.btn_box.pack_start(valid_button, True, True, 0)
|
|
| 1123 |
- self.btn_box.show_all()
|
|
| 1124 |
- vbox.pack_start(self.btn_box, False, False, 0)
|
|
| 1125 |
- if self.parent_win:
|
|
| 1126 |
- self.parent_win.redraw_tab(self, 'attention')
|
|
| 1127 |
- else:
|
|
| 1128 |
- self.attention_flag = True
|
|
| 1129 |
- if '100' in obj.status_code:
|
|
| 1130 |
- # Room is not anonymous
|
|
| 1131 |
- self.is_anonymous = False
|
|
| 1150 |
+ |
|
| 1132 | 1151 |
if not obj.nick:
|
| 1133 | 1152 |
# message from server
|
| 1134 | 1153 |
self.print_conversation(
|
| ... | ... | @@ -1416,40 +1435,40 @@ class GroupchatControl(ChatControlBase): |
| 1416 | 1435 |
else:
|
| 1417 | 1436 |
self.subject_button.show()
|
| 1418 | 1437 |
|
| 1419 |
- def _nec_gc_config_changed_received(self, obj):
|
|
| 1420 |
- # statuscode is a list
|
|
| 1438 |
+ def _nec_gc_config_changed_received(self, event):
|
|
| 1421 | 1439 |
# http://www.xmpp.org/extensions/xep-0045.html#roomconfig-notify
|
| 1422 |
- # http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes...
|
|
| 1423 |
- # -init
|
|
| 1424 |
- if obj.room_jid != self.room_jid or obj.conn.name != self.account:
|
|
| 1440 |
+ if event.account != self.account:
|
|
| 1441 |
+ return
|
|
| 1442 |
+ |
|
| 1443 |
+ if event.room_jid != self.room_jid:
|
|
| 1425 | 1444 |
return
|
| 1426 | 1445 |
|
| 1427 | 1446 |
changes = []
|
| 1428 |
- if '100' in obj.status_code:
|
|
| 1447 |
+ if '100' in event.status_codes:
|
|
| 1429 | 1448 |
# Can be a presence (see chg_contact_status in groupchat_control.py)
|
| 1430 | 1449 |
changes.append(_('Any occupant is allowed to see your full JID'))
|
| 1431 | 1450 |
self.is_anonymous = False
|
| 1432 |
- if '102' in obj.status_code:
|
|
| 1451 |
+ if '102' in event.status_codes:
|
|
| 1433 | 1452 |
changes.append(_('Room now shows unavailable members'))
|
| 1434 |
- if '103' in obj.status_code:
|
|
| 1453 |
+ if '103' in event.status_codes:
|
|
| 1435 | 1454 |
changes.append(_('Room now does not show unavailable members'))
|
| 1436 |
- if '104' in obj.status_code:
|
|
| 1455 |
+ if '104' in event.status_codes:
|
|
| 1437 | 1456 |
changes.append(_('A setting not related to privacy has been '
|
| 1438 | 1457 |
'changed'))
|
| 1439 | 1458 |
app.connections[self.account].get_module('Discovery').disco_muc(
|
| 1440 | 1459 |
self.room_jid, self.update_actions, update=True)
|
| 1441 |
- if '170' in obj.status_code:
|
|
| 1460 |
+ if '170' in event.status_codes:
|
|
| 1442 | 1461 |
# Can be a presence (see chg_contact_status in groupchat_control.py)
|
| 1443 | 1462 |
changes.append(_('Room logging is now enabled'))
|
| 1444 |
- if '171' in obj.status_code:
|
|
| 1463 |
+ if '171' in event.status_codes:
|
|
| 1445 | 1464 |
changes.append(_('Room logging is now disabled'))
|
| 1446 |
- if '172' in obj.status_code:
|
|
| 1465 |
+ if '172' in event.status_codes:
|
|
| 1447 | 1466 |
changes.append(_('Room is now non-anonymous'))
|
| 1448 | 1467 |
self.is_anonymous = False
|
| 1449 |
- if '173' in obj.status_code:
|
|
| 1468 |
+ if '173' in event.status_codes:
|
|
| 1450 | 1469 |
changes.append(_('Room is now semi-anonymous'))
|
| 1451 | 1470 |
self.is_anonymous = True
|
| 1452 |
- if '174' in obj.status_code:
|
|
| 1471 |
+ if '174' in event.status_codes:
|
|
| 1453 | 1472 |
changes.append(_('Room is now fully anonymous'))
|
| 1454 | 1473 |
self.is_anonymous = True
|
| 1455 | 1474 |
|
| ... | ... | @@ -2172,6 +2191,10 @@ class GroupchatControl(ChatControlBase): |
| 2172 | 2191 |
ged.GUI1, self._nec_mam_decrypted_message_received)
|
| 2173 | 2192 |
app.ged.remove_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE,
|
| 2174 | 2193 |
self._message_sent)
|
| 2194 |
+ app.ged.remove_event_handler('captcha-challenge', ged.GUI1,
|
|
| 2195 |
+ self._on_captcha_challenge)
|
|
| 2196 |
+ app.ged.remove_event_handler('voice-approval', ged.GUI1,
|
|
| 2197 |
+ self._on_voice_approval)
|
|
| 2175 | 2198 |
|
| 2176 | 2199 |
if self.is_connected:
|
| 2177 | 2200 |
app.connections[self.account].send_gc_status(self.nick,
|
| ... | ... | @@ -20,12 +20,11 @@ from gi.repository import GLib |
| 20 | 20 |
from gajim.common import app
|
| 21 | 21 |
from gajim.common import helpers
|
| 22 | 22 |
from gajim.common.i18n import _
|
| 23 |
-from gajim.common.modules import dataforms
|
|
| 24 | 23 |
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
| 25 | 24 |
|
| 26 |
-from gajim.dataforms_widget import DataFormWidget
|
|
| 27 | 25 |
from gajim.conversation_textview import ConversationTextview
|
| 28 | 26 |
|
| 27 |
+from gajim.gtk.dataform import DataFormWidget
|
|
| 29 | 28 |
from gajim.gtk.dialogs import ErrorDialog
|
| 30 | 29 |
from gajim.gtk.dialogs import AspellDictError
|
| 31 | 30 |
from gajim.gtk.util import get_builder
|
| ... | ... | @@ -83,9 +82,7 @@ class SingleMessageWindow: |
| 83 | 82 |
parent_box = self.xml.get_object('conversation_scrolledwindow').\
|
| 84 | 83 |
get_parent()
|
| 85 | 84 |
if form_node:
|
| 86 |
- dataform = dataforms.extend_form(node=form_node)
|
|
| 87 |
- dataform.type_ = 'submit'
|
|
| 88 |
- self.form_widget = DataFormWidget(dataform)
|
|
| 85 |
+ self.form_widget = DataFormWidget(form_node)
|
|
| 89 | 86 |
self.form_widget.show_all()
|
| 90 | 87 |
parent_box.add(self.form_widget)
|
| 91 | 88 |
parent_box.child_set_property(self.form_widget, 'position',
|
| ... | ... | @@ -282,7 +279,7 @@ class SingleMessageWindow: |
| 282 | 279 |
message = self.message_tv_buffer.get_text(begin, end, True)
|
| 283 | 280 |
|
| 284 | 281 |
if self.form_widget:
|
| 285 |
- form_node = self.form_widget.data_form
|
|
| 282 |
+ form_node = self.form_widget.get_submit_form()
|
|
| 286 | 283 |
else:
|
| 287 | 284 |
form_node = None
|
| 288 | 285 |
|
| ... | ... | @@ -385,8 +385,8 @@ class GajimRemote(Server): |
| 385 | 385 |
# event has not been handled at GUI level
|
| 386 | 386 |
return
|
| 387 | 387 |
self.raise_signal('GCMessage', (obj.conn.name, [obj.fjid, obj.msgtxt,
|
| 388 |
- obj.timestamp, obj.delayed, obj.xhtml_msgtxt, obj.status_code,
|
|
| 389 |
- obj.displaymarking, obj.captcha_form, obj.needs_highlight]))
|
|
| 388 |
+ obj.timestamp, obj.delayed, obj.xhtml_msgtxt,
|
|
| 389 |
+ obj.displaymarking, obj.needs_highlight]))
|
|
| 390 | 390 |
|
| 391 | 391 |
def on_our_status(self, obj):
|
| 392 | 392 |
self.raise_signal('AccountPresence', (obj.show, obj.conn.name))
|
| ... | ... | @@ -22,7 +22,7 @@ test_suite = test |
| 22 | 22 |
install_requires =
|
| 23 | 23 |
cssutils>=1.0.2
|
| 24 | 24 |
keyring
|
| 25 |
- nbxmpp>=0.9.90
|
|
| 25 |
+ nbxmpp>=0.9.90.2
|
|
| 26 | 26 |
precis-i18n>=1.0.0
|
| 27 | 27 |
pyOpenSSL>=0.12
|
| 28 | 28 |
|