diff --git a/gajim/common/connection.py b/gajim/common/connection.py index fa9b15d70..d06bd7aaa 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -1684,14 +1684,6 @@ class Connection(CommonConnection, ConnectionHandlers): show=show, caps=ptype != 'unavailable') - def send_captcha(self, jid, form_node): - if not app.account_is_connected(self.name): - return - iq = nbxmpp.Iq(typ='set', to=jid) - captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA) - captcha.addChild(node=form_node) - self.connection.send(iq) - def check_unique_room_id_support(self, server, instance): if not app.account_is_connected(self.name): return diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py index 5eb615aa4..d0309d358 100644 --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -416,30 +416,6 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent): from gajim.common.modules.security_labels import parse_securitylabel self.displaymarking = parse_securitylabel(self.stanza) - self.captcha_form = None - captcha_tag = self.stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA) - if captcha_tag: - self.captcha_form = captcha_tag.getTag('x', - namespace=nbxmpp.NS_DATA) - for field in self.captcha_form.getTags('field'): - for media in field.getTags('media'): - for uri in media.getTags('uri'): - uri_data = uri.getData() - if uri_data.startswith('cid:'): - uri_data = uri_data[4:] - found = False - for data in self.stanza.getTags('data', - namespace=nbxmpp.NS_BOB): - if data.getAttr('cid') == uri_data: - uri.setData(data.getData()) - found = True - if not found: - self.conn.get_module('BitsOfBinary').get_bob_data( - uri_data, self.fjid, - self.conn._dispatch_gc_msg_with_captcha, - [self.stanza, self.msg_obj], 0) - return - from gajim.common.modules.misc import parse_correction self.correct_id = parse_correction(self.stanza) diff --git a/gajim/common/modules/message.py b/gajim/common/modules/message.py index cbfb6870d..b70f01794 100644 --- a/gajim/common/modules/message.py +++ b/gajim/common/modules/message.py @@ -28,7 +28,6 @@ from gajim.common.helpers import AdditionalDataDict from gajim.common.modules.security_labels import parse_securitylabel from gajim.common.modules.user_nickname import parse_nickname from gajim.common.modules.carbons import parse_carbon -from gajim.common.modules.bits_of_binary import parse_bob_data from gajim.common.modules.misc import parse_delay from gajim.common.modules.misc import parse_eme from gajim.common.modules.misc import parse_correction @@ -58,7 +57,8 @@ class Message: nbxmpp.NS_MAM_1, nbxmpp.NS_MAM_2, nbxmpp.NS_CONFERENCE, - nbxmpp.NS_IBB]) + nbxmpp.NS_IBB, + nbxmpp.NS_CAPTCHA,]) def _message_received(self, _con, stanza): # https://tools.ietf.org/html/rfc6120#section-8.1.1.1 @@ -259,8 +259,6 @@ class Message: event.additional_data.set_value( 'gajim', 'user_timestamp', user_timestamp) - parse_bob_data(event.stanza) - event_attr = { 'popup': False, 'msg_log_id': None, diff --git a/gajim/common/modules/muc.py b/gajim/common/modules/muc.py index db0661a46..0df7d2a59 100644 --- a/gajim/common/modules/muc.py +++ b/gajim/common/modules/muc.py @@ -22,12 +22,13 @@ import weakref import nbxmpp from gajim.common import i18n -from gajim.common.modules import dataforms from gajim.common import app from gajim.common import helpers from gajim.common.caps_cache import muc_caps_cache from gajim.common.nec import NetworkEvent from gajim.common.nec import NetworkIncomingEvent +from gajim.common.modules import dataforms +from gajim.common.modules.bits_of_binary import parse_bob_data log = logging.getLogger('gajim.c.m.muc') @@ -41,6 +42,7 @@ class MUC: ('message', self._on_config_change, '', nbxmpp.NS_MUC_USER), ('message', self._mediated_invite, '', nbxmpp.NS_MUC_USER), ('message', self._direct_invite, '', nbxmpp.NS_CONFERENCE), + ('message', self._on_captcha_challenge, '', nbxmpp.NS_CAPTCHA), ] def pass_disco(self, from_, identities, features, _data, _node): @@ -112,6 +114,35 @@ class MUC: log.info('Set subject for %s', room_jid) self._con.connection.send(message) + def _on_captcha_challenge(self, _con, stanza): + captcha = stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA) + if captcha is None: + return + + parse_bob_data(stanza) + room_jid = str(stanza.getFrom()) + contact = app.contacts.get_groupchat_contact(self._account, room_jid) + if contact is None: + return + + log.info('Captcha challenge received from %s', room_jid) + data_form = captcha.getTag('x', namespace=nbxmpp.NS_DATA) + data_form = dataforms.extend_form(node=data_form) + app.nec.push_incoming_event( + NetworkEvent('captcha-challenge', + account=self._account, + room_jid=room_jid, + form=data_form)) + raise nbxmpp.NodeProcessed + + def send_captcha(self, room_jid, form_node): + if not app.account_is_connected(self._account): + return + iq = nbxmpp.Iq(typ='set', to=room_jid) + captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA) + captcha.addChild(node=form_node) + self._con.connection.send(iq) + def request_config(self, room_jid): if not app.account_is_connected(self._account): return diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py index 6d45aecae..c1f510a17 100644 --- a/gajim/groupchat_control.py +++ b/gajim/groupchat_control.py @@ -44,7 +44,6 @@ from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import message_control from gajim import vcard -from gajim import dataforms_widget from gajim.common.const import AvatarSize from gajim.common.caps_cache import muc_caps_cache @@ -53,7 +52,6 @@ from gajim.common import app from gajim.common import helpers from gajim.common.helpers import launch_browser_mailer from gajim.common.helpers import AdditionalDataDict -from gajim.common.modules import dataforms from gajim.common import ged from gajim.common import i18n from gajim.common.i18n import _ @@ -77,6 +75,7 @@ from gajim.gtk.add_contact import AddNewContactWindow from gajim.gtk.tooltips import GCTooltip from gajim.gtk.groupchat_config import GroupchatConfig from gajim.gtk.adhoc_commands import CommandWindow +from gajim.gtk.dataform import DataFormWidget from gajim.gtk.util import NickCompletionGenerator from gajim.gtk.util import get_icon_name from gajim.gtk.util import get_affiliation_surface @@ -330,6 +329,8 @@ class GroupchatControl(ChatControlBase): self._nec_decrypted_message_received) app.ged.register_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE, self._message_sent) + app.ged.register_event_handler('captcha-challenge', ged.GUI1, + self._on_captcha_challenge) self.is_connected = False # disable win, we are not connected yet ChatControlBase.got_disconnected(self) @@ -1073,6 +1074,48 @@ class GroupchatControl(ChatControlBase): return self._update_banner_state_image() + def _on_captcha_challenge(self, event): + if event.account != self.account: + return + if event.room_jid != self.room_jid: + return + + if self.form_widget: + self.form_widget.hide() + self.form_widget.destroy() + self.btn_box.destroy() + + self.form_widget = DataFormWidget(event.form) + + def on_send_dataform_clicked(widget): + if not self.form_widget: + return + form_node = self.form_widget.get_submit_form() + con = app.connections[self.account] + con.get_module('MUC').send_captcha(self.room_jid, form_node) + self.form_widget.hide() + self.form_widget.destroy() + self.btn_box.destroy() + self.form_widget = None + del self.btn_box + + # self.form_widget.connect('validated', on_send_dataform_clicked) + self.form_widget.show_all() + vbox = self.xml.get_object('gc_textviews_vbox') + vbox.pack_start(self.form_widget, False, True, 0) + + valid_button = Gtk.Button(stock=Gtk.STOCK_OK) + valid_button.connect('clicked', on_send_dataform_clicked) + self.btn_box = Gtk.HButtonBox() + self.btn_box.set_layout(Gtk.ButtonBoxStyle.END) + self.btn_box.pack_start(valid_button, True, True, 0) + self.btn_box.show_all() + vbox.pack_start(self.btn_box, False, False, 0) + if self.parent_win: + self.parent_win.redraw_tab(self, 'attention') + else: + self.attention_flag = True + def _nec_mam_decrypted_message_received(self, obj): if obj.conn.name != self.account: return @@ -1090,42 +1133,7 @@ class GroupchatControl(ChatControlBase): def _nec_gc_message_received(self, obj): if obj.room_jid != self.room_jid or obj.conn.name != self.account: return - if obj.captcha_form: - if self.form_widget: - self.form_widget.hide() - self.form_widget.destroy() - self.btn_box.destroy() - dataform = dataforms.extend_form(node=obj.captcha_form) - self.form_widget = dataforms_widget.DataFormWidget(dataform) - def on_send_dataform_clicked(widget): - if not self.form_widget: - return - form_node = self.form_widget.data_form.get_purged() - form_node.type_ = 'submit' - obj.conn.send_captcha(self.room_jid, form_node) - self.form_widget.hide() - self.form_widget.destroy() - self.btn_box.destroy() - self.form_widget = None - del self.btn_box - - self.form_widget.connect('validated', on_send_dataform_clicked) - self.form_widget.show_all() - vbox = self.xml.get_object('gc_textviews_vbox') - vbox.pack_start(self.form_widget, False, True, 0) - - valid_button = Gtk.Button(stock=Gtk.STOCK_OK) - valid_button.connect('clicked', on_send_dataform_clicked) - self.btn_box = Gtk.HButtonBox() - self.btn_box.set_layout(Gtk.ButtonBoxStyle.END) - self.btn_box.pack_start(valid_button, True, True, 0) - self.btn_box.show_all() - vbox.pack_start(self.btn_box, False, False, 0) - if self.parent_win: - self.parent_win.redraw_tab(self, 'attention') - else: - self.attention_flag = True if not obj.nick: # message from server self.print_conversation( @@ -2169,6 +2177,8 @@ class GroupchatControl(ChatControlBase): ged.GUI1, self._nec_mam_decrypted_message_received) app.ged.remove_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE, self._message_sent) + app.ged.remove_event_handler('captcha-challenge', ged.GUI1, + self._on_captcha_challenge) if self.is_connected: app.connections[self.account].send_gc_status(self.nick, diff --git a/gajim/remote_control.py b/gajim/remote_control.py index 30e3122a7..6e682dbad 100644 --- a/gajim/remote_control.py +++ b/gajim/remote_control.py @@ -386,7 +386,7 @@ class GajimRemote(Server): return self.raise_signal('GCMessage', (obj.conn.name, [obj.fjid, obj.msgtxt, obj.timestamp, obj.delayed, obj.xhtml_msgtxt, - obj.displaymarking, obj.captcha_form, obj.needs_highlight])) + obj.displaymarking, obj.needs_highlight])) def on_our_status(self, obj): self.raise_signal('AccountPresence', (obj.show, obj.conn.name))