def set_entity_time(self, obj): if obj.conn.name != self.account: return if self.xml.get_object('information_notebook').get_n_pages() < 5: return if self.gc_contact: if obj.fjid != self.contact.jid: return elif app.get_jid_without_resource(obj.fjid) != self.contact.jid: return i = 0 time_s = '' while i in self.time_info: if self.time_info[i]['resource'] == obj.resource: if obj.time_info: self.time_info[i]['time'] = obj.time_info else: self.time_info[i]['time'] = Q_('?Time:Unknown') else: if not self.time_info[i]['time']: self.time_info[i]['time'] = Q_('?Time:Unknown') if i > 0: time_s += '\n' time_s += self.time_info[i]['time'] i += 1 self.xml.get_object('time_label').set_text(time_s) self.entity_time_arrived = True
def _fill_content(self, content): description_node = nbxmpp.simplexml.Node( tag=nbxmpp.NS_JINGLE_FILE_TRANSFER_5 + ' description') file_tag = description_node.setTag('file') if self.file_props.name: node = nbxmpp.simplexml.Node(tag='name') node.addData(self.file_props.name) file_tag.addChild(node=node) if self.file_props.date: node = nbxmpp.simplexml.Node(tag='date') node.addData(self.file_props.date) file_tag.addChild(node=node) if self.file_props.size: node = nbxmpp.simplexml.Node(tag='size') node.addData(self.file_props.size) file_tag.addChild(node=node) if self.file_props.type_ == 'r': if self.file_props.hash_: file_tag.addChild('hash', attrs={'algo': self.file_props.algo}, namespace=nbxmpp.NS_HASHES_2, payload=self.file_props.hash_) else: # if the file is less than 10 mb, then it is small # lets calculate it right away if self.file_props.size < 10000000 and not self.file_props.hash_: hash_data = self._compute_hash() if hash_data: file_tag.addChild(node=hash_data) pjid = app.get_jid_without_resource(self.session.peerjid) file_info = { 'name': self.file_props.name, 'file-name': self.file_props.file_name, 'hash': self.file_props.hash_, 'size': self.file_props.size, 'date': self.file_props.date, 'peerjid': pjid } self.session.connection.get_module('Jingle').set_file_info( file_info) desc = file_tag.setTag('desc') if self.file_props.desc: desc.setData(self.file_props.desc) if self.use_security: security = nbxmpp.simplexml.Node(tag=nbxmpp.NS_JINGLE_XTLS + ' security') certpath = os.path.join(configpaths.get('MY_CERT'), SELF_SIGNED_CERTIFICATE) + '.cert' cert = load_cert_file(certpath) if cert: digest_algo = (cert.get_signature_algorithm().decode( 'utf-8').split('With')[0]) security.addChild('fingerprint').addData( cert.digest(digest_algo).decode('utf-8')) for m in ('x509', ): # supported authentication methods method = nbxmpp.simplexml.Node(tag='method') method.setAttr('name', m) security.addChild(node=method) content.addChild(node=security) content.addChild(node=description_node)
def on_ok(_waitid): # if timeout: # self._owner.set_timeout(timeout) to = stanza.getTo() to = app.get_jid_without_resource(to) try: item = self.roster[to] except KeyError: # Contact offline item = None conn = None if to in self.recipient_to_hash: conn = self.connections[self.recipient_to_hash[to]] elif item: the_address = None for address in item['addresses']: if address['address'] in self.ip_to_hash: the_address = address if the_address and the_address['address'] in self.ip_to_hash: hash_ = self.ip_to_hash[the_address['address']] if self.hash_to_port[hash_] == the_address['port']: conn = self.connections[hash_] if func: conn.Dispatcher.on_responses[_waitid] = (func, args) conn.onreceive(conn.Dispatcher._WaitForData) conn.Dispatcher._expected[_waitid] = None
def close(ctrl): if reason is not None: # We are leaving gc with a status message ctrl.shutdown(reason) else: # We are leaving gc without status message or it's a chat ctrl.shutdown() # Update external state app.events.remove_events(ctrl.account, ctrl.get_full_jid, types=['printed_msg', 'chat', 'gc_msg']) fjid = ctrl.get_full_jid() jid = app.get_jid_without_resource(fjid) fctrl = self.get_control(fjid, ctrl.account) bctrl = self.get_control(jid, ctrl.account) # keep last_message_time around unless this was our last control with # that jid if not fctrl and not bctrl and \ fjid in app.last_message_time[ctrl.account]: del app.last_message_time[ctrl.account][fjid] self.notebook.remove_page(self.notebook.page_num(ctrl.widget)) del self._controls[ctrl.account][fjid] if not self._controls[ctrl.account]: del self._controls[ctrl.account] self.check_tabs() self.show_title()
def _connect_error(self, sid, error, error_type, msg=None): """ Called when there is an error establishing BS connection, or when connection is rejected """ if not app.account_is_connected(self._account): return file_props = FilesProp.getFileProp(self._account, sid) if file_props is None: log.error('can not send iq error on failed transfer') return if file_props.type_ == 's': to = file_props.receiver else: to = file_props.sender iq = nbxmpp.Iq(to=to, typ='error') iq.setAttr('id', file_props.request_id) err = iq.setTag('error') err.setAttr('type', error_type) err.setTag(error, namespace=nbxmpp.NS_STANZAS) self._con.connection.send(iq) if msg: self.disconnect_transfer(file_props) file_props.error = -3 app.nec.push_incoming_event( NetworkEvent('file-request-error', conn=self._con, jid=app.get_jid_without_resource(to), file_props=file_props, error_msg=msg))
def encrypt_message(self, conn, event, callback, groupchat): if not event.message: callback(event) return to_jid = app.get_jid_without_resource(event.jid) omemo_message = self.backend.encrypt(to_jid, event.message) if omemo_message is None: session = event.session if hasattr(event, 'session') else None app.nec.push_incoming_event( NetworkEvent('message-not-sent', conn=conn, jid=event.jid, message=event.message, error=_('Encryption error'), time_=time.time(), session=session)) return create_omemo_message(event.msg_iq, omemo_message, node_whitelist=ALLOWED_TAGS) if groupchat: self._muc_temp_store[omemo_message.payload] = event.message else: event.xhtml = None event.encrypted = ENCRYPTION_NAME event.additional_data['encrypted'] = {'name': ENCRYPTION_NAME} self._debug_print_stanza(event.msg_iq) callback(event)
def send_contacts(self, contacts, fjid, type_='message'): if not app.account_is_connected(self._account): return if type_ == 'message': if len(contacts) == 1: msg = _('Sent contact: "%(jid)s" (%(name)s)') % { 'jid': contacts[0].get_full_jid(), 'name': contacts[0].get_shown_name() } else: msg = _('Sent contacts:') for contact in contacts: msg += '\n "%s" (%s)' % (contact.get_full_jid(), contact.get_shown_name()) stanza = nbxmpp.Message(to=app.get_jid_without_resource(fjid), body=msg) elif type_ == 'iq': stanza = nbxmpp.Iq(to=fjid, typ='set') x = stanza.addChild(name='x', namespace=nbxmpp.NS_ROSTERX) for contact in contacts: name = contact.get_shown_name() x.addChild(name='item', attrs={ 'action': 'add', 'jid': contact.jid, 'name': name }) log.info('Send contact: %s %s', contact.jid, name) self._con.connection.send(stanza)
def _remove_transfer(self, iter_, sid, file_props): self.model.remove(iter_) if not file_props: return if file_props.tt_account: # file transfer is set account = file_props.tt_account if account in app.connections: # there is a connection to the account app.connections[account].remove_transfer(file_props) if file_props.type_ == 'r': # we receive a file other = file_props.sender else: # we send a file other = file_props.receiver if isinstance(other, str): jid = app.get_jid_without_resource(other) else: # It's a Contact instance jid = other.jid for ev_type in ('file-error', 'file-completed', 'file-request-error', 'file-send-error', 'file-stopped'): for event in app.events.get_events(account, jid, [ev_type]): if event.file_props.sid == file_props.sid: app.events.remove_events(account, jid, event) app.interface.roster.draw_contact(jid, account) app.interface.roster.show_title() FilesProp.deleteFileProp(file_props) del (file_props)
def _nec_raw_message(self, obj): if not HAS_GOOCANVAS: return if obj.stanza.getTag('sxe', namespace=NS_SXE): account = obj.conn.name try: fjid = helpers.get_full_jid_from_iq(obj.stanza) except helpers.InvalidFormat: obj.conn.dispatch('ERROR', (_('Invalid XMPP Address'), _('A message from a non-valid XMPP address ' 'arrived. It has been ignored.'))) jid = app.get_jid_without_resource(fjid) ctrl = (app.interface.msg_win_mgr.get_control(fjid, account) or app.interface.msg_win_mgr.get_control(jid, account)) if not ctrl: return sxe = obj.stanza.getTag('sxe') if not sxe: return sid = sxe.getAttr('session') if (jid, sid) not in obj.conn.get_module('Jingle')._sessions: pass # newjingle = JingleSession(con=self, weinitiate=False, jid=jid, # sid=sid) # self.addJingle(newjingle) # We already have such session in dispatcher session = obj.conn.get_module('Jingle').get_jingle_session(fjid, sid) cn = session.contents[('initiator', 'xhtml')] error = obj.stanza.getTag('error') if error: action = 'iq-error' else: action = 'edit' cn.on_stanza(obj.stanza, sxe, error, action) # def __editCB(self, stanza, content, error, action): # new_tags = sxe.getTags('new') # remove_tags = sxe.getTags('remove') # if new_tags is not None: # # Process new elements # for tag in new_tags: # if tag.getAttr('type') == 'element': # ctrl.whiteboard.recieve_element(tag) # elif tag.getAttr('type') == 'attr': # ctrl.whiteboard.recieve_attr(tag) # ctrl.whiteboard.apply_new() # if remove_tags is not None: # # Delete rids # for tag in remove_tags: # target = tag.getAttr('target') # ctrl.whiteboard.image.del_rid(target) # Stop propagating this event, it's handled return True
def send_file_approval(self, file_props): """ Send iq, confirming that we want to download the file """ # user response to ConfirmationDialog may come after we've disconneted if not self.connection or self.connected < 2: return # file transfer initiated by a jingle session log.info("send_file_approval: jingle session accept") if file_props.session_type == 'jingle': session = self.get_jingle_session(file_props.sender, file_props.sid) if not session: return content = None for c in session.contents.values(): if c.transport.sid == file_props.transport_sid: content = c break if not content: return if not session.accepted: content = session.get_content('file', content.name) if content.use_security: fingerprint = content.x509_fingerprint if not jingle_xtls.check_cert( app.get_jid_without_resource(file_props.sender), fingerprint): id_ = jingle_xtls.send_cert_request( self, file_props.sender) jingle_xtls.key_exchange_pend(id_, content.on_cert_received, []) return session.approve_session() session.approve_content('file', content.name) return iq = nbxmpp.Iq(to=file_props.sender, typ='result') iq.setAttr('id', file_props.request_id) si = iq.setTag('si', namespace=nbxmpp.NS_SI) if file_props.offset: file_tag = si.setTag('file', namespace=nbxmpp.NS_FILE) range_tag = file_tag.setTag('range') range_tag.setAttr('offset', file_props.offset) feature = si.setTag('feature', namespace=nbxmpp.NS_FEATURE) _feature = nbxmpp.DataForm(typ='submit') feature.addChild(node=_feature) field = _feature.setField('stream-method') field.delAttr('type') if nbxmpp.NS_BYTESTREAM in file_props.stream_methods: field.setValue(nbxmpp.NS_BYTESTREAM) else: file_props.transport_sid = file_props.sid field.setValue(nbxmpp.NS_IBB) self.connection.send(iq)
def delete_session(self, jid, thread_id): if not jid in self.sessions: jid = app.get_jid_without_resource(jid) if not jid in self.sessions: return del self.sessions[jid][thread_id] if not self.sessions[jid]: del self.sessions[jid]
def get_sessions(self, jid): """ Get all sessions for the given full jid """ if not app.interface.is_pm_contact(jid, self.name): jid = app.get_jid_without_resource(jid) try: return list(self.sessions[jid].values()) except KeyError: return []
def __on_transport_info(self, stanza, content, error, action): log.info("__on_transport_info") cand_error = content.getTag('transport').getTag('candidate-error') cand_used = content.getTag('transport').getTag('candidate-used') if (cand_error or cand_used) and \ self.state >= State.CAND_SENT_AND_RECEIVED: raise nbxmpp.NodeProcessed if cand_error: if not app.socks5queue.listener.connections: app.socks5queue.listener.disconnect() self.nominated_cand['peer-cand'] = False if self.state == State.CAND_SENT: if not self.nominated_cand['our-cand'] and \ not self.nominated_cand['peer-cand']: if not self.weinitiate: return self.__state_changed(State.TRANSPORT_REPLACE) else: response = stanza.buildReply('result') response.delChild(response.getQuery()) self.session.connection.connection.send(response) self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: args = {'candError' : True} self.__state_changed(State.CAND_RECEIVED, args) return if cand_used: streamhost_cid = cand_used.getAttr('cid') streamhost_used = None for cand in self.transport.candidates: if cand['candidate_id'] == streamhost_cid: streamhost_used = cand break if streamhost_used is None or streamhost_used['type'] == 'proxy': if app.socks5queue.listener and \ not app.socks5queue.listener.connections: app.socks5queue.listener.disconnect() if content.getTag('transport').getTag('activated'): self.state = State.TRANSFERING jid = app.get_jid_without_resource(self.session.ourjid) app.socks5queue.send_file(self.file_props, self.session.connection.name, 'client') return args = {'content': content, 'sendCand': False} if self.state == State.CAND_SENT: self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: self.__state_changed(State.CAND_RECEIVED, args)
def encrypt_message(self, con, event, callback): if not event.message: callback(event) return to_jid = app.get_jid_without_resource(event.jid) try: key_id, own_key_id = self._get_key_ids(to_jid) except NoKeyIdFound as error: self._log.warning(error) return always_trust = key_id in self._always_trust self._encrypt(con, event, [key_id, own_key_id], callback, always_trust)
def __send_hash(self): # Send hash in a session info checksum = nbxmpp.Node(tag='checksum', payload=[nbxmpp.Node(tag='file', payload=[self._compute_hash()])]) checksum.setNamespace(nbxmpp.NS_JINGLE_FILE_TRANSFER_5) self.session.__session_info(checksum) pjid = app.get_jid_without_resource(self.session.peerjid) file_info = {'name' : self.file_props.name, 'file-name' : self.file_props.file_name, 'hash' : self.file_props.hash_, 'size' : self.file_props.size, 'date' : self.file_props.date, 'peerjid' : pjid } self.session.connection.get_module('Jingle').set_file_info(file_info)
def handle_new_cert(con, obj, jid_from): jid = app.get_jid_without_resource(jid_from) certpath = configpaths.get('MY_PEER_CERTS').expanduser() / (jid + '.cert') id_ = obj.getAttr('id') x509cert = obj.getTag('pubkeys').getTag('keyinfo').getTag('x509cert') cert = x509cert.getData() f = open(certpath, 'w') f.write('-----BEGIN CERTIFICATE-----\n') f.write(cert) f.write('-----END CERTIFICATE-----\n') f.close() approve_pending_content(id_)
def _on_bytestream_error(self, _con, iq_obj): id_ = iq_obj.getAttr('id') frm = helpers.get_full_jid_from_iq(iq_obj) query = iq_obj.getTag('query') app.proxy65_manager.error_cb(frm, query) jid = helpers.get_jid_from_iq(iq_obj) id_ = id_[3:] file_props = FilesProp.getFilePropBySid(id_) if not file_props: return file_props.error = -4 app.nec.push_incoming_event( NetworkEvent('file-request-error', conn=self._con, jid=app.get_jid_without_resource(jid), file_props=file_props, error_msg='')) raise nbxmpp.NodeProcessed
def __init__(self, conn, jid, thread_id, type_): self.conn = conn self.jid = jid self.type_ = type_ self.resource = jid.getResource() if thread_id: self.received_thread_id = True self.thread_id = thread_id else: self.received_thread_id = False self.thread_id = self.generate_thread_id() contact = app.contacts.get_contact( conn.name, app.get_jid_without_resource(str(jid))) self.name = contact.get_shown_name() self.base = None self.control = None self.enable_encryption = False
def start_file_transfer(self, jid, file_props, request=False): logger.info("start file transfer with file: %s", file_props) contact = app.contacts.get_contact_with_highest_priority( self._account, app.get_jid_without_resource(jid)) if app.contacts.is_gc_contact(self._account, jid): gcc = jid.split('/') if len(gcc) == 2: contact = app.contacts.get_gc_contact(self._account, gcc[0], gcc[1]) if contact is None: return None use_security = contact.supports(Namespace.JINGLE_XTLS) jingle = JingleSession(self._con, weinitiate=True, jid=jid, werequest=request) # this is a file transfer jingle.session_type_ft = True self._sessions[jingle.sid] = jingle file_props.sid = jingle.sid if contact.supports(Namespace.JINGLE_BYTESTREAM): transport = JingleTransportSocks5() elif contact.supports(Namespace.JINGLE_IBB): transport = JingleTransportIBB() else: transport = None senders = 'initiator' if request: senders = 'responder' transfer = JingleFileTransfer(jingle, transport=transport, file_props=file_props, use_security=use_security, senders=senders) file_props.transport_sid = transport.sid file_props.algo = self.__hash_support(contact) jingle.add_content('file' + helpers.get_random_string(), transfer) jingle.start_session() return transfer.transport.sid
def get_or_create_session(self, fjid, thread_id): """ Return an existing session between this connection and 'jid', returns a new one if none exist """ pm = True jid = fjid if not app.interface.is_pm_contact(fjid, self.name): pm = False jid = app.get_jid_without_resource(fjid) session = self.find_session(jid, thread_id) if session: return session if pm: return self.make_new_session(fjid, thread_id, type_='pm') return self.make_new_session(fjid, thread_id)
def __on_session_accept(self, stanza, content, error, action): log.info("__on_session_accept") con = self.session.connection security = content.getTag('security') if not security: # responder can not verify our fingerprint self.use_security = False else: fingerprint = security.getTag('fingerprint') if fingerprint: fingerprint = fingerprint.getData() self.x509_fingerprint = fingerprint if not jingle_xtls.check_cert(app.get_jid_without_resource( self.session.responder), fingerprint): id_ = jingle_xtls.send_cert_request(con, self.session.responder) jingle_xtls.key_exchange_pend(id_, self.continue_session_accept, [stanza]) raise nbxmpp.NodeProcessed self.continue_session_accept(stanza)
def __init__(self, account, contact_jid, sid, content_types): self.instances[(contact_jid, sid)] = self self.account = account self.fjid = contact_jid self.sid = sid self.content_types = content_types xml = get_builder('voip_call_received_dialog.ui') xml.connect_signals(self) jid = app.get_jid_without_resource(self.fjid) contact = app.contacts.get_first_contact_from_jid(account, jid) if contact and contact.name: self.contact_text = '%s (%s)' % (contact.name, jid) else: self.contact_text = contact_jid self.dialog = xml.get_object('voip_call_received_messagedialog') self.set_secondary_text() self.dialog.show_all()
def stop_all_active_file_transfers(self, contact): """ Stop all active transfer to or from the given contact """ for file_props in FilesProp.getAllFileProp(): if is_transfer_stopped(file_props): continue receiver_jid = file_props.receiver if contact.get_full_jid() == receiver_jid: file_props.error = -5 self.remove_transfer(file_props) app.nec.push_incoming_event( NetworkEvent('file-request-error', conn=self._con, jid=app.get_jid_without_resource(contact.jid), file_props=file_props, error_msg='')) sender_jid = file_props.sender if contact.get_full_jid() == sender_jid: file_props.error = -3 self.remove_transfer(file_props)
def send_file_approval(self, file_props): """ Send iq, confirming that we want to download the file """ # user response to ConfirmationDialog may come after we've disconneted if not app.account_is_connected(self._account): return # file transfer initiated by a jingle session log.info("send_file_approval: jingle session accept") session = self._con.get_module('Jingle').get_jingle_session( file_props.sender, file_props.sid) if not session: return content = None for content_ in session.contents.values(): if content_.transport.sid == file_props.transport_sid: content = content_ break if not content: return if not session.accepted: content = session.get_content('file', content.name) if content.use_security: fingerprint = content.x509_fingerprint if not jingle_xtls.check_cert( app.get_jid_without_resource(file_props.sender), fingerprint): id_ = jingle_xtls.send_cert_request( self._con, file_props.sender) jingle_xtls.key_exchange_pend(id_, content.on_cert_received, []) return session.approve_session() session.approve_content('file', content.name)
def set_os_info(self, obj): if obj.conn.name != self.account: return if self.xml.get_object('information_notebook').get_n_pages() < 5: return if self.gc_contact: if obj.fjid != self.contact.jid: return elif app.get_jid_without_resource(obj.fjid) != self.contact.jid: return i = 0 client = '' os = '' while i in self.os_info: if self.os_info[i]['resource'] == obj.resource: if obj.client_info: self.os_info[i]['client'] = obj.client_info else: self.os_info[i]['client'] = Q_('?Client:Unknown') if obj.os_info: self.os_info[i]['os'] = obj.os_info else: self.os_info[i]['os'] = Q_('?OS:Unknown') else: if not self.os_info[i]['client']: self.os_info[i]['client'] = Q_('?Client:Unknown') if not self.os_info[i]['os']: self.os_info[i]['os'] = Q_('?OS:Unknown') if i > 0: client += '\n' os += '\n' client += self.os_info[i]['client'] os += self.os_info[i]['os'] i += 1 self.xml.get_object('client_name_version_label').set_text(client) self.xml.get_object('os_label').set_text(os) self.os_info_arrived = True
def _send_socks5_info(self, file_props): """ Send iq for the present streamhosts and proxies """ if not app.account_is_connected(self._account): return receiver = file_props.receiver sender = file_props.sender sha_str = helpers.get_auth_sha(file_props.sid, sender, receiver) file_props.sha_str = sha_str port = app.config.get('file_transfers_port') listener = app.socks5queue.start_listener(port, sha_str, self._result_socks5_sid, file_props) if not listener: file_props.error = -5 app.nec.push_incoming_event( NetworkEvent('file-request-error', conn=self._con, jid=app.get_jid_without_resource(receiver), file_props=file_props, error_msg='')) self._connect_error(file_props.sid, error='not-acceptable', error_type='modify') else: iq = nbxmpp.Iq(to=receiver, typ='set') file_props.request_id = 'id_' + file_props.sid iq.setID(file_props.request_id) query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM) query.setAttr('sid', file_props.sid) self._add_addiditional_streamhosts_to_query(query, file_props) self._add_local_ips_as_streamhosts_to_query(query, file_props) self._add_proxy_streamhosts_to_query(query, file_props) self._add_upnp_igd_as_streamhost_to_query(query, file_props, iq)
def make_new_session(self, jid, thread_id=None, type_='chat', cls=None): """ Create and register a new session thread_id=None to generate one. type_ should be 'chat' or 'pm'. """ if not cls: cls = app.default_session_type sess = cls(self, nbxmpp.JID(jid), thread_id, type_) # determine if this session is a pm session # if not, discard the resource so that all sessions are stored bare if type_ != 'pm': jid = app.get_jid_without_resource(jid) if not jid in self.sessions: self.sessions[jid] = {} self.sessions[jid][sess.thread_id] = sess return sess
def _send_marker(self, contact, marker, id_, type_): jid = contact.jid if contact.is_pm_contact: jid = app.get_jid_without_resource(contact.jid) if type_ in ('gc', 'pm'): if not app.settings.get_group_chat_setting(self._account, jid, 'send_marker'): return else: if not app.settings.get_contact_setting(self._account, jid, 'send_marker'): return typ = 'groupchat' if type_ == 'gc' else 'chat' message = OutgoingMessage(account=self._account, contact=contact, message=None, type_=typ, marker=(marker, id_), play_sound=False) self._con.send_message(message) self._log.info('Send %s: %s', marker, contact.jid)
def generate(self): jid = str(self.file_props.receiver) self.jid = app.get_jid_without_resource(jid) return True
def generate(self): self.jid = app.get_jid_without_resource(self.jid) return True