示例#1
0
    def _NH_IncomingFileTransferHandlerDidEnd(self, notification):
        notification.center.remove_observer(self, sender=self)

        remote_hash = self.file_selector.hash
        if not self.transfer_finished:
            log.msg('File transfer of %s cancelled' % os.path.basename(self.filename))
            self.remove_bogus_file(self.filename)
            self.status = 'INCOMPLETE'
        else:
            local_hash = 'sha1:' + ':'.join(re.findall(r'..', self.hash.hexdigest().upper()))
            if local_hash != remote_hash:
                log.warning('Hash of transferred file does not match the remote hash (file may have changed).')
                self.status = 'HASH_MISSMATCH'
                self.remove_bogus_file(self.filename)
            else:
                self.status = 'OK'

        self_uri = SIPURI.new(self.session.local_identity.uri)
        self_uri.parameters.clear()
        sender_uri = SIPURI.new(self.session.remote_identity.uri)
        sender_uri.parameters.clear()

        self.session = None
        self.stream = None

        file = File(self.filename, remote_hash, self.file_selector.size)
        notification.center.post_notification('IncomingFileTransferHandlerGotFile', sender=self, data=NotificationData(local_uri=self_uri, remote_uri=sender_uri, file=file))
示例#2
0
 def __init__(self, account, target_uri, filename, hash):
     self.account = account
     self._file_selector = FileSelector(name=os.path.basename(filename),
                                        hash=hash)
     self.remote_identity = format_identity_to_string(target_uri)
     self.target_uri = SIPURI.new(target_uri)
     self._ended = False
示例#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.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)
示例#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.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)
示例#5
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)
示例#6
0
 def incoming_sip_message(self, message_request, data):
     # Handle incoming MESSAGE
     from_header = data.headers.get('From', Null)
     to_header = data.headers.get('To', Null)
     content_type = data.headers.get('Content-Type', Null)[0]
     if from_header is Null or to_header is Null:
         message_request.answer(400)
         return
     message_request.answer(200)
     if content_type not in ('text/plain', 'text/html'):
         return
     source_uri = SIPURI.new(to_header.uri)
     destination_uri = SIPURI.new(from_header.uri)
     try:
         fact = self.facts.next()
     except StopIteration:
         return
     else:
         self.send_chuck_norris_fact(source_uri, destination_uri, fact)
 def incoming_sip_message(self, message_request, data):
     # Handle incoming MESSAGE
     from_header = data.headers.get('From', Null)
     to_header = data.headers.get('To', Null)
     content_type = data.headers.get('Content-Type', Null)[0]
     if from_header is Null or to_header is Null:
         message_request.answer(400)
         return
     message_request.answer(200)
     if content_type not in ('text/plain', 'text/html'):
         return
     source_uri = SIPURI.new(to_header.uri)
     destination_uri = SIPURI.new(from_header.uri)
     try:
         fact = self.facts.next()
     except StopIteration:
         return
     else:
         self.send_chuck_norris_fact(source_uri, destination_uri, fact)
示例#8
0
 def _NH_DNSLookupDidSucceed(self, notification):
     notification_center = NotificationCenter()
     notification_center.remove_observer(self, sender=notification.sender)
     account = DefaultAccount()
     conference_application = ConferenceApplication()
     try:
         room = conference_application.get_room(self.room_uri)
     except RoomNotFoundError:
         log.info('Room %s - failed to add %s' %
                  (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     active_media = set(room.active_media).intersection(('audio', 'chat'))
     if not active_media:
         log.info('Room %s - failed to add %s' %
                  (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     for stream_type in active_media:
         self.streams.append(MediaStreamRegistry.get(stream_type)())
     self.session = Session(account)
     notification_center.add_observer(self, sender=self.session)
     original_from_header = self._refer_headers.get('From')
     if original_from_header.display_name:
         original_identity = "%s <%s@%s>" % (
             original_from_header.display_name,
             original_from_header.uri.user, original_from_header.uri.host)
     else:
         original_identity = "%s@%s" % (original_from_header.uri.user,
                                        original_from_header.uri.host)
     from_header = FromHeader(SIPURI.new(self.room_uri), u'Conference Call')
     to_header = ToHeader(self.refer_to_uri)
     extra_headers = []
     if self._refer_headers.get('Referred-By', None) is not None:
         extra_headers.append(
             Header.new(self._refer_headers.get('Referred-By')))
     else:
         extra_headers.append(
             Header('Referred-By', str(original_from_header.uri)))
     if ThorNodeConfig.enabled:
         extra_headers.append(Header('Thor-Scope', 'conference-invitation'))
     extra_headers.append(
         Header('X-Originator-From', str(original_from_header.uri)))
     extra_headers.append(
         SubjectHeader(u'Join conference request from %s' %
                       original_identity))
     route = notification.data.result[0]
     self.session.connect(from_header,
                          to_header,
                          route=route,
                          streams=self.streams,
                          is_focus=True,
                          extra_headers=extra_headers)
示例#9
0
    def _NH_IncomingFileTransferHandlerDidEnd(self, notification):
        notification.center.remove_observer(self, sender=self)

        remote_hash = self.file_selector.hash
        if not self.transfer_finished:
            log.msg('File transfer of %s cancelled' %
                    os.path.basename(self.filename))
            self.remove_bogus_file(self.filename)
            self.status = 'INCOMPLETE'
        else:
            local_hash = 'sha1:' + ':'.join(
                re.findall(r'..',
                           self.hash.hexdigest().upper()))
            if local_hash != remote_hash:
                log.warning(
                    'Hash of transferred file does not match the remote hash (file may have changed).'
                )
                self.status = 'HASH_MISSMATCH'
                self.remove_bogus_file(self.filename)
            else:
                self.status = 'OK'

        self_uri = SIPURI.new(self.session.local_identity.uri)
        self_uri.parameters.clear()
        sender_uri = SIPURI.new(self.session.remote_identity.uri)
        sender_uri.parameters.clear()

        self.session = None
        self.stream = None

        file = File(self.filename, remote_hash, self.file_selector.size)
        notification.center.post_notification(
            'IncomingFileTransferHandlerGotFile',
            sender=self,
            data=NotificationData(local_uri=self_uri,
                                  remote_uri=sender_uri,
                                  file=file))
示例#10
0
 def __init__(self, account, target_uri, filename, hash):
     self.account = account
     self.end_session_when_done = True
     self.error = False
     self.file_selector = FileSelector(name=filename, hash=hash)
     self.finished_transfer = False
     self.hash = hashlib.sha1()
     self.interrupted = False
     self.remote_identity = format_identity_to_string(target_uri)
     self.session = None
     self.session_ended = False
     self.started = False
     self.stream = None
     self.target_uri = SIPURI.new(target_uri)
     self.timer = None
     self.transfer_id = str(uuid.uuid1())
示例#11
0
 def __init__(self, account, target_uri, filename, hash):
     self.account = account
     self.end_session_when_done = True
     self.error = False
     self.file_selector = FileSelector(name=filename, hash=hash)
     self.finished_transfer = False
     self.hash = hashlib.sha1()
     self.interrupted = False
     self.remote_identity = format_identity_to_string(target_uri)
     self.session = None
     self.session_ended = False
     self.started = False
     self.stream = None
     self.target_uri = SIPURI.new(target_uri)
     self.timer = None
     self.transfer_id = str(uuid.uuid1())
示例#12
0
 def _NH_DNSLookupDidSucceed(self, notification):
     notification_center = NotificationCenter()
     notification_center.remove_observer(self, sender=notification.sender)
     account = DefaultAccount()
     conference_application = ConferenceApplication()
     try:
         room = conference_application.get_room(self.room_uri)
     except RoomNotFoundError:
         log.msg("Room %s - failed to add %s" % (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     active_media = set(room.active_media).intersection(("audio", "chat"))
     if not active_media:
         log.msg("Room %s - failed to add %s" % (self.room_uri_str, self.refer_to_uri))
         self._refer_request.end(500)
         return
     registry = MediaStreamRegistry()
     for stream_type in active_media:
         self.streams.append(registry.get(stream_type)())
     self.session = Session(account)
     notification_center.add_observer(self, sender=self.session)
     original_from_header = self._refer_headers.get("From")
     if original_from_header.display_name:
         original_identity = "%s <%s@%s>" % (
             original_from_header.display_name,
             original_from_header.uri.user,
             original_from_header.uri.host,
         )
     else:
         original_identity = "%s@%s" % (original_from_header.uri.user, original_from_header.uri.host)
     from_header = FromHeader(SIPURI.new(self.room_uri), u"Conference Call")
     to_header = ToHeader(self.refer_to_uri)
     extra_headers = []
     if self._refer_headers.get("Referred-By", None) is not None:
         extra_headers.append(Header.new(self._refer_headers.get("Referred-By")))
     else:
         extra_headers.append(Header("Referred-By", str(original_from_header.uri)))
     if ThorNodeConfig.enabled:
         extra_headers.append(Header("Thor-Scope", "conference-invitation"))
     extra_headers.append(Header("X-Originator-From", str(original_from_header.uri)))
     extra_headers.append(SubjectHeader(u"Join conference request from %s" % original_identity))
     route = notification.data.result[0]
     self.session.connect(
         from_header, to_header, route=route, streams=self.streams, is_focus=True, extra_headers=extra_headers
     )
示例#13
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)
示例#14
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)
示例#15
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)
示例#16
0
    def _run(self):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        sender_uri = self.sender.uri.as_sip_uri()
        recipient_uri = self.recipient.uri.as_sip_uri()
        participant_uri = self.participant.uri.as_sip_uri()

        try:
            # Lookup routes
            account = DefaultAccount()
            if account.sip.outbound_proxy is not None and account.sip.outbound_proxy.transport in settings.sip.transport_list:
                uri = SIPURI(host=account.sip.outbound_proxy.host,
                             port=account.sip.outbound_proxy.port,
                             parameters={
                                 'transport':
                                 account.sip.outbound_proxy.transport
                             })
            elif account.sip.always_use_my_proxy:
                uri = SIPURI(host=account.id.domain)
            else:
                uri = SIPURI.new(recipient_uri)
            lookup = DNSLookup()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError as e:
                raise ReferralError(error='DNS lookup failed: %s' % e)

            timeout = time() + 30
            for route in routes:
                self.route = route
                remaining_time = timeout - time()
                if remaining_time > 0:
                    transport = route.transport
                    parameters = {} if transport == 'udp' else {
                        'transport': transport
                    }
                    contact_uri = SIPURI(user=account.contact.username,
                                         host=SIPConfig.local_ip.normalized,
                                         port=getattr(Engine(),
                                                      '%s_port' % transport),
                                         parameters=parameters)
                    refer_to_header = ReferToHeader(str(participant_uri))
                    refer_to_header.parameters['method'] = 'INVITE'
                    referral = Referral(recipient_uri, FromHeader(sender_uri),
                                        ToHeader(recipient_uri),
                                        refer_to_header,
                                        ContactHeader(contact_uri),
                                        RouteHeader(route.uri),
                                        account.credentials)
                    notification_center.add_observer(self, sender=referral)
                    try:
                        referral.send_refer(
                            timeout=limit(remaining_time, min=1, max=5))
                    except SIPCoreError:
                        notification_center.remove_observer(self,
                                                            sender=referral)
                        timeout = 5
                        raise ReferralError(error='Internal error')
                    self._referral = referral
                    try:
                        while True:
                            notification = self._channel.wait()
                            if notification.name == 'SIPReferralDidStart':
                                break
                    except SIPReferralDidFail as e:
                        notification_center.remove_observer(self,
                                                            sender=referral)
                        self._referral = None
                        if e.data.code in (403, 405):
                            raise ReferralError(
                                error=sip_status_messages[e.data.code],
                                code=e.data.code)
                        else:
                            # Otherwise just try the next route
                            continue
                    else:
                        break
            else:
                self.route = None
                raise ReferralError(error='No more routes to try')
            # At this point it is subscribed. Handle notifications and ending/failures.
            try:
                self.active = True
                while True:
                    notification = self._channel.wait()
                    if notification.name == 'SIPReferralDidEnd':
                        break
            except SIPReferralDidFail as e:
                notification_center.remove_observer(self,
                                                    sender=self._referral)
                raise ReferralError(error=e.data.reason, code=e.data.code)
            else:
                notification_center.remove_observer(self,
                                                    sender=self._referral)
            finally:
                self.active = False
        except ReferralError as e:
            self._failure = MucInvitationFailure(e.code, e.error)
        finally:
            notification_center.remove_observer(
                self, name='NetworkConditionsDidChange')
            self._referral = None
            if self._failure is not None:
                notification_center.post_notification(
                    'X2SMucInvitationHandlerDidFail',
                    sender=self,
                    data=NotificationData(failure=self._failure))
            else:
                notification_center.post_notification(
                    'X2SMucInvitationHandlerDidEnd', sender=self)
示例#17
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)