def _NH_SIPAccountGotMessageSummary(self, account, data): BlinkLogger().log_info(u"Received voicemail notification for account %s" % account.id) summary = data.message_summary if summary.summaries.get('voice-message') is None: return voice_messages = summary.summaries['voice-message'] growl_data = NotificationData() new_messages = int(voice_messages['new_messages']) old_messages = int(voice_messages['old_messages']) growl_data.new_messages = new_messages growl_data.old_messages = old_messages MWIData.store(account, summary) if summary.messages_waiting and growl_data.new_messages > 0: self.notification_center.post_notification("GrowlGotMWI", sender=self, data=growl_data) nc_title = NSLocalizedString("New Voicemail Message", "System notification title") if new_messages == 1 else NSLocalizedString("New Voicemail Messages", "System notification title") nc_subtitle = NSLocalizedString("On Voicemail Server", "System notification subtitle") if old_messages > 0: nc_body = NSLocalizedString("You have %d new and " % new_messages, "System notification body") + NSLocalizedString("%d old voicemail messages" % old_messages, "System notification body") else: nc_body = NSLocalizedString("You have %d new voicemail messages" % new_messages, "System notification body") NSApp.delegate().gui_notify(nc_title, nc_body, nc_subtitle)
def verified(self, value): peer_fingerprint = self.peer_fingerprint old_verified = peer_fingerprint in self.otr_cache.trusted_peers new_verified = bool(value) if peer_fingerprint is None or new_verified == old_verified: return if new_verified: self.otr_cache.trusted_peers.add(OTRTrustedPeer(peer_fingerprint, description=self.peer_name)) else: self.otr_cache.trusted_peers.remove(peer_fingerprint) self.otr_cache.save() notification_center = NotificationCenter() notification_center.post_notification("ChatStreamOTRVerifiedStateChanged", sender=self.stream, data=NotificationData(verified=new_verified))
def _CH_newline(self, char): if self.input.current_line: # copy the current line to the last line self.input.copy_current_line() window_size = self.window_size # calculate the length of the line just entered text_len = len(self.prompt) + len(self.input.current_line) text_lines = (text_len-1)/window_size.x + 1 # save the current line and add a new input line current_line = self.input.current_line self.input.add_line() # see if it's a command or plain text notification_center = NotificationCenter() if current_line.startswith(self.command_sequence): # calculate the new position of the prompt if self.display_commands: self.prompt_y += text_lines # we need to scroll if the new prompt position is below the window margin, otherwise # some text might go over it scroll_up = self.prompt_y - window_size.y if scroll_up > 0: self.prompt_y -= scroll_up self._scroll_up(scroll_up) # send a notification about the new input words = [word for word in re.split(r'\s+', current_line[len(self.command_sequence):]) if word] notification_center.post_notification('UIInputGotCommand', sender=self, data=NotificationData(command=words[0], args=words[1:])) else: # calculate the new position of the prompt if self.display_text: self.prompt_y += text_lines # we need to scroll if the new prompt position is below the window margin, otherwise # some text might go over it scroll_up = self.prompt_y - window_size.y if scroll_up > 0: self.prompt_y -= scroll_up self._scroll_up(scroll_up) # send a notification about the new input notification_center.post_notification('UIInputGotText', sender=self, data=NotificationData(text=current_line)) # redisplay the prompt self._update_prompt()
def _run(self): wait_control_char = False while True: stdin_fd = sys.__stdin__.fileno() if select.select([stdin_fd], [], [], None)[0]: chars = list(os.read(stdin_fd, 4096)) while chars: if self.stopping: return with self.lock: char = chars.pop(0) if ord(char) < 32 or ord(char) == 127: if char == '\x1b': if chars and chars[0] == '[': char += chars.pop(0) while chars and not chars[0].isalpha(): char += chars.pop(0) if chars: char += chars.pop(0) if self.questions: pass elif char == self.application_control_char: wait_control_char = not wait_control_char elif not self.questions: wait_control_char = False handler = getattr(self, '_CH_%s' % self.control_chars.get(char, 'default')) handler(char) elif wait_control_char: wait_control_char = False if char in self.application_control_bindings: notification_center = NotificationCenter() words = [word for word in re.split(r'\s+', self.application_control_bindings[char]) if word] notification_center.post_notification('UIInputGotCommand', sender=self, data=NotificationData(command=words[0], args=words[1:])) elif self.questions: question = self.questions[0] if char in question.answers: self._raw_write(char) self.displaying_question = False self.remove_question(question) notification_center = NotificationCenter() notification_center.post_notification('UIQuestionGotAnswer', sender=question, data=NotificationData(answer=char)) else: # insert char in input.current_line at input.cursor_position and advance cursor self.input.current_line = self.input.current_line[:self.input.cursor_position] + char + self.input.current_line[self.input.cursor_position:] self.input.cursor_position += 1 self._update_prompt()
def _check_hold(self, direction, is_initial): was_on_hold_by_local = self.on_hold_by_local was_on_hold_by_remote = self.on_hold_by_remote self.direction = direction inactive = self.direction == "inactive" self.on_hold_by_local = was_on_hold_by_local if inactive else direction == "sendonly" self.on_hold_by_remote = "send" not in direction if self.on_hold_by_local or self.on_hold_by_remote: self._pause() elif not self.on_hold_by_local and not self.on_hold_by_remote and (was_on_hold_by_local or was_on_hold_by_remote): self._resume() if not was_on_hold_by_local and self.on_hold_by_local: self.notification_center.post_notification('RTPStreamDidChangeHoldState', sender=self, data=NotificationData(originator="local", on_hold=True)) if was_on_hold_by_local and not self.on_hold_by_local: self.notification_center.post_notification('RTPStreamDidChangeHoldState', sender=self, data=NotificationData(originator="local", on_hold=False)) if not was_on_hold_by_remote and self.on_hold_by_remote: self.notification_center.post_notification('RTPStreamDidChangeHoldState', sender=self, data=NotificationData(originator="remote", on_hold=True)) if was_on_hold_by_remote and not self.on_hold_by_remote: self.notification_center.post_notification('RTPStreamDidChangeHoldState', sender=self, data=NotificationData(originator="remote", on_hold=False))
def save(self): """ Use the ConfigurationManager to store the object under its id in the specified group or top-level otherwise, depending on whether group is None. This method will also post a CFGSettingsObjectDidChange notification, regardless of whether the settings have been saved to persistent storage or not. If the save does fail, a CFGManagerSaveFailed notification is posted as well. """ if self.__state__ == 'deleted': return configuration = ConfigurationManager() notification_center = NotificationCenter() oldkey = self.__oldkey__ # save this here as get_modified will reset it modified_id = self.__class__.__id__.get_modified(self) if isinstance(self.__class__.__id__, SettingsObjectID) else None modified_settings = self.get_modified() if not modified_id and not modified_settings and self.__state__ != 'new': return if self.__state__ == 'new': configuration.update(self.__key__, self.__getstate__()) self.__state__ = 'active' notification_center.post_notification('CFGSettingsObjectWasActivated', sender=self) notification_center.post_notification('CFGSettingsObjectWasCreated', sender=self) modified_data = None elif not modified_id and all(isinstance(self.__settings__[key], RuntimeSetting) for key in modified_settings): notification_center.post_notification('CFGSettingsObjectDidChange', sender=self, data=NotificationData(modified=modified_settings)) return else: if modified_id: configuration.rename(oldkey, self.__key__) if modified_settings: configuration.update(self.__key__, self.__getstate__()) modified_data = modified_settings or {} if modified_id: modified_data['__id__'] = modified_id notification_center.post_notification('CFGSettingsObjectDidChange', sender=self, data=NotificationData(modified=modified_data)) try: configuration.save() except Exception as e: log.exception() notification_center.post_notification('CFGManagerSaveFailed', sender=configuration, data=NotificationData(object=self, operation='save', modified=modified_data, exception=e))
def _clear_pending_receipts(self): notification_center = NotificationCenter() while self.pending_receipts: message_id, timer = self.pending_receipts.popitem() timer.cancel() notification_center.post_notification('XMPPChatSessionDidNotDeliverMessage', sender=self, data=NotificationData(message_id=message_id, code=408, reason='Timeout'))
def _run(self): notification_center = NotificationCenter() while True: item = self.channel.wait() if isinstance(item, ChatMessage): notification_center.post_notification('XMPPChatSessionGotMessage', sender=self, data=NotificationData(message=item)) elif isinstance(item, ChatComposingIndication): if item.state == 'gone': self._clear_pending_receipts() notification_center.post_notification('XMPPChatSessionDidEnd', sender=self, data=NotificationData(originator='remote')) self.state = 'terminated' break else: notification_center.post_notification('XMPPChatSessionGotComposingIndication', sender=self, data=NotificationData(message=item)) elif isinstance(item, MessageReceipt): if item.receipt_id in self.pending_receipts: timer = self.pending_receipts.pop(item.receipt_id) timer.cancel() notification_center.post_notification('XMPPChatSessionDidDeliverMessage', sender=self, data=NotificationData(message_id=item.receipt_id)) elif isinstance(item, ErrorStanza): if item.id in self.pending_receipts: timer = self.pending_receipts.pop(item.id) timer.cancel() # TODO: translate cause notification_center.post_notification('XMPPChatSessionDidNotDeliverMessage', sender=self, data=NotificationData(message_id=item.id, code=503, reason='Service Unavailable')) self._proc = None
def lookup_xcap_server(self, uri, timeout=3.0, lifetime=15.0): """ Performs a TXT query against xcap.<uri.host> and returns all results that look like HTTP URIs. """ log_context = dict(context='lookup_xcap_server', uri=uri) notification_center = NotificationCenter() try: # If the host part of the URI is an IP address, we cannot not do any lookup if re.match("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", uri.host.decode()): raise DNSLookupError("Cannot perform DNS query because the host is an IP address") resolver = DNSResolver() resolver.cache = self.cache resolver.timeout = timeout resolver.lifetime = lifetime record_name = 'xcap.%s' % uri.host.decode() results = [] try: answer = resolver.query(record_name, rdatatype.TXT) except (gresolver.Timeout, gresolver.NoNameservers) as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='TXT', query_name=str(record_name), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) raise except exception.DNSException as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='TXT', query_name=str(record_name), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) else: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='TXT', query_name=str(record_name), nameservers=resolver.nameservers, answer=answer, error=None, **log_context)) for result_uri in list(chain(*(r.strings for r in answer.rrset))): parsed_uri = urlparse(result_uri.decode()) if parsed_uri.scheme in ('http', 'https') and parsed_uri.netloc: results.append(result_uri.decode()) if not results: raise DNSLookupError('No XCAP servers found for domain %s' % uri.host.decode()) return results except (gresolver.Timeout, gresolver.NoNameservers): raise DNSLookupError('Timeout in lookup for XCAP servers for domain %s' % uri.host.decode())
def _msrp_reader(self): notification_center = NotificationCenter() while True: data = self.incoming_msrp_queue.wait() notification_center.post_notification('ScreenSharingStreamGotData', sender=self, data=NotificationData(data=data))
def _msrp_writer(self): while True: try: data = self.outgoing_queue.wait() chunk = self.msrp.make_send_request(data=data) chunk.add_header(SuccessReportHeader('no')) chunk.add_header(FailureReportHeader('partial')) chunk.add_header(ContentTypeHeader('application/x-rfb')) self.msrp.write_chunk(chunk) except Exception as e: self.msrp_writer_thread = None # avoid issues caused by the notification handler killing this greenlet during post_notification if self.shutting_down and isinstance(e, ConnectionDone): break self._failure_reason = str(e) NotificationCenter().post_notification('MediaStreamDidFail', sender=self, data=NotificationData(context='sending', reason=self._failure_reason)) break
def _msrp_reader(self): while True: try: chunk = self.msrp.read_chunk() if chunk.method in (None, 'REPORT'): continue elif chunk.method == 'SEND': if chunk.content_type in self.accept_types: self.incoming_queue.send(chunk.data) response = make_response(chunk, 200, 'OK') report = make_report(chunk, 200, 'OK') else: response = make_response(chunk, 415, 'Invalid Content-Type') report = None else: response = make_response(chunk, 501, 'Unknown method') report = None if response is not None: self.msrp.write_chunk(response) if report is not None: self.msrp.write_chunk(report) except Exception as e: self.msrp_reader_thread = None # avoid issues caused by the notification handler killing this greenlet during post_notification if self.shutting_down and isinstance(e, ConnectionDone): break self._failure_reason = str(e) NotificationCenter().post_notification('MediaStreamDidFail', sender=self, data=NotificationData(context='reading', reason=self._failure_reason)) break
def _start_vnc_connection(self): try: self.vnc_socket = GreenSocket(tcp_socket()) self.vnc_socket.settimeout(self.connect_timeout) self.vnc_socket.connect(self.address) self.vnc_socket.settimeout(None) except Exception as e: self.vnc_starter_thread = None # avoid issues caused by the notification handler killing this greenlet during post_notification NotificationCenter().post_notification('ScreenSharingHandlerDidFail', sender=self, data=NotificationData(context='connecting', reason=str(e))) else: self.msrp_reader_thread = spawn(self._msrp_reader) self.msrp_writer_thread = spawn(self._msrp_writer) finally: self.vnc_starter_thread = None
def _msrp_writer(self): while True: try: data = self.vnc_socket.recv(2048) if not data: raise VNCConnectionError("connection to the VNC server was closed") self.outgoing_msrp_queue.send(data) except Exception as e: self.msrp_writer_thread = None # avoid issues caused by the notification handler killing this greenlet during post_notification NotificationCenter().post_notification('ScreenSharingHandlerDidFail', sender=self, data=NotificationData(context='reading', reason=str(e))) break
def __init__(self, **kwargs): self.timestamp = datetime.now(tzlocal()) NotificationData.__init__(self, **kwargs)
def _msrp_reader(self): while True: try: data = self.incoming_msrp_queue.wait() self.vnc_socket.sendall(data) except Exception as e: self.msrp_reader_thread = None # avoid issues caused by the notification handler killing this greenlet during post_notification NotificationCenter().post_notification('ScreenSharingHandlerDidFail', sender=self, data=NotificationData(context='sending', reason=str(e))) break
def _lookup_a_records(self, resolver, hostnames, additional_records=[], log_context={}): notification_center = NotificationCenter() additional_addresses = dict((rset.name.to_text(), rset) for rset in additional_records if rset.rdtype == rdatatype.A) addresses = {} for hostname in hostnames: if hostname in additional_addresses: addresses[hostname] = [r.address for r in additional_addresses[hostname]] else: try: answer = resolver.query(hostname, rdatatype.A) except (gresolver.Timeout, gresolver.NoNameservers) as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='A', query_name=str(hostname), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) raise except exception.DNSException as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='A', query_name=str(hostname), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) addresses[hostname] = [] else: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='A', query_name=str(hostname), nameservers=resolver.nameservers, answer=answer, error=None, **log_context)) addresses[hostname] = [r.address for r in answer.rrset] return addresses
def _receipt_timer_expired(self, message_id): self.pending_receipts.pop(message_id) NotificationCenter().post_notification('XMPPChatSessionDidNotDeliverMessage', sender=self, data=NotificationData(message_id=message_id, code=408, reason='Timeout'))
def _lookup_srv_records(self, resolver, srv_names, additional_records=[], log_context={}): notification_center = NotificationCenter() additional_services = dict((rset.name.to_text(), rset) for rset in additional_records if rset.rdtype == rdatatype.SRV) services = {} for srv_name in srv_names: services[srv_name] = [] if srv_name in additional_services: addresses = self._lookup_a_records(resolver, [r.target.to_text() for r in additional_services[srv_name]], additional_records) for record in additional_services[srv_name]: services[srv_name].extend(SRVResult(record.priority, record.weight, record.port, addr) for addr in addresses.get(record.target.to_text(), ())) else: try: answer = resolver.query(srv_name, rdatatype.SRV) except (gresolver.Timeout, gresolver.NoNameservers) as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='SRV', query_name=str(srv_name), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) raise except exception.DNSException as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='SRV', query_name=str(srv_name), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) else: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='SRV', query_name=str(srv_name), nameservers=resolver.nameservers, answer=answer, error=None, **log_context)) addresses = self._lookup_a_records(resolver, [r.target.to_text() for r in answer.rrset], answer.response.additional, log_context) for record in answer.rrset: services[srv_name].extend(SRVResult(record.priority, record.weight, record.port, addr) for addr in addresses.get(record.target.to_text(), ())) services[srv_name].sort(key=lambda result: (result.priority, -result.weight)) return services
def __setstate__(self, state): configuration_manager = ConfigurationManager() notification_center = NotificationCenter() for name, value in state.items(): attribute = getattr(self.__class__, name, None) if isinstance(attribute, SettingsGroupMeta): group = getattr(self, name) try: group.__setstate__(value) except ValueError as e: notification_center.post_notification('CFGManagerLoadFailed', sender=configuration_manager, data=NotificationData(attribute=name, container=self, error=e)) elif isinstance(attribute, AbstractSetting): try: attribute.__setstate__(self, value) except ValueError as e: notification_center.post_notification('CFGManagerLoadFailed', sender=configuration_manager, data=NotificationData(attribute=name, container=self, error=e))
def _lookup_naptr_record(self, resolver, domain, services, log_context={}): notification_center = NotificationCenter() pointers = [] try: answer = resolver.query(domain, rdatatype.NAPTR) except (gresolver.Timeout, gresolver.NoNameservers) as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='NAPTR', query_name=str(domain), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) raise except exception.DNSException as e: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='NAPTR', query_name=str(domain), nameservers=resolver.nameservers, answer=None, error=e, **log_context)) else: notification_center.post_notification('DNSLookupTrace', sender=self, data=NotificationData(query_type='NAPTR', query_name=str(domain), nameservers=resolver.nameservers, answer=answer, error=None, **log_context)) records = [r for r in answer.rrset if r.service.decode().lower() in services] services = self._lookup_srv_records(resolver, [r.replacement.to_text() for r in records], answer.response.additional, log_context) for record in records: pointers.extend(NAPTRResult(record.service.decode().lower(), record.order, record.preference, r.priority, r.weight, r.port, r.address) for r in services.get(record.replacement.to_text(), ())) pointers.sort(key=lambda result: (result.order, result.preference)) return pointers
def delete(self): """ Remove this object from the persistent configuration. """ if self.__id__ is self.__class__.__id__: raise TypeError("cannot delete %s instance with default id" % self.__class__.__name__) if self.__state__ == 'deleted': return self.__state__ = 'deleted' configuration = ConfigurationManager() notification_center = NotificationCenter() configuration.delete(self.__oldkey__) # we need the key that wasn't yet saved notification_center.post_notification('CFGSettingsObjectWasDeleted', sender=self) try: configuration.save() except Exception as e: log.exception() notification_center.post_notification('CFGManagerSaveFailed', sender=configuration, data=NotificationData(object=self, operation='delete', exception=e))
def nameservers(self, value): old_value = self.__dict__.get('nameservers', Null) self.__dict__['nameservers'] = value if old_value is Null: NotificationCenter().post_notification('DNSResolverDidInitialize', sender=self, data=NotificationData(nameservers=value)) elif value != old_value: NotificationCenter().post_notification('DNSNameserversDidChange', sender=self, data=NotificationData(nameservers=value))
def end(self): with self._lock: if self.state == "ENDED" or self._done: return self._done = True if not self._initialized: self.state = "ENDED" self.notification_center.post_notification('MediaStreamDidNotInitialize', sender=self, data=NotificationData(reason='Interrupted')) return if self._keyframe_timer is not None: self._keyframe_timer.stop() self.notification_center.remove_observer(self, sender=self._keyframe_timer) self._keyframe_timer = None self.notification_center.post_notification('MediaStreamWillEnd', sender=self) if self._transport is not None: self.notification_center.remove_observer(self, sender=self._transport) self.notification_center.remove_observer(self, sender=self._rtp_transport) call_in_thread('device-io', self._transport.stop) self._transport = None self._rtp_transport = None self.state = "ENDED" self.notification_center.post_notification('MediaStreamDidEnd', sender=self, data=NotificationData(error=self._failure_reason)) self.session = None
def wrapper(obj, *args, **kwargs): notification_center = NotificationCenter() try: result = func(obj, *args, **kwargs) except DNSLookupError as e: notification_center.post_notification('DNSLookupDidFail', sender=obj, data=NotificationData(error=str(e))) raise else: notification_center.post_notification('DNSLookupDidSucceed', sender=obj, data=NotificationData(result=result)) return result
def _CH_eof(self, char): notification_center = NotificationCenter() notification_center.post_notification('UIInputGotCommand', sender=self, data=NotificationData(command='eof', args=[]))
def end(self): self._proc.kill() self._proc = None NotificationCenter().post_notification('XMPPIncomingMucSessionDidEnd', sender=self, data=NotificationData(originator='local')) self.state = 'terminated'
def peer_name(self, name): old_name = self.peer_name new_name = self.__dict__['peer_name'] = name if old_name != new_name: trusted_peer = self.otr_cache.trusted_peers.get(self.peer_fingerprint, None) if trusted_peer is not None: trusted_peer.description = new_name self.otr_cache.save() notification_center = NotificationCenter() notification_center.post_notification("ChatStreamOTRPeerNameChanged", sender=self.stream, data=NotificationData(name=name))
def _run(self): notification_center = NotificationCenter() while True: item = self.channel.wait() if isinstance(item, GroupChatMessage): notification_center.post_notification('XMPPIncomingMucSessionGotMessage', sender=self, data=NotificationData(message=item)) elif isinstance(item, GroupChatSubject): notification_center.post_notification('XMPPIncomingMucSessionSubject', sender=self, data=NotificationData(message=item)) elif isinstance(item, MUCAvailabilityPresence): if item.available: nickname = item.recipient.uri.resource notification_center.post_notification('XMPPIncomingMucSessionChangedNickname', sender=self, data=NotificationData(stanza=item, nickname=nickname)) else: notification_center.post_notification('XMPPIncomingMucSessionDidEnd', sender=self, data=NotificationData(originator='local')) self.state = 'terminated' break self._proc = None
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'): 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() viewer.gotMessage(sender_identity, call_id, body, is_html, is_replication_message, replication_timestamp) self.windowForViewer(viewer).noteView_isComposing_(viewer, False) if is_replication_message: return if not self.windowForViewer(viewer).window().isKeyWindow(): # notify growl if is_html: nc_body = html2txt(body) else: nc_body = body growl_data = NotificationData() growl_data.content = nc_body growl_data.sender = format_identity_to_string(sender_identity, format='compact') self.notification_center.post_notification("GrowlGotSMS", sender=self, data=growl_data) nc_title = 'SMS Message Received' nc_subtitle = format_identity_to_string(sender_identity, format='full') NSApp.delegate().gui_notify(nc_title, nc_body, nc_subtitle)
def end(self): self.send_composing_indication('gone') self._clear_pending_receipts() self._proc.kill() self._proc = None NotificationCenter().post_notification('XMPPChatSessionDidEnd', sender=self, data=NotificationData(originator='local')) self.state = 'terminated'
def send_composing_indication(self, state, message_id=None, use_receipt=False): message = ChatComposingIndication(self.local_identity, self.remote_identity, state, id=message_id, use_receipt=use_receipt) self.xmpp_manager.send_stanza(message) if message_id is not None: timer = reactor.callLater(30, self._receipt_timer_expired, message_id) self.pending_receipts[message_id] = timer NotificationCenter().post_notification('XMPPChatSessionDidSendMessage', sender=self, data=NotificationData(message=message))
def _subscription_handler(self, command): notification_center = NotificationCenter() settings = SIPSimpleSettings() subscription_uri = self.subscription_uri refresh_interval = command.refresh_interval or self.account.sip.subscribe_interval valid_transports = self.__transports__.intersection( settings.sip.transport_list) try: # Lookup routes if self.account.sip.outbound_proxy is not None and self.account.sip.outbound_proxy.transport in valid_transports: uri = SIPURI(host=self.account.sip.outbound_proxy.host, port=self.account.sip.outbound_proxy.port, parameters={ 'transport': self.account.sip.outbound_proxy.transport }) elif self.account.sip.always_use_my_proxy: uri = SIPURI(host=self.account.id.domain) else: uri = SIPURI(host=subscription_uri.domain) lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy(uri, valid_transports).wait() except DNSLookupError as e: raise SubscriptionError('DNS lookup failed: %s' % e, retry_after=random.uniform(15, 30)) subscription_uri = SIPURI(user=subscription_uri.username, host=subscription_uri.domain) content = self.content timeout = time() + 30 for route in routes: remaining_time = timeout - time() if remaining_time > 0: try: contact_uri = self.account.contact[NoGRUU, route] except KeyError: continue subscription = Subscription( subscription_uri, FromHeader(self.account.uri, self.account.display_name), ToHeader(subscription_uri), ContactHeader(contact_uri), self.event.encode(), RouteHeader(route.uri), credentials=self.account.credentials, refresh=refresh_interval) notification_center.add_observer(self, sender=subscription) try: subscription.subscribe( body=content.body, content_type=content.type, extra_headers=self.extra_headers, timeout=limit(remaining_time, min=1, max=5)) except SIPCoreError: notification_center.remove_observer( self, sender=subscription) raise SubscriptionError('Internal error', retry_after=5) self._subscription = subscription try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionDidStart': break except SIPSubscriptionDidFail as e: notification_center.remove_observer( self, sender=subscription) self._subscription = None if e.data.code == 407: # Authentication failed, so retry the subscription in some time raise SubscriptionError('Authentication failed', retry_after=random.uniform( 60, 120)) elif e.data.code == 423: # Get the value of the Min-Expires header if e.data.min_expires is not None and e.data.min_expires > self.account.sip.subscribe_interval: refresh_interval = e.data.min_expires else: refresh_interval = None raise SubscriptionError( 'Interval too short', retry_after=random.uniform(60, 120), refresh_interval=refresh_interval) elif e.data.code in (405, 406, 489): raise SubscriptionError( 'Method or event not supported', retry_after=3600) elif e.data.code == 1400: raise SubscriptionError(e.data.reason, retry_after=3600) else: # Otherwise just try the next route continue else: self.subscribed = True command.signal() break else: # There are no more routes to try, reschedule the subscription raise SubscriptionError('No more routes to try', retry_after=random.uniform(60, 180)) # At this point it is subscribed. Handle notifications and ending/failures. notification_center.post_notification(self.__nickname__ + 'SubscriptionDidStart', sender=self) try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionGotNotify': notification_center.post_notification( self.__nickname__ + 'SubscriptionGotNotify', sender=self, data=notification.data) elif notification.name == 'SIPSubscriptionDidEnd': notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='remote')) if self.active: self._command_channel.send(Command('subscribe')) break except SIPSubscriptionDidFail: notification_center.post_notification(self.__nickname__ + 'SubscriptionDidFail', sender=self) if self.active: self._command_channel.send(Command('subscribe')) notification_center.remove_observer(self, sender=self._subscription) except InterruptSubscription as e: if not self.subscribed: command.signal(e) if self._subscription is not None: notification_center.remove_observer(self, sender=self._subscription) try: self._subscription.end(timeout=2) except SIPCoreError: pass finally: notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='local')) except TerminateSubscription as e: if not self.subscribed: command.signal(e) if self._subscription is not None: try: self._subscription.end(timeout=2) except SIPCoreError: pass else: try: while True: notification = self._data_channel.wait() if notification.name == 'SIPSubscriptionDidEnd': break except SIPSubscriptionDidFail: pass finally: notification_center.remove_observer( self, sender=self._subscription) notification_center.post_notification( self.__nickname__ + 'SubscriptionDidEnd', sender=self, data=NotificationData(originator='local')) except SubscriptionError as e: def subscribe(e): if self.active: self._command_channel.send( Command('subscribe', command.event, refresh_interval=e.refresh_interval)) self._subscription_timer = None self._subscription_timer = reactor.callLater( e.retry_after, subscribe, e) notification_center.post_notification(self.__nickname__ + 'SubscriptionDidFail', sender=self) finally: self.subscribed = False self._subscription = None self._subscription_proc = None