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)
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)
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)
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)
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
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
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)
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)
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)
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
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)
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)
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
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)
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)
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'
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'
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)
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
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)
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)
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()
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
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)
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