Exemplo n.º 1
0
    def _NH_XMPPGotComposingIndication(self, notification):
        composing_indication = notification.data.composing_indication
        sender = composing_indication.sender
        recipient = composing_indication.recipient
        if not XMPPGatewayConfig.use_msrp_for_chat:
            state = 'active' if composing_indication.state == 'composing' else 'idle'
            try:
                interval = composing_indication.interval
            except AttributeError:
                interval = 60

            body = IsComposingMessage(
                state=State(state),
                refresh=Refresh(interval),
                last_active=LastActive(ISOTimestamp.now()),
                content_type=ContentType('text')).toxml()
            message = NormalMessage(sender, recipient, body)
            sip_message_sender = SIPMessageSender(
                message,
                content_type=IsComposingDocument.content_type,
                use_cpim=XMPPGatewayConfig.use_cpim)
            if XMPPGatewayConfig.log_iscomposing:
                log.info('xmpp:%s to sip:%s chat is %s' %
                         (sender, recipient, composing_indication.state))

            try:
                sip_message_sender.send().wait()
            except SIPMessageError as e:
                if XMPPGatewayConfig.log_iscomposing:
                    log.error('SIP Message from %s to %s failed: %s (%s)' %
                              (sender, recipient, e.reason, e.code))
Exemplo n.º 2
0
    def incoming_message(self, message_request, data):
        content_type = data.headers.get("Content-Type", Null).content_type
        from_header = data.headers.get("From", Null)
        to_header = data.headers.get("To", Null)
        if Null in (content_type, from_header, to_header):
            message_request.answer(400)
            return
        log.msg("New SIP Message from %s to %s" % (from_header.uri, to_header.uri))

        # Check domain
        if from_header.uri.host not in XMPPGatewayConfig.domains:
            log.msg("Message rejected: From domain is not a local XMPP domain")
            message_request.answer(606)
            return

        if content_type == "message/cpim":
            try:
                cpim_message = CPIMPayload.decode(data.body)
            except CPIMParserError:
                log.msg("Message rejected: CPIM parse error")
                message_request.answer(400)
                return
            else:
                body = cpim_message.content
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                from_uri = sender.uri
        else:
            body = data.body
            from_uri = from_header.uri
        to_uri = str(to_header.uri)
        message_request.answer(200)
        if from_uri.parameters.get("gr", None) is None:
            from_uri = SIPURI.new(from_uri)
            from_uri.parameters["gr"] = generate_sylk_resource()
        sender = Identity(FrozenURI.parse(from_uri))
        recipient = Identity(FrozenURI.parse(to_uri))
        if content_type in ("text/plain", "text/html"):
            if content_type == "text/plain":
                html_body = None
            else:
                html_body = body
                body = None
            if XMPPGatewayConfig.use_msrp_for_chat:
                message = NormalMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
            else:
                message = ChatMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
        elif content_type == IsComposingDocument.content_type:
            if not XMPPGatewayConfig.use_msrp_for_chat:
                try:
                    msg = IsComposingMessage.parse(body)
                except ParserError:
                    pass
                else:
                    state = "composing" if msg.state == "active" else "paused"
                    message = ChatComposingIndication(sender, recipient, state, use_receipt=False)
                    self.xmpp_manager.send_stanza(message)
Exemplo n.º 3
0
    def incoming_message(self, message_request, data):
        content_type = data.headers.get('Content-Type', Null).content_type
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        if Null in (content_type, from_header, to_header):
            message_request.answer(400)
            return
        log.msg('New SIP Message from %s to %s' % (from_header.uri, to_header.uri))

        # Check domain
        if from_header.uri.host not in XMPPGatewayConfig.domains:
            log.msg('Message rejected: From domain is not a local XMPP domain')
            message_request.answer(606)
            return

        if content_type == 'message/cpim':
            try:
                cpim_message = CPIMMessage.parse(data.body)
            except CPIMParserError:
                log.msg('Message rejected: CPIM parse error')
                message_request.answer(400)
                return
            else:
                body = cpim_message.body
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                from_uri = sender.uri
        else:
            body = data.body
            from_uri = from_header.uri
        to_uri = str(to_header.uri)
        message_request.answer(200)
        if from_uri.parameters.get('gr', None) is None:
            from_uri = SIPURI.new(from_uri)
            from_uri.parameters['gr'] = generate_sylk_resource()
        sender = Identity(FrozenURI.parse(from_uri))
        recipient = Identity(FrozenURI.parse(to_uri))
        if content_type in ('text/plain', 'text/html'):
            if content_type == 'text/plain':
                html_body = None
            else:
                html_body = body
                body = None
            if XMPPGatewayConfig.use_msrp_for_chat:
                message = NormalMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
            else:
                message = ChatMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
        elif content_type == IsComposingDocument.content_type:
            if not XMPPGatewayConfig.use_msrp_for_chat:
                try:
                    msg = IsComposingMessage.parse(body)
                except ParserError:
                    pass
                else:
                    state = 'composing' if msg.state == 'active' else 'paused'
                    message = ChatComposingIndication(sender, recipient, state, use_receipt=False)
                    self.xmpp_manager.send_stanza(message)
Exemplo n.º 4
0
    def incoming_message(self, message_request, data):
        content_type = data.headers.get('Content-Type', Null).content_type
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        if Null in (content_type, from_header, to_header):
            message_request.answer(400)
            return
        log.info('New SIP Message from %s to %s' % (from_header.uri, to_header.uri))

        # Check domain
        if from_header.uri.host not in XMPPGatewayConfig.domains:
            log.info('Message rejected: From domain is not a local XMPP domain')
            message_request.answer(606)
            return

        if content_type == 'message/cpim':
            try:
                cpim_message = CPIMPayload.decode(data.body)
            except CPIMParserError:
                log.info('Message rejected: CPIM parse error')
                message_request.answer(400)
                return
            else:
                body = cpim_message.content
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                from_uri = sender.uri
        else:
            body = data.body
            from_uri = from_header.uri
        to_uri = str(to_header.uri)
        message_request.answer(200)
        if from_uri.parameters.get('gr', None) is None:
            from_uri = SIPURI.new(from_uri)
            from_uri.parameters['gr'] = generate_sylk_resource()
        sender = Identity(FrozenURI.parse(from_uri))
        recipient = Identity(FrozenURI.parse(to_uri))
        if content_type in ('text/plain', 'text/html'):
            if content_type == 'text/plain':
                html_body = None
            else:
                html_body = body
                body = None
            if XMPPGatewayConfig.use_msrp_for_chat:
                message = NormalMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
            else:
                message = ChatMessage(sender, recipient, body, html_body, use_receipt=False)
                self.xmpp_manager.send_stanza(message)
        elif content_type == IsComposingDocument.content_type:
            if not XMPPGatewayConfig.use_msrp_for_chat:
                try:
                    msg = IsComposingMessage.parse(body)
                except ParserError:
                    pass
                else:
                    state = 'composing' if msg.state == 'active' else 'paused'
                    message = ChatComposingIndication(sender, recipient, state, use_receipt=False)
                    self.xmpp_manager.send_stanza(message)
Exemplo n.º 5
0
 def chatView_becameActive_(self, chatView, last_active):
     if self.enableIsComposing:
         content = IsComposingMessage(
             state=State("active"),
             refresh=Refresh(60),
             last_active=LastActive(last_active or datetime.now()),
             content_type=ContentType('text')).toxml()
         self.sendMessage(content, IsComposingDocument.content_type)
Exemplo n.º 6
0
 def _NH_XMPPGotComposingIndication(self, notification):
     composing_indication = notification.data.composing_indication
     sender = composing_indication.sender
     recipient = composing_indication.recipient
     if not XMPPGatewayConfig.use_msrp_for_chat:
         state = 'active' if composing_indication.state == 'composing' else 'idle'
         body = IsComposingMessage(state=state, refresh=composing_indication.interval or 30).toxml()
         message = NormalMessage(sender, recipient, body, IsComposingDocument.content_type)
         sip_message_sender = SIPMessageSender(message)
         try:
             sip_message_sender.send().wait()
         except SIPMessageError as e:
             # TODO report back an error stanza
             log.error('Error sending SIP Message: %s' % e)
Exemplo n.º 7
0
    def _NH_SIPEngineGotMessage(self, sender, data):
        account = AccountManager().find_account(data.request_uri)
        if not account:
            BlinkLogger().log_warning(
                "Could not find local account for incoming SMS to %s, using default"
                % data.request_uri)
            account = AccountManager().default_account

        call_id = data.headers.get('Call-ID', Null).body
        try:
            self.received_call_ids.remove(call_id)
        except KeyError:
            self.received_call_ids.add(call_id)
        else:
            # drop duplicate message received
            return

        is_cpim = False
        cpim_message = None
        is_replication_message = False

        if data.content_type == 'message/cpim':
            try:
                cpim_message = CPIMPayload.decode(data.body)
            except CPIMParserError:
                BlinkLogger().log_warning(
                    "Incoming SMS from %s to %s has invalid CPIM content" %
                    format_identity_to_string(data.from_header), account.id)
                return
            else:
                is_cpim = True
                content = cpim_message.content
                content_type = cpim_message.content_type
                sender_identity = cpim_message.sender or data.from_header
                if cpim_message.sender and data.from_header.uri == data.to_header.uri and data.from_header.uri == cpim_message.sender.uri:
                    is_replication_message = True
                    window_tab_identity = cpim_message.recipients[
                        0] if cpim_message.recipients else data.to_header
                else:
                    window_tab_identity = data.from_header
        else:
            content = data.body.decode('utf-8')
            content_type = data.content_type
            sender_identity = data.from_header
            window_tab_identity = sender_identity

        is_html = content_type == 'text/html'

        if content_type in ('text/plain', 'text/html'):
            pass
            #BlinkLogger().log_info(u"Incoming SMS %s from %s to %s received" % (call_id, format_identity_to_string(sender_identity), account.id))
        elif content_type == 'application/im-iscomposing+xml':
            # body must not be utf-8 decoded
            content = cpim_message.content if is_cpim else data.body
            msg = IsComposingMessage.parse(content)
            state = msg.state.value
            refresh = msg.refresh.value if msg.refresh is not None else None
            content_type = msg.content_type.value if msg.content_type is not None else None
            last_active = msg.last_active.value if msg.last_active is not None else None

            viewer = self.openMessageWindow(SIPURI.new(
                window_tab_identity.uri),
                                            window_tab_identity.display_name,
                                            account,
                                            create_if_needed=False,
                                            note_new_message=False)
            if viewer:
                viewer.gotIsComposing(self.windowForViewer(viewer), state,
                                      refresh, last_active)
            return
        else:
            BlinkLogger().log_warning(
                "Incoming SMS %s from %s to %s has unknown content-type %s" %
                (call_id, format_identity_to_string(
                    data.from_header), account.id, data.content_type))
            return

        # display the message
        note_new_message = False if is_replication_message else True
        viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri),
                                        window_tab_identity.display_name,
                                        account,
                                        note_new_message=note_new_message)
        self.windowForViewer(viewer).noteNewMessageForSession_(viewer)
        replication_state = None
        replication_timestamp = None

        if is_replication_message:
            replicated_response_code = data.headers.get(
                'X-Replication-Code', Null).body
            if replicated_response_code == '202':
                replication_state = 'deferred'
            elif replicated_response_code == '200':
                replication_state = 'delivered'
            else:
                replication_state = 'failed'
            replicated_timestamp = data.headers.get('X-Replication-Timestamp',
                                                    Null).body
            try:
                replication_timestamp = ISOTimestamp(replicated_timestamp)
            except Exception:
                replication_timestamp = ISOTimestamp.now()

        window = self.windowForViewer(viewer).window()
        viewer.gotMessage(sender_identity,
                          call_id,
                          content,
                          is_html,
                          is_replication_message,
                          replication_timestamp,
                          window=window)
        self.windowForViewer(viewer).noteView_isComposing_(viewer, False)
Exemplo n.º 8
0
    def _NH_SIPEngineGotMessage(self, sender, data):
        account = AccountManager().find_account(data.request_uri)
        if not account:
            BlinkLogger().log_warning(u"Could not find recipient account for message to %s, using default" % data.request_uri)
            account = AccountManager().default_account

        is_cpim = False
        cpim_message = None
        replication_message = False

        if data.content_type == 'message/cpim':
            try:
                cpim_message = CPIMMessage.parse(data.body)
            except CPIMParserError:
                BlinkLogger().log_warning(u"SMS from %s has invalid CPIM content" % format_identity_to_string(data.from_header))
                return
            else:
                is_cpim = True
                body = cpim_message.body
                content_type = cpim_message.content_type
                sender_identity = cpim_message.sender or data.from_header
                if cpim_message.sender and data.from_header.uri == data.to_header.uri and data.from_header.uri == cpim_message.sender.uri:
                    replication_message = True
                    window_tab_identity = cpim_message.recipients[0] if cpim_message.recipients else data.to_header
                else:
                    window_tab_identity = data.from_header
        else:
            body = data.body.decode('utf-8')
            content_type = data.content_type
            sender_identity = data.from_header
            window_tab_identity = sender_identity

        is_html = content_type == 'text/html'

        if content_type in ('text/plain', 'text/html'):
            BlinkLogger().log_info(u"Got SMS from %s" % format_identity_to_string(sender_identity))
        elif content_type == 'application/im-iscomposing+xml':
            # body must not be utf-8 decoded
            body = cpim_message.body if is_cpim else data.body
            msg = IsComposingMessage.parse(body)
            state = msg.state.value
            refresh = msg.refresh.value if msg.refresh is not None else None
            content_type = msg.content_type.value if msg.content_type is not None else None
            last_active = msg.last_active.value if msg.last_active is not None else None

            viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, create_if_needed=False, note_new_message=False)
            if viewer:
                viewer.gotIsComposing(self.windowForViewer(viewer), state, refresh, last_active)
            return
        else:
            BlinkLogger().log_warning(u"SMS from %s has unknown content-type %s" % (format_identity_to_string(data.from_header), data.content_type))
            return

        # display the message
        note_new_message = False if replication_message else True
        viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, note_new_message=note_new_message)
        self.windowForViewer(viewer).noteNewMessageForSession_(viewer)
        replication_state = None
        replication_timestamp = None

        if replication_message:
            replicated_response_code = data.headers.get('X-Replication-Code', Null).body
            if replicated_response_code == '202':
                replication_state = 'deferred'
            elif replicated_response_code == '200':
                replication_state = 'delivered'
            else:
                replication_state = 'failed'
            replicated_timestamp = data.headers.get('X-Replication-Timestamp', Null).body
            try:
                replication_timestamp = Timestamp.parse(replicated_timestamp)
            except (TypeError, ValueError):
                replication_timestamp = Timestamp(datetime.datetime.now(tzlocal()))

        viewer.gotMessage(sender_identity, body, is_html, replication_state, replication_timestamp)
        self.windowForViewer(viewer).noteView_isComposing_(viewer, False)

        if replication_message:
            return

        if not self.windowForViewer(viewer).window().isKeyWindow():
            # notify growl
            growl_data = TimestampedNotificationData()
            if is_html:
                growl_data.content = html2txt(body)
            else:
                growl_data.content = body
            growl_data.sender = format_identity_to_string(sender_identity, format='compact')
            self.notification_center.post_notification("GrowlGotSMS", sender=self, data=growl_data)
Exemplo n.º 9
0
    def _NH_SIPEngineGotMessage(self, notification):
        account_manager = AccountManager()
        account = account_manager.find_account(notification.data.request_uri)

        if account is None:
            return

        data = notification.data
        content_type = data.headers.get('Content-Type', Null).content_type
        from_header = data.headers.get('From', Null)
        x_replicated_message = data.headers.get('X-Replicated-Message', Null)
        to_header = data.headers.get('To', Null)

        if x_replicated_message is Null:
            cpim_message = None
            if content_type == "message/cpim":
                try:
                    cpim_message = CPIMPayload.decode(data.body)
                except CPIMParserError:
                    log.warning(
                        'SIP message from %s to %s rejected: CPIM parse error'
                        % (from_header.uri, '%s@%s' %
                           (to_header.uri.user, to_header.uri.host)))
                    return
                body = cpim_message.content if isinstance(
                    cpim_message.content,
                    str) else cpim_message.content.decode()
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                disposition = next(
                    ([item.strip() for item in header.value.split(',')]
                     for header in cpim_message.additional_headers
                     if header.name == 'Disposition-Notification'), None)
                message_id = next(
                    (header.value for header in cpim_message.additional_headers
                     if header.name == 'Message-ID'), str(uuid.uuid4()))
            else:
                payload = SimplePayload.decode(data.body, data.content_type)
                body = payload.content.decode()
                content_type = payload.content_type
                sender = from_header
                disposition = None
                message_id = str(uuid.uuid4())

            if (content_type.lower().startswith('text/')
                    and '-----BEGIN PGP MESSAGE-----' in body
                    and body.strip().endswith('-----END PGP MESSAGE-----')
                    and content_type != 'text/pgp-private-key'):
                return

            if content_type.lower() == 'text/pgp-public-key':
                return

            from blink.contacts import URIUtils
            contact, contact_uri = URIUtils.find_contact(sender.uri)
            session_manager = SessionManager()

            notification_center = NotificationCenter()
            try:
                blink_session = next(
                    session for session in self.sessions if session.reusable
                    and session.contact.settings is contact.settings)
            except StopIteration:
                if content_type.lower() in [
                        IsComposingDocument.content_type,
                        IMDNDocument.content_type
                ]:
                    return
                else:
                    blink_session = session_manager.create_session(
                        contact,
                        contact_uri, [StreamDescription('messages')],
                        account=account,
                        connect=False)

            if content_type.lower() == IsComposingDocument.content_type:
                try:
                    document = IsComposingMessage.parse(body)
                except ParserError as e:
                    log.warning('Failed to parse Is-Composing payload: %s' %
                                str(e))
                else:
                    data = NotificationData(
                        state=document.state.value,
                        refresh=document.refresh.value
                        if document.refresh is not None else 120,
                        content_type=document.content_type.value
                        if document.content_type is not None else None,
                        last_active=document.last_active.value
                        if document.last_active is not None else None,
                        sender=sender)
                    notification_center.post_notification(
                        'BlinkGotComposingIndication',
                        sender=blink_session,
                        data=data)
                return

            timestamp = str(
                cpim_message.timestamp
            ) if cpim_message is not None and cpim_message.timestamp is not None else str(
                ISOTimestamp.now())

            if account.sms.use_cpim and account.sms.enable_imdn and content_type.lower(
            ) == IMDNDocument.content_type:
                # print("-- IMDN received")
                document = IMDNDocument.parse(body)
                imdn_message_id = document.message_id.value
                imdn_status = document.notification.status.__str__()
                imdn_datetime = document.datetime.__str__()
                notification_center.post_notification(
                    'BlinkGotDispositionNotification',
                    sender=blink_session,
                    data=NotificationData(id=imdn_message_id,
                                          status=imdn_status))
                return

            message = BlinkMessage(body,
                                   content_type,
                                   sender,
                                   timestamp=timestamp,
                                   id=message_id,
                                   disposition=disposition)
            notification_center.post_notification('BlinkMessageIsParsed',
                                                  sender=blink_session,
                                                  data=message)

            if disposition is not None and 'positive-delivery' in disposition:
                # print("-- Should send delivered imdn")
                self.send_imdn_message(blink_session, message_id, timestamp,
                                       'delivered')

            self._add_contact_to_messages_group(blink_session)
            notification_center.post_notification('BlinkGotMessage',
                                                  sender=blink_session,
                                                  data=message)
        else:
            # TODO handle replicated messages
            pass
Exemplo n.º 10
0
    def _NH_SIPEngineGotMessage(self, sender, data):
        account = AccountManager().find_account(data.request_uri)
        if not account:
            BlinkLogger().log_warning(
                "Could not find local account for incoming SMS to %s, using default"
                % data.request_uri)
            account = AccountManager().default_account

        call_id = data.headers.get('Call-ID', Null).body

        try:
            self.received_call_ids.remove(call_id)
        except KeyError:
            self.received_call_ids.add(call_id)
        else:
            # drop duplicate message received
            return

        is_cpim = False
        cpim_message = None
        is_replication_message = False
        imdn_id = None
        imdn_timestamp = None

        if data.content_type == 'message/cpim':
            try:
                cpim_message = CPIMPayload.decode(data.body)
            except CPIMParserError:
                BlinkLogger().log_warning(
                    "Incoming SMS from %s to %s has invalid CPIM content" %
                    format_identity_to_string(data.from_header), account.id)
                return
            else:
                is_cpim = True
                content = cpim_message.content
                content_type = cpim_message.content_type
                sender_identity = cpim_message.sender or data.from_header
                cpim_imdn_events = None
                imdn_timestamp = cpim_message.timestamp
                for h in cpim_message.additional_headers:
                    if h.name == "Message-ID":
                        imdn_id = h.value
                    if h.name == "Disposition-Notification":
                        cpim_imdn_events = h.value

                if imdn_id:
                    if cpim_imdn_events and 'positive-delivery' in cpim_imdn_events and imdn_timestamp:
                        BlinkLogger().log_info(
                            "Will send IMDN delivery notification for %s" %
                            imdn_id)
                    else:
                        imdn_id = None

                if cpim_message.sender and data.from_header.uri == data.to_header.uri and data.from_header.uri == cpim_message.sender.uri:
                    is_replication_message = True
                    window_tab_identity = cpim_message.recipients[
                        0] if cpim_message.recipients else data.to_header
                else:
                    window_tab_identity = data.from_header
        else:
            content = data.body
            content_type = data.content_type
            sender_identity = data.from_header
            window_tab_identity = sender_identity

        if content_type in ('text/plain', 'text/html'):
            BlinkLogger().log_info(
                u"Incoming SMS %s from %s to %s received" %
                (call_id, format_identity_to_string(sender_identity),
                 account.id))
        elif content_type in ('text/rsa-public-key'):
            uri = format_identity_to_string(sender_identity)
            BlinkLogger().log_info(
                u"Public key from %s received" %
                (format_identity_to_string(sender_identity)))

            if uri == account.id:
                BlinkLogger().log_info(
                    u"Public key save skipped for own account")
                return

            public_key = ''
            start_public = False

            for l in content.decode().split("\n"):
                if l == "-----BEGIN RSA PUBLIC KEY-----":
                    start_public = True

                if l == "-----END RSA PUBLIC KEY-----":
                    public_key = public_key + l
                    start_public = False
                    break

                if start_public:
                    public_key = public_key + l + '\n'

            if public_key:
                blink_contact = NSApp.delegate(
                ).contactsWindowController.getFirstContactFromAllContactsGroupMatchingURI(
                    uri)

                if blink_contact is not None:
                    contact = blink_contact.contact
                    if contact.public_key != public_key:
                        contact.public_key = public_key
                        contact.public_key_checksum = hashlib.sha1(
                            public_key.encode()).hexdigest()
                        contact.save()
                        BlinkLogger().log_info(
                            u"Public key %s from %s saved " %
                            (contact.public_key_checksum,
                             data.from_header.uri))
                        nc_title = NSLocalizedString(
                            "Public key", "System notification title")
                        nc_subtitle = format_identity_to_string(
                            sender_identity, check_contact=True, format='full')
                        nc_body = NSLocalizedString(
                            "Public key has changed",
                            "System notification title")
                        NSApp.delegate().gui_notify(nc_title, nc_body,
                                                    nc_subtitle)

                    else:
                        BlinkLogger().log_info(
                            u"Public key from %s has not changed" %
                            data.from_header.uri)
                else:
                    BlinkLogger().log_info(u"No contact found to save the key")

            return
        elif content_type in ('text/rsa-private-key'):
            BlinkLogger().log_info(u"Private key from %s to %s received" %
                                   (data.from_header.uri, account.id))

            if account.id == str(data.from_header.uri).split(":")[1]:
                self.import_key_window = ImportPrivateKeyController(
                    account, content)
                self.import_key_window.show()
            return
        elif content_type in ('message/imdn+xml'):
            document = IMDNDocument.parse(content)
            imdn_message_id = document.message_id.value
            imdn_status = document.notification.status.__str__()
            BlinkLogger().log_info(u"Received IMDN message %s" % imdn_status)
            viewer = self.openMessageWindow(
                SIPURI.new(window_tab_identity.uri),
                window_tab_identity.display_name, account)
            if viewer and imdn_status == 'displayed':
                viewer.chatViewController.markMessage(imdn_message_id,
                                                      MSG_STATE_DISPLAYED)
            return
        elif content_type == 'application/im-iscomposing+xml':
            content = cpim_message.content if is_cpim else data.body
            msg = IsComposingMessage.parse(content)
            state = msg.state.value
            refresh = msg.refresh.value if msg.refresh is not None else None
            content_type = msg.content_type.value if msg.content_type is not None else None
            last_active = msg.last_active.value if msg.last_active is not None else None

            viewer = self.openMessageWindow(SIPURI.new(
                window_tab_identity.uri),
                                            window_tab_identity.display_name,
                                            account,
                                            create_if_needed=False,
                                            note_new_message=False)
            if viewer:
                viewer.gotIsComposing(self.windowForViewer(viewer), state,
                                      refresh, last_active)
            return
        else:
            BlinkLogger().log_warning(
                "Incoming SMS %s from %s to %s has unknown content-type %s" %
                (call_id, format_identity_to_string(
                    data.from_header), account.id, content_type))
            return

        # display the message
        note_new_message = False if is_replication_message else True
        viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri),
                                        window_tab_identity.display_name,
                                        account,
                                        note_new_message=note_new_message)
        self.windowForViewer(viewer).noteNewMessageForSession_(viewer)
        replication_state = None
        replication_timestamp = None

        if is_replication_message:
            replicated_response_code = data.headers.get(
                'X-Replication-Code', Null).body
            if replicated_response_code == '202':
                replication_state = 'deferred'
            elif replicated_response_code == '200':
                replication_state = 'delivered'
            else:
                replication_state = 'failed'
            replicated_timestamp = data.headers.get('X-Replication-Timestamp',
                                                    Null).body
            try:
                replication_timestamp = ISOTimestamp(replicated_timestamp)
            except Exception:
                replication_timestamp = ISOTimestamp.now()

        window = self.windowForViewer(viewer).window()
        viewer.gotMessage(sender_identity,
                          call_id,
                          content,
                          content_type,
                          is_replication_message,
                          replication_timestamp,
                          window=window,
                          imdn_id=imdn_id,
                          imdn_timestamp=imdn_timestamp)

        self.windowForViewer(viewer).noteView_isComposing_(viewer, False)
Exemplo n.º 11
0
    def _NH_SIPEngineGotMessage(self, sender, data):
        account = AccountManager().find_account(data.request_uri)
        if not account:
            BlinkLogger().log_warning(u"Could not find local account for incoming SMS to %s, using default" % data.request_uri)
            account = AccountManager().default_account

        call_id = data.headers.get('Call-ID', Null).body
        try:
            self.received_call_ids.remove(call_id)
        except KeyError:
            self.received_call_ids.add(call_id)
        else:
            # drop duplicate message received
            return

        is_cpim = False
        cpim_message = None
        is_replication_message = False

        if data.content_type == 'message/cpim':
            try:
                cpim_message = CPIMMessage.parse(data.body)
            except CPIMParserError:
                BlinkLogger().log_warning(u"Incoming SMS from %s to %s has invalid CPIM content" % format_identity_to_string(data.from_header), account.id)
                return
            else:
                is_cpim = True
                body = cpim_message.body
                content_type = cpim_message.content_type
                sender_identity = cpim_message.sender or data.from_header
                if cpim_message.sender and data.from_header.uri == data.to_header.uri and data.from_header.uri == cpim_message.sender.uri:
                    is_replication_message = True
                    window_tab_identity = cpim_message.recipients[0] if cpim_message.recipients else data.to_header
                else:
                    window_tab_identity = data.from_header
        else:
            body = data.body.decode('utf-8')
            content_type = data.content_type
            sender_identity = data.from_header
            window_tab_identity = sender_identity

        is_html = content_type == 'text/html'

        if content_type in ('text/plain', 'text/html'):
            pass
            #BlinkLogger().log_info(u"Incoming SMS %s from %s to %s received" % (call_id, format_identity_to_string(sender_identity), account.id))
        elif content_type == 'application/im-iscomposing+xml':
            # body must not be utf-8 decoded
            body = cpim_message.body if is_cpim else data.body
            msg = IsComposingMessage.parse(body)
            state = msg.state.value
            refresh = msg.refresh.value if msg.refresh is not None else None
            content_type = msg.content_type.value if msg.content_type is not None else None
            last_active = msg.last_active.value if msg.last_active is not None else None

            viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, create_if_needed=False, note_new_message=False)
            if viewer:
                viewer.gotIsComposing(self.windowForViewer(viewer), state, refresh, last_active)
            return
        else:
            BlinkLogger().log_warning(u"Incoming SMS %s from %s to %s has unknown content-type %s" % (call_id, format_identity_to_string(data.from_header), account.id, data.content_type))
            return

        # display the message
        note_new_message = False if is_replication_message else True
        viewer = self.openMessageWindow(SIPURI.new(window_tab_identity.uri), window_tab_identity.display_name, account, note_new_message=note_new_message)
        self.windowForViewer(viewer).noteNewMessageForSession_(viewer)
        replication_state = None
        replication_timestamp = None

        if is_replication_message:
            replicated_response_code = data.headers.get('X-Replication-Code', Null).body
            if replicated_response_code == '202':
                replication_state = 'deferred'
            elif replicated_response_code == '200':
                replication_state = 'delivered'
            else:
                replication_state = 'failed'
            replicated_timestamp = data.headers.get('X-Replication-Timestamp', Null).body
            try:
                replication_timestamp = ISOTimestamp(replicated_timestamp)
            except Exception:
                replication_timestamp = ISOTimestamp.now()

        window = self.windowForViewer(viewer).window()
        viewer.gotMessage(sender_identity, call_id, body, is_html, is_replication_message, replication_timestamp, window=window)
        self.windowForViewer(viewer).noteView_isComposing_(viewer, False)