Philipp Hörist pushed to branch master at gajim / gajim
Commits:
b749eccf by Philipp Hörist at 2018-05-27T10:51:57+02:00
Fix idle detection
Fixes #9149
- - - - -
2 changed files:
- gajim/common/idle.py
- gajim/gui_interface.py
Changes:
=====================================
gajim/common/idle.py
=====================================
--- a/gajim/common/idle.py
+++ b/gajim/common/idle.py
@@ -194,6 +194,7 @@ class IdleMonitor:
def is_available(self):
return self._idle_monitor is not None
+ @property
def state(self):
if not self.is_available():
return IdleState.UNKNOWN
=====================================
gajim/gui_interface.py
=====================================
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -1116,7 +1116,7 @@ class Interface:
app.block_signed_in_notifications[account] = True
connected = obj.conn.connected
- if idle.Monitor.is_unknown() and connected in (2, 3):
+ if not idle.Monitor.is_unknown() and connected in (2, 3):
# we go online or free for chat, so we activate auto status
app.sleeper_state[account] = 'online'
elif not ((idle.Monitor.is_away() and connected == 4) or \
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/b749eccf51098e6463c5bc7281c0dd321c…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/b749eccf51098e6463c5bc7281c0dd321c…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
70525c00 by André Apitzsch at 2018-05-27T02:22:21+02:00
Config: use with-statement
- - - - -
1 changed file:
- gajim/config.py
Changes:
=====================================
gajim/config.py
=====================================
--- a/gajim/config.py
+++ b/gajim/config.py
@@ -2535,18 +2535,16 @@ class AccountCreationWizardWindow:
certs = ''
my_ca_certs = configpaths.get('MY_CACERTS')
if os.path.isfile(my_ca_certs):
- f = open(my_ca_certs)
- certs = f.read()
- f.close()
+ with open(my_ca_certs) as f:
+ certs = f.read()
if self.ssl_cert in certs:
dialogs.ErrorDialog(_('Certificate Already in File'),
_('This certificate is already in file %s, so it\'s '
'not added again.') % my_ca_certs)
else:
- f = open(my_ca_certs, 'a')
- f.write(hostname + '\n')
- f.write(self.ssl_cert + '\n\n')
- f.close()
+ with open(my_ca_certs, 'a') as f:
+ f.write(hostname + '\n')
+ f.write(self.ssl_cert + '\n\n')
app.connections[self.account].new_account_info[
'ssl_fingerprint_sha1'] = self.ssl_fingerprint_sha1
app.connections[self.account].new_account_info[
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/70525c00d26380b02e40cb498ae545778c…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/70525c00d26380b02e40cb498ae545778c…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
13e838b4 by André Apitzsch at 2018-05-26T13:16:01+02:00
Flatpak: portal is used to access home directory
- - - - -
1 changed file:
- org.gajim.Gajim.json
Changes:
=====================================
org.gajim.Gajim.json
=====================================
--- a/org.gajim.Gajim.json
+++ b/org.gajim.Gajim.json
@@ -12,7 +12,6 @@
"--socket=x11",
"--socket=wayland",
"--socket=pulseaudio",
- "--filesystem=home",
"--system-talk-name=org.freedesktop.GeoClue2",
"--system-talk-name=org.freedesktop.login1",
"--talk-name=org.gnome.ScreenSaver",
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/13e838b4c9c17331ac10811bea5e802c63…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/13e838b4c9c17331ac10811bea5e802c63…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
c70b883f by Philipp Hörist at 2018-05-25T22:37:28+02:00
Remove python3-avahi dependency
- - - - -
2 changed files:
- README.md
- org.gajim.Gajim.json
Changes:
=====================================
README.md
=====================================
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
- python3-pil (pillow) for support of webp avatars
- python3-crypto to enable End to end encryption
- python3-gnupg to enable GPG encryption
-- For zeroconf (bonjour) you need dbus-glib, python-avahi
+- For zeroconf (bonjour) you need python3-dbus
- gir1.2-gspell-1 and hunspell-LANG where lang is your locale eg. en, fr etc
- gir1.2-secret-1 for GNOME Keyring or KDE support as password storage
- D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.80 is required.
=====================================
org.gajim.Gajim.json
=====================================
--- a/org.gajim.Gajim.json
+++ b/org.gajim.Gajim.json
@@ -247,34 +247,6 @@
}
]
},
- /* Zeroconf support */
- {
- "name": "avahi",
- "cleanup": [
- "/bin",
- "/lib/avahi",
- "/share/avahi",
- "avahi.mo"
- ],
- "config-opts": [
- "--with-distro=none",
- "--disable-qt3",
- "--disable-qt4",
- "--disable-libdaemon",
- "--disable-pygtk",
- "--disable-gdbm",
- "--disable-mono",
- "--disable-monodoc",
- "--disable-manpages"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://github.com/lathiat/avahi/archive/v0.7.tar.gz",
- "sha256": "fd45480cef0559b3eab965ea3ad4fe2d7a8f27db32c851a032ee0b487c378329"
- }
- ]
- },
/* OMEMO support */
{
"name": "protobuf",
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/c70b883fdd8fed870ddc7686aef8dbf761…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/c70b883fdd8fed870ddc7686aef8dbf761…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
bc24ab47 by Philipp Hörist at 2018-05-23T08:38:09+02:00
Fix translation in flatpak build
Fixes #9138
- - - - -
1 changed file:
- gajim/common/i18n.py
Changes:
=====================================
gajim/common/i18n.py
=====================================
--- a/gajim/common/i18n.py
+++ b/gajim/common/i18n.py
@@ -81,6 +81,9 @@ def get_locale_dir():
path, tail = os.path.split(path)
path, tail = os.path.split(path)
localedir, tail = os.path.split(path)
+ elif os.path.exists('/app/share/run-as-flatpak'):
+ # Check if we run as flatpak
+ return '/app/share/locale'
else:
# fallback to user locale
base = os.getenv('XDG_DATA_HOME')
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/bc24ab470d87896425684dbee543e95635…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/bc24ab470d87896425684dbee543e95635…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
d0ec9812 by Philipp Hörist at 2018-05-22T23:38:04+02:00
Fix Zeroconf
- Port pybonjour code from gajim_0.16 branch
- Fix some other small things that broke zeroconf
- - - - -
6 changed files:
- gajim/common/connection_handlers.py
- gajim/common/connection_handlers_events.py
- gajim/common/zeroconf/client_zeroconf.py
- gajim/common/zeroconf/connection_zeroconf.py
- gajim/common/zeroconf/zeroconf_avahi.py
- gajim/common/zeroconf/zeroconf_bonjour.py
Changes:
=====================================
gajim/common/connection_handlers.py
=====================================
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -1069,7 +1069,10 @@ class ConnectionHandlersBase:
if not jid_to:
reply = True
else:
- fjid_to = helpers.parse_jid(str(jid_to))
+ fjid_to = str(jid_to)
+ if self.name != 'Local':
+ # Dont check precis for zeroconf
+ fjid_to = helpers.parse_jid(str(jid_to))
jid_to = app.get_jid_without_resource(fjid_to)
if jid_to == app.get_jid_from_account(self.name):
reply = True
=====================================
gajim/common/connection_handlers_events.py
=====================================
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -885,6 +885,7 @@ class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
self.resource = 'local'
self.prio = 0
self.keyID = None
+ self.idle_time = None
self.timestamp = 0
self.contact_nickname = None
self.avatar_sha = None
@@ -1528,7 +1529,7 @@ class ZeroconfMessageReceivedEvent(MessageReceivedEvent):
base_network_events = []
def get_jid_resource(self):
- self.fjid =self.stanza.getFrom()
+ self.fjid = str(self.stanza.getFrom())
if self.fjid is None:
for key in self.conn.connection.zeroconf.contacts:
@@ -1833,7 +1834,12 @@ class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'message-error'
base_network_events = []
+ def init(self):
+ self.zeroconf = False
+
def generate(self):
+ if self.zeroconf:
+ return True
self.get_id()
#only alert for errors of explicitly sent messages (see https://trac.gajim.org/ticket/8222)
if self.id_ in self.conn.sent_message_ids:
=====================================
gajim/common/zeroconf/client_zeroconf.py
=====================================
--- a/gajim/common/zeroconf/client_zeroconf.py
+++ b/gajim/common/zeroconf/client_zeroconf.py
@@ -442,7 +442,7 @@ class P2PConnection(IdleObject, PlugIn):
if self.state <= 0:
return
- r = packet
+ r = str(packet).encode('utf-8')
if now:
self.sendqueue.insert(0, (r, is_message))
@@ -532,6 +532,9 @@ class P2PConnection(IdleObject, PlugIn):
if self.state < 0:
return
+
+ received = received.decode('utf-8')
+
if self.on_receive:
if self._owner.sock_type == TYPE_CLIENT:
self.set_timeout(ACTIVITY_TIMEOUT_SECONDS)
@@ -609,7 +612,8 @@ class P2PConnection(IdleObject, PlugIn):
if self.sent_data and self.sent_data.strip():
log.debug('sent: %s' % self.sent_data)
if hasattr(self._owner, 'Dispatcher'):
- self._owner.Dispatcher.Event('', DATA_SENT, self.sent_data)
+ self._owner.Dispatcher.Event(
+ '', DATA_SENT, self.sent_data.decode('utf-8'))
self.sent_data = None
if self.buff_is_message:
self._owner.on_message_sent(self.fd)
@@ -662,7 +666,7 @@ class ClientZeroconf:
def resolve_all(self):
if self.zeroconf:
- self.zeroconf.resolve_all()
+ return self.zeroconf.resolve_all()
def reannounce(self, txt):
self.remove_announce()
@@ -711,7 +715,7 @@ class ClientZeroconf:
self.disconnect()
def kill_all_connections(self):
- for connection in self.connections.values():
+ for connection in list(self.connections.values()):
connection.force_disconnect()
def add_connection(self, connection, ip, port, recipient):
=====================================
gajim/common/zeroconf/connection_zeroconf.py
=====================================
--- a/gajim/common/zeroconf/connection_zeroconf.py
+++ b/gajim/common/zeroconf/connection_zeroconf.py
@@ -69,6 +69,8 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
CommonConnection.__init__(self, name)
self.is_zeroconf = True
+ app.ged.register_event_handler('message-outgoing', ged.OUT_CORE,
+ self._nec_message_outgoing)
app.ged.register_event_handler('stanza-message-outgoing', ged.OUT_CORE,
self._nec_stanza_message_outgoing)
@@ -107,7 +109,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
def check_jid(self, jid):
return jid
- def get_own_jid(self):
+ def get_own_jid(self, *args, **kwargs):
return nbxmpp.JID(self.username + '@' + self.host)
def reconnect(self):
@@ -123,7 +125,9 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
def _on_resolve_timeout(self):
if self.connected:
- self.connection.resolve_all()
+ if not self.connection.resolve_all():
+ self._on_disconnected()
+ return False
diffs = self.roster.getDiffs()
for key in diffs:
self.roster.setItem(key)
@@ -205,7 +209,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
else: # result is None
app.nec.push_incoming_event(ConnectionLostEvent(None,
conn=self, title=_('Could not start local service'),
- msg=_('Please check if avahi-daemon is running.')))
+ msg=_('Please check if avahi/bonjour-daemon is running.')))
self.disconnect()
return
else:
@@ -321,23 +325,24 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
title=_('Could not change status of account "%s"') % self.name,
msg=_('Please check if avahi-daemon is running.')))
+ def _nec_message_outgoing(self, obj):
+ if obj.account != self.name:
+ return
+ self._prepare_message(obj)
+
def _nec_stanza_message_outgoing(self, obj):
if obj.conn.name != self.name:
return
def on_send_ok(stanza_id):
- app.nec.push_incoming_event(MessageSentEvent(None, conn=self,
- jid=obj.jid, message=obj.message, keyID=obj.keyID,
- automatic_message=obj.automatic_message, chatstate=None,
- stanza_id=stanza_id))
-
+ app.nec.push_incoming_event(MessageSentEvent(None, **vars(obj)))
self.log_message(obj, obj.jid)
def on_send_not_ok(reason):
reason += ' ' + _('Your message could not be sent.')
- app.nec.push_incoming_event(MessageErrorEvent(None, conn=self,
- fjid=obj.jid, error_code=-1, error_msg=reason, msg=None,
- time_=None, session=obj.session))
+ app.nec.push_incoming_event(MessageErrorEvent(
+ None, conn=self, fjid=obj.jid, error_code=-1, error_msg=reason,
+ msg=None, time_=None, session=obj.session, zeroconf=True))
# Dont propagate event
return True
@@ -347,10 +352,12 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
if ret == -1:
# Contact Offline
- app.nec.push_incoming_event(MessageErrorEvent(None, conn=self,
- fjid=obj.jid, error_code=-1, error_msg=_(
- 'Contact is offline. Your message could not be sent.'),
- msg=None, time_=None, session=obj.session))
+ error_message = _(
+ 'Contact is offline. Your message could not be sent.')
+ app.nec.push_incoming_event(MessageErrorEvent(
+ None, conn=self, fjid=obj.jid, error_code=-1,
+ error_msg=error_message, msg=None, time_=None,
+ session=obj.session, zeroconf=True))
# Dont propagate event
return True
@@ -369,9 +376,12 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
thread_id = data[1]
frm = data[0]
session = self.get_or_create_session(frm, thread_id)
+ error_message = _(
+ 'Connection to host could not be established: '
+ 'Timeout while sending data.')
app.nec.push_incoming_event(MessageErrorEvent(
- None, conn=self, fjid=frm, error_code=-1, error_msg=_(
- 'Connection to host could not be established: Timeout while '
- 'sending data.'), msg=None, time_=None, session=session))
+ None, conn=self, fjid=frm, error_code=-1,
+ error_msg=error_message, msg=None, time_=None,
+ session=session, zeroconf=True))
# END ConnectionZeroconf
=====================================
gajim/common/zeroconf/zeroconf_avahi.py
=====================================
--- a/gajim/common/zeroconf/zeroconf_avahi.py
+++ b/gajim/common/zeroconf/zeroconf_avahi.py
@@ -160,7 +160,7 @@ class Zeroconf:
# we don't want to see ourselves in the list
if name != self.name:
- resolved_info = [(interface, protocol, host, aprotocol, address, port)]
+ resolved_info = [(interface, protocol, host, aprotocol, address, int(port))]
if name in self.contacts:
# Decide whether to try to merge with existing resolved info:
old_name, old_domain, old_resolved_info, old_bare_name, old_txt = self.contacts[name]
@@ -186,7 +186,7 @@ class Zeroconf:
# gajim instance on the same machine,
# it will be used when we get a new name.
self.invalid_self_contact[name] = (name, domain,
- (interface, protocol, host, aprotocol, address, port),
+ (interface, protocol, host, aprotocol, address, int(port)),
bare_name, txt)
@@ -445,7 +445,7 @@ class Zeroconf:
# refresh txt data of all contacts manually (no callback available)
def resolve_all(self):
if not self.connected:
- return
+ return False
for val in self.contacts.values():
# get txt data from last recorded resolved info
# TODO: Better try to get it from last IPv6 mDNS, then last IPv4?
@@ -456,6 +456,8 @@ class Zeroconf:
reply_handler=self.service_resolved_all_callback,
error_handler=self.error_callback)
+ return True
+
def get_contacts(self):
return self.contacts
=====================================
gajim/common/zeroconf/zeroconf_bonjour.py
=====================================
--- a/gajim/common/zeroconf/zeroconf_bonjour.py
+++ b/gajim/common/zeroconf/zeroconf_bonjour.py
@@ -1,28 +1,27 @@
-## common/zeroconf/zeroconf_bonjour.py
-##
-## Copyright (C) 2006 Stefan Bethge <stefan(a)lanpartei.de>
-##
-## This file is part of Gajim.
-##
-## Gajim is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published
-## by the Free Software Foundation; version 3 only.
-##
-## Gajim is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
-##
-
-from gajim.common import app
+# Copyright (C) 2006 Stefan Bethge <stefan(a)lanpartei.de>
+# Copyright (C) 2006 Philipp Hörist <philipp(a)hoerist.com>
+#
+# This file is part of Gajim.
+#
+# Gajim is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; version 3 only.
+#
+# Gajim is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
+
+import logging
import select
+import socket
import re
-import logging
from gajim.common.zeroconf.zeroconf import Constant
+
log = logging.getLogger('gajim.c.z.zeroconf_bonjour')
try:
@@ -30,18 +29,17 @@ try:
except ImportError:
pass
-
resolve_timeout = 1
+
class Zeroconf:
def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB,
- disconnected_CB, error_CB, name, host, port):
- self.domain = None # specific domain to browse
+ disconnected_CB, error_CB, name, host, port):
self.stype = '_presence._tcp'
- self.port = port # listening port that gets announced
+ self.port = port # listening port that gets announced
self.username = name
self.host = host
- self.txt = pybonjour.TXTRecord() # service data
+ self.txt = {} # service data
# XXX these CBs should be set to None when we destroy the object
# (go offline), because they create a circular reference
@@ -51,67 +49,76 @@ class Zeroconf:
self.disconnected_CB = disconnected_CB
self.error_CB = error_CB
- self.contacts = {} # all current local contacts with data
+ self.contacts = {} # all current local contacts with data
self.connected = False
self.announced = False
self.invalid_self_contact = {}
+ self.resolved_contacts = {}
self.resolved = []
+ self.queried = []
-
- def browse_callback(self, sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain):
- log.debug('Found service %s in domain %s on %i(type: %s).' % (serviceName, replyDomain, interfaceIndex, regtype))
+ def browse_callback(self, sdRef, flags, interfaceIndex, errorCode,
+ serviceName, regtype, replyDomain):
+ log.debug('Found service %s in domain %s on %i(type: %s).',
+ serviceName, replyDomain, interfaceIndex, regtype)
if not self.connected:
return
if errorCode != pybonjour.kDNSServiceErr_NoError:
+ log.debug('Error in browse_callback: %s', str(errorCode))
return
if not (flags & pybonjour.kDNSServiceFlagsAdd):
self.remove_service_callback(serviceName)
return
- # asynchronous resolving
- resolve_sdRef = pybonjour.DNSServiceResolve(0, interfaceIndex, serviceName, regtype, replyDomain, self.service_resolved_callback)
-
try:
+ # asynchronous resolving
+ resolve_sdRef = None
+ resolve_sdRef = pybonjour.DNSServiceResolve(
+ 0, interfaceIndex, serviceName,
+ regtype, replyDomain, self.service_resolved_callback)
+
while not self.resolved:
ready = select.select([resolve_sdRef], [], [], resolve_timeout)
if resolve_sdRef not in ready[0]:
- log.debug('Resolve timed out')
+ log.info('Resolve timed out')
break
pybonjour.DNSServiceProcessResult(resolve_sdRef)
else:
self.resolved.pop()
+
+ except pybonjour.BonjourError as error:
+ log.info('Error when resolving DNS: %s', error)
+
finally:
- resolve_sdRef.close()
+ if resolve_sdRef:
+ resolve_sdRef.close()
def remove_service_callback(self, name):
- log.debug('Service %s disappeared.' % name)
+ log.info('Service %s disappeared.' % name)
if not self.connected:
return
if name != self.name:
for key in self.contacts.keys():
- if self.contacts[key][Constant.BARE_NAME] == name:
+ if self.contacts[key][Constant.NAME] == name:
del self.contacts[key]
self.remove_serviceCB(key)
return
- def new_domain_callback(self, interface, protocol, domain, flags):
- if domain != "local":
- self.browse_domain(domain)
-
- # takes a TXTRecord instance
def txt_array_to_dict(self, txt):
- items = pybonjour.TXTRecord.parse(txt)._items
+ if isinstance(txt, pybonjour.TXTRecord):
+ items = txt._items
+ else:
+ items = pybonjour.TXTRecord.parse(txt)._items
return dict((v[0], v[1]) for v in items.values())
- def service_resolved_callback(self, sdRef, flags, interfaceIndex, errorCode, fullname,
- hosttarget, port, txtRecord):
-
+ @staticmethod
+ def _parse_name(fullname):
+ log.debug('Parse name: %s', fullname)
# TODO: do proper decoding...
- escaping= {
- r'\.': '.',
- r'\032': ' ',
- r'\064': '@',
- }
+ escaping = {r'\.': '.',
+ r'\032': ' ',
+ r'\064': '@',
+ }
# Split on '.' but do not split on '\.'
result = re.split('(?<!\\\\)\.', fullname)
@@ -122,21 +129,59 @@ class Zeroconf:
for src, trg in escaping.items():
name = name.replace(src, trg)
+ bare_name = name
+ if '@' not in name:
+ name = name + '@' + name
+ log.debug('End parse: %s %s %s %s',
+ name, bare_name, protocol, domain)
+
+ return name, bare_name, protocol, domain
+
+ def query_txt_callback(self, sdRef, flags, interfaceIndex, errorCode,
+ hosttarget, rrtype, rrclass, rdata, ttl):
+ # Callback from DNSServiceQueryRecord, it does not call decode()
+ # on rdata
+ rdata = rdata.decode()
+
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ log.error('Error in query_record_callback: %s', str(errorCode))
+ return
+
+ name, bare_name, protocol, domain = self._parse_name(hosttarget)
+
+ if name != self.name:
+ # update TXT data only, as intended according to
+ # resolve_all comment
+ old_contact = self.contacts[name]
+ self.contacts[name] = old_contact[0:Constant.TXT] + (rdata,) + old_contact[Constant.TXT+1:]
+ log.debug(self.contacts[name])
+
+ self.queried.append(True)
+
+ def query_record_callback(self, sdRef, flags, interfaceIndex, errorCode,
+ hosttarget, rrtype, rrclass, rdata, ttl):
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ log.error('Error in query_record_callback: %s', str(errorCode))
+ return
+
+ fullname, port, txtRecord = self.resolved_contacts[hosttarget]
+
txt = pybonjour.TXTRecord.parse(txtRecord)
+ ip = socket.inet_ntoa(rdata)
- log.debug('Service data for service %s on %i:' % (fullname, interfaceIndex))
- log.debug('Host %s, port %i, TXT data: %s' % (hosttarget, port, txt._items))
+ name, bare_name, protocol, domain = self._parse_name(fullname)
+
+ log.info('Service data for service %s on %i:',
+ fullname, interfaceIndex)
+ log.info('Host %s, ip %s, port %i, TXT data: %s',
+ hosttarget, ip, port, txt._items)
if not self.connected:
return
- bare_name = name
- if '@' not in name:
- name = name + '@' + name
-
# we don't want to see ourselves in the list
if name != self.name:
- resolved_info = [(interfaceIndex, protocol, hosttarget, -1, port)]
+ resolved_info = [(interfaceIndex, protocol, hosttarget, fullname, ip, port)]
self.contacts[name] = (name, domain, resolved_info, bare_name, txtRecord)
self.new_serviceCB(name)
@@ -145,57 +190,71 @@ class Zeroconf:
# In case this is not our own record but of another
# gajim instance on the same machine,
# it will be used when we get a new name.
- self.invalid_self_contact[name] = (name, domain, (interfaceIndex, protocol, hosttarget, -1, port), bare_name, txtRecord)
- # count services
- self.resolved.append(True)
+ self.invalid_self_contact[name] = \
+ (name, domain,
+ (interfaceIndex, protocol, hosttarget, fullname, ip, port),
+ bare_name, txtRecord)
- # different handler when resolving all contacts
- def service_resolved_all_callback(self, sdRef, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtRecord):
- if not self.connected:
- return
+ self.queried.append(True)
- escaping= {
- r'\.': '.',
- r'\032': ' ',
- r'\064': '@',
- }
+ def service_resolved_callback(self, sdRef, flags, interfaceIndex,
+ errorCode, fullname, hosttarget, port,
+ txtRecord):
- name, stype, protocol, domain, dummy = fullname.split('.')
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ log.error('Error in service_resolved_callback: %s', str(errorCode))
+ return
- # Replace the escaped values
- for src, trg in escaping.items():
- name = name.replace(src, trg)
+ self.resolved_contacts[hosttarget] = (fullname, port, txtRecord)
- bare_name = name
- if name.find('@') == -1:
- name = name + '@' + name
+ try:
+ query_sdRef = None
+ query_sdRef = \
+ pybonjour.DNSServiceQueryRecord(
+ interfaceIndex=interfaceIndex,
+ fullname=hosttarget,
+ rrtype=pybonjour.kDNSServiceType_A,
+ callBack=self.query_record_callback)
+
+ while not self.queried:
+ ready = select.select([query_sdRef], [], [], resolve_timeout)
+ if query_sdRef not in ready[0]:
+ log.warning('Query record timed out')
+ break
+ pybonjour.DNSServiceProcessResult(query_sdRef)
+ else:
+ self.queried.pop()
- # we don't want to see ourselves in the list
- if name != self.name:
- # update TXT data only, as intended according to resolve_all comment
- old_contact = self.contacts[name]
- self.contacts[name] = old_contact[0:Constant.TXT] + (self.txt,) + old_contact[Constant.TXT+1:]
+ except pybonjour.BonjourError as error:
+ if error.errorCode == pybonjour.kDNSServiceErr_ServiceNotRunning:
+ log.info('Service not running')
+ else:
+ self.error_CB(_('Error while adding service. %s') % error)
+
+ finally:
+ if query_sdRef:
+ query_sdRef.close()
+ self.resolved.append(True)
- def service_added_callback(self, sdRef, flags, errorCode, name, regtype, domain):
+ def service_added_callback(self, sdRef, flags, errorCode,
+ name, regtype, domain):
if errorCode == pybonjour.kDNSServiceErr_NoError:
- log.debug('Service successfully added')
+ log.info('Service successfully added')
- def service_add_fail_callback(self, err):
- if err[0][0] == pybonjour.kDNSServiceErr_NameConflict:
- log.debug('Error while adding service. %s' % str(err))
+ elif errorCode == pybonjour.kDNSServiceErr_NameConflict:
+ log.error('Error while adding service. %s', errorCode)
parts = self.username.split(' ')
- #check if last part is a number and if, increment it
+ # check if last part is a number and if, increment it
try:
stripped = str(int(parts[-1]))
except Exception:
stripped = 1
- alternative_name = self.username + str(stripped+1)
+ alternative_name = self.username + str(stripped + 1)
self.name_conflictCB(alternative_name)
- return
- self.error_CB(_('Error while adding service. %s') % str(err))
- self.disconnect()
+ else:
+ self.error_CB(_('Error while adding service. %s') % str(errorCode))
# make zeroconf-valid names
def replace_show(self, show):
@@ -208,8 +267,8 @@ class Zeroconf:
def create_service(self):
txt = {}
- #remove empty keys
- for key, val in self.txt:
+ # remove empty keys
+ for key, val in self.txt.items():
if val:
txt[key] = val
@@ -222,22 +281,27 @@ class Zeroconf:
txt['status'] = self.replace_show(self.txt['status'])
else:
txt['status'] = 'avail'
-
- self.txt = pybonjour.TXTRecord(txt, strict=True)
-
+ self.txt = txt
try:
- sdRef = pybonjour.DNSServiceRegister(name = self.name,
- regtype = self.stype, port = self.port, txtRecord = self.txt,
- callBack = self.service_added_callback)
- self.service_sdRef = sdRef
- except pybonjour.BonjourError as e:
- self.service_add_fail_callback(e)
- else:
- log.debug('Publishing service %s of type %s' % (self.name, self.stype))
-
- ready = select.select([sdRef], [], [], resolve_timeout)
- if sdRef in ready[0]:
- pybonjour.DNSServiceProcessResult(sdRef)
+ self.service_sdRef = pybonjour.DNSServiceRegister(
+ name=self.name,
+ regtype=self.stype,
+ port=self.port,
+ txtRecord=pybonjour.TXTRecord(self.txt, strict=True),
+ callBack=self.service_added_callback)
+
+ log.info('Publishing service %s of type %s', self.name, self.stype)
+
+ ready = select.select([self.service_sdRef], [], [])
+ if self.service_sdRef in ready[0]:
+ pybonjour.DNSServiceProcessResult(self.service_sdRef)
+
+ except pybonjour.BonjourError as error:
+ if error.errorCode == pybonjour.kDNSServiceErr_ServiceNotRunning:
+ log.info('Service not running')
+ else:
+ self.error_CB(_('Error while adding service. %s') % error)
+ self.disconnect()
def announce(self):
if not self.connected:
@@ -254,28 +318,21 @@ class Zeroconf:
self.service_sdRef.close()
self.announced = False
return True
- except pybonjour.BonjourError as e:
- log.debug(e)
+ except pybonjour.BonjourError as error:
+ log.error('Error when removing announce: %s', error)
return False
-
def connect(self):
- self.name = self.username + '@' + self.host # service name
+ self.name = self.username + '@' + self.host # service name
self.connected = True
# start browsing
- if self.domain is None:
- # Explicitly browse .local
- self.browse_domain()
-
- # Browse for other browsable domains
- #self.domain_sdRef = pybonjour.DNSServiceEnumerateDomains(flags, interfaceIndex=0, callBack=self.new_domain_callback)
-
+ if self.browse_domain():
+ return True
else:
- self.browse_domain(self.domain)
-
- return True
+ self.disconnect()
+ return False
def disconnect(self):
if self.connected:
@@ -285,54 +342,92 @@ class Zeroconf:
self.remove_announce()
def browse_domain(self, domain=None):
- log.debug('starting to browse')
try:
- self.browse_sdRef = pybonjour.DNSServiceBrowse(regtype=self.stype, domain=domain, callBack=self.browse_callback)
- except pybonjour.BonjourError as e:
- self.error_CB("Error while browsing: %s" % str(e))
+ self.browse_sdRef = pybonjour.DNSServiceBrowse(
+ regtype=self.stype,
+ domain=domain,
+ callBack=self.browse_callback)
+ log.info('Starting to browse .local')
+ return True
+ except pybonjour.BonjourError as error:
+ if error.errorCode == pybonjour.kDNSServiceErr_ServiceNotRunning:
+ log.info('Service not running')
+ else:
+ log.error('Error while browsing for services. %s', error)
+ return False
def browse_loop(self):
- ready = select.select([self.browse_sdRef], [], [], 0)
- if self.browse_sdRef in ready[0]:
- pybonjour.DNSServiceProcessResult(self.browse_sdRef)
+ try:
+ ready = select.select([self.browse_sdRef], [], [], 0)
+ if self.browse_sdRef in ready[0]:
+ pybonjour.DNSServiceProcessResult(self.browse_sdRef)
+ except pybonjour.BonjourError as error:
+ if error.errorCode == pybonjour.kDNSServiceErr_ServiceNotRunning:
+ log.info('Service not running')
+ return False
+ else:
+ log.error('Error while browsing for services. %s', error)
+ return True
- # refresh txt data of all contacts manually (no callback available)
+ # resolve_all() is called every X seconds and querys for new clients
+ # and monitors TXT records for changed status
def resolve_all(self):
if not self.connected:
- return
-
+ return False
# for now put here as this is synchronous
- self.browse_loop()
+ if not self.browse_loop():
+ return False
+ # Monitor TXT Records with DNSServiceQueryRecord because
+ # its more efficient (see pybonjour documentation)
for val in self.contacts.values():
- resolve_sdRef = pybonjour.DNSServiceResolve(0,
- pybonjour.kDNSServiceInterfaceIndexAny, val[Constant.BARE_NAME],
- self.stype + '.', val[Constant.DOMAIN] + '.',
- self.service_resolved_all_callback)
-
try:
- ready = select.select([resolve_sdRef], [], [], resolve_timeout)
- if resolve_sdRef not in ready[0]:
- log.debug('Resolve timed out (in resolve_all)')
- break
- pybonjour.DNSServiceProcessResult(resolve_sdRef)
+ query_sdRef = None
+ query_sdRef = \
+ pybonjour.DNSServiceQueryRecord(
+ interfaceIndex=pybonjour.kDNSServiceInterfaceIndexAny,
+ fullname=val[Constant.RESOLVED_INFO][0][Constant.BARE_NAME],
+ rrtype=pybonjour.kDNSServiceType_TXT,
+ callBack=self.query_txt_callback)
+
+ while not self.queried:
+ ready = select.select(
+ [query_sdRef], [], [], resolve_timeout)
+ if query_sdRef not in ready[0]:
+ log.info('Query record timed out')
+ break
+ pybonjour.DNSServiceProcessResult(query_sdRef)
+ else:
+ self.queried.pop()
+
+ except pybonjour.BonjourError as error:
+ if error.errorCode == pybonjour.kDNSServiceErr_ServiceNotRunning:
+ log.info('Service not running')
+ return False
+ else:
+ log.error('Error in query for TXT records. %s', error)
finally:
- resolve_sdRef.close()
+ if query_sdRef:
+ query_sdRef.close()
+
+ return True
def get_contacts(self):
return self.contacts
def get_contact(self, jid):
- if not jid in self.contacts:
+ if jid not in self.contacts:
return None
return self.contacts[jid]
- def update_txt(self, show = None):
+ def update_txt(self, show=None):
if show:
self.txt['status'] = self.replace_show(show)
+ txt = pybonjour.TXTRecord(self.txt, strict=True)
try:
- pybonjour.DNSServiceUpdateRecord(self.service_sdRef, None, 0, self.txt)
- except pybonjour.BonjourError:
+ pybonjour.DNSServiceUpdateRecord(self.service_sdRef, None, 0, txt)
+ except pybonjour.BonjourError as e:
+ log.error('Error when updating TXT Record: %s', e)
return False
return True
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/d0ec9812a6b0163fd25c63751ac86175c9…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/d0ec9812a6b0163fd25c63751ac86175c9…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
cfd64926 by André Apitzsch at 2018-05-22T23:12:29+02:00
Work around flatpak cleanup issue
cleaning /share/locale/ from one component can affect later components,
i.e. locales are also removed there
- - - - -
1 changed file:
- org.gajim.Gajim.json
Changes:
=====================================
org.gajim.Gajim.json
=====================================
--- a/org.gajim.Gajim.json
+++ b/org.gajim.Gajim.json
@@ -253,7 +253,8 @@
"cleanup": [
"/bin",
"/lib/avahi",
- "/share"
+ "/share/avahi",
+ "avahi.mo"
],
"config-opts": [
"--with-distro=none",
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/cfd64926b919cba18d8be1d8b50055f353…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/cfd64926b919cba18d8be1d8b50055f353…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
3c474f94 by Philipp Hörist at 2018-05-21T22:24:48+02:00
Remove version key in desktop.in
This is not for the Gajim version, its the version of the spec this
file conforms to.
This key is not required by the spec
- - - - -
1 changed file:
- data/org.gajim.Gajim.desktop.in
Changes:
=====================================
data/org.gajim.Gajim.desktop.in
=====================================
--- a/data/org.gajim.Gajim.desktop.in
+++ b/data/org.gajim.Gajim.desktop.in
@@ -5,7 +5,6 @@ GenericName=Jabber IM Client
Comment=A GTK+ Jabber client
#Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=chat;messaging;im;xmpp;bonjour;voip;
-Version=1.0.3
Exec=gajim %u
#Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gajim.Gajim
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/3c474f9405b9304d8f965c88d3e916449d…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/3c474f9405b9304d8f965c88d3e916449d…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
7b0cbb77 by Philipp Hörist at 2018-05-21T21:49:19+02:00
Fix detecting language
- - - - -
1 changed file:
- gajim/common/i18n.py
Changes:
=====================================
gajim/common/i18n.py
=====================================
--- a/gajim/common/i18n.py
+++ b/gajim/common/i18n.py
@@ -65,7 +65,7 @@ def initialize_lang():
if default is None:
# LC_ALL=C
return
- LANG = LANG[:2]
+ LANG = default[:2]
except (ValueError, locale.Error):
pass
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/7b0cbb7763b8be450b2b2b8efd4eca6a03…
---
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/7b0cbb7763b8be450b2b2b8efd4eca6a03…
You're receiving this email because of your account on dev.gajim.org.