Ejemplo n.º 1
0
        def on_yes(dummy, fjid, file_props, account):
            # Delete old file
            os.remove(file_props.file_name)
            jid, resource = app.get_room_and_nick_from_fjid(fjid)
            if resource:
                contact = app.contacts.get_contact(account, jid, resource)
            else:
                contact = app.contacts.get_contact_with_highest_priority(
                    account, jid)
                fjid = contact.get_full_jid()
            # Request the file to the sender
            sid = helpers.get_random_string()
            new_file_props = FilesProp.getNewFileProp(account, sid)
            new_file_props.file_name = file_props.file_name
            new_file_props.name = file_props.name
            new_file_props.desc = file_props.desc
            new_file_props.size = file_props.size
            new_file_props.date = file_props.date
            new_file_props.hash_ = file_props.hash_
            new_file_props.type_ = 'r'
            tsid = app.connections[account].get_module(
                'Jingle').start_file_transfer(fjid, new_file_props, True)

            new_file_props.transport_sid = tsid
            self.add_transfer(account, contact, new_file_props)
Ejemplo n.º 2
0
 def _get_contact_or_gc_contact_for_jid(self, jid):
     contact = app.contacts.get_contact_from_full_jid(self._account, jid)
     if contact is None:
         room_jid, nick = app.get_room_and_nick_from_fjid(jid)
         contact = app.contacts.get_gc_contact(self._account, room_jid,
                                               nick)
     return contact
Ejemplo n.º 3
0
    def execute(self, request):
        account = self.connection.name
        # Forward messages
        events = app.events.get_events(account, types=['chat', 'normal'])
        j, resource = app.get_room_and_nick_from_fjid(self.jid)
        for jid in events:
            for event in events[jid]:
                ev_typ = event.type_
                if ev_typ == 'printed_chat':
                    ev_typ = 'chat'
                app.nec.push_outgoing_event(MessageOutgoingEvent(None,
                    account=account, jid=j, message=event.message, type_=ev_typ,
                    subject=event.subject, resource=resource, forward_from=jid,
                    delayed=event.time_, now=True))

        response, cmd = self.buildResponse(request, status = 'completed')
        cmd.addChild('note', {}, _('The status has been changed.'))

        # if going offline, we need to push response so it won't go into
        # queue and disappear
        self.connection.connection.send(response, now = True)

        # send new status
        app.interface.roster.send_status(self.connection.name, 'offline', '')
        # finish the session
        return False
Ejemplo n.º 4
0
 def _raise_event(self, name, **kwargs):
     jid, resource = app.get_room_and_nick_from_fjid(self.peerjid)
     app.nec.push_incoming_event(
         NetworkEvent(name,
                      conn=self.connection,
                      fjid=self.peerjid,
                      jid=jid,
                      sid=self.sid,
                      resource=resource,
                      jingle_session=self,
                      **kwargs))
Ejemplo n.º 5
0
 def get_jid_resource(self, check_fake_jid=False):
     if check_fake_jid and hasattr(self, 'id_') and \
             self.id_ in self.conn.groupchat_jids:
         self.fjid = self.conn.groupchat_jids[self.id_]
         del self.conn.groupchat_jids[self.id_]
     else:
         self.fjid = helpers.get_full_jid_from_iq(self.stanza)
     if self.fjid is None:
         self.jid = None
     else:
         self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid)
Ejemplo n.º 6
0
    def on_event_added(self, event):
        account = event.account
        jid = event.jid
        when = time.time()
        contact = ""
        key = (account, jid)

        events = [
            'chat', 'printed_chat', 'printed_normal', 'normal', 'file-request',
            'jingle-incoming'
        ]

        if event.type_ in events:
            contact = app.contacts.get_contact_from_full_jid(account, jid)
            if contact:
                contact = contact.get_shown_name()
            else:
                contact = jid
        elif event.type_ == "pm" or event.type_ == "printed_pm":
            contact = app.get_nick_from_jid(app.get_room_from_fjid(jid)) + \
                    "/" + app.get_room_and_nick_from_fjid(jid)[1]
        elif event.type_ == "printed_marked_gc_msg":
            contact = app.get_nick_from_jid(app.get_room_from_fjid(jid))
        else:
            return

        event.time = when
        if key not in self.events:
            icon = None
            if app.config.get("show_avatars_in_roster"):
                pix = app.contacts.get_avatar(account, jid, size=16)
                icon = Gtk.Image()
                icon.set_from_pixbuf(pix)
            item = Gtk.ImageMenuItem(contact + " (1)")
            if icon:
                item.set_image(icon)
                item.set_always_show_image(True)
            item.connect("activate", self.event_raise, event)
            item.show()
            self.menu.insert(item, self.menuEventInsertIndex)
            self.event_separator.show()
            self.events[key] = {}
            self.events[key]['item'] = item
            self.events[key]['contact'] = contact
            self.events[key]['events'] = [event]
        else:
            self.events[key]['events'].append(event)
            item = self.events[key]['item']
            item.set_label(self.events[key]['contact'] + " (" +
                           str(len(self.events[key]['events'])) + ")")
        self.indicator.set_status(appindicator.IndicatorStatus.ATTENTION)
Ejemplo n.º 7
0
    def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE:
        now = time.time()
        for jid in list(self._last_mouse_activity.keys()):
            time_ = self._last_mouse_activity[jid]
            current_state = self._chatstates.get(jid)
            if current_state is None:
                self._last_mouse_activity.pop(jid, None)
                self._last_keyboard_activity.pop(jid, None)
                continue

            if current_state in (State.GONE, State.INACTIVE):
                continue

            new_chatstate = None
            if now - time_ > INACTIVE_AFTER:
                new_chatstate = State.INACTIVE

            elif current_state == State.COMPOSING:
                key_time = self._last_keyboard_activity[jid]
                if now - key_time > PAUSED_AFTER:
                    new_chatstate = State.PAUSED

            if new_chatstate is not None:
                if self._chatstates.get(jid) != new_chatstate:
                    contact = app.contacts.get_contact(self._account, jid)
                    if contact is None:
                        room, nick = app.get_room_and_nick_from_fjid(jid)
                        contact = app.contacts.get_gc_contact(
                            self._account, room, nick)
                        if contact is not None:
                            contact = contact.as_contact()
                        else:
                            # Contact not found, maybe we left the group chat
                            # or the contact was removed from the roster
                            self._log.info(
                                'Contact %s not found, reset chatstate', jid)
                            self._chatstates.pop(jid, None)
                            self._last_mouse_activity.pop(jid, None)
                            self._last_keyboard_activity.pop(jid, None)
                            continue
                self.set_chatstate(contact, new_chatstate)

        return GLib.SOURCE_CONTINUE
Ejemplo n.º 8
0
 def generate(self):
     self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid)
     self.resource = 'local'
     self.prio = 0
     self.keyID = None
     self.idle_time = None
     self.timestamp = 0
     self.contact_nickname = None
     self.avatar_sha = None
     self.need_add_in_roster = False
     self.need_redraw = False
     if self.show == 'offline':
         self.ptype = 'unavailable'
     else:
         self.ptype = None
     self.is_gc = False
     self.user_nick = ''
     self.transport_auto_auth = False
     self.errcode = None
     self.errmsg = ''
     self.popup = False # Do we want to open chat window ?
     return True
Ejemplo n.º 9
0
    def execute(self, request):
        account = self.connection.name
        # Forward messages
        events = app.events.get_events(account, types=['chat', 'normal',
            'printed_chat'])
        j, resource = app.get_room_and_nick_from_fjid(self.jid)
        for jid in events:
            for event in events[jid]:
                ev_typ = event.type_
                if ev_typ == 'printed_chat':
                    ev_typ = 'chat'
                app.nec.push_outgoing_event(MessageOutgoingEvent(None,
                    account=account, jid=j, message=event.message, type_=ev_typ,
                    subject=event.subject, resource=resource, forward_from=jid,
                    delayed=event.time_))

        # Inform other client of completion
        response, cmd = self.buildResponse(request, status = 'completed')
        cmd.addChild('note', {}, _('All unread messages have been forwarded.'))

        self.connection.connection.send(response)

        return False    # finish the session
Ejemplo n.º 10
0
    def _messageCB(self, con, stanza, properties):
        """
        Called when we receive a message
        """
        if properties.type.is_error:
            return
        log.info('Zeroconf MessageCB')

        # Don’t trust from attr set by sender
        stanza.setFrom(con._owner.to)

        app.nec.push_incoming_event(
            NetworkEvent('raw-message-received',
                         conn=self,
                         stanza=stanza,
                         account=self.name))

        type_ = stanza.getType()
        if type_ is None:
            type_ = 'normal'

        id_ = stanza.getID()

        fjid = str(stanza.getFrom())

        jid, resource = app.get_room_and_nick_from_fjid(fjid)

        msgtxt = stanza.getBody()

        session = self.get_or_create_session(fjid, properties.thread)

        if properties.thread and not session.received_thread_id:
            session.received_thread_id = True

        timestamp = time.time()
        session.last_receive = timestamp

        additional_data = AdditionalDataDict()
        parse_oob(properties, additional_data)
        parse_xhtml(properties, additional_data)

        if properties.is_encrypted:
            additional_data['encrypted'] = properties.encrypted.additional_data
        else:
            if properties.eme is not None:
                msgtxt = get_eme_message(properties.eme)

        event_attr = {
            'conn': self,
            'stanza': stanza,
            'account': self.name,
            'additional_data': additional_data,
            'timestamp': time.time(),
            'fjid': fjid,
            'jid': jid,
            'resource': resource,
            'unique_id': id_,
            'correct_id': parse_correction(properties),
            'msgtxt': msgtxt,
            'session': session,
            'gc_control': None,
            'popup': False,
            'msg_log_id': None,
            'displaymarking': None,
            'stanza_id': id_,
            'properties': properties,
        }

        app.nec.push_incoming_event(
            NetworkEvent('decrypted-message-received', **event_attr))
Ejemplo n.º 11
0
 def generate(self):
     self.fjid = self.jingle_session.peerjid
     self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid)
     self.sid = self.jingle_session.sid
     return True
Ejemplo n.º 12
0
    def _fill_completion_dict(self):
        """
        Fill completion_dict for key auto completion. Then load history for
        current jid (by calling another function)

        Key will be either jid or full_completion_name (contact name or long
        description like "pm-contact from groupchat....").

        {key : (jid, account, nick_name, full_completion_name}
        This is a generator and does pseudo-threading via idle_add().
        """
        liststore = get_completion_liststore(
            self._ui.query_entry.get_child())
        liststore.set_sort_column_id(1, Gtk.SortType.ASCENDING)
        self._ui.query_entry.get_child().get_completion().connect(
            'match-selected', self.on_jid_entry_match_selected)

        self._ui.query_entry.set_model(liststore)

        # Add all jids in logs.db:
        db_jids = app.logger.get_jids_in_db()
        completion_dict = dict.fromkeys(db_jids)

        self.accounts_seen_online = list(app.contacts.get_accounts())

        # Enhance contacts of online accounts with contact.
        # Needed for mapping below
        for account in self.accounts_seen_online:
            completion_dict.update(
                helpers.get_contact_dict_for_account(account))

        muc_active_icon = get_icon_name('muc-active')
        online_icon = get_icon_name('online')

        keys = list(completion_dict.keys())
        # Move the actual jid at first so we load history faster
        actual_jid = self._ui.query_entry.get_child().get_text()
        if actual_jid in keys:
            keys.remove(actual_jid)
            keys.insert(0, actual_jid)
        if '' in keys:
            keys.remove('')
        if None in keys:
            keys.remove(None)
        # Map jid to info tuple
        # Warning : This for is time critical with big DB
        for key in keys:
            completed = key
            completed2 = None
            contact = completion_dict[completed]
            if contact:
                info_name = contact.get_shown_name()
                info_completion = info_name
                info_jid = contact.jid
            else:
                # Corresponding account is offline, we know nothing
                info_name = completed.split('@')[0]
                info_completion = completed
                info_jid = completed

            info_acc = self._get_account_for_jid(info_jid)

            if (app.logger.jid_is_room_jid(completed) or
                    app.logger.jid_is_from_pm(completed)):
                icon = muc_active_icon
                if app.logger.jid_is_from_pm(completed):
                    # It's PM. Make it easier to find
                    room, nick = app.get_room_and_nick_from_fjid(completed)
                    info_completion = '%s from %s' % (nick, room)
                    completed = info_completion
                    info_completion2 = '%s/%s' % (room, nick)
                    completed2 = info_completion2
                    info_name = nick
            else:
                icon = online_icon

            if len(completed) > 70:
                completed = completed[:70] + '[\u2026]'
            liststore.append((icon, completed))
            self.completion_dict[key] = (
                info_jid, info_acc, info_name, info_completion)
            self.completion_dict[completed] = (
                info_jid, info_acc, info_name, info_completion)
            if completed2:
                if len(completed2) > 70:
                    completed2 = completed2[:70] + '[\u2026]'
                liststore.append((icon, completed2))
                self.completion_dict[completed2] = (
                    info_jid, info_acc, info_name, info_completion2)
            if key == actual_jid:
                self._load_history(info_jid, self.account or info_acc)
            yield True
        keys.sort()
        yield False
Ejemplo n.º 13
0
    def _message_received(self, con, stanza):
        # https://tools.ietf.org/html/rfc6120#section-8.1.1.1
        # If the stanza does not include a 'to' address then the client MUST
        # treat it as if the 'to' address were included with a value of the
        # client's full JID.
        #
        # Implementation Note: However, if the client does
        # check the 'to' address then it is suggested to check at most the
        # bare JID portion (not the full JID)

        own_jid = self._con.get_own_jid().getStripped()
        to = stanza.getTo()
        if to is None:
            stanza.setTo(own_jid)
        elif not to.bareMatch(own_jid):
            log.warning('Message addressed to someone else: %s', stanza)
            raise nbxmpp.NodeProcessed

        # Check if a child of the message contains any
        # namespaces that we handle in other modules.
        # nbxmpp executes less common handlers last
        if self._message_namespaces & set(stanza.getProperties()):
            return

        muc_user = stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
        if muc_user is not None:
            if muc_user.getChildren():
                # Not a PM, handled by MUC module
                return

        log.info('Received from %s', stanza.getFrom())

        app.nec.push_incoming_event(
            NetworkEvent('raw-message-received',
                         conn=self._con,
                         stanza=stanza,
                         account=self._account))

        if stanza.getFrom() == self._con.get_own_jid(warn=True):
            # Drop messages sent from our own full jid
            # It can happen that when we sent message to our own bare jid
            # that the server routes that message back to us
            log.info('Received message from self: %s, message is dropped',
                     stanza.getFrom())
            return

        stanza, sent, forwarded = parse_carbon(self._con, stanza)

        from_ = stanza.getFrom()
        type_ = stanza.getType()
        if type_ is None:
            type_ = 'normal'
        self_message = is_self_message(stanza, type_ == 'groupchat')
        muc_pm = is_muc_pm(stanza, from_, type_ == 'groupchat')

        id_ = stanza.getID()

        fjid = None
        if from_ is not None:
            try:
                fjid = helpers.parse_jid(str(from_))
            except helpers.InvalidFormat:
                log.warning('Invalid JID: %s, ignoring it', stanza.getFrom())
                return

        jid, resource = app.get_room_and_nick_from_fjid(fjid)

        # Check for duplicates
        stanza_id, origin_id = self._get_unique_id(stanza, forwarded, sent,
                                                   self_message, muc_pm)

        # Check groupchat messages for duplicates,
        # We do this because of MUC History messages
        if type_ == 'groupchat' or self_message or muc_pm:
            if type_ == 'groupchat':
                archive_jid = stanza.getFrom().getStripped()
            else:
                archive_jid = own_jid
            if app.logger.find_stanza_id(self._account, archive_jid, stanza_id,
                                         origin_id, type_ == 'groupchat'):
                return

        thread_id = stanza.getThread()
        msgtxt = stanza.getBody()

        # TODO: remove all control UI stuff
        gc_control = app.interface.msg_win_mgr.get_gc_control(
            jid, self._account)
        if not gc_control:
            minimized = app.interface.minimized_controls[self._account]
            gc_control = minimized.get(jid)

        if gc_control and jid == fjid:
            if type_ == 'error':
                msgtxt = _('error while sending %(message)s ( %(error)s )') % {
                    'message': msgtxt,
                    'error': stanza.getErrorMsg()
                }
                # TODO: why is this here?
                if stanza.getTag('html'):
                    stanza.delChild('html')

        session = None
        if type_ != 'groupchat':
            if muc_pm and type_ == 'error':
                session = self._con.find_session(fjid, thread_id)
                if not session:
                    session = self._con.get_latest_session(fjid)
                if not session:
                    session = self._con.make_new_session(fjid,
                                                         thread_id,
                                                         type_='pm')
            else:
                session = self._con.get_or_create_session(fjid, thread_id)

            if thread_id and not session.received_thread_id:
                session.received_thread_id = True

            session.last_receive = time.time()

        timestamp = parse_delay(stanza)
        if timestamp is None:
            timestamp = time.time()

        event_attr = {
            'conn': self._con,
            'stanza': stanza,
            'account': self._account,
            'id_': id_,
            'encrypted': False,
            'additional_data': {},
            'forwarded': forwarded,
            'sent': sent,
            'timestamp': timestamp,
            'fjid': fjid,
            'jid': jid,
            'resource': resource,
            'stanza_id': stanza_id,
            'unique_id': stanza_id or origin_id,
            'mtype': type_,
            'msgtxt': msgtxt,
            'thread_id': thread_id,
            'session': session,
            'self_message': self_message,
            'muc_pm': muc_pm,
            'gc_control': gc_control
        }

        event = MessageReceivedEvent(None, **event_attr)
        app.nec.push_incoming_event(event)

        app.plugin_manager.extension_point('decrypt', self._con, event,
                                           self._on_message_decrypted)
        if not event.encrypted:
            eme = parse_eme(event.stanza)
            if eme is not None:
                event.msgtxt = eme
            self._on_message_decrypted(event)
Ejemplo n.º 14
0
    def fill_jabber_page(self):
        self.xml.get_object('nickname_label').set_markup(
            '<b><span size="x-large">' + self.contact.get_shown_name() +
            '</span></b>')
        self.xml.get_object('jid_label').set_text(self.contact.jid)

        subscription_label = self.xml.get_object('subscription_label')
        ask_label = self.xml.get_object('ask_label')
        if self.gc_contact:
            self.xml.get_object('subscription_title_label').set_markup(
                Q_("?Role in Group Chat:<b>Role:</b>"))
            uf_role = helpers.get_uf_role(self.gc_contact.role)
            subscription_label.set_text(uf_role)

            self.xml.get_object('ask_title_label').set_markup(
                _("<b>Affiliation:</b>"))
            uf_affiliation = helpers.get_uf_affiliation(
                self.gc_contact.affiliation)
            ask_label.set_text(uf_affiliation)
        else:
            uf_sub = helpers.get_uf_sub(self.contact.sub)
            subscription_label.set_text(uf_sub)
            if self.contact.sub == 'from':
                tt_text = _(
                    "This contact is interested in your presence information, but you are not interested in their presence"
                )
            elif self.contact.sub == 'to':
                tt_text = _(
                    "You are interested in the contact's presence information, but it is not mutual"
                )
            elif self.contact.sub == 'both':
                tt_text = _(
                    "The contact and you want to exchange presence information"
                )
            else:  # None
                tt_text = _(
                    "You and the contact have a mutual disinterest in each-others presence information"
                )
            subscription_label.set_tooltip_text(tt_text)

            uf_ask = helpers.get_uf_ask(self.contact.ask)
            ask_label.set_text(uf_ask)
            if self.contact.ask == 'subscribe':
                tt_text = _(
                    "You are waiting contact's answer about your subscription request"
                )
            else:
                tt_text = _("There is no pending subscription request.")
            ask_label.set_tooltip_text(tt_text)

        resources = '%s (%s)' % (self.contact.resource,
                                 str(self.contact.priority))
        uf_resources = self.contact.resource + _(' resource with priority ')\
                + str(self.contact.priority)
        if not self.contact.status:
            self.contact.status = ''

        con = app.connections[self.account]

        # do not wait for os_info if contact is not connected or has error
        # additional check for observer is needed, as show is offline for him
        if self.contact.show in ('offline', 'error')\
        and not self.contact.is_observer():
            self.os_info_arrived = True
        else:  # Request os info if contact is connected
            if self.gc_contact:
                con.get_module('SoftwareVersion').request_software_version(
                    self.real_jid,
                    callback=self.set_os_info,
                    user_data=self.real_jid)
            else:
                jid = self.contact.get_full_jid()
                con.get_module('SoftwareVersion').request_software_version(
                    jid, callback=self.set_os_info, user_data=jid)

        # do not wait for entity_time if contact is not connected or has error
        # additional check for observer is needed, as show is offline for him
        if self.contact.show in ('offline', 'error')\
        and not self.contact.is_observer():
            self.entity_time_arrived = True
        else:  # Request entity time if contact is connected
            if self.gc_contact:
                j, r = app.get_room_and_nick_from_fjid(self.real_jid)
                GLib.idle_add(
                    con.get_module('EntityTime').request_entity_time, j, r)
            else:
                GLib.idle_add(
                    con.get_module('EntityTime').request_entity_time,
                    self.contact.jid, self.contact.resource)

        self.os_info = {
            0: {
                'resource': self.real_resource,
                'client': '',
                'os': ''
            }
        }
        self.time_info = {0: {'resource': self.real_resource, 'time': ''}}
        i = 1
        contact_list = app.contacts.get_contacts(self.account,
                                                 self.contact.jid)
        if contact_list:
            for c in contact_list:
                if c.resource != self.contact.resource:
                    resources += '\n%s (%s)' % (c.resource, str(c.priority))
                    uf_resources += '\n' + c.resource + \
                            _(' resource with priority ') + str(c.priority)
                    if c.show not in ('offline', 'error'):
                        jid = c.get_full_jid()
                        con.get_module(
                            'SoftwareVersion').request_software_version(
                                jid, callback=self.set_os_info, user_data=jid)
                        GLib.idle_add(
                            con.get_module('EntityTime').request_entity_time,
                            c.jid, c.resource)
                    self.os_info[i] = {
                        'resource': c.resource,
                        'client': '',
                        'os': ''
                    }
                    self.time_info[i] = {'resource': c.resource, 'time': ''}
                    i += 1

        self.xml.get_object('resource_prio_label').set_text(resources)
        resource_prio_label_eventbox = self.xml.get_object(
            'resource_prio_label_eventbox')
        resource_prio_label_eventbox.set_tooltip_text(uf_resources)

        self.fill_status_label()

        if self.gc_contact:
            con.get_module('VCardTemp').request_vcard(
                self._nec_vcard_received,
                self.gc_contact.get_full_jid(),
                room=True)
        else:
            con.get_module('VCardTemp').request_vcard(self._nec_vcard_received,
                                                      self.contact.jid)
Ejemplo n.º 15
0
    def _messageCB(self, con, stanza, properties):
        """
        Called when we receive a message
        """
        log.info('Zeroconf MessageCB')

        # Dont trust from attr set by sender
        stanza.setFrom(con._owner.to)

        app.nec.push_incoming_event(NetworkEvent(
            'raw-message-received',
            conn=self,
            stanza=stanza,
            account=self.name))

        type_ = stanza.getType()
        if type_ is None:
            type_ = 'normal'

        id_ = stanza.getID()

        fjid = str(stanza.getFrom())

        jid, resource = app.get_room_and_nick_from_fjid(fjid)

        thread_id = stanza.getThread()
        msgtxt = stanza.getBody()

        session = self.get_or_create_session(fjid, thread_id)

        if thread_id and not session.received_thread_id:
            session.received_thread_id = True

        session.last_receive = time.time()

        event_attr = {
            'conn': self,
            'stanza': stanza,
            'account': self.name,
            'id_': id_,
            'encrypted': False,
            'additional_data': AdditionalDataDict(),
            'forwarded': False,
            'sent': False,
            'timestamp': time.time(),
            'fjid': fjid,
            'jid': jid,
            'resource': resource,
            'unique_id': id_,
            'message_id': properties.id,
            'mtype': type_,
            'msgtxt': msgtxt,
            'thread_id': thread_id,
            'session': session,
            'self_message': False,
            'muc_pm': False,
            'gc_control': None}

        event = ZeroconfMessageReceivedEvent(None, **event_attr)
        app.nec.push_incoming_event(event)

        app.plugin_manager.extension_point(
            'decrypt', self, event, self._on_message_decrypted)
        if not event.encrypted:
            if properties.eme is not None:
                event.msgtxt = get_eme_message(properties.eme)
            self._on_message_decrypted(event)
Ejemplo n.º 16
0
    def handle_negotiation(self, form):
        if form.getField('accept') and not form['accept'] in ('1', 'true'):
            self.cancelled_negotiation()
            return

        # encrypted session states. these are described in stanza_session.py

        try:
            if form.getType() == 'form' and 'security' in form.asDict():
                security_options = [x[1] for x in form.getField('security').\
                    getOptions()]
                if security_options == ['none']:
                    self.respond_archiving(form)
                else:
                    # bob responds

                    # we don't support 3-message negotiation as the responder
                    if 'dhkeys' in form.asDict():
                        self.fail_bad_negotiation(
                            '3 message negotiation not '
                            'supported when responding', ('dhkeys', ))
                        return

                    negotiated, not_acceptable, ask_user = \
                        self.verify_options_bob(form)

                    if ask_user:

                        def accept_nondefault_options(is_checked):
                            self.dialog.destroy()
                            negotiated.update(ask_user)
                            self.respond_e2e_bob(form, negotiated,
                                                 not_acceptable)

                        def reject_nondefault_options():
                            self.dialog.destroy()
                            for key in ask_user.keys():
                                not_acceptable.append(key)
                            self.respond_e2e_bob(form, negotiated,
                                                 not_acceptable)

                        self.dialog = dialogs.YesNoDialog(
                            _('Confirm these '
                              'session options'),
                            _('The remote client wants to negotiate a session '
                              'with these features:\n\n%s\n\nAre these options '
                              'acceptable?'
                              '') % (negotiation.describe_features(ask_user)),
                            on_response_yes=accept_nondefault_options,
                            on_response_no=reject_nondefault_options,
                            transient_for=self.control.parent_win.window)
                    else:
                        self.respond_e2e_bob(form, negotiated, not_acceptable)

                return

            elif self.status == 'requested-archiving' and form.getType() == \
            'submit':
                try:
                    self.archiving_accepted(form)
                except exceptions.NegotiationError as details:
                    self.fail_bad_negotiation(details)

                return

            # alice accepts
            elif self.status == 'requested-e2e' and form.getType() == 'submit':
                negotiated, not_acceptable, ask_user = self.verify_options_alice(
                    form)

                if ask_user:

                    def accept_nondefault_options(is_checked):
                        if dialog:
                            dialog.destroy()

                        if is_checked:
                            allow_no_log_for = app.config.get_per(
                                'accounts', self.conn.name,
                                'allow_no_log_for').split()
                            jid = str(self.jid)
                            if jid not in allow_no_log_for:
                                allow_no_log_for.append(jid)
                                app.config.set_per('accounts', self.conn.name,
                                                   'allow_no_log_for',
                                                   ' '.join(allow_no_log_for))

                        negotiated.update(ask_user)

                        try:
                            self.accept_e2e_alice(form, negotiated)
                        except exceptions.NegotiationError as details:
                            self.fail_bad_negotiation(details)

                    def reject_nondefault_options():
                        self.reject_negotiation()
                        dialog.destroy()

                    allow_no_log_for = app.config.get_per(
                        'accounts', self.conn.name,
                        'allow_no_log_for').split()
                    if str(self.jid) in allow_no_log_for:
                        dialog = None
                        accept_nondefault_options(False)
                    else:
                        dialog = dialogs.YesNoDialog(
                            _('Confirm these session '
                              'options'),
                            _('The remote client selected these options:\n\n%s'
                              '\n\nContinue with the session?') %
                            (negotiation.describe_features(ask_user)),
                            _('Always accept for this contact'),
                            on_response_yes=accept_nondefault_options,
                            on_response_no=reject_nondefault_options,
                            transient_for=self.control.parent_win.window)
                else:
                    try:
                        self.accept_e2e_alice(form, negotiated)
                    except exceptions.NegotiationError as details:
                        self.fail_bad_negotiation(details)

                return
            elif self.status == 'responded-archiving' and form.getType() == \
            'result':
                try:
                    self.we_accept_archiving(form)
                except exceptions.NegotiationError as details:
                    self.fail_bad_negotiation(details)

                return
            elif self.status == 'responded-e2e' and form.getType() == 'result':
                try:
                    self.accept_e2e_bob(form)
                except exceptions.NegotiationError as details:
                    self.fail_bad_negotiation(details)

                return
            elif self.status == 'identified-alice' and form.getType(
            ) == 'result':
                try:
                    self.final_steps_alice(form)
                except exceptions.NegotiationError as details:
                    self.fail_bad_negotiation(details)

                return
        except exceptions.Cancelled:
            # user cancelled the negotiation

            self.reject_negotiation()

            return

        if form.getField('terminate') and\
        form.getField('terminate').getValue() in ('1', 'true'):
            self.acknowledge_termination()

            self.conn.delete_session(str(self.jid), self.thread_id)

            return

        # non-esession negotiation. this isn't very useful, but i'm keeping it
        # around to test my test suite.
        if form.getType() == 'form':
            if not self.control:
                jid, resource = app.get_room_and_nick_from_fjid(str(self.jid))

                account = self.conn.name
                contact = app.contacts.get_contact(account, str(self.jid),
                                                   resource)

                if not contact:
                    contact = app.contacts.create_contact(
                        jid=jid,
                        account=account,
                        resource=resource,
                        show=self.conn.get_status())

                app.interface.new_chat(contact,
                                       account,
                                       resource=resource,
                                       session=self)

            negotiation.FeatureNegotiationWindow(account, str(self.jid), self,
                                                 form)
    def _messageCB(self, ip, con, stanza):
        """
        Called when we receive a message
        """
        log.debug('Zeroconf MessageCB')

        app.nec.push_incoming_event(
            NetworkEvent('raw-message-received',
                         conn=self,
                         stanza=stanza,
                         account=self.name))

        type_ = stanza.getType()
        if type_ is None:
            type_ = 'normal'

        id_ = stanza.getID()

        fjid = str(stanza.getFrom())

        if fjid is None:
            for key in self.connection.zeroconf.contacts:
                if ip == self.connection.zeroconf.contacts[key][
                        Constant.ADDRESS]:
                    fjid = key
                    break

        jid, resource = app.get_room_and_nick_from_fjid(fjid)

        thread_id = stanza.getThread()
        msgtxt = stanza.getBody()

        session = self.get_or_create_session(fjid, thread_id)

        if thread_id and not session.received_thread_id:
            session.received_thread_id = True

        session.last_receive = time.time()

        event_attr = {
            'conn': self,
            'stanza': stanza,
            'account': self.name,
            'id_': id_,
            'encrypted': False,
            'additional_data': {},
            'forwarded': False,
            'sent': False,
            'timestamp': time.time(),
            'fjid': fjid,
            'jid': jid,
            'resource': resource,
            'unique_id': id_,
            'mtype': type_,
            'msgtxt': msgtxt,
            'thread_id': thread_id,
            'session': session,
            'self_message': False,
            'muc_pm': False,
            'gc_control': None
        }

        event = ZeroconfMessageReceivedEvent(None, **event_attr)
        app.nec.push_incoming_event(event)

        app.plugin_manager.extension_point('decrypt', self, event,
                                           self._on_message_decrypted)
        if not event.encrypted:
            eme = parse_eme(event.stanza)
            if eme is not None:
                event.msgtxt = eme
            self._on_message_decrypted(event)