Example #1
0
    def textView_doCommandBySelector_(self, textView, selector):
        if selector == "insertNewline:" and self.chatViewController.inputText == textView:
            content = str(textView.string())
            textView.setString_("")
            textView.didChangeText()

            if content:
                self.sendMessage(content)

            self.chatViewController.resetTyping()

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

            return True

        return False
    def add_to_history(self, message):
        # writes the record to the sql database
        cpim_to = format_identity_to_string(message.recipient) if message.recipient else ''
        cpim_from = format_identity_to_string(message.sender) if message.sender else ''
        cpim_timestamp = str(message.timestamp)
        content_type="html" if "html" in message.content_type else "text"

        self.history.add_message(message.msgid, 'sms', self.local_uri, self.remote_uri, message.direction, cpim_from, cpim_to, cpim_timestamp, message.text, content_type, "0", message.status, call_id=message.call_id)
 def updateTitle(self, display_name = None):
     session = self.selectedSessionController()
     if session:
         sip_address = '%s@%s' % (session.target_uri.user, session.target_uri.host)
         if display_name and display_name != sip_address:
             title = u"Instant Messages with %s <%s>" % (display_name, format_identity_to_string(session.target_uri))
         else:
             title = u"Instant Messages with %s" %  format_identity_to_string(session.target_uri)
     else:
         title = u"Instant Messages"
     self.window().setTitle_(title)
    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)
 def toolbarButtonClicked_(self, sender):
     session = self.selectedSessionController()
     contactWindow = self._owner._owner
     if sender.itemIdentifier() == 'audio':
         contactWindow.startSessionWithTarget(format_identity_to_string(session.target_uri))
     elif sender.itemIdentifier() == 'video':
         contactWindow.startSessionWithTarget(format_identity_to_string(session.target_uri), media_type="video")
     elif sender.itemIdentifier() == 'smileys':
         chatViewController = self.selectedSessionController().chatViewController
         chatViewController.expandSmileys = not chatViewController.expandSmileys
         sender.setImage_(NSImage.imageNamed_("smiley_on" if chatViewController.expandSmileys else "smiley_off"))
         chatViewController.toggleSmileys(chatViewController.expandSmileys)
     elif sender.itemIdentifier() == 'history' and NSApp.delegate().applicationName != 'Blink Lite':
         contactWindow.showHistoryViewer_(None)
         contactWindow.historyViewer.filterByURIs((format_identity_to_string(session.target_uri),))
    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)
Example #7
0
    def showMessage(self, msgid, direction, sender, icon_path, text, timestamp, is_html=False, state='', recipient='', is_private=False, history_entry=False):
        if not history_entry and not self.delegate.isOutputFrameVisible():
            self.delegate.showChatViewWhileVideoActive()

        # keep track of rendered messages to toggle the smileys
        rendered_message = ChatMessageObject(msgid, text, is_html)
        self.rendered_messages.add(rendered_message)

        if timestamp.date() != datetime.date.today():
            displayed_timestamp = time.strftime("%F %T", time.localtime(calendar.timegm(timestamp.utctimetuple())))
        else:
            displayed_timestamp = time.strftime("%T", time.localtime(calendar.timegm(timestamp.utctimetuple())))

        text = processHTMLText(text, self.expandSmileys, is_html)
        private = 1 if is_private else "null"

        if is_private and recipient:
            label = 'Private message to %s' % cgi.escape(recipient) if direction == 'outgoing' else 'Private message from %s' % cgi.escape(sender)
        else: 
            label = cgi.escape(format_identity_to_string(self.account, format='full')) if sender is None else cgi.escape(sender)

        script = """renderMessage('%s', '%s', '%s', '%s', "%s", '%s', '%s', %s)""" % (msgid, direction, label, icon_path, text, displayed_timestamp, state, private)

        if self.finishedLoading:
            self.outputView.stringByEvaluatingJavaScriptFromString_(script)
        else:
            self.messageQueue.append(script)

        if hasattr(self.delegate, "chatViewDidGetNewMessage_"):
            self.delegate.chatViewDidGetNewMessage_(self)
Example #8
0
 def copy_(self, sender):
     if self.delegate is None:
         return
     pb = NSPasteboard.generalPasteboard()
     copy_text = format_identity_to_string(self.delegate.sessionController.remotePartyObject, check_contact=True, format='full')
     pb.declareTypes_owner_(NSArray.arrayWithObject_(NSStringPboardType), self)
     pb.setString_forType_(copy_text, NSStringPboardType)
Example #9
0
 def __init__(self, session, stream):
     self.session = session
     self.stream = stream
     self.handler = stream.handler
     self.account = session.account
     self.remote_identity = format_identity_to_string(
         session.remote_identity)
Example #10
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
Example #11
0
    def get_recordings(self, filter_uris=[]):
        result = []
        historydir = self.get_recordings_directory()

        for acct in os.listdir(historydir):
            dirname = historydir + "/" + acct
            if not os.path.isdir(dirname):
                continue

            files = [dirname+"/"+f for f in os.listdir(dirname)]

            for file in files:
                try:
                    recording_type = "audio" if file.endswith(".wav") else "video"
                    stat = os.stat(file)
                    toks = file.split("/")[-1].split("-", 2)
                    if len(toks) == 3:
                        date, time, rest = toks
                        timestamp = date[:4]+"/"+date[4:6]+"/"+date[6:8]+" "+time[:2]+":"+time[2:4]

                        pos = rest.rfind(".")
                        if pos >= 0:
                            remote = rest[:pos]
                        else:
                            remote = rest
                        try:
                            identity = SIPURI.parse('sip:'+str(remote))
                            remote_party = format_identity_to_string(identity, check_contact=True)
                        except SIPCoreError:
                            remote_party = "%s" % (remote)

                    else:
                        try:
                            identity = SIPURI.parse('sip:'+str(file[:-4]))
                            remote_party = format_identity_to_string(identity, check_contact=True)
                        except SIPCoreError:
                            remote_party = file[:-4]
                        timestamp = datetime.fromtimestamp(int(stat.st_ctime)).strftime("%E %T")

                    if filter_uris and remote_party not in filter_uris:
                        continue
                    result.append((timestamp, remote_party, file, recording_type))
                except Exception:
                    pass

        sorted(result, key=lambda x: x[0])
        return result
Example #12
0
    def get_audio_recordings(self, filter_uris=[]):
        result = []
        historydir = self.get_audio_recordings_directory()

        for acct in os.listdir(historydir):
            dirname = historydir + "/" + acct
            if not os.path.isdir(dirname):
                continue

            files = [dirname+"/"+f for f in os.listdir(dirname) if f.endswith(".wav")]

            for file in files:
                try:
                    stat = os.stat(file)
                    toks = file.split("/")[-1].split("-", 2)
                    if len(toks) == 3:
                        date, time, rest = toks
                        timestamp = date[:4]+"/"+date[4:6]+"/"+date[6:8]+" "+time[:2]+":"+time[2:4]

                        pos = rest.rfind("-")
                        if pos >= 0:
                            remote = rest[:pos]
                        else:
                            remote = rest
                        try:
                            identity = SIPURI.parse('sip:'+str(remote))
                            remote_party = format_identity_to_string(identity, check_contact=True)
                        except SIPCoreError:
                            remote_party = "%s" % (remote)

                    else:
                        try:
                            identity = SIPURI.parse('sip:'+str(file[:-4]))
                            remote_party = format_identity_to_string(identity, check_contact=True)
                        except SIPCoreError:
                            remote_party = file[:-4]
                        timestamp = datetime.fromtimestamp(int(stat.st_ctime)).strftime("%E %T")

                    if filter_uris and remote_party not in filter_uris:
                        continue
                    result.append((timestamp, remote_party, file))
                except Exception:
                    pass

        result.sort(lambda a,b: cmp(a[0],b[0]))
        return result
    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)
Example #14
0
    def start(self, restart=False):
        notification_center = NotificationCenter()
        file_path = self._file_selector.name.decode() if isinstance(
            self._file_selector.name, bytes) else self._file_selector.name

        self.ft_info = FileTransferInfo(
            transfer_id=str(uuid.uuid4()),
            direction='outgoing',
            file_size=self._file_selector.size,
            local_uri=format_identity_to_string(self.account)
            if self.account is not BonjourAccount() else 'bonjour.local',
            remote_uri=self.remote_identity,
            file_path=file_path)

        self.status = NSLocalizedString("Offering File...", "Label")
        self.ft_info.status = "proposing"

        self.log_info("Initiating DNS Lookup of %s to %s" %
                      (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account,
                      Account) and 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
                         })
            self.log_info("Initiating DNS Lookup for %s (through proxy %s)" %
                          (self.target_uri, uri))
        elif isinstance(self.account,
                        Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(
                "Initiating DNS Lookup for %s (through account %s proxy)" %
                (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            self.log_info("Initiating DNS Lookup for %s" % self.target_uri)

        settings = SIPSimpleSettings()

        tls_name = None
        if isinstance(self.account, Account):
            tls_name = self.account.sip.tls_name or self.account.id.domain

        lookup.lookup_sip_proxy(uri,
                                settings.sip.transport_list,
                                tls_name=tls_name)

        if restart:
            notification_center.post_notification(
                "BlinkFileTransferWillRestart", self)
        else:
            notification_center.post_notification(
                "BlinkFileTransferNewOutgoing", sender=self)
    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)
Example #16
0
 def decideForProposalRequest(self, action, session, streams):
     sessionController = self.sessionControllersManager.sessionControllerForSession(session)
     if action == ACCEPT:
         try:
             sessionController.log_info(u"Accepting proposal from %s" % format_identity_to_string(session.remote_identity))
             self.acceptProposedStreams(session)
         except Exception, exc:
             sessionController.log_info(u"Error accepting proposal: %s" % exc)
             self.removeSession(session)
Example #17
0
 def titleLong(self):
     session = self.selectedSessionController()
     if session:
         display_name = session.display_name
         sip_address = '%s@%s' % (session.target_uri.user.decode(),
                                  session.target_uri.host.decode())
         if display_name and display_name != sip_address:
             title = NSLocalizedString(
                 "Short Messages with %s", "Window Title"
             ) % display_name + " <%s>" % format_identity_to_string(
                 session.target_uri)
         else:
             title = NSLocalizedString(
                 "Short Messages with %s",
                 "Window Title") % format_identity_to_string(
                     session.target_uri)
     else:
         title = NSLocalizedString("Short Messages", "Window Title")
     return title
Example #18
0
 def decideForSessionRequest(self, action, session):
     sessionController = self.sessionControllersManager.sessionControllerForSession(session)
     if action == ACCEPT:
         NSApp.activateIgnoringOtherApps_(True)
         try:
             sessionController.log_info(u"Accepting session from %s" % format_identity_to_string(session.remote_identity))
             self.acceptStreams(session)
         except Exception, exc:
             sessionController.log_info(u"Error accepting session: %s" % exc)
             self.removeSession(session)
 def addViewer_(self, viewer):
     tabItem = NSTabViewItem.alloc().initWithIdentifier_(viewer)
     tabItem.setView_(viewer.getContentView())
     sip_address = '%s@%s' % (viewer.target_uri.user, viewer.target_uri.host)
     if viewer.display_name and viewer.display_name != sip_address:
         tabItem.setLabel_("%s" % viewer.display_name)
     else:
         tabItem.setLabel_(format_identity_to_string(viewer.target_uri))
     self.tabSwitcher.addTabViewItem_(tabItem)
     self.tabSwitcher.selectLastTabViewItem_(None)
     self.window().makeFirstResponder_(viewer.chatViewController.inputText)
 def copy_(self, sender):
     if self.delegate is None:
         return
     pb = NSPasteboard.generalPasteboard()
     copy_text = format_identity_to_string(
         self.delegate.sessionController.remoteIdentity,
         check_contact=True,
         format='full')
     pb.declareTypes_owner_(NSArray.arrayWithObject_(NSStringPboardType),
                            self)
     pb.setString_forType_(copy_text, NSStringPboardType)
Example #21
0
 def addViewer_(self, viewer):
     tabItem = NSTabViewItem.alloc().initWithIdentifier_(viewer)
     tabItem.setView_(viewer.getContentView())
     sip_address = '%s@%s' % (viewer.target_uri.user.decode(),
                              viewer.target_uri.host.decode())
     if viewer.display_name and viewer.display_name != sip_address:
         tabItem.setLabel_("%s" % viewer.display_name)
     else:
         tabItem.setLabel_(format_identity_to_string(viewer.target_uri))
     self.tabSwitcher.addTabViewItem_(tabItem)
     self.tabSwitcher.selectLastTabViewItem_(None)
     self.window().makeFirstResponder_(viewer.chatViewController.inputText)
Example #22
0
    def makeDragImage(self):
        if self.delegate is None:
            return

        image = NSImage.alloc().initWithSize_(self.frame().size)
        image.lockFocus()

        frame = self.frame()
        frame.origin = NSZeroPoint
        rect = NSInsetRect(frame, 1.5, 1.5)

        if self.conferencing and not self.draggedOut:
            NSColor.selectedControlColor().colorWithAlphaComponent_(0.7).set()
        else:
            NSColor.whiteColor().colorWithAlphaComponent_(0.7).set()
        path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius_(rect, 5.0, 5.0)
        path.fill()

        if self.selected:
            path.setLineWidth_(3)
            NSColor.grayColor().set()
        else:
            path.setLineWidth_(1)
            NSColor.grayColor().set()
        path.stroke()

        NSColor.blackColor().set()
        point = NSMakePoint(8, NSMaxY(frame)-20)
        uri = format_identity_to_string(self.delegate.sessionController.remotePartyObject, check_contact=False, format='compact')
        NSString.stringWithString_(uri).drawAtPoint_withAttributes_(point,
              NSDictionary.dictionaryWithObjectsAndKeys_(NSFont.boldSystemFontOfSize_(12), NSFontAttributeName))
        point = NSMakePoint(8, 6)
        if self.conferencing:
            NSString.stringWithString_(NSLocalizedString("Drop outside to remove from conference", "Audio session label")).drawAtPoint_withAttributes_(point,
                  NSDictionary.dictionaryWithObjectsAndKeys_(NSFont.systemFontOfSize_(10), NSFontAttributeName))
        else:
            audio_sessions = [sess.hasStreamOfType("audio") for sess in NSApp.delegate().contactsWindowController.sessionControllersManager.sessionControllers]
            if self.delegate.transferEnabled:
                text = NSLocalizedString("Drop this over a session or contact", "Audio session label") if len(audio_sessions) > 1 else NSLocalizedString("Drop this over a contact to transfer", "Audio session label")
            else:
                text = NSLocalizedString("Drop this over a session to conference", "Audio session label")
            NSString.stringWithString_(text).drawAtPoint_withAttributes_(point,
                  NSDictionary.dictionaryWithObjectsAndKeys_(NSFont.systemFontOfSize_(10), NSFontAttributeName))

        icon = NSImage.imageNamed_("NSEveryone")
        rect = frame
        s = icon.size()
        p = NSMakePoint(NSWidth(rect) - s.width - 8, rect.size.height - s.height - 8)
        r = NSMakeRect(0, 0, s.width, s.height)
        icon.drawAtPoint_fromRect_operation_fraction_(p, r, NSCompositeSourceOver, 0.5)

        image.unlockFocus()
        return image
Example #23
0
    def showMessage(self,
                    msgid,
                    direction,
                    sender,
                    icon_path,
                    text,
                    timestamp,
                    is_html=False,
                    state='',
                    recipient='',
                    is_private=False,
                    history_entry=False):
        if not history_entry and not self.delegate.isOutputFrameVisible():
            self.delegate.showChatViewWhileVideoActive()

        # keep track of rendered messages to toggle the smileys
        rendered_message = ChatMessageObject(msgid, text, is_html)
        self.rendered_messages.add(rendered_message)

        if timestamp.date() != datetime.date.today():
            displayed_timestamp = time.strftime(
                "%F %T",
                time.localtime(calendar.timegm(timestamp.utctimetuple())))
        else:
            displayed_timestamp = time.strftime(
                "%T",
                time.localtime(calendar.timegm(timestamp.utctimetuple())))

        text = processHTMLText(text, self.expandSmileys, is_html)
        private = 1 if is_private else "null"

        if is_private and recipient:
            label = 'Private message to %s' % cgi.escape(
                recipient
            ) if direction == 'outgoing' else 'Private message from %s' % cgi.escape(
                sender)
        else:
            label = cgi.escape(
                format_identity_to_string(
                    self.account,
                    format='full')) if sender is None else cgi.escape(sender)

        script = """renderMessage('%s', '%s', '%s', '%s', "%s", '%s', '%s', %s)""" % (
            msgid, direction, label, icon_path, text, displayed_timestamp,
            state, private)

        if self.finishedLoading:
            self.outputView.stringByEvaluatingJavaScriptFromString_(script)
        else:
            self.messageQueue.append(script)

        if hasattr(self.delegate, "chatViewDidGetNewMessage_"):
            self.delegate.chatViewDidGetNewMessage_(self)
Example #24
0
    def add_to_history(self, message):
        # writes the record to the sql database
        cpim_to = format_identity_to_string(
            message.recipient) if message.recipient else ''
        cpim_from = format_identity_to_string(
            message.sender) if message.sender else ''
        cpim_timestamp = str(message.timestamp)
        content_type = "html" if "html" in message.content_type else "text"

        self.history.add_message(message.id,
                                 'sms',
                                 self.local_uri,
                                 self.remote_uri,
                                 message.direction,
                                 cpim_from,
                                 cpim_to,
                                 cpim_timestamp,
                                 message.content,
                                 content_type,
                                 "0",
                                 message.status,
                                 call_id=message.call_id)
Example #25
0
 def toolbarButtonClicked_(self, sender):
     session = self.selectedSessionController()
     contactWindow = self._owner._owner
     if sender.itemIdentifier() == 'audio':
         contactWindow.startSessionWithTarget(
             format_identity_to_string(session.target_uri))
     elif sender.itemIdentifier() == 'video':
         contactWindow.startSessionWithTarget(format_identity_to_string(
             session.target_uri),
                                              media_type="video")
     elif sender.itemIdentifier() == 'smileys':
         chatViewController = self.selectedSessionController(
         ).chatViewController
         chatViewController.expandSmileys = not chatViewController.expandSmileys
         sender.setImage_(
             NSImage.imageNamed_("smiley_on" if chatViewController.
                                 expandSmileys else "smiley_off"))
         chatViewController.toggleSmileys(chatViewController.expandSmileys)
     elif sender.itemIdentifier() == 'history' and NSApp.delegate(
     ).history_enabled:
         contactWindow.showHistoryViewer_(None)
         contactWindow.historyViewer.filterByURIs(
             (format_identity_to_string(session.target_uri), ))
 def __init__(self, account, target_uri, file_path):
     self.account = account
     self.end_session_when_done = True
     self.file_path = file_path
     self.file_selector = None
     self.finished_transfer = False
     self.interrupted = False
     self.remote_identity = format_identity_to_string(target_uri)
     self.session = None
     self.stream = None
     self.started = False
     self.stop_event = Event()
     self.target_uri = target_uri
     self.transfer_id = str(uuid.uuid1())
     self.direction = 'outgoing'
Example #27
0
    def mouseDragged_(self, event):
        if self.delegate is None:
            return
        pos = event.locationInWindow()
        if abs(self.dragPos.x - pos.x) > 3 or abs(self.dragPos.y - pos.y) > 3:
            image = self.makeDragImage()

            pos.x -= image.size().width/2
            pos.y -= image.size().height/2
            pboard = NSPasteboard.pasteboardWithName_(NSDragPboard)
            pboard.declareTypes_owner_(NSArray.arrayWithObject_("x-blink-audio-session"), self)
            uri = format_identity_to_string(self.delegate.sessionController.remotePartyObject, check_contact=False, format='compact')
            pboard.setString_forType_(uri, "x-blink-audio-session")
            self.window().dragImage_at_offset_event_pasteboard_source_slideBack_(image,
                    pos, NSZeroPoint, event, pboard, self, False)
            self.draggedOut = False
 def __init__(self, session, stream):
     self.account = session.account
     self.end_session_when_done = True
     self.error = False
     self.file_selector = stream.file_selector
     self.finished_transfer = False
     self.hash = hashlib.sha1()
     self.remote_identity = format_identity_to_string(session.remote_identity)
     self.session = session
     self.session_ended = False
     self.started = False
     self.stream = stream
     self.target_uri = session.remote_identity.uri
     self.timer = None
     self.transfer_id = str(uuid.uuid1())
     self.direction = 'incoming'
 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())
     self.direction = 'outgoing'
Example #30
0
 def __init__(self, controller, type='chat'):
     self.controller = controller
     NSBundle.loadNibNamed_owner_("ChatOtrSmp", self)
     self.statusText.setStringValue_('')
     self.progressBar.startAnimation_(None)
     if type == 'chat':
         _t = self.controller.sessionController.getTitleShort()
         self.window.setTitle_(NSLocalizedString("Identity Verification for %s", "Window title") % _t)
         self.stream = self.controller.stream
         self.remote_address = self.controller.sessionController.remoteSIPAddress
         self.otr_context_id = self.controller.sessionController.call_id
     elif type == 'sms':
         _t = format_identity_to_string(self.controller.target_uri)
         self.window.setTitle_(NSLocalizedString("Identity Verification for %s", "Window title") % _t)
         self.stream = self.controller
         self.remote_address = self.controller.remote_uri
         self.otr_context_id = self.controller.session_id
     else:
         self.stream = None
         self.remote_address = ''
         self.otr_context_id = ''
    def mouseDragged_(self, event):
        if self.delegate is None:
            return
        pos = event.locationInWindow()
        if abs(self.dragPos.x - pos.x) > 3 or abs(self.dragPos.y - pos.y) > 3:
            image = self.makeDragImage()

            pos.x -= image.size().width / 2
            pos.y -= image.size().height / 2
            pboard = NSPasteboard.pasteboardWithName_(NSDragPboard)
            pboard.declareTypes_owner_(
                NSArray.arrayWithObject_("x-blink-audio-session"), self)
            uri = format_identity_to_string(
                self.delegate.sessionController.remoteIdentity,
                check_contact=False,
                format='compact')
            pboard.setString_forType_(uri, "x-blink-audio-session")
            self.window(
            ).dragImage_at_offset_event_pasteboard_source_slideBack_(
                image, pos, NSZeroPoint, event, pboard, self, False)
            self.draggedOut = False
    def start(self):
        notification_center = NotificationCenter()
        self.ft_info = FileTransferInfo(
            transfer_id=self.stream.transfer_id,
            direction='incoming',
            local_uri=format_identity_to_string(self.account)
            if self.account is not BonjourAccount() else 'bonjour.local',
            file_size=self.file_selector.size,
            remote_uri=self.remote_identity,
            file_path=self.file_path)
        self.log_info("Will write file to %s" % self.file_path)

        self.status = NSLocalizedString("Accepting File Transfer...", "Label")

        notification_center.add_observer(self, sender=self.stream)
        notification_center.add_observer(self, sender=self.handler)

        self.log_info("Initiating Incoming File Transfer")

        notification_center.post_notification("BlinkFileTransferNewIncoming",
                                              sender=self)
Example #33
0
    def decideForAllSessionRequests(self, action):
        if self.attention is not None:
            NSApp.cancelUserAttentionRequest_(self.attention)
            self.attention = None
        self.panel.close()

        if action == ACCEPT:
            NSApp.activateIgnoringOtherApps_(True)
            for session in self.sessions.keys():
                sessionController = self.sessionControllersManager.sessionControllerForSession(session)
                if sessionController is None:
                    continue
                is_proposal = self.proposals.has_key(session)
                try:
                    if is_proposal:
                        sessionController.log_info(u"Accepting all proposed streams from %s" % format_identity_to_string(session.remote_identity))
                        self.acceptProposedStreams(session)
                    else:
                        sessionController.log_info(u"Accepting session from %s" % format_identity_to_string(session.remote_identity))
                        self.acceptStreams(session)
                except Exception, exc:
                    sessionController.log_info(u"Error accepting session: %s" % exc)
                    self.removeSession(session)
    def makeDragImage(self):
        if self.delegate is None:
            return

        image = NSImage.alloc().initWithSize_(self.frame().size)
        image.lockFocus()

        frame = self.frame()
        frame.origin = NSZeroPoint
        rect = NSInsetRect(frame, 1.5, 1.5)

        if self.conferencing and not self.draggedOut:
            NSColor.selectedControlColor().colorWithAlphaComponent_(0.7).set()
        else:
            NSColor.whiteColor().colorWithAlphaComponent_(0.7).set()
        path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius_(
            rect, 5.0, 5.0)
        path.fill()

        if self.selected:
            path.setLineWidth_(3)
            NSColor.grayColor().set()
        else:
            path.setLineWidth_(1)
            NSColor.grayColor().set()
        path.stroke()

        NSColor.blackColor().set()
        point = NSMakePoint(8, NSMaxY(frame) - 20)
        uri = format_identity_to_string(
            self.delegate.sessionController.remoteIdentity,
            check_contact=False,
            format='compact')
        NSString.stringWithString_(uri).drawAtPoint_withAttributes_(
            point,
            NSDictionary.dictionaryWithObjectsAndKeys_(
                NSFont.boldSystemFontOfSize_(12), NSFontAttributeName))
        point = NSMakePoint(8, 6)
        if self.conferencing:
            NSString.stringWithString_(
                NSLocalizedString(
                    "Drop outside to remove from conference",
                    "Audio status label")).drawAtPoint_withAttributes_(
                        point,
                        NSDictionary.dictionaryWithObjectsAndKeys_(
                            NSFont.systemFontOfSize_(10), NSFontAttributeName))
        else:
            audio_sessions = [
                sess.hasStreamOfType("audio")
                for sess in NSApp.delegate().contactsWindowController.
                sessionControllersManager.sessionControllers
            ]
            if self.delegate.transferEnabled:
                text = NSLocalizedString(
                    "Drop this over a session or contact", "Audio status label"
                ) if len(audio_sessions) > 1 else NSLocalizedString(
                    "Drop this over a contact to transfer",
                    "Audio status label")
            else:
                text = NSLocalizedString(
                    "Drop this over a session to conference",
                    "Audio status label")
            NSString.stringWithString_(text).drawAtPoint_withAttributes_(
                point,
                NSDictionary.dictionaryWithObjectsAndKeys_(
                    NSFont.systemFontOfSize_(10), NSFontAttributeName))

        icon = NSImage.imageNamed_("NSEveryone")
        rect = frame
        s = icon.size()
        p = NSMakePoint(
            NSWidth(rect) - s.width - 8, rect.size.height - s.height - 8)
        r = NSMakeRect(0, 0, s.width, s.height)
        icon.drawAtPoint_fromRect_operation_fraction_(p, r,
                                                      NSCompositeSourceOver,
                                                      0.5)

        image.unlockFocus()
        return image
 def getTitle(self):
     session = self.selectedSessionController()
     if session:
         display_name = session.display_name
         sip_address = '%s@%s' % (session.target_uri.user, session.target_uri.host)
         if display_name and display_name != sip_address:
             title = NSLocalizedString("Instant Messages with %s", "Window Title") % display_name +  " <%s>" % format_identity_to_string(session.target_uri)
         else:
             title = NSLocalizedString("Instant Messages with %s", "Window Title") %  format_identity_to_string(session.target_uri)
     else:
         title = NSLocalizedString("Instant Messages", "Window Title")
     return title
Example #36
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)
    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)
    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)
Example #39
0
 def rejectAllSessions(self):
     for session in self.sessions.keys():
         sessionController = self.sessionControllersManager.sessionControllerForSession(session)
         is_proposal = self.proposals.has_key(session)
         try:
             if is_proposal:
                 sessionController.log_info(u"Rejecting %s proposal from %s"%([stream.type for stream in session.proposed_streams], format_identity_to_string(session.remote_identity)))
                 try:
                     self.rejectProposal(session)
                 except Exception, exc:
                     sessionController.log_info(u"Error rejecting proposal: %s" % exc)
                     self.removeSession(session)
             else:
                 sessionController.log_info(u"Rejecting session from %s with Busy Everywhere" % format_identity_to_string(session.remote_identity))
                 self.rejectSession(session, 603, "Busy Everywhere")
    def start(self):
        notification_center = NotificationCenter()

        download_folder = unicodedata.normalize('NFC', NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, True)[0])

        for name in self.filename_generator(os.path.join(download_folder, self.file_name)):
            if not os.path.exists(name) and not os.path.exists(name+".download"):
                self.file_path = name + '.download'
                break

        self.ft_info = FileTransferInfo(transfer_id=self.transfer_id, direction='incoming', local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour' , file_size=self.file_size, remote_uri=self.remote_identity, file_path=self.file_path)

        self.log_info(u"Will write file to %s" % self.file_path)
        self.file_selector.fd = open(self.file_path, "w+")

        self.ft_info.status = "preparing"
        self.status = "Accepting File Transfer..."

        notification_center.add_observer(self, sender=self)
        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.log_info("Initiating Incoming File Transfer")
        notification_center.post_notification("BlinkFileTransferInitializing", self)
        notification_center.post_notification("BlinkFileTransferInitiated", self)
Example #41
0
    def _addIncomingSession(self, session, streams, is_update_proposal):
        view = self.getItemView()
        self.sessions[session] = view
        settings = SIPSimpleSettings()
        stream_type_list = list(set(stream.type for stream in streams))

        if len(self.sessions) == 1:
            if "screen-sharing" in stream_type_list:
                base_text = NSLocalizedString("Screen Sharing from %s", "Label")
            elif "video" in stream_type_list:
                base_text = NSLocalizedString("Video call from %s", "Label")
            elif "audio" in stream_type_list:
                base_text = NSLocalizedString("Audio call from %s", "Label")
            elif stream_type_list == ["file-transfer"]:
                base_text = NSLocalizedString("File transfer from %s", "Label")
            elif stream_type_list == ["chat"]:
                base_text = NSLocalizedString("Chat from %s", "Label")
            else:
                base_text = NSLocalizedString("Call from %s", "Label")

            title = base_text % format_identity_to_string(session.remote_identity, check_contact=True, format='compact')
            self.panel.setTitle_(title)

            if settings.sounds.enable_speech_synthesizer:
                self.speak_text = title
                self.startSpeechSynthesizerTimer()
        else:
            self.panel.setTitle_(NSLocalizedString("Multiple Incoming Calls", "Label"))

        NotificationCenter().add_observer(self, sender=session)

        subjectLabel     = view.viewWithTag_(1)
        fromLabel        = view.viewWithTag_(2)
        accountLabel     = view.viewWithTag_(3)
        acceptButton     = view.viewWithTag_(5)
        rejectButton     = view.viewWithTag_(7)
        accepyOnlyButton = view.viewWithTag_(6)
        busyButton       = view.viewWithTag_(8)
        callerIcon       = view.viewWithTag_(99)
        chatIcon         = view.viewWithTag_(31)
        audioIcon        = view.viewWithTag_(32)
        fileIcon         = view.viewWithTag_(33)
        screenIcon       = view.viewWithTag_(34)
        videoIcon        = view.viewWithTag_(35)

        stream_types = [s.type for s in streams]

        session_manager = SessionManager()
        have_audio_call = any(s for s in session_manager.sessions if s is not session and s.streams and 'audio' in (stream.type for stream in s.streams))
        if not have_audio_call:
            self.startSpeechRecognition()

        typeCount = 0
        if 'audio' in stream_types:
            frame = audioIcon.frame()
            typeCount+= 1
            frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount
            audioIcon.setFrame_(frame)
            audioIcon.setHidden_(False)

            if not is_update_proposal:
                frame = view.frame()
                frame.size.height += 20 # give extra space for the counter label
                view.setFrame_(frame)
                if session.account.audio.auto_accept:
                    have_audio_call = any(s for s in session_manager.sessions if s is not session and s.streams and 'audio' in (stream.type for stream in s.streams))
                    if not have_audio_call:
                        self.enableAutoAnswer(view, session, session.account.audio.answer_delay)
                elif settings.answering_machine.enabled or (is_anonymous(session.remote_identity.uri) and session.account.pstn.anonymous_to_answering_machine):
                    self.enableAnsweringMachine(view, session)

        if 'chat' in stream_types:
            frame = chatIcon.frame()
            typeCount+= 1
            frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount
            chatIcon.setFrame_(frame)
            chatIcon.setHidden_(False)

        if 'screen-sharing' in stream_types:
            frame = screenIcon.frame()
            typeCount+= 1
            frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount
            screenIcon.setFrame_(frame)
            screenIcon.setHidden_(False)

        if 'video' in stream_types:
            #have_video_call = any(s for s in session_manager.sessions if s is not session and s.streams and 'video' in (stream.type for stream in s.streams))
            #if not have_video_call:
            #    NSApp.delegate().contactsWindowController.showLocalVideoWindow()

            frame = videoIcon.frame()
            typeCount+= 1
            frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount
            videoIcon.setFrame_(frame)
            videoIcon.setHidden_(False)

        is_file_transfer = False
        if 'file-transfer' in stream_types:
            is_file_transfer = True
            frame = fileIcon.frame()
            typeCount+= 1
            frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount
            fileIcon.setFrame_(frame)
            fileIcon.setHidden_(False)
            if settings.file_transfer.auto_accept and NSApp.delegate().contactsWindowController.my_device_is_active:
                BlinkLogger().log_info(u"Auto answer enabled for file transfers from known contacts")
                self.enableAutoAnswer(view, session, random.uniform(10, 20))

        self.sessionsListView.addSubview_(view)
        frame = self.sessionsListView.frame()
        frame.origin.y = self.extraHeight - 14
        frame.size.height = self.sessionsListView.minimumHeight()
        self.sessionsListView.setFrame_(frame)
        height = frame.size.height + self.extraHeight
        size = NSMakeSize(NSWidth(self.panel.frame()), height)

        screenSize = NSScreen.mainScreen().frame().size
        if size.height > (screenSize.height * 2) / 3:
            size.height = (screenSize.height * 2) / 3

        frame = self.panel.frame()
        frame.size.height = size.height
        frame.size.height = NSHeight(self.panel.frameRectForContentRect_(frame))
        self.panel.setFrame_display_animate_(frame, True, True)
        self.sessionsListView.relayout()

        acceptButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(0))
        rejectButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(2))
        busyButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(3))

        # no Busy or partial accept option for Stream Update Proposals
        busyButton.setHidden_(is_update_proposal or is_file_transfer)
        accepyOnlyButton.setHidden_(is_update_proposal)
        if is_file_transfer:
            busyButton.setAttributedTitle_("")

        if is_update_proposal:
            subject, only_button_title, only_button_object = self.format_subject_for_incoming_reinvite(session, streams)
            only_button_title = ""
        else:
            subject, only_button_title, only_button_object = self.format_subject_for_incoming_invite(session, streams)
        subjectLabel.setStringValue_(subject)
        accepyOnlyButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(only_button_object))
        frame = subjectLabel.frame()
        frame.size.width = NSWidth(self.sessionsListView.frame()) - 80 - 40 * typeCount
        subjectLabel.setFrame_(frame)

        has_audio_streams = any(s for s in reduce(lambda a,b:a+b, [session.proposed_streams for session in self.sessions.keys()], []) if s.type=="audio")
        caller_contact = NSApp.delegate().contactsWindowController.getFirstContactMatchingURI(session.remote_identity.uri)
        if caller_contact:
            if caller_contact.icon:
                callerIcon.setImage_(caller_contact.icon)

            if not is_update_proposal and caller_contact.auto_answer and NSApp.delegate().contactsWindowController.my_device_is_active:
                if has_audio_streams:
                    if not NSApp.delegate().contactsWindowController.has_audio:
                        BlinkLogger().log_info(u"Auto answer enabled for this contact")
                        video_requested = any(s for s in session.blink_supported_streams if s.type == "video")
                        if video_requested and not settings.video.enable_when_auto_answer:
                            blink_supported_streams = [s for s in session.blink_supported_streams if s.type != "video"]
                            session.blink_supported_streams = blink_supported_streams
                        self.enableAutoAnswer(view, session, session.account.audio.answer_delay)
                else:
                    video_requested = any(s for s in session.blink_supported_streams if s.type == "video")
                    if video_requested and not settings.video.enable_when_auto_answer:
                        blink_supported_streams = [s for s in session.blink_supported_streams if s.type != "video"]
                        session.blink_supported_streams = blink_supported_streams
                    BlinkLogger().log_info(u"Auto answer enabled for this contact")
                    self.enableAutoAnswer(view, session, session.account.audio.answer_delay)

        fromLabel.setStringValue_(u"%s" % format_identity_to_string(session.remote_identity, check_contact=True, format='full'))
        fromLabel.sizeToFit()

        if has_audio_streams:
            outdev = settings.audio.output_device
            indev = settings.audio.input_device

            if outdev == u"system_default":
                outdev = SIPManager()._app.engine.default_output_device
            if indev == u"system_default":
                indev = SIPManager()._app.engine.default_input_device

            outdev = outdev.strip() if outdev is not None else 'None'
            indev = indev.strip() if indev is not None else 'None'

            if outdev != indev:
                if indev.startswith('Built-in Mic') and outdev.startswith(u'Built-in Out'):
                    self.deviceLabel.setStringValue_(NSLocalizedString("Using Built-in Microphone and Output", "Label"))
                else:
                    self.deviceLabel.setStringValue_(NSLocalizedString("Using %s for output ", "Label") % outdev.strip() + NSLocalizedString(" and %s for input", "Label") % indev.strip())
            else:
                self.deviceLabel.setStringValue_(NSLocalizedString("Using audio device", "Label") + " " + outdev.strip())

            BlinkLogger().log_info(u"Using input/output audio devices: %s/%s" % (indev.strip(), outdev.strip()))

            self.deviceLabel.sizeToFit()
            self.deviceLabel.setHidden_(False)
        else:
            self.deviceLabel.setHidden_(True)

        acceptButton.setTitle_(NSLocalizedString("Accept", "Button title"))
        accepyOnlyButton.setTitle_(only_button_title or "")

        if False and sum(a.enabled for a in AccountManager().iter_accounts())==1:
            accountLabel.setHidden_(True)
        else:
            accountLabel.setHidden_(False)
            if isinstance(session.account, BonjourAccount):
                accountLabel.setStringValue_(NSLocalizedString("To Bonjour account", "Label"))
            else:
                to = format_identity_to_string(session.account)
                accountLabel.setStringValue_(NSLocalizedString("To %s", "Label") % to)
            accountLabel.sizeToFit()

        if len(self.sessions) == 1:
            self.acceptAllButton.setTitle_(NSLocalizedString("Accept", "Button title"))
            self.acceptAllButton.setHidden_(False)
            self.acceptButton.setTitle_(only_button_title or "")
            self.acceptButton.setHidden_(not only_button_title)
            self.rejectButton.setTitle_(NSLocalizedString("Reject", "Button title"))

            self.acceptAllButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(0))
            self.rejectButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(2))
            self.busyButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(3))
            self.acceptButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(only_button_object))
            self.answeringMachineButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(4))
            self.conferenceButton.cell().setRepresentedObject_(NSNumber.numberWithInt_(5))

            self.busyButton.setHidden_(is_update_proposal or is_file_transfer)

            for i in (5, 6, 7, 8):
                view.viewWithTag_(i).setHidden_(True)

        else:
            self.acceptAllButton.setHidden_(False)
            self.acceptAllButton.setTitle_(NSLocalizedString("Accept All", "Button title"))
            self.acceptButton.setHidden_(True)
            self.busyButton.setHidden_(is_update_proposal or is_file_transfer)
            self.rejectButton.setTitle_(NSLocalizedString("Reject All", "Button title"))

            for v in self.sessions.values():
                for i in (5, 6, 7, 8):
                    btn = v.viewWithTag_(i)
                    btn.setHidden_(len(btn.attributedTitle()) == 0)

        if not has_audio_streams or is_update_proposal:
            self.answeringMachineButton.setHidden_(True)
        else:
            self.answeringMachineButton.setHidden_(not settings.answering_machine.show_in_alert_panel)

        if not self.isConferencing:
            self.conferenceButton.setHidden_(True)
        else:
            self.conferenceButton.setHidden_(False)
    def start(self, restart=False):
        self.ft_info = FileTransferInfo(transfer_id=self.transfer_id, direction='outgoing', file_size=self.file_size, local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour', remote_uri=self.remote_identity, file_path=self.file_path)
        self.ft_info.status = "pending"
        self.status = "Pending"

        notification_center = NotificationCenter()
        if restart:
            notification_center.post_notification("BlinkFileTransferRestarting", self)
        else:
            notification_center.post_notification("BlinkFileTransferInitializing", self)

        self.log_info(u"Computing checksum for file %s" % os.path.basename(self.file_path))

        self.stop_event.clear()
        self.initiate_file_transfer()
Example #43
0
                self.removeSession(session)

    def decideForSessionRequest(self, action, session):
        sessionController = self.sessionControllersManager.sessionControllerForSession(session)
        if action == ACCEPT:
            NSApp.activateIgnoringOtherApps_(True)
            try:
                sessionController.log_info(u"Accepting session from %s" % format_identity_to_string(session.remote_identity))
                self.acceptStreams(session)
            except Exception, exc:
                sessionController.log_info(u"Error accepting session: %s" % exc)
                self.removeSession(session)
        elif action == ONLY_CHAT:
            NSApp.activateIgnoringOtherApps_(True)
            try:
                sessionController.log_info(u"Accepting chat from %s" % format_identity_to_string(session.remote_identity))
                self.acceptChatStream(session)
            except Exception, exc:
                sessionController.log_info(u"Error accepting session: %s" % exc)
                self.removeSession(session)
        elif action == ONLY_AUDIO:
            NSApp.activateIgnoringOtherApps_(True)
            try:
                sessionController.log_info(u"Accepting audio  from %s" % format_identity_to_string(session.remote_identity))
                self.acceptChatStream(session)
            except Exception, exc:
                sessionController.log_info(u"Error accepting session: %s" % exc)
                self.removeSession(session)
        elif action == REJECT:
            try:
                sessionController.log_info(u"Rejecting session from %s with Busy Everywhere" % format_identity_to_string(session.remote_identity))
    def start(self):
        notification_center = NotificationCenter()
        settings = SIPSimpleSettings()

        download_folder = unicodedata.normalize('NFC', NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, True)[0])
        for name in self.filename_generator(os.path.join(download_folder, self.file_name)):
            if not os.path.exists(name) and not os.path.exists(name+".download"):
                self.file_path = name + '.download'
                break

        self.log_info(u"File will be written to %s" % self.file_path)
        self.file_selector.fd = open(self.file_path, "w+")

        self.ft_info = FileTransferInfo(transfer_id=self.transfer_id, direction='incoming', local_uri=format_identity_to_string(self.account) if self.account is not BonjourAccount() else 'bonjour' , file_size=self.file_size, remote_uri=self.remote_identity, file_path=self.file_path)

        self.log_info("Pull File Transfer Request started %s" % self.file_path)

        self.stream = FileTransferStream(self.file_selector, 'recvonly')
        self.session = Session(self.account)

        notification_center.add_observer(self, sender=self)
        notification_center.add_observer(self, sender=self.session)
        notification_center.add_observer(self, sender=self.stream)

        self.status = "Requesting File..."
        self.ft_info.status = "requesting"

        self.log_info(u"Initiating DNS Lookup of %s to %s" % (self.account, self.target_uri))
        lookup = DNSLookup()
        notification_center.add_observer(self, sender=lookup)

        if isinstance(self.account, Account) and 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})
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through proxy %s)" % (self.target_uri, uri))
        elif isinstance(self.account, Account) and self.account.sip.always_use_my_proxy:
            uri = SIPURI(host=self.account.id.domain)
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s (through account %s proxy)" % (self.target_uri, self.account.id))
        else:
            uri = self.target_uri
            self.log_info(u"Initiating DNS Lookup for SIP routes of %s" % self.target_uri)
        notification_center.post_notification("BlinkFileTransferInitializing", self)
        notification_center.post_notification("BlinkFileTransferInitiated", self)
        lookup.lookup_sip_proxy(uri, settings.sip.transport_list)
    def textView_doCommandBySelector_(self, textView, selector):
        if selector == "insertNewline:" and self.chatViewController.inputText == textView:
            text = unicode(textView.string())
            textView.setString_("")
            textView.didChangeText()

            if text:
                self.sendMessage(text)
            self.chatViewController.resetTyping()

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

            return True
        return False
Example #46
0
    def gotMessage(self,
                   sender,
                   call_id,
                   content,
                   content_type,
                   is_replication_message=False,
                   timestamp=None,
                   window=None):
        is_html = content_type == 'text/html'
        encrypted = False
        try:
            content = self.encryption.otr_session.handle_input(
                content, content_type)
        except IgnoreMessage:
            return None
        except UnencryptedMessage:
            encrypted = False
            encryption_active = True
        except EncryptedMessageError as e:
            self.log_info('OTP encrypted message error: %s' % str(e))
            return None
        except OTRError as e:
            self.log_info('OTP error: %s' % str(e))
            return None
        else:
            encrypted = encryption_active = self.encryption.active

        content = content.decode() if isinstance(content, bytes) else content

        if content.startswith('?OTR:'):
            self.log_info('Dropped OTR message that could not be decoded')
            return None

        self.enableIsComposing = True

        icon = NSApp.delegate().contactsWindowController.iconPathForURI(
            format_identity_to_string(sender))
        timestamp = timestamp or ISOTimestamp.now()

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

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

        if not is_replication_message and not window.isKeyWindow():
            nc_body = html2txt(content) if is_html else content
            nc_title = NSLocalizedString("SMS Message Received", "Label")
            nc_subtitle = format_identity_to_string(sender, format='full')
            NSApp.delegate().gui_notify(nc_title, nc_body, nc_subtitle)

        self.log_info("Incoming message %s received" % call_id)

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

        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.local',
                check_contact=True))

        # save to history
        if not is_replication_message or (is_replication_message and
                                          self.local_uri == self.account.id):
            message = MessageInfo(id,
                                  call_id=call_id,
                                  direction='incoming',
                                  sender=sender,
                                  recipient=self.account,
                                  timestamp=timestamp,
                                  content=content,
                                  content_type=content_type,
                                  status="delivered",
                                  encryption=encryption)
            self.add_to_history(message)
Example #47
0
 def __init__(self, account, target_uri, file_path):
     self.account = account
     self._file_selector = FileSelector.for_file(file_path)
     self.remote_identity = format_identity_to_string(target_uri)
     self.target_uri = target_uri
     self._ended = False