示例#1
0
    def _message_queue_handler(self):
        notification_center = NotificationCenter()
        try:
            while True:
                message = self.message_queue.wait()
                if self.msrp_session is None:
                    if message.notify_progress:
                        data = NotificationData(message_id=message.id, message=None, code=0, reason='Stream ended')
                        notification_center.post_notification('ChatStreamDidNotDeliverMessage', sender=self, data=data)
                    break

                try:
                    if isinstance(message.content, unicode):
                        message.content = message.content.encode('utf8')
                        charset = 'utf8'
                    else:
                        charset = None

                    if not isinstance(message, QueuedOTRInternalMessage):
                        try:
                            message.content = self.encryption.otr_session.handle_output(message.content, message.content_type)
                        except OTRError, e:
                            raise ChatStreamError(str(e))

                    message.sender = message.sender or self.local_identity
                    message.recipients = message.recipients or [self.remote_identity]

                    # check if we MUST use CPIM
                    need_cpim = (message.sender != self.local_identity or message.recipients != [self.remote_identity] or
                                 message.courtesy_recipients or message.subject or message.timestamp or message.required or message.additional_headers)

                    if need_cpim or not contains_mime_type(self.remote_accept_types, message.content_type):
                        if not contains_mime_type(self.remote_accept_wrapped_types, message.content_type):
                            raise ChatStreamError('Unsupported content_type for outgoing message: %r' % message.content_type)
                        if not self.cpim_enabled:
                            raise ChatStreamError('Additional message meta-data cannot be sent, because the CPIM wrapper is not used')
                        if not self.private_messages_allowed and message.recipients != [self.remote_identity]:
                            raise ChatStreamError('The remote end does not support private messages')
                        if message.timestamp is None:
                            message.timestamp = ISOTimestamp.now()
                        payload = CPIMPayload(charset=charset, **{name: getattr(message, name) for name in Message.__slots__})
                    elif self.prefer_cpim and self.cpim_enabled and contains_mime_type(self.remote_accept_wrapped_types, message.content_type):
                        if message.timestamp is None:
                            message.timestamp = ISOTimestamp.now()
                        payload = CPIMPayload(charset=charset, **{name: getattr(message, name) for name in Message.__slots__})
                    else:
                        payload = SimplePayload(message.content, message.content_type, charset)
                except ChatStreamError, e:
                    if message.notify_progress:
                        data = NotificationData(message_id=message.id, message=None, code=0, reason=e.args[0])
                        notification_center.post_notification('ChatStreamDidNotDeliverMessage', sender=self, data=data)
                    continue
示例#2
0
    def _message_queue_handler(self):
        notification_center = NotificationCenter()
        try:
            while True:
                message = self.message_queue.wait()
                if self.msrp_session is None:
                    if message.notify_progress:
                        data = NotificationData(message_id=message.id, message=None, code=0, reason='Stream ended')
                        notification_center.post_notification('ChatStreamDidNotDeliverMessage', sender=self, data=data)
                    break

                try:
                    if isinstance(message.content, unicode):
                        message.content = message.content.encode('utf8')
                        charset = 'utf8'
                    else:
                        charset = None

                    if not isinstance(message, QueuedOTRInternalMessage):
                        try:
                            message.content = self.encryption.otr_session.handle_output(message.content, message.content_type)
                        except OTRError, e:
                            raise ChatStreamError(str(e))

                    message.sender = message.sender or self.local_identity
                    message.recipients = message.recipients or [self.remote_identity]

                    # check if we MUST use CPIM
                    need_cpim = (message.sender != self.local_identity or message.recipients != [self.remote_identity] or
                                 message.courtesy_recipients or message.subject or message.timestamp or message.required or message.additional_headers)

                    if need_cpim or not contains_mime_type(self.remote_accept_types, message.content_type):
                        if not contains_mime_type(self.remote_accept_wrapped_types, message.content_type):
                            raise ChatStreamError('Unsupported content_type for outgoing message: %r' % message.content_type)
                        if not self.cpim_enabled:
                            raise ChatStreamError('Additional message meta-data cannot be sent, because the CPIM wrapper is not used')
                        if not self.private_messages_allowed and message.recipients != [self.remote_identity]:
                            raise ChatStreamError('The remote end does not support private messages')
                        if message.timestamp is None:
                            message.timestamp = ISOTimestamp.now()
                        payload = CPIMPayload(charset=charset, **{name: getattr(message, name) for name in Message.__slots__})
                    elif self.prefer_cpim and self.cpim_enabled and contains_mime_type(self.remote_accept_wrapped_types, message.content_type):
                        if message.timestamp is None:
                            message.timestamp = ISOTimestamp.now()
                        payload = CPIMPayload(charset=charset, **{name: getattr(message, name) for name in Message.__slots__})
                    else:
                        payload = SimplePayload(message.content, message.content_type, charset)
                except ChatStreamError, e:
                    if message.notify_progress:
                        data = NotificationData(message_id=message.id, message=None, code=0, reason=e.args[0])
                        notification_center.post_notification('ChatStreamDidNotDeliverMessage', sender=self, data=data)
                    continue
示例#3
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))
示例#4
0
 def __init__(self,
              content,
              content_type,
              charset=None,
              sender=None,
              recipients=None,
              courtesy_recipients=None,
              subject=None,
              timestamp=None,
              required=None,
              additional_headers=None):
     if not isinstance(content, bytes):
         raise TypeError("content should be an instance of bytes")
     self.content = content
     self.content_type = content_type
     self.charset = charset
     self.sender = sender
     self.recipients = recipients or []
     self.courtesy_recipients = courtesy_recipients or []
     self.subject = subject if isinstance(
         subject,
         (MultilingualText, type(None))) else MultilingualText(subject)
     self.timestamp = ISOTimestamp(
         timestamp) if timestamp is not None else None
     self.required = required or []
     self.additional_headers = additional_headers or []
示例#5
0
    def add_to_history(self):
        FileTransferHistory().add_transfer(
            transfer_id=self.ft_info.transfer_id,
            direction=self.ft_info.direction,
            local_uri=self.ft_info.local_uri,
            remote_uri=self.ft_info.remote_uri,
            file_path=self.ft_info.file_path,
            bytes_transfered=self.ft_info.bytes_transfered,
            file_size=self.ft_info.file_size or 0,
            status=self.ft_info.status)

        message = "<h3>%s File Transfer</h3>" % self.ft_info.direction.capitalize(
        )
        message += "<p>%s (%s)" % (self.ft_info.file_path,
                                   format_size(self.ft_info.file_size or 0))
        media_type = 'file-transfer'
        local_uri = self.ft_info.local_uri
        remote_uri = self.ft_info.remote_uri
        direction = self.ft_info.direction
        status = 'delivered' if self.ft_info.status == 'completed' else 'failed'
        cpim_from = self.ft_info.remote_uri
        cpim_to = self.ft_info.remote_uri
        timestamp = str(ISOTimestamp.now())

        ChatHistory().add_message(self.ft_info.transfer_id, media_type,
                                  local_uri, remote_uri, direction, cpim_from,
                                  cpim_to, timestamp, message, "html", "0",
                                  status)
示例#6
0
    def offline_state(self):
        if self.account is BonjourAccount():
            return None

        blink_settings = BlinkSettings()

        account_id = hashlib.md5(self.account.id).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add('offline')
        doc.add(person)

        service = pidf.Service('SID-%s' % account_id)
        service.status = 'closed'
        service.status.extended = 'offline'
        service.contact = str(self.account.uri)
        service.timestamp = timestamp
        service.capabilities = caps.ServiceCapabilities()
        service.display_name = self.account.display_name or None
        service.icon = "%s#blink-icon%s" % (self.account.xcap.icon.url, self.account.xcap.icon.etag) if self.account.xcap.icon is not None else None
        if blink_settings.presence.offline_note:
            service.notes.add(blink_settings.presence.offline_note)
        doc.add(service)

        return doc
    def showSystemMessage(self,
                          call_id,
                          content,
                          timestamp=None,
                          is_error=False):
        msgid = str(uuid.uuid1())
        rendered_message = ChatMessageObject(call_id, msgid, content, False,
                                             timestamp)
        self.rendered_messages.append(rendered_message)

        if timestamp is None:
            timestamp = ISOTimestamp.now()
        if isinstance(timestamp, datetime.datetime):
            if timestamp.date() != datetime.date.today():
                timestamp = time.strftime(
                    "%F %H:%M",
                    time.localtime(calendar.timegm(timestamp.utctimetuple())))
            else:
                timestamp = time.strftime(
                    "%H:%M",
                    time.localtime(calendar.timegm(timestamp.utctimetuple())))

        is_error = 1 if is_error else "null"
        script = """renderSystemMessage('%s', "%s", "%s", %s)""" % (
            msgid, processHTMLText(content), timestamp, is_error)

        if self.finishedLoading:
            self.executeJavaScript(script)
        else:
            self.messageQueue.append(script)
示例#8
0
    def offline_state(self):
        blink_settings = BlinkSettings()

        if self.account is BonjourAccount() or not blink_settings.presence.offline_note:
            return None

        account_id = hashlib.md5(self.account.id).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add('offline')
        doc.add(person)

        service = pidf.Service('SID-%s' % account_id)
        service.status = 'closed'
        service.status.extended = 'offline'
        service.contact = str(self.account.uri)
        service.timestamp = timestamp
        service.capabilities = caps.ServiceCapabilities()
        service.notes.add(blink_settings.presence.offline_note)
        doc.add(service)

        return doc
示例#9
0
    def gotIsComposing(self, window, state, refresh, last_active):
        self.enableIsComposing = True

        flag = state == "active"
        if flag:
            if refresh is None:
                refresh = 120

            if last_active is not None and (
                    last_active - ISOTimestamp.now() >
                    datetime.timedelta(seconds=refresh)):
                # message is old, discard it
                return

            if self.remoteTypingTimer:
                # if we don't get any indications in the request refresh, then we assume remote to be idle
                self.remoteTypingTimer.setFireDate_(
                    NSDate.dateWithTimeIntervalSinceNow_(refresh))
            else:
                self.remoteTypingTimer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(
                    refresh, self, "remoteBecameIdle:", window, False)
        else:
            if self.remoteTypingTimer:
                self.remoteTypingTimer.invalidate()
                self.remoteTypingTimer = None

        window.noteView_isComposing_(self, flag)
示例#10
0
    def offline_state(self):
        if self.account is BonjourAccount():
            return None

        blink_settings = BlinkSettings()

        account_id = hashlib.md5(self.account.id.encode()).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add('offline')
        doc.add(person)

        service = pidf.Service('SID-%s' % account_id)
        service.status = 'closed'
        service.status.extended = 'offline'
        service.contact = str(self.account.uri)
        service.timestamp = timestamp
        service.capabilities = caps.ServiceCapabilities()
        service.display_name = self.account.display_name or None
        service.icon = "%s#blink-icon%s" % (
            self.account.xcap.icon.url, self.account.xcap.icon.etag
        ) if self.account.xcap.icon is not None else None
        if blink_settings.presence.offline_note:
            service.notes.add(blink_settings.presence.offline_note)
        doc.add(service)

        return doc
示例#11
0
 def from_session(cls, session):
     if session.start_time is None and session.end_time is not None:
         # Session may have anded before it fully started
         session.start_time = session.end_time
     call_time = session.start_time or ISOTimestamp.now()
     if session.start_time and session.end_time:
         duration = session.end_time - session.start_time
     else:
         duration = None
     remote_uri = '%s@%s' % (session.remote_identity.uri.user,
                             session.remote_identity.uri.host)
     match = cls.phone_number_re.match(remote_uri)
     if match:
         remote_uri = match.group('number')
     try:
         contact = next(contact
                        for contact in AddressbookManager().get_contacts()
                        if remote_uri in (addr.uri
                                          for addr in contact.uris))
     except StopIteration:
         display_name = session.remote_identity.display_name
     else:
         display_name = contact.name
     return cls(session.direction, display_name, remote_uri,
                unicode(session.account.id), call_time, duration)
示例#12
0
    def sendReplicationMessage(self,
                               response_code,
                               content,
                               content_type="message/cpim",
                               timestamp=None):
        timestamp = timestamp or ISOTimestamp.now()
        # Lookup routes
        if self.account.sip.outbound_proxy is not None:
            uri = SIPURI(host=self.account.sip.outbound_proxy.host,
                         port=self.account.sip.outbound_proxy.port,
                         parameters={
                             'transport':
                             self.account.sip.outbound_proxy.transport
                         })
        else:
            uri = SIPURI(host=self.account.id.domain)

        route = None
        if self.last_route is None:
            lookup = DNSLookup()
            settings = SIPSimpleSettings()
            try:
                routes = lookup.lookup_sip_proxy(
                    uri, settings.sip.transport_list).wait()
            except DNSLookupError:
                pass
            else:
                route = routes[0]
        else:
            route = self.last_route

        if route:
            extra_headers = [
                Header("X-Offline-Storage", "no"),
                Header("X-Replication-Code", str(response_code)),
                Header("X-Replication-Timestamp", str(ISOTimestamp.now()))
            ]
            message_request = Message(FromHeader(self.account.uri,
                                                 self.account.display_name),
                                      ToHeader(self.account.uri),
                                      RouteHeader(route.uri),
                                      content_type,
                                      content,
                                      credentials=self.account.credentials,
                                      extra_headers=extra_headers)
            message_request.send(
                15 if content_type != "application/im-iscomposing+xml" else 5)
示例#13
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 ISOTimestamp.now()),
             content_type=ContentType('text')).toxml()
         self.sendMessage(content, IsComposingDocument.content_type)
示例#14
0
 def _janus_send_request(self, req):
     data = json.dumps(req.as_dict())
     if JanusConfig.trace_janus:
         self.factory.janus_logger.msg("OUT", ISOTimestamp.now(), data)
     self.sendMessage(data)
     d = defer.Deferred()
     self._janus_pending_transactions[req.transaction_id] = (req, d)
     return d
示例#15
0
 def _janus_send_request(self, req):
     data = json.dumps(req.as_dict())
     if JanusConfig.trace_janus:
         self.factory.janus_logger.msg("OUT", ISOTimestamp.now(), data)
     self.sendMessage(data)
     d = defer.Deferred()
     self._janus_pending_transactions[req.transaction_id] = (req, d)
     return d
示例#16
0
 def inject(self, msg, appdata=None):
     msg = unicode(msg)
     if appdata is not None:
         stream = appdata.get('stream', None)
         if stream is not None:
             try:
                 stream.send_message(msg, timestamp=ISOTimestamp.now())
             except ChatStreamError, e:
                 BlinkLogger().log_error(u"Error sending OTR chat message: %s" % e)
    def updateIdleTimer_(self, timer):
        must_publish = False
        hostname = socket.gethostname().split(".")[0]
        if hostname != self.hostname:
            must_publish = True
            self.hostname = hostname

        last_time_offset = int(pidf.TimeOffset())
        if last_time_offset != self.last_time_offset:
            must_publish = True
            self.last_time_offset = last_time_offset

        # secret sausage after taking the red pill = indigestion
        last_idle_counter = CGEventSourceSecondsSinceLastEventType(0, int(4294967295))
        self.previous_idle_counter = last_idle_counter
        if self.previous_idle_counter > last_idle_counter:
            self.last_input = ISOTimestamp.now()

        selected_item = self.owner.presenceActivityPopUp.selectedItem()
        if selected_item is None:
            return

        activity_object = selected_item.representedObject()
        if activity_object is None:
            return

        if activity_object['title'] not in ('Available', 'Away'):
            if must_publish:
                self.publish()
            return

        settings = SIPSimpleSettings()
        if last_idle_counter > settings.gui.idle_threshold:
            if not self.idle_mode:
                self.user_input = {'state': 'idle', 'last_input': self.last_input}
                if activity_object['title'] != "Away":
                    i = self.owner.presenceActivityPopUp.indexOfItemWithTitle_('Away')
                    self.owner.presenceActivityPopUp.selectItemAtIndex_(i)
                    self.presenceStateBeforeIdle = activity_object
                    self.presenceStateBeforeIdle['note'] = unicode(self.owner.presenceNoteText.stringValue())
                self.idle_mode = True
                must_publish = True
        else:
            if self.idle_mode:
                self.user_input = {'state': 'active', 'last_input': None}
                if activity_object['title'] == "Away":
                    if self.presenceStateBeforeIdle:
                        i = self.owner.presenceActivityPopUp.indexOfItemWithRepresentedObject_(self.presenceStateBeforeIdle)
                        self.owner.presenceActivityPopUp.selectItemAtIndex_(i)
                        self.owner.presenceNoteText.setStringValue_(self.presenceStateBeforeIdle['note'])
                        self.presenceStateBeforeIdle = None
                self.idle_mode = False
                must_publish = True

        if must_publish:
            self.publish()
示例#18
0
 def __init__(self, content, content_type, sender=None, recipients=None, courtesy_recipients=None, subject=None, timestamp=None, required=None, additional_headers=None):
     self.content = content
     self.content_type = content_type
     self.sender = sender
     self.recipients = recipients or []
     self.courtesy_recipients = courtesy_recipients or []
     self.subject = subject
     self.timestamp = ISOTimestamp(timestamp) if timestamp is not None else None
     self.required = required or []
     self.additional_headers = additional_headers or []
    def updateIdleTimer_(self, timer):
        must_publish = False
        hostname = socket.gethostname().split(".")[0]
        if hostname != self.hostname:
            must_publish = True
            self.hostname = hostname

        last_time_offset = int(pidf.TimeOffset())
        if last_time_offset != self.last_time_offset:
            must_publish = True
            self.last_time_offset = last_time_offset

        last_idle_counter = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGEventMouseMoved)
        self.previous_idle_counter = last_idle_counter
        if self.previous_idle_counter > last_idle_counter:
            self.last_input = ISOTimestamp.now()

        selected_item = self.owner.presenceActivityPopUp.selectedItem()
        if selected_item is None:
            return

        activity_object = selected_item.representedObject()
        if activity_object is None:
            return

        if activity_object['title'] not in ('Available', 'Away'):
            if must_publish:
                self.publish()
            return

        settings = SIPSimpleSettings()
        if last_idle_counter > settings.gui.idle_threshold:
            if not self.idle_mode:
                self.user_input = {'state': 'idle', 'last_input': self.last_input}
                if activity_object['title'] != "Away":
                    i = self.owner.presenceActivityPopUp.indexOfItemWithTitle_('Away')
                    self.owner.presenceActivityPopUp.selectItemAtIndex_(i)
                    self.presenceStateBeforeIdle = activity_object
                    self.presenceStateBeforeIdle['note'] = str(settings.presence_state.note)
                self.idle_mode = True
                must_publish = True
        else:
            if self.idle_mode:
                self.user_input = {'state': 'active', 'last_input': None}
                if activity_object['title'] == "Away":
                    if self.presenceStateBeforeIdle:
                        i = self.owner.presenceActivityPopUp.indexOfItemWithRepresentedObject_(self.presenceStateBeforeIdle)
                        self.owner.presenceActivityPopUp.selectItemAtIndex_(i)
                        self.owner.presenceNoteText.setStringValue_(self.presenceStateBeforeIdle['note'])
                        self.presenceStateBeforeIdle = None
                self.idle_mode = False
                must_publish = True

        if must_publish:
            self.publish()
示例#20
0
 def onMessage(self, payload, isBinary):
     if isBinary:
         log.warn('Unexpected binary payload received')
         return
     if JanusConfig.trace_janus:
         self.factory.janus_logger.msg("IN", ISOTimestamp.now(), payload)
     try:
         data = json.loads(payload)
     except Exception, e:
         log.warn('Error decoding payload: %s' % e)
         return
示例#21
0
 def onMessage(self, payload, isBinary):
     if isBinary:
         log.warn('Unexpected binary payload received')
         return
     if JanusConfig.trace_janus:
         self.factory.janus_logger.msg("IN", ISOTimestamp.now(), payload)
     try:
         data = json.loads(payload)
     except Exception, e:
         log.warn('Error decoding payload: %s' % e)
         return
示例#22
0
    def sendMessage(self, content, content_type="text/plain"):
        # entry point for sending messages, they will be added to self.message_queue
        if content_type != "application/im-iscomposing+xml":
            icon = NSApp.delegate().contactsWindowController.iconPathForSelf()

            if not isinstance(content, OTRInternalMessage):
                timestamp = ISOTimestamp.now()
                hash = hashlib.sha1()
                content = content.decode() if isinstance(content,
                                                         bytes) else content
                hash.update((content + str(timestamp)).encode("utf-8"))
                id = hash.hexdigest()
                call_id = ''

                encryption = ''
                if self.encryption.active:
                    encryption = 'verified' if self.encryption.verified else 'unverified'

                self.chatViewController.showMessage(call_id,
                                                    id,
                                                    'outgoing',
                                                    None,
                                                    icon,
                                                    content,
                                                    timestamp,
                                                    state="sent",
                                                    media_type='sms',
                                                    encryption=encryption)

                recipient = ChatIdentity(self.target_uri, self.display_name)
                mInfo = MessageInfo(id,
                                    sender=self.account,
                                    recipient=recipient,
                                    timestamp=timestamp,
                                    content_type=content_type,
                                    content=content,
                                    status="queued",
                                    encryption=encryption)

                self.messages[id] = mInfo
                self.message_queue.put(mInfo)
            else:
                self.message_queue.put(content)

        # Async DNS lookup
        if host is None or host.default_ip is None:
            self.setRoutesFailed(
                NSLocalizedString("No Internet connection", "Label"))
            return

        if self.last_route is None:
            self.lookup_destination(self.target_uri)
        else:
            self.setRoutesResolved([self.last_route])
示例#23
0
 def onMessage(self, payload, is_binary):
     if is_binary:
         log.warn('Received invalid binary message')
         return
     if GeneralConfig.trace_websocket:
         self.factory.ws_logger.msg("IN", ISOTimestamp.now(), payload)
     try:
         data = json.loads(payload)
     except Exception, e:
         log.warn('Error parsing WebSocket payload: %s' % e)
         return
示例#24
0
    def _handle_SEND(self, chunk):
        if chunk.size == 0:  # keep-alive
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        content_type = chunk.content_type.lower()
        if not contains_mime_type(self.accept_types, content_type):
            self.msrp_session.send_report(chunk, 413, 'Unwanted Message')
            return
        if chunk.contflag == '#':
            self.incoming_queue.pop(chunk.message_id, None)
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        elif chunk.contflag == '+':
            self.incoming_queue[chunk.message_id].append(chunk.data)
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        else:
            data = ''.join(self.incoming_queue.pop(chunk.message_id, [])) + chunk.data

        if content_type == 'message/cpim':
            try:
                payload = CPIMPayload.decode(data)
            except CPIMParserError:
                self.msrp_session.send_report(chunk, 400, 'CPIM Parser Error')
                return
            else:
                message = Message(**{name: getattr(payload, name) for name in Message.__slots__})
                if not contains_mime_type(self.accept_wrapped_types, message.content_type):
                    self.msrp_session.send_report(chunk, 413, 'Unwanted Message')
                    return
                if message.timestamp is None:
                    message.timestamp = ISOTimestamp.now()
                if message.sender is None:
                    message.sender = self.remote_identity
                private = self.session.remote_focus and len(message.recipients) == 1 and message.recipients[0] != self.remote_identity
        else:
            payload = SimplePayload.decode(data, content_type)
            message = Message(payload.content, payload.content_type, sender=self.remote_identity, recipients=[self.local_identity], timestamp=ISOTimestamp.now())
            private = False

        try:
            message.content = self.encryption.otr_session.handle_input(message.content, message.content_type)
        except IgnoreMessage:
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        except UnencryptedMessage:
            encrypted = False
            encryption_active = True
        except EncryptedMessageError, e:
            self.msrp_session.send_report(chunk, 400, str(e))
            notification_center = NotificationCenter()
            notification_center.post_notification('ChatStreamOTRError', sender=self, data=NotificationData(error=str(e)))
            return
    def _NH_SIPApplicationDidStart(self, notification):
        settings = SIPSimpleSettings()
        if settings.presence_state.timestamp is None:
            settings.presence_state.timestamp = ISOTimestamp.now()
            settings.save()

        self.get_location([account for account in AccountManager().iter_accounts() if account is not BonjourAccount()])
        self.publish()

        idle_timer = NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(1.0, self, "updateIdleTimer:", None, True)
        NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSRunLoopCommonModes)
        NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSEventTrackingRunLoopMode)
示例#26
0
    def _handle_SEND(self, chunk):
        if chunk.size == 0:  # keep-alive
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        content_type = chunk.content_type.lower()
        if not contains_mime_type(self.accept_types, content_type):
            self.msrp_session.send_report(chunk, 413, 'Unwanted Message')
            return
        if chunk.contflag == '#':
            self.incoming_queue.pop(chunk.message_id, None)
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        elif chunk.contflag == '+':
            self.incoming_queue[chunk.message_id].append(chunk.data)
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        else:
            data = ''.join(self.incoming_queue.pop(chunk.message_id, [])) + chunk.data

        if content_type == 'message/cpim':
            try:
                payload = CPIMPayload.decode(data)
            except CPIMParserError:
                self.msrp_session.send_report(chunk, 400, 'CPIM Parser Error')
                return
            else:
                message = Message(**{name: getattr(payload, name) for name in Message.__slots__})
                if not contains_mime_type(self.accept_wrapped_types, message.content_type):
                    self.msrp_session.send_report(chunk, 413, 'Unwanted Message')
                    return
                if message.timestamp is None:
                    message.timestamp = ISOTimestamp.now()
                if message.sender is None:
                    message.sender = self.remote_identity
                private = self.session.remote_focus and len(message.recipients) == 1 and message.recipients[0] != self.remote_identity
        else:
            payload = SimplePayload.decode(data, content_type)
            message = Message(payload.content, payload.content_type, sender=self.remote_identity, recipients=[self.local_identity], timestamp=ISOTimestamp.now())
            private = False

        try:
            message.content = self.encryption.otr_session.handle_input(message.content, message.content_type)
        except IgnoreMessage:
            self.msrp_session.send_report(chunk, 200, 'OK')
            return
        except UnencryptedMessage:
            encrypted = False
            encryption_active = True
        except EncryptedMessageError, e:
            self.msrp_session.send_report(chunk, 400, str(e))
            notification_center = NotificationCenter()
            notification_center.post_notification('ChatStreamOTRError', sender=self, data=NotificationData(error=str(e)))
            return
示例#27
0
    def _send_message(self, message):
        if (not self.last_route):
            self.log_info('No route found')
            return

        message.timestamp = ISOTimestamp.now()

        if not isinstance(message, OTRInternalMessage):
            try:
                content = self.encryption.otr_session.handle_output(
                    message.content, message.content_type)
            except OTRError as e:
                if 'has ended the private conversation' in str(e):
                    self.log_info(
                        'Encryption has been disabled by remote party, please resend the message again'
                    )
                    self.encryption.stop()
                else:
                    self.log_info('Failed to encrypt outgoing message: %s' %
                                  str(e))
                return

        timeout = 5
        if message.content_type != "application/im-iscomposing+xml":
            self.enableIsComposing = True
            timeout = 15

        message_request = Message(FromHeader(self.account.uri,
                                             self.account.display_name),
                                  ToHeader(self.target_uri),
                                  RouteHeader(self.last_route.uri),
                                  message.content_type,
                                  message.content,
                                  credentials=self.account.credentials)

        self.notification_center.add_observer(self, sender=message_request)

        message_request.send(timeout)
        message.status = 'sent'
        message.call_id = message_request._request.call_id.decode()

        if not isinstance(message, OTRInternalMessage):
            if self.encryption.active:
                self.log_info(
                    'Sending encrypted %s message %s to %s' %
                    (message.content_type, message.id, self.last_route.uri))
            else:
                self.log_info(
                    'Sending %s message %s to %s' %
                    (message.content_type, message.id, self.last_route.uri))

        id = str(message_request)
        self.messages[id] = message
    def _NH_SIPApplicationDidStart(self, notification):
        settings = SIPSimpleSettings()
        if settings.presence_state.timestamp is None:
            settings.presence_state.timestamp = ISOTimestamp.now()
            settings.save()

        self.get_location([account for account in AccountManager().iter_accounts() if account is not BonjourAccount()])
        self.publish()

        idle_timer = NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(1.0, self, "updateIdleTimer:", None, True)
        NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSRunLoopCommonModes)
        NSRunLoop.currentRunLoop().addTimer_forMode_(idle_timer, NSEventTrackingRunLoopMode)
示例#29
0
 def _NH_XMPPSubscriptionGotNotify(self, notification):
     stanza = notification.data.presence
     self._stanza_cache[stanza.sender.uri] = stanza
     stanza.timestamp = ISOTimestamp.now()    # TODO: mirror the one in the stanza, if present
     pidf_doc = self._build_pidf()
     if XMPPGatewayConfig.log_presence:
         log.msg('XMPP notification from %s to %s for presence flow 0x%x' % (format_uri(self.xmpp_identity.uri, 'xmpp'), format_uri(self.sip_identity.uri, 'sip'), id(self)))
     for subscription in self._sip_subscriptions:
         try:
             subscription.push_content(pidf.PIDFDocument.content_type, pidf_doc)
         except SIPCoreError, e:
             if XMPPGatewayConfig.log_presence:
                 log.msg('Failed to send SIP NOTIFY from %s to %s for presence flow 0x%x: %s' % (format_uri(self.xmpp_identity.uri, 'xmpp'), format_uri(self.sip_identity.uri, 'sip'), id(self), e))
示例#30
0
 def _NH_XMPPSubscriptionGotNotify(self, notification):
     stanza = notification.data.presence
     self._stanza_cache[stanza.sender.uri] = stanza
     stanza.timestamp = ISOTimestamp.now()    # TODO: mirror the one in the stanza, if present
     pidf_doc = self._build_pidf()
     if XMPPGatewayConfig.log_presence:
         log.msg('XMPP notification from %s to %s for presence flow 0x%x' % (format_uri(self.xmpp_identity.uri, 'xmpp'), format_uri(self.sip_identity.uri, 'sip'), id(self)))
     for subscription in self._sip_subscriptions:
         try:
             subscription.push_content(pidf.PIDFDocument.content_type, pidf_doc)
         except SIPCoreError, e:
             if XMPPGatewayConfig.log_presence:
                 log.msg('Failed to send SIP NOTIFY from %s to %s for presence flow 0x%x: %s' % (format_uri(self.xmpp_identity.uri, 'xmpp'), format_uri(self.sip_identity.uri, 'sip'), id(self), e))
示例#31
0
 def _NH_ChatStreamOTREncryptionStateChanged(self, stream, data):
     if data.new_state is OTRState.Encrypted:
         local_fingerprint = stream.encryption.key_fingerprint
         remote_fingerprint = stream.encryption.peer_fingerprint
         self.log_info("Chat encryption activated using OTR protocol")
         self.log_info("OTR local fingerprint %s" % local_fingerprint)
         self.log_info("OTR remote fingerprint %s" % remote_fingerprint)
         self.chatViewController.showSystemMessage("0",
                                                   "Encryption enabled",
                                                   ISOTimestamp.now())
         self.showSystemMessage("Encryption enabled", ISOTimestamp.now())
     elif data.new_state is OTRState.Finished:
         self.log_info("Chat encryption deactivated")
         self.chatViewController.showSystemMessage("0",
                                                   "Encryption deactivated",
                                                   ISOTimestamp.now(),
                                                   is_error=True)
     elif data.new_state is OTRState.Plaintext:
         self.log_info("Chat encryption deactivated")
         self.chatViewController.showSystemMessage("0",
                                                   "Encryption deactivated",
                                                   ISOTimestamp.now(),
                                                   is_error=True)
示例#32
0
def missed_session(originator, destination, tokens):
    for token in tokens:
        data = {'to': token,
                'notification': {},
                'data': {'sylkrtc': {}},
                'content_available': True
        }
        data['notification']['body'] = 'Missed session from %s' % originator
        data['priority'] = 'high'
        # No TTL, default is 4 weeks
        data['data']['sylkrtc']['event'] = 'missed_session'
        data['data']['sylkrtc']['originator'] = originator
        data['data']['sylkrtc']['destination'] = destination
        data['data']['sylkrtc']['timestamp'] = str(ISOTimestamp.now())
        _send_push_notification(json.dumps(data))
    def addAnsweringMachineRecordingToHistory(self, filename, duration):
        message = "<h3>Answering Machine Recording</h3>"
        message += "<p>%s" % filename
        message += "<br>Duration: %s seconds" % duration
        message += "<p><audio src='%s' controls='controls'>" %  urllib.parse.quote(filename)
        media_type = 'voicemail'
        local_uri = format_identity_to_string(self.session.account)
        remote_uri = format_identity_to_string(self.session.remote_identity)
        direction = 'incoming'
        status = 'delivered'
        cpim_from = format_identity_to_string(self.session.remote_identity)
        cpim_to = format_identity_to_string(self.session.remote_identity)
        timestamp = str(ISOTimestamp.now())

        self.add_to_history(media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, status)
示例#34
0
def missed_session(originator, destination, tokens):
    for token in tokens:
        data = dict(to=token,
                    notification={},
                    data={'sylkrtc': {}},
                    content_available=True)
        data['notification']['body'] = 'Missed call from %s' % originator
        data['notification']['sound'] = 'Blow'
        data['priority'] = 'high'
        # No TTL, default is 4 weeks
        data['data']['sylkrtc']['event'] = 'missed_session'
        data['data']['sylkrtc']['originator'] = originator
        data['data']['sylkrtc']['destination'] = destination
        data['data']['sylkrtc']['timestamp'] = str(ISOTimestamp.now())
        _send_push_notification(json.dumps(data))
示例#35
0
 def renderMessage(self, message):
     if message.direction == 'outgoing':
         icon = NSApp.delegate().contactsWindowController.iconPathForSelf()
     else:
         sender_uri = sipuri_components_from_string(message.cpim_from)[0]
         # TODO: How to render the icons from Address Book? Especially in sandbox mode we do not have access to other folders
         icon = NSApp.delegate().contactsWindowController.iconPathForURI(sender_uri)
     try:
         timestamp=ISOTimestamp(message.cpim_timestamp)
     except Exception:
         pass
     else:
         is_html = False if message.content_type == 'text' else True
         private = True if message.private == "1" else False
         self.chatViewController.showMessage(message.sip_callid, message.msgid, message.direction, message.cpim_from, icon, message.body, timestamp, is_private=private, recipient=message.cpim_to, state=message.status, is_html=is_html, history_entry=True, media_type=message.media_type, encryption=message.encryption if message.media_type == 'chat' else None)
示例#36
0
def incoming_session(originator, destination, tokens):
    for token in tokens:
        data = {'to': token,
                'notification': {},
                'data': {'sylkrtc': {}},
                'content_available': True
        }
        data['notification']['body'] = 'Incoming session from %s' % originator
        data['priority'] = 'high'
        data['time_to_live'] = 60    # don't deliver if phone is out for over a minute
        data['data']['sylkrtc']['event'] = 'incoming_session'
        data['data']['sylkrtc']['originator'] = originator
        data['data']['sylkrtc']['destination'] = destination
        data['data']['sylkrtc']['timestamp'] = str(ISOTimestamp.now())
        _send_push_notification(json.dumps(data))
    def add_to_history(self):
        FileTransferHistory().add_transfer(transfer_id=self.ft_info.transfer_id, direction=self.ft_info.direction, local_uri=self.ft_info.local_uri, remote_uri=self.ft_info.remote_uri, file_path=self.ft_info.file_path, bytes_transfered=self.ft_info.bytes_transfered, file_size=self.ft_info.file_size or 0, status=self.ft_info.status)

        message  = "<h3>%s File Transfer</h3>" % self.ft_info.direction.capitalize()
        message += "<p>%s (%s)" % (self.ft_info.file_path, format_size(self.ft_info.file_size or 0))
        media_type = 'file-transfer'
        local_uri = self.ft_info.local_uri
        remote_uri = self.ft_info.remote_uri
        direction = self.ft_info.direction
        status = 'delivered' if self.ft_info.status == 'completed' else 'failed'
        cpim_from = self.ft_info.remote_uri
        cpim_to = self.ft_info.remote_uri
        timestamp = str(ISOTimestamp.now())

        ChatHistory().add_message(self.ft_info.transfer_id, media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, "html", "0", status)
示例#38
0
    def addAnsweringMachineRecordingToHistory(self, filename, duration):
        message = "<h3>Answering Machine Recording</h3>"
        message += "<p>%s" % filename
        message += "<br>Duration: %s seconds" % duration
        message += "<p><audio src='%s' controls='controls'>" %  urllib.quote(filename)
        media_type = 'voicemail'
        local_uri = format_identity_to_string(self.session.account)
        remote_uri = format_identity_to_string(self.session.remote_identity)
        direction = 'incoming'
        status = 'delivered'
        cpim_from = format_identity_to_string(self.session.remote_identity)
        cpim_to = format_identity_to_string(self.session.remote_identity)
        timestamp = str(ISOTimestamp.now())

        self.add_to_history(media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, status)
示例#39
0
 def from_session(cls, session):
     if session.start_time is None and session.end_time is not None:
         # Session may have anded before it fully started
         session.start_time = session.end_time
     call_time = session.start_time or ISOTimestamp.now()
     if session.start_time and session.end_time:
         duration = session.end_time - session.start_time
     else:
         duration = None
     remote_uri = '%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host)
     match = cls.phone_number_re.match(remote_uri)
     if match:
         remote_uri = match.group('number')
     display_name = session.remote_identity.display_name
     return cls(session.direction, display_name, remote_uri, unicode(session.account.id), call_time, duration)
示例#40
0
    def updateDuration(self):
        if self.sessionController is not None and self.sessionController.session is not None:
            if self.sessionController.session.end_time:
                now = self.sessionController.session.end_time
            else:
                now = ISOTimestamp.now()

            if self.sessionController.session.start_time and now >= self.sessionController.session.start_time:
                elapsed = now - self.sessionController.session.start_time
                h = elapsed.days * 24 + elapsed.seconds / (60 * 60)
                m = (elapsed.seconds / 60) % 60
                s = elapsed.seconds % 60
                text = "%02i:%02i:%02i" % (h, m, s)
                self.duration.setStringValue_(text)
            else:
                self.duration.setStringValue_('')
示例#41
0
def incoming_session(originator, destination, tokens):
    for token in tokens:
        data = dict(to=token,
                    notification={},
                    data={'sylkrtc': {}},
                    content_available=True)
        data['notification']['body'] = 'Incoming call from %s' % originator
        data['notification']['sound'] = 'Blow'
        data['priority'] = 'high'
        data[
            'time_to_live'] = 60  # don't deliver if phone is out for over a minute
        data['data']['sylkrtc']['event'] = 'incoming_session'
        data['data']['sylkrtc']['originator'] = originator
        data['data']['sylkrtc']['destination'] = destination
        data['data']['sylkrtc']['timestamp'] = str(ISOTimestamp.now())
        _send_push_notification(json.dumps(data))
示例#42
0
    def sendMessage(self, text, content_type="text/plain"):
        self.lookup_destination(self.target_uri)

        timestamp = ISOTimestamp.now()
        hash = hashlib.sha1()
        hash.update(text.encode("utf-8")+str(timestamp))
        msgid = hash.hexdigest()
        call_id = ''

        if content_type != "application/im-iscomposing+xml":
            icon = NSApp.delegate().contactsWindowController.iconPathForSelf()
            self.chatViewController.showMessage(call_id, msgid, 'outgoing', None, icon, text, timestamp, state="sent", media_type='sms')

            recipient=CPIMIdentity(self.target_uri, self.display_name)
            self.messages[msgid] = MessageInfo(msgid, sender=self.account, recipient=recipient, timestamp=timestamp, content_type=content_type, text=text, status="queued")

        self.queue.append((msgid, text, content_type))
示例#43
0
    def gotMessage(self, sender, call_id, message, is_html=False, is_replication_message=False, timestamp=None):
        self.enableIsComposing = True
        icon = NSApp.delegate().contactsWindowController.iconPathForURI(format_identity_to_string(sender))
        timestamp = timestamp or ISOTimestamp.now()

        hash = hashlib.sha1()
        hash.update(message.encode('utf-8')+str(timestamp)+str(sender))
        msgid = hash.hexdigest()

        self.chatViewController.showMessage(call_id, msgid, 'incoming', format_identity_to_string(sender), icon, message, timestamp, is_html=is_html, state="delivered", media_type='sms')

        self.notification_center.post_notification('ChatViewControllerDidDisplayMessage', sender=self, data=NotificationData(direction='incoming', history_entry=False, remote_party=format_identity_to_string(sender), local_party=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour', check_contact=True))

        # save to history
        if not is_replication_message:
            message = MessageInfo(msgid, call_id=call_id, direction='incoming', sender=sender, recipient=self.account, timestamp=timestamp, text=message, content_type="html" if is_html else "text", status="delivered")
            self.add_to_history(message)
示例#44
0
    def addRecordingToHistory(self, filename):
        message = "<h3>Video Call Recorded</h3>"
        message += "<p>%s" % filename
        message += "<p><video src='%s' width=800 controls='controls'>" % urllib.parse.quote(
            filename)
        media_type = 'video-recording'
        local_uri = format_identity_to_string(self.sessionController.account)
        remote_uri = format_identity_to_string(
            self.sessionController.target_uri)
        direction = 'incoming'
        status = 'delivered'
        cpim_from = format_identity_to_string(
            self.sessionController.target_uri)
        cpim_to = format_identity_to_string(self.sessionController.target_uri)
        timestamp = str(ISOTimestamp.now())

        self.add_to_history(media_type, local_uri, remote_uri, direction,
                            cpim_from, cpim_to, timestamp, message, status)
示例#45
0
 def from_session(cls, session):
     if session.start_time is None and session.end_time is not None:
         # Session may have ended before it fully started
         session.start_time = session.end_time
     call_time = session.start_time or ISOTimestamp.now()
     if session.start_time and session.end_time:
         duration = session.end_time - session.start_time
     else:
         duration = None
     remote_uri = '%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host)
     match = cls.phone_number_re.match(remote_uri)
     if match:
         remote_uri = match.group('number')
     try:
         contact = next(contact for contact in AddressbookManager().get_contacts() if remote_uri in (addr.uri for addr in contact.uris))
     except StopIteration:
         display_name = session.remote_identity.display_name
     else:
         display_name = contact.name
     return cls(session.direction, display_name, remote_uri, unicode(session.account.id), call_time, duration)
    def showSystemMessage(self, call_id, text, timestamp=None, is_error=False):
        msgid = str(uuid.uuid1())
        rendered_message = ChatMessageObject(call_id, msgid, text, False, timestamp)
        self.rendered_messages.append(rendered_message)

        if timestamp is None:
            timestamp = ISOTimestamp.now()
        if isinstance(timestamp, datetime.datetime):
            if timestamp.date() != datetime.date.today():
                timestamp = time.strftime("%F %T", time.localtime(calendar.timegm(timestamp.utctimetuple())))
            else:
                timestamp = time.strftime("%T", time.localtime(calendar.timegm(timestamp.utctimetuple())))

        is_error = 1 if is_error else "null"
        script = """renderSystemMessage('%s', "%s", "%s", %s)""" % (msgid, processHTMLText(text), timestamp, is_error)

        if self.finishedLoading:
            self.executeJavaScript(script)
        else:
            self.messageQueue.append(script)
示例#47
0
 def sendReplicationMessage(self, response_code, text, content_type="message/cpim", timestamp=None):
     timestamp = timestamp or ISOTimestamp.now()
     # Lookup routes
     if self.account.sip.outbound_proxy is not None:
         uri = SIPURI(host=self.account.sip.outbound_proxy.host,
                      port=self.account.sip.outbound_proxy.port,
                      parameters={'transport': self.account.sip.outbound_proxy.transport})
     else:
         uri = SIPURI(host=self.account.id.domain)
     lookup = DNSLookup()
     settings = SIPSimpleSettings()
     try:
         routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait()
     except DNSLookupError:
         pass
     else:
         utf8_encode = content_type not in ('application/im-iscomposing+xml', 'message/cpim')
         extra_headers = [Header("X-Offline-Storage", "no"), Header("X-Replication-Code", str(response_code)), Header("X-Replication-Timestamp", str(ISOTimestamp.now()))]
         message_request = Message(FromHeader(self.account.uri, self.account.display_name), ToHeader(self.account.uri),
                                   RouteHeader(routes[0].uri), content_type, text.encode('utf-8') if utf8_encode else text, credentials=self.account.credentials, extra_headers=extra_headers)
         message_request.send(15 if content_type != "application/im-iscomposing+xml" else 5)
示例#48
0
 def __init__(self,
              account,
              contact,
              content,
              content_type='text/plain',
              recipients=None,
              courtesy_recipients=None,
              subject=None,
              timestamp=None,
              required=None,
              additional_headers=None,
              id=None):
     self.lookup = None
     self.account = account
     self.uri = contact.uri.uri
     self.content_type = content_type
     self.content = content
     self.id = id if id is not None else str(uuid.uuid4())
     self.timestamp = timestamp if timestamp is not None else ISOTimestamp.now(
     )
     self.sip_uri = SIPURI.parse('sip:%s' % self.uri)
示例#49
0
    def gotIsComposing(self, window, state, refresh, last_active):
        self.enableIsComposing = True

        flag = state == "active"
        if flag:
            if refresh is None:
                refresh = 120

            if last_active is not None and (last_active - ISOTimestamp.now() > datetime.timedelta(seconds=refresh)):
                # message is old, discard it
                return

            if self.remoteTypingTimer:
                # if we don't get any indications in the request refresh, then we assume remote to be idle
                self.remoteTypingTimer.setFireDate_(NSDate.dateWithTimeIntervalSinceNow_(refresh))
            else:
                self.remoteTypingTimer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(refresh, self, "remoteBecameIdle:", window, False)
        else:
            if self.remoteTypingTimer:
                self.remoteTypingTimer.invalidate()
                self.remoteTypingTimer = None

        window.noteView_isComposing_(self, flag)
示例#50
0
    def setRoutesFailed(self, reason):
        self.message_queue.stop()
        self.started = False

        for msgObject in self.message_queue:
            id = msgObject.id

            try:
                message = self.messages.pop(id)
            except KeyError:
                pass
            else:
                if content_type not in ('application/im-iscomposing+xml',
                                        'message/cpim'):
                    self.chatViewController.markMessage(
                        message.id, MSG_STATE_FAILED)
                    message.status = 'failed'
                    self.add_to_history(message)
                    log_text = NSLocalizedString("Routing failure: %s",
                                                 "Label") % msg
                    self.chatViewController.showSystemMessage(
                        '0', reason, ISOTimestamp.now(), True)
                    self.log_info(log_text)
示例#51
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)
示例#52
0
    def online_state(self):
        blink_settings = BlinkSettings()

        state = blink_settings.presence.current_state.state
        note = blink_settings.presence.current_state.note

        state = 'offline' if state=='Invisible' else state.lower()

        if self.account is BonjourAccount():
            return BonjourPresenceState(state, note)

        try:
            hostname = socket.gethostname()
        except Exception:
            hostname = 'localhost'
        account_id = hashlib.md5(self.account.id).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add(state)
        doc.add(person)

        if state == 'offline':
            service = pidf.Service('SID-%s' % account_id)
            service.status = 'closed'
            service.status.extended = state
            service.contact = str(self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            doc.add(service)
        else:
            settings = SIPSimpleSettings()
            instance_id = str(uuid.UUID(settings.instance_id))
            service = pidf.Service('SID-%s' % instance_id)
            service.status = 'open'
            service.status.extended = state
            service.contact = str(self.account.contact.public_gruu or self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            service.capabilities.audio = True
            service.capabilities.text = False
            service.capabilities.message = True
            service.capabilities.file_transfer = True
            service.capabilities.screen_sharing_server = True
            service.capabilities.screen_sharing_client = True
            service.display_name = self.account.display_name or None
            service.icon = "%s#blink-icon%s" % (self.account.xcap.icon.url, self.account.xcap.icon.etag) if self.account.xcap.icon is not None else None
            service.device_info = pidf.DeviceInfo(instance_id, description=hostname, user_agent=settings.user_agent)
            service.device_info.time_offset = pidf.TimeOffset()
            # TODO: Add real user input data -Saul
            service.user_input = rpid.UserInput()
            service.user_input.idle_threshold = 600
            service.add(pidf.DeviceID(instance_id))
            if note:
                service.notes.add(note)
            doc.add(service)

            device = pidf.Device('DID-%s' % instance_id, device_id=pidf.DeviceID(instance_id))
            device.timestamp = timestamp
            device.notes.add(u'%s at %s' % (settings.user_agent, hostname))
            doc.add(device)

        return doc
示例#53
0
文件: api.py 项目: madhawa/sylkserver
 def _send_data(self, data):
     if GeneralConfig.trace_websocket:
         self.factory.ws_logger.msg("OUT", ISOTimestamp.now(), data)
     self.sendMessage(data, False)
示例#54
0
    def online_state(self):
        blink_settings = BlinkSettings()

        state = blink_settings.presence.current_state.state
        note = blink_settings.presence.current_state.note

        state = 'offline' if state == 'Invisible' else state.lower()

        if self.account is BonjourAccount():
            return BonjourPresenceState(state, note)

        try:
            hostname = socket.gethostname()
        except Exception:
            hostname = 'localhost'
        account_id = hashlib.md5(self.account.id.encode()).hexdigest()
        timestamp = ISOTimestamp.now()

        doc = pidf.PIDF(str(self.account.uri))

        person = pidf.Person('PID-%s' % account_id)
        person.timestamp = timestamp
        person.activities = rpid.Activities()
        person.activities.add(state)
        doc.add(person)

        if state == 'offline':
            service = pidf.Service('SID-%s' % account_id)
            service.status = 'closed'
            service.status.extended = state
            service.contact = str(self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            service.display_name = self.account.display_name or None
            service.icon = "%s#blink-icon%s" % (
                self.account.xcap.icon.url, self.account.xcap.icon.etag
            ) if self.account.xcap.icon is not None else None
            doc.add(service)
        else:
            settings = SIPSimpleSettings()
            instance_id = str(uuid.UUID(settings.instance_id))
            service = pidf.Service('SID-%s' % instance_id)
            service.status = 'open'
            service.status.extended = state
            service.contact = str(self.account.contact.public_gruu
                                  or self.account.uri)
            service.timestamp = timestamp
            service.capabilities = caps.ServiceCapabilities()
            service.capabilities.audio = True
            service.capabilities.text = False
            service.capabilities.message = True
            service.capabilities.file_transfer = True
            service.capabilities.screen_sharing_server = True
            service.capabilities.screen_sharing_client = True
            service.display_name = self.account.display_name or None
            service.icon = "%s#blink-icon%s" % (
                self.account.xcap.icon.url, self.account.xcap.icon.etag
            ) if self.account.xcap.icon is not None else None
            service.device_info = pidf.DeviceInfo(
                instance_id,
                description=hostname,
                user_agent=settings.user_agent)
            service.device_info.time_offset = pidf.TimeOffset()
            # TODO: Add real user input data -Saul
            service.user_input = rpid.UserInput()
            service.user_input.idle_threshold = 600
            service.add(pidf.DeviceID(instance_id))
            if note:
                service.notes.add(note)
            doc.add(service)

            device = pidf.Device('DID-%s' % instance_id,
                                 device_id=pidf.DeviceID(instance_id))
            device.timestamp = timestamp
            device.notes.add('%s at %s' % (settings.user_agent, hostname))
            doc.add(device)

        return doc
示例#55
0
 def logDataIn(buf):
     buf = buf.strip()
     if buf:
         xmpp_logger.msg("RECEIVED", ISOTimestamp.now(), buf)
示例#56
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 ISOTimestamp.now()), content_type=ContentType('text')).toxml()
         self.sendMessage(content, IsComposingDocument.content_type)
示例#57
0
 def logDataOut(buf):
     buf = buf.strip()
     if buf:
         xmpp_logger.msg("SENDING", ISOTimestamp.now(), buf)
示例#58
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)