From 9deb76a8ad3310ca5bbe9ee3d93537fc5e4a359c Mon Sep 17 00:00:00 2001 From: junglecow Date: Sat, 23 Dec 2006 21:18:07 +0000 Subject: [PATCH] - Started new way of logging, with configurable level for each subsystem - Added -q, --quiet (speaks for itself) - Added -l, --loglevel subsystem=LEVEL,subsystem2=LEVEL2,... - Quell winsock 10035 error. (Equivalent of EINPROGRESS, but winsock likes to have its own error numbers.) - Hide SSL certificate debug stuff unless gajim.c.x.transports loglevel is DEBUG or lower - Avoid unicode problems if we set a profile - Move fingerprint checks from _register_handlers to _connect_success - Some enhancements to fpr checking code --- src/common/configpaths.py | 4 ++ src/common/connection.py | 67 +++++++++++------------ src/common/xmpp/transports_nb.py | 26 ++++----- src/gajim.py | 94 ++++++++++++++++++++++++++------ src/gtkgui_helpers.py | 26 ++++----- 5 files changed, 133 insertions(+), 84 deletions(-) diff --git a/src/common/configpaths.py b/src/common/configpaths.py index d4a377df7..2ae780f22 100644 --- a/src/common/configpaths.py +++ b/src/common/configpaths.py @@ -104,6 +104,10 @@ def init(): gajimpaths = init() def init_profile(profile, paths=gajimpaths): + # no unicode + if isinstance(profile, unicode): + profile = profile.encode(sys.getfilesystemencoding()) + conffile = windowsify('config') pidfile = windowsify('gajim') diff --git a/src/common/connection.py b/src/common/connection.py index 945cbf497..c1eafb282 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -43,14 +43,7 @@ USE_GPG = GnuPG.USE_GPG from common.rst_xhtml_generator import create_xhtml import logging -h = logging.StreamHandler() -f = logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s') -h.setFormatter(f) -log = logging.getLogger('Gajim.connection') -log.addHandler(h) -log.setLevel(logging.DEBUG) -log.propagate = False -del h, f +log = logging.getLogger('gajim.c.connection') import gtkgui_helpers @@ -120,7 +113,7 @@ class Connection(ConnectionHandlers): # Do not try to reco while we are already trying self.time_to_reconnect = None if self.connected < 2: #connection failed - gajim.log.debug('reconnect') + log.debug('reconnect') self.connected = 1 self.dispatch('STATUS', 'connecting') self.retrycount += 1 @@ -147,7 +140,7 @@ class Connection(ConnectionHandlers): def _disconnectedReconnCB(self): '''Called when we are disconnected''' - gajim.log.debug('disconnectedReconnCB') + log.debug('disconnectedReconnCB') if gajim.account_is_connected(self.name): # we cannot change our status to offline or connecting # after we auth to server @@ -168,7 +161,7 @@ class Connection(ConnectionHandlers): self.last_time_to_reconnect *= 1.5 self.last_time_to_reconnect += randomsource.randint(0, 5) self.time_to_reconnect = int(self.last_time_to_reconnect) - gajim.log.info("Reconnect to %s in %ss", self.name, self.time_to_reconnect) + log.info("Reconnect to %s in %ss", self.name, self.time_to_reconnect) gajim.idlequeue.set_alarm(self._reconnect_alarm, self.time_to_reconnect) elif self.on_connect_failure: @@ -393,13 +386,13 @@ class Connection(ConnectionHandlers): if self.on_connect_success == self._on_new_account: con.RegisterDisconnectHandler(self._on_new_account) - gajim.log.info("Connecting to %s: [%s:%d]", self.name, host['host'], host['port']) + log.info("Connecting to %s: [%s:%d]", self.name, host['host'], host['port']) con.connect((host['host'], host['port']), proxy = self._proxy, secure = self._secure) return else: if not retry and self.retrycount == 0: - gajim.log.error("Out of hosts, giving up connecting to %s", self.name) + log.debug("Out of hosts, giving up connecting to %s", self.name) self.time_to_reconnect = None if self.on_connect_failure: self.on_connect_failure() @@ -427,21 +420,15 @@ class Connection(ConnectionHandlers): return self.hosts = [] if not con_type: - gajim.log.debug('Could not connect to %s:%s' % (self._current_host['host'], + 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'], + log.debug(_('Connected to server %s:%s with %s') % (self._current_host['host'], self._current_host['port'], con_type)) 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') @@ -463,19 +450,23 @@ class Connection(ConnectionHandlers): log.debug("sha1: %s", repr(sha1)) log.debug("md5: %s", repr(md5)) - for got in (sha1, md5): - svent = servers.get(hostname) - if not svent: continue - expected = svent[2]['digest'].get(got.algo) - if expected: - fpr_good = got == expected - break + sv = servers.get(hostname) + if sv: + for got in (sha1, md5): + expected = sv[2]['digest'].get(got.algo) + if expected: + fpr_good = (got == expected) + break except AttributeError: - log.debug("Connection to %s doesn't seem to have a fingerprint:", hostname, exc_info=True) + if con_type in ('ssl', 'tls'): + log.error(_("Missing fingerprint in SSL connection to %s") + ':', hostname, exc_info=True) + # fpr_good = False # FIXME: enable this when sequence is sorted + else: + log.debug("Connection to %s doesn't seem to have a fingerprint:", hostname, exc_info=True) if fpr_good == False: - log.error("Fingerprint mismatch for %s: Got %s, expected %s", hostname, got, expected) + log.error(_("Fingerprint mismatch for %s: Got %s, expected %s"), hostname, got, expected) self.disconnect(on_purpose = True) self.dispatch('STATUS', 'offline') self.dispatch('CONNECTION_LOST', @@ -490,10 +481,18 @@ class Connection(ConnectionHandlers): log.warning(_("No fingerprint in database for %s. Connection could be insecure."), hostname) if fpr_good == True: - log.debug("Fingerprint found and matched for %s.", hostname) + log.info("Fingerprint found and matched for %s.", hostname) con.auth(name, self.password, resource, 1, self.__on_auth) + 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) + def __on_auth(self, con, auth): if not con: self.disconnect(on_purpose = True) @@ -853,14 +852,14 @@ class Connection(ConnectionHandlers): def ack_subscribed(self, jid): if not self.connection: return - gajim.log.debug('ack\'ing subscription complete for %s' % jid) + log.debug('ack\'ing subscription complete for %s' % jid) p = common.xmpp.Presence(jid, 'subscribe') self.connection.send(p) def ack_unsubscribed(self, jid): if not self.connection: return - gajim.log.debug('ack\'ing unsubscription complete for %s' % jid) + log.debug('ack\'ing unsubscription complete for %s' % jid) p = common.xmpp.Presence(jid, 'unsubscribe') self.connection.send(p) @@ -868,7 +867,7 @@ class Connection(ConnectionHandlers): auto_auth = False, user_nick = ''): if not self.connection: return - gajim.log.debug('subscription request for %s' % jid) + log.debug('subscription request for %s' % jid) if auto_auth: self.jids_for_auto_auth.append(jid) # RFC 3921 section 8.2 diff --git a/src/common/xmpp/transports_nb.py b/src/common/xmpp/transports_nb.py index fff25f013..3e7959641 100644 --- a/src/common/xmpp/transports_nb.py +++ b/src/common/xmpp/transports_nb.py @@ -30,14 +30,7 @@ import traceback import thread import logging -h = logging.StreamHandler() -f = logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s') -h.setFormatter(f) -log = logging.getLogger('Gajim.transports') -log.addHandler(h) -log.setLevel(logging.DEBUG) -log.propagate = False -del h, f +log = logging.getLogger('gajim.c.x.transports') USE_PYOPENSSL = False @@ -534,7 +527,8 @@ class NonBlockingTcp(PlugIn, IdleObject): self._sock.connect(self._server) except socket.error, e: errnum = e[0] - if errnum != errno.EINPROGRESS: + # 10035 - winsock equivalent of EINPROGRESS + if errnum not in (errno.EINPROGRESS, 10035): log.error("_do_connect:", exc_info=True) #traceback.print_exc() # in progress, or would block @@ -747,15 +741,15 @@ class NonBlockingTLS(PlugIn): tcpsock.serverDigestSHA1 = cert.digest('sha1') tcpsock.serverDigestMD5 = cert.digest('md5') - # FIXME: remove debug prints - peercert = tcpsock._sslObj.get_peer_certificate() - ciphers = tcpsock._sslObj.get_cipher_list() + if log.getEffectiveLevel() <= logging.DEBUG: + peercert = tcpsock._sslObj.get_peer_certificate() + ciphers = tcpsock._sslObj.get_cipher_list() - print >> sys.stderr, "Ciphers:", ciphers - print >> sys.stderr, "Peer cert:", peercert - self._dumpX509(peercert) + print >> sys.stderr, "Ciphers:", ciphers + print >> sys.stderr, "Peer cert:", peercert + self._dumpX509(peercert) - print >> sys.stderr, OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, peercert) + print >> sys.stderr, OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, peercert) def _startSSL_stdlib(self): log.debug("_startSSL_stdlib called") diff --git a/src/gajim.py b/src/gajim.py index fcc0d1f76..1468f6588 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -21,8 +21,83 @@ import sys import os import urllib +import logging +consoleloghandler = logging.StreamHandler() +consoleloghandler.setLevel(logging.WARNING) +consoleloghandler.setFormatter( +logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s')) +log = logging.getLogger('gajim') +log.setLevel(logging.INFO) +log.addHandler(consoleloghandler) +log.propagate = False +log = logging.getLogger('gajim.gajim') + +# create intermediate loggers +logging.getLogger('gajim.c') +logging.getLogger('gajim.c.x') + +import getopt from common import i18n +def parseLogLevel(arg): + if arg.isdigit(): + return int(arg) + if arg.isupper(): + return getattr(logging, arg) + raise ValueError(_("%s is not a valid loglevel"), repr(arg)) + +def parseLogTarget(arg): + arg = arg.lower() + if arg.startswith('.'): return arg[1:] + if arg.startswith('gajim'): return arg + return 'gajim.' + arg + +def parseAndSetLogLevels(arg): + directives = arg.split(',') + for directive in directives: + directive = directive.strip() + target, level = directive.split('=') + target = parseLogTarget(target.strip()) + level = parseLogLevel(level.strip()) + + if target == '': + consoleloghandler.setLevel(level) + print "consoleloghandler level set to %s" % level + else: + logger = logging.getLogger(target) + logger.setLevel(level) + print "Logger %s level set to %d" % (target, level) + +def parseOpts(): + profile = '' + verbose = False + + try: + shortargs = 'hqvl:p:' + longargs = 'help quiet verbose loglevel= profile=' + opts, args = getopt.getopt(sys.argv[1:], shortargs, longargs.split()) + except getopt.error, msg: + print msg + print 'for help use --help' + sys.exit(2) + for o, a in opts: + if o in ('-h', '--help'): + print 'gajim [--help] [--quiet] [--verbose] [--loglevel subsystem=level[,subsystem=level[...]]] [--profile name]' + sys.exit() + elif o in ('-q', '--quiet'): + consoleloghandler.setLevel(logging.CRITICAL) + verbose = False + elif o in ('-v', '--verbose'): + consoleloghandler.setLevel(logging.INFO) + verbose = True + elif o in ('-p', '--profile'): # gajim --profile name + profile = a + elif o in ('-l', '--loglevel'): + parseAndSetLogLevels(a) + return profile, verbose + +profile, verbose = parseOpts() + import message_control from chat_control import ChatControlBase @@ -116,24 +191,7 @@ from common import gajim from common import helpers from common import optparser -profile = '' -try: - opts, args = getopt.getopt(sys.argv[1:], 'hvp:', ['help', 'verbose', - 'profile=', 'sm-config-prefix=', 'sm-client-id=']) -except getopt.error, msg: - print msg - print 'for help use --help' - sys.exit(2) -for o, a in opts: - if o in ('-h', '--help'): - print 'gajim [--help] [--verbose] [--profile name]' - sys.exit() - elif o in ('-v', '--verbose'): - gajim.verbose = True - elif o in ('-p', '--profile'): # gajim --profile name - profile = a -del opts -del args +if verbose: gajim.verbose = True import locale profile = unicode(profile, locale.getpreferredencoding()) diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py index 3f329cb0a..e1a0e9fa1 100644 --- a/src/gtkgui_helpers.py +++ b/src/gtkgui_helpers.py @@ -260,27 +260,22 @@ def resize_window(window, w, h): class HashDigest: def __init__(self, algo, digest): - self.algo = self.cleanAlgo(algo) - self.digest = self.cleanDigest(digest) + self.algo = self.cleanID(algo) + self.digest = self.cleanID(digest) - def cleanAlgo(self, algo): - algo = algo.strip().lower() - for strip in (' :.-_'): algo = algo.replace(strip, '') - return algo - - def cleanDigest(self, digest): - digest = digest.strip().lower() - for strip in (' :.'): digest = digest.replace(strip, '') - return digest + def cleanID(self, id): + id = id.strip().lower() + for strip in (' :.-_'): id = id.replace(strip, '') + return id def __eq__(self, other): sa, sd = self.algo, self.digest if isinstance(other, self.__class__): oa, od = other.algo, other.digest elif isinstance(other, basestring): - sa, oa, od = None, None, self.cleanDigest(other) + sa, oa, od = None, None, self.cleanID(other) elif isinstance(other, tuple) and len(other) == 2: - oa, od = self.cleanAlgo(other[0]), self.cleanDigest(other[1]) + oa, od = self.cleanID(other[0]), self.cleanID(other[1]) else: return False @@ -318,7 +313,7 @@ class ServersXMLHandler(xml.sax.ContentHandler): sitem[0] = jid elif attribute == 'hidden': hidden = attributes.getValue(attribute) - if hidden.lower() in ('1', 'yes', 'true'): + if hidden.lower() in ('1', 'y', 'yes', 't', 'true', 'on'): sitem[2]['hidden'] = True self.servers.append(sitem) elif name == 'active': @@ -329,8 +324,7 @@ class ServersXMLHandler(xml.sax.ContentHandler): # number to the last jid in the list self.servers[-1][1] = port elif name == 'digest': - algo=None - digest=None + algo, digest = None, None for attribute in attributes.getNames(): if attribute == 'algo': algo = attributes.getValue(attribute)