trying to show contacts on the roster

This commit is contained in:
Stefan Bethge 2006-05-29 19:57:39 +00:00
parent 589abe37f7
commit 77e53f7488
6 changed files with 117 additions and 1909 deletions

View File

@ -0,0 +1,12 @@
from common import roster_zeroconf
class ClientZeroconf:
def __init__(self, zeroconf):
self.roster = roster_zeroconf.Roster(zeroconf)
def getRoster(self):
return self.roster.getRoster()
def send(self, str):
pass

View File

@ -54,6 +54,7 @@ class Connection(ConnectionHandlers):
self.connection = None # xmpppy ClientCommon instance self.connection = None # xmpppy ClientCommon instance
# this property is used to prevent double connections # this property is used to prevent double connections
self.last_connection = None # last ClientCommon instance self.last_connection = None # last ClientCommon instance
self.is_zeroconf = False
self.gpg = None self.gpg = None
self.status = '' self.status = ''
self.old_show = '' self.old_show = ''

File diff suppressed because it is too large Load Diff

View File

@ -34,12 +34,12 @@ import signal
if os.name != 'nt': if os.name != 'nt':
signal.signal(signal.SIGPIPE, signal.SIG_DFL) signal.signal(signal.SIGPIPE, signal.SIG_DFL)
# import common.xmpp
from common import helpers from common import helpers
from common import gajim from common import gajim
from common import GnuPG from common import GnuPG
from common import zeroconf from common import zeroconf
from common import connection_handlers_zeroconf from common import connection_handlers_zeroconf
from common import client_zeroconf
from connection_handlers_zeroconf import * from connection_handlers_zeroconf import *
USE_GPG = GnuPG.USE_GPG USE_GPG = GnuPG.USE_GPG
@ -55,10 +55,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.zeroconf = zeroconf.Zeroconf() self.zeroconf = zeroconf.Zeroconf()
self.connected = 0 # offline self.connected = 0 # offline
self.connection = None # dummy connection variable self.connection = None # dummy connection variable
# this property is used to prevent double connections # this property is used to prevent double connections
# self.last_connection = None # last ClientCommon instance # self.last_connection = None # last ClientCommon instance
self.gpg = None self.gpg = None
self.is_zeroconf = True
self.status = '' self.status = ''
self.old_show = '' self.old_show = ''
# increase/decrease default timeout for server responses # increase/decrease default timeout for server responses
@ -119,8 +119,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
gajim.log.debug('reconnect') gajim.log.debug('reconnect')
# TODO: no gpg for now, add some day signed = self.get_signed_msg(self.status)
# signed = self.get_signed_msg(self.status)
# We are doing disconnect at so many places, better use one function in all # We are doing disconnect at so many places, better use one function in all
@ -134,103 +133,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.connection = None self.connection = None
self.zeroconf.disconnect() self.zeroconf.disconnect()
'''
def _disconnectedReconnCB(self):
# Called when we are disconnected
gajim.log.debug('disconnectedReconnCB')
if self.connected > 1:
# we cannot change our status to offline or connectiong
# after we auth to server
self.old_show = STATUS_LIST[self.connected]
self.connected = 0
self.dispatch('STATUS', 'offline')
if not self.on_purpose:
self.disconnect()
if gajim.config.get_per('accounts', self.name, 'autoreconnect') \
and self.retrycount <= 10:
self.connected = 1
self.dispatch('STATUS', 'connecting')
self.time_to_reconnect = 10
# this check has moved from _reconnect method
if self.retrycount > 5:
self.time_to_reconnect = 20
else:
self.time_to_reconnect = 10
gajim.idlequeue.set_alarm(self._reconnect_alarm,
self.time_to_reconnect)
elif self.on_connect_failure:
self.on_connect_failure()
self.on_connect_failure = None
else:
# show error dialog
self._connection_lost()
else:
self.disconnect()
self.on_purpose = False
# END disconenctedReconnCB
'''
'''
def _connection_lost(self):
self.disconnect(on_purpose = False)
self.dispatch('STATUS', 'offline')
self.dispatch('ERROR',
(_('Connection with account "%s" has been lost') % self.name,
_('To continue sending and receiving messages, you will need to reconnect.')))
'''
'''
def _event_dispatcher(self, realm, event, data):
if realm == common.xmpp.NS_REGISTER:
if event == common.xmpp.features_nb.REGISTER_DATA_RECEIVED:
# data is (agent, DataFrom, is_form)
if self.new_account_info and\
self.new_account_info['hostname'] == data[0]:
#it's a new account
if not data[1]: # wrong answer
print self.connection.lastErr
self.dispatch('ACC_NOT_OK', (
_('Transport %s answered wrongly to register request.') % \
data[0]))
return
req = data[1].asDict()
req['username'] = self.new_account_info['name']
req['password'] = self.new_account_info['password']
def _on_register_result(result):
if not common.xmpp.isResultNode(result):
self.dispatch('ACC_NOT_OK', (result.getError()))
return
self.connected = 0
self.password = self.new_account_info['password']
if USE_GPG:
self.gpg = GnuPG.GnuPG()
gajim.config.set('usegpg', True)
else:
gajim.config.set('usegpg', False)
gajim.connections[self.name] = self
self.dispatch('ACC_OK', (self.new_account_info))
self.new_account_info = None
self.connection = None
common.xmpp.features_nb.register(self.connection, data[0],
req, _on_register_result)
return
if not data[1]: # wrong answer
self.dispatch('ERROR', (_('Invalid answer'),
_('Transport %s answered wrongly to register request.') % \
data[0]))
return
is_form = data[2]
if is_form:
conf = self.parse_data_form(data[1])
else:
conf = data[1].asDict()
self.dispatch('REGISTER_AGENT_INFO', (data[0], conf, is_form))
elif realm == '':
if event == common.xmpp.transports.DATA_RECEIVED:
self.dispatch('STANZA_ARRIVED', unicode(data, errors = 'ignore'))
elif event == common.xmpp.transports.DATA_SENT:
self.dispatch('STANZA_SENT', unicode(data))
'''
def select_next_host(self, hosts): def select_next_host(self, hosts):
hosts_best_prio = [] hosts_best_prio = []
best_prio = 65535 best_prio = 65535
@ -255,278 +157,11 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
return h return h
def connect(self, data = None, show = 'online'):
if self.connection:
return self.connection, ''
self.zeroconf.connect()
self.connection = 1
self.connected = STATUS_LIST.index(show)
''' Start a connection to the Jabber server.
Returns connection, and connection type ('tls', 'ssl', 'tcp', '')
data MUST contain name, hostname, resource, usessl, proxy,
use_custom_host, custom_host (if use_custom_host), custom_port (if
use_custom_host), '''
'''
if self.connection:
return self.connection, ''
if data:
name = data['name']
hostname = data['hostname']
resource = data['resource']
usessl = data['usessl']
self.try_connecting_for_foo_secs = 45
p = data['proxy']
use_srv = True
use_custom = data['use_custom_host']
if use_custom:
custom_h = data['custom_host']
custom_p = data['custom_port']
else:
name = gajim.config.get_per('accounts', self.name, 'name')
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
resource = gajim.config.get_per('accounts', self.name, 'resource')
usessl = gajim.config.get_per('accounts', self.name, 'usessl')
self.try_connecting_for_foo_secs = gajim.config.get_per('accounts',
self.name, 'try_connecting_for_foo_secs')
p = gajim.config.get_per('accounts', self.name, 'proxy')
use_srv = gajim.config.get_per('accounts', self.name, 'use_srv')
use_custom = gajim.config.get_per('accounts', self.name,
'use_custom_host')
custom_h = gajim.config.get_per('accounts', self.name, 'custom_host')
custom_p = gajim.config.get_per('accounts', self.name, 'custom_port')
#create connection if it doesn't already exist
self.connected = 1
if p and p in gajim.config.get_per('proxies'):
proxy = {'host': gajim.config.get_per('proxies', p, 'host')}
proxy['port'] = gajim.config.get_per('proxies', p, 'port')
proxy['user'] = gajim.config.get_per('proxies', p, 'user')
proxy['password'] = gajim.config.get_per('proxies', p, 'pass')
else:
proxy = None
h = hostname
p = 5222
# autodetect [for SSL in 5223/443 and for TLS if broadcasted]
secur = None
if usessl:
p = 5223
secur = 1 # 1 means force SSL no matter what the port will be
use_srv = False # wants ssl? disable srv lookup
if use_custom:
h = custom_h
p = custom_p
use_srv = False
hosts = []
# SRV resolver
self._proxy = proxy
self._secure = secur
self._hosts = [ {'host': h, 'port': p, 'prio': 10, 'weight': 10} ]
self._hostname = hostname
if use_srv:
# add request for srv query to the resolve, on result '_on_resolve' will be called
gajim.resolver.resolve('_xmpp-client._tcp.' + h.encode('utf-8'), self._on_resolve)
else:
self._on_resolve('', [])
'''
'''
def _on_resolve(self, host, result_array):
# SRV query returned at least one valid result, we put it in hosts dict
if len(result_array) != 0:
self._hosts = [i for i in result_array]
self.connect_to_next_host()
'''
'''
def connect_to_next_host(self, retry = False):
if len(self._hosts):
if self.last_connection:
self.last_connection.socket.disconnect()
self.last_connection = None
self.connection = None
if gajim.verbose:
con = common.xmpp.NonBlockingClient(self._hostname, caller = self,
on_connect = self.on_connect_success,
on_connect_failure = self.connect_to_next_host)
else:
con = common.xmpp.NonBlockingClient(self._hostname, debug = [], caller = self,
on_connect = self.on_connect_success,
on_connect_failure = self.connect_to_next_host)
self.last_connection = con
# increase default timeout for server responses
common.xmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = self.try_connecting_for_foo_secs
con.set_idlequeue(gajim.idlequeue)
host = self.select_next_host(self._hosts)
self._current_host = host
self._hosts.remove(host)
con.connect((host['host'], host['port']), proxy = self._proxy,
secure = self._secure)
return
else:
if not retry or self.retrycount > 10:
self.retrycount = 0
self.time_to_reconnect = None
if self.on_connect_failure:
self.on_connect_failure()
self.on_connect_failure = None
else:
# shown error dialog
self._connection_lost()
else:
# try reconnect if connection has failed before auth to server
self._disconnectedReconnCB()
'''
'''
def _connect_failure(self, con_type = None):
if not con_type:
# we are not retrying, and not conecting
if not self.retrycount and self.connected != 0:
self.disconnect(on_purpose = True)
self.dispatch('STATUS', 'offline')
self.dispatch('ERROR', (_('Could not connect to "%s"') % self._hostname,
_('Check your connection or try again later.')))
'''
'''
def _connect_success(self, con, con_type):
if not self.connected: # We went offline during connecting process
# FIXME - not possible, maybe it was when we used threads
return
self.hosts = []
if not con_type:
gajim.log.debug('Could not connect to %s:%s' % (self._current_host['host'],
self._current_host['port']))
self.connected_hostname = self._current_host['host']
self.on_connect_failure = None
con.RegisterDisconnectHandler(self._disconnectedReconnCB)
gajim.log.debug(_('Connected to server %s:%s with %s') % (self._current_host['host'],
self._current_host['port'], con_type))
# Ask metacontacts before roster
self.get_metacontacts()
self._register_handlers(con, con_type)
return True
'''
'''
def _register_handlers(self, con, con_type):
self.peerhost = con.get_peerhost()
# notify the gui about con_type
self.dispatch('CON_TYPE', con_type)
ConnectionHandlers._register_handlers(self, con, con_type)
name = gajim.config.get_per('accounts', self.name, 'name')
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
resource = gajim.config.get_per('accounts', self.name, 'resource')
self.connection = con
con.auth(name, self.password, resource, 1, self.__on_auth)
'''
'''
def __on_auth(self, con, auth):
if not con:
self.disconnect(on_purpose = True)
self.dispatch('STATUS', 'offline')
self.dispatch('ERROR', (_('Could not connect to "%s"') % self._hostname,
_('Check your connection or try again later')))
if self.on_connect_auth:
self.on_connect_auth(None)
self.on_connect_auth = None
return
if not self.connected: # We went offline during connecting process
if self.on_connect_auth:
self.on_connect_auth(None)
self.on_connect_auth = None
return
if hasattr(con, 'Resource'):
self.server_resource = con.Resource
if auth:
self.last_io = gajim.idlequeue.current_time()
self.connected = 2
if self.on_connect_auth:
self.on_connect_auth(con)
self.on_connect_auth = None
else:
# Forget password if needed
if not gajim.config.get_per('accounts', self.name, 'savepass'):
self.password = None
gajim.log.debug("Couldn't authenticate to %s" % self._hostname)
self.disconnect(on_purpose = True)
self.dispatch('STATUS', 'offline')
self.dispatch('ERROR', (_('Authentication failed with "%s"') % self._hostname,
_('Please check your login and password for correctness.')))
if self.on_connect_auth:
self.on_connect_auth(None)
self.on_connect_auth = None
# END connect
'''
def quit(self, kill_core): def quit(self, kill_core):
if kill_core and self.connected > 1: if kill_core and self.connected > 1:
self.disconnect(on_purpose = True) self.disconnect(on_purpose = True)
'''
#invisible == no service announced( privacy rule? )
def build_privacy_rule(self, name, action):
#Build a Privacy rule stanza for invisibility
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
l = iq.getTag('query').setTag('list', {'name': name})
i = l.setTag('item', {'action': action, 'order': '1'})
i.setTag('presence-out')
return iq
'''
'''
def activate_privacy_rule(self, name):
activate a privacy rule
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
iq.getTag('query').setTag('active', {'name': name})
self.connection.send(iq)
'''
'''
def send_invisible_presence(self, msg, signed, initial = False):
# try to set the privacy rule
iq = self.build_privacy_rule('invisible', 'deny')
self.connection.SendAndCallForResponse(iq, self._continue_invisible,
{'msg': msg, 'signed': signed, 'initial': initial})
'''
'''
def _continue_invisible(self, con, iq_obj, msg, signed, initial):
ptype = ''
show = ''
# FIXME: JEP 126 need some modifications (see http://lists.jabber.ru/pipermail/ejabberd/2005-July/001252.html). So I disable it for the moment
if 1 or iq_obj.getType() == 'error': #server doesn't support privacy lists
# We use the old way which is not xmpp complient
ptype = 'invisible'
show = 'invisible'
else:
# active the privacy rule
self.privacy_rules_supported = True
self.activate_privacy_rule('invisible')
prio = unicode(gajim.config.get_per('accounts', self.name, 'priority'))
p = common.xmpp.Presence(typ = ptype, priority = prio, show = show)
p = self.add_sha(p, ptype != 'unavailable')
if msg:
p.setStatus(msg)
if signed:
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
self.connection.send(p)
self.dispatch('STATUS', 'invisible')
if initial:
#ask our VCard
self.request_vcard(None)
#Get bookmarks from private namespace
self.get_bookmarks()
#Inform GUI we just signed in
self.dispatch('SIGNED_IN', ())
'''
def test_gpg_passphrase(self, password): def test_gpg_passphrase(self, password):
self.gpg.passphrase = password self.gpg.passphrase = password
keyID = gajim.config.get_per('accounts', self.name, 'keyid') keyID = gajim.config.get_per('accounts', self.name, 'keyid')
@ -553,45 +188,27 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.dispatch('BAD_PASSPHRASE', ()) self.dispatch('BAD_PASSPHRASE', ())
return signed return signed
def connect(self, data = None, show = 'online'):
if self.connection:
return self.connection, ''
def connect_and_auth(self): self.zeroconf.connect()
''' self.connection = client_zeroconf.ClientZeroconf(self.zeroconf)
self.on_connect_success = self._connect_success self.connected = STATUS_LIST.index(show)
self.on_connect_failure = self._connect_failure
self.connect()
'''
pass
def connect_and_init(self, show, msg, signed): def connect_and_init(self, show, msg, signed):
'''
self.continue_connect_info = [show, msg, signed] self.continue_connect_info = [show, msg, signed]
self.on_connect_auth = self._init_roster
self.connect_and_auth()
'''
self.zeroconf.txt['status'] = show self.zeroconf.txt['status'] = show
self.zeroconf.txt['msg'] = msg self.zeroconf.txt['msg'] = msg
self.connect('',show) self.connect('',show)
def _init_roster(self, con):
'''
self.connection = con
if self.connection:
con.set_send_timeout(self.keepalives, self.send_keepalive)
self.connection.onreceive(None)
# Ask metacontacts before roster
self.get_metacontacts()
'''
pass
def change_status(self, show, msg, sync = False, auto = False): def change_status(self, show, msg, sync = False, auto = False):
print "change_status: show: %s msg: %s" % (show, msg) print "change_status: show: %s msg: %s" % (show, msg)
if not show in STATUS_LIST: if not show in STATUS_LIST:
return -1 return -1
# connect # 'connect'
if show != 'offline' and not self.connected: if show != 'offline' and not self.connected:
print "connect in change_status" print "connect in change_status"
self.on_purpose = False self.on_purpose = False
@ -601,11 +218,13 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
else: else:
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
# disconnect # 'disconnect'
elif show == 'offline' and self.connected: elif show == 'offline' and self.connected:
print "disconnect in change_status" print "disconnect in change_status"
self.connected = 0 self.connected = 0
self._on_disconnected() self.dispatch('STATUS', 'offline')
self.disconnect()
#self._on_disconnected()
# update status # update status
elif show != 'offline' and self.connected: elif show != 'offline' and self.connected:
@ -625,9 +244,11 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.zeroconf.update_txt(txt) self.zeroconf.update_txt(txt)
self.dispatch('STATUS', show) self.dispatch('STATUS', show)
'''
def _on_disconnected(self): def _on_disconnected(self):
self.dispatch('STATUS', 'offline') self.dispatch('STATUS', 'offline')
self.disconnect() self.disconnect()
'''
def get_status(self): def get_status(self):
return STATUS_LIST[self.connected] return STATUS_LIST[self.connected]
@ -1198,21 +819,8 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
pass pass
def send_keepalive(self): def send_keepalive(self):
'''
# nothing received for the last foo seconds (60 secs by default) # nothing received for the last foo seconds (60 secs by default)
if self.connection: if self.connection:
self.connection.send(' ') self.connection.send(' ')
'''
pass
def _reconnect_alarm(self): # END ConnectionZeroconf
'''
if self.time_to_reconnect:
if self.connected < 2:
self._reconnect()
else:
self.time_to_reconnect = None
'''
pass
# END Connection

View File

@ -0,0 +1,37 @@
from common import zeroconf
class Roster:
def __init__(self, zeroconf):
self._data = {}
self.zeroconf = zeroconf # our zeroconf instance
def getRoster(self):
print 'getRoster in Roster'
self._data = self.zeroconf.get_contacts()
return self
def getItem(self, jid):
print 'getItem(%s) in Roster' % jid
if self._data.has_key(jid):
return self._data[jid]
def __getitem__(self,item):
print '__getitem__ in Roster'
return self._data[item]
def getRaw(self):
return self._data
def getResources(self, jid):
print 'getResources(%s) in Roster' % jid
# return self
'''
getRaw()
delItem(jid)
getItem(jid)
getResources(jid)
getStatus(jid)
getPriority(jid)
getShow(jid)
'''

View File

@ -34,11 +34,13 @@ class Zeroconf:
print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol) print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol)
#synchronous resolving #synchronous resolving
self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved_callback, error_handler=self.print_error_callback) self.server.ResolveService( int(interface), int(protocol), name, stype, \
domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), \
reply_handler=self.service_resolved_callback, error_handler=self.print_error_callback)
def remove_service_callback(self, interface, protocol, name, stype, domain, flags): def remove_service_callback(self, interface, protocol, name, stype, domain, flags):
print "Service '%s' in domain '%s' on %i.%i disappeared." % (name, domain, interface, protocol) print "Service '%s' in domain '%s' on %i.%i disappeared." % (name, domain, interface, protocol)
del self.contacts[(interface, name, domain)] del self.contacts[(name, stype, domain, interface)]
def new_service_type(self, interface, protocol, stype, domain, flags): def new_service_type(self, interface, protocol, stype, domain, flags):
# Are we already browsing this domain for this type? # Are we already browsing this domain for this type?
@ -59,11 +61,26 @@ class Zeroconf:
if domain != "local": if domain != "local":
self.browse_domain(interface, protocol, domain) self.browse_domain(interface, protocol, domain)
def txt_array_to_dict(self,t):
l = {}
for s in t:
str = avahi.byte_array_to_string(s)
poseq = str.find('=')
l[str[:poseq]] = str[poseq+1:]
return l
def service_resolved_callback(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): def service_resolved_callback(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
print "Service data for service '%s' in domain '%s' on %i.%i:" % (name, domain, interface, protocol) print "Service data for service '%s' in domain '%s' on %i.%i:" % (name, domain, interface, protocol)
print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt))) print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
self.contacts[(interface, name, domain)] = (interface, name, protocol, domain, host, address, port, txt) # add domain to stay unique
if domain != 'local':
add_domain = '%'+domain
else:
add_domain = ''
self.contacts[name+add_domain+'@'+host] = (name, stype, domain, interface, protocol, host, address, port, txt)
def service_added_callback(self): def service_added_callback(self):
@ -191,7 +208,7 @@ class Zeroconf:
# END Zeroconf # END Zeroconf
''' '''
def main(): # how to use...
zeroconf = Zeroconf() zeroconf = Zeroconf()
zeroconf.connect() zeroconf.connect()
@ -201,15 +218,7 @@ def main():
# updating after announcing # updating after announcing
txt = {} txt = {}
txt['status'] = 'avail' # out of avail/away/dnd txt['status'] = 'avail'
txt['msg'] = 'Here I am' txt['msg'] = 'Here I am'
zeroconf.update_txt(txt) zeroconf.update_txt(txt)
try:
gobject.MainLoop().run()
except KeyboardInterrupt, k:
pass
if __name__ == "__main__":
main()
''' '''