Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
d85cb5e5 by Philipp Hörist at 2019-01-21T21:33:26Z
Add Blocking (XEP-0191) module
- - - - -
f90126ec by Philipp Hörist at 2019-01-21T21:33:26Z
BOSH: Fix setting language on stream
- - - - -
4 changed files:
- nbxmpp/bosh.py
- nbxmpp/dispatcher_nb.py
- + nbxmpp/modules/blocking.py
- nbxmpp/structs.py
Changes:
=====================================
nbxmpp/bosh.py
=====================================
@@ -45,7 +45,6 @@ class NonBlockingBOSH(NonBlockingTransport):
idlequeue, estabilish_tls, certs, tls_version, cipher_list)
self.bosh_sid = None
- self.bosh_xml_lang = self._owner.lang
self.http_version = 'HTTP/1.1'
self.http_persistent = True
@@ -414,7 +413,7 @@ class NonBlockingBOSH(NonBlockingTransport):
t = BOSHBody(
attrs={ 'to': self.bosh_to,
'sid': self.bosh_sid,
- 'xml:lang': self.bosh_xml_lang,
+ 'xml:lang': self._owner.lang,
'xmpp:restart': 'true',
'secure': self.bosh_secure,
'xmlns:xmpp': 'urn:xmpp:xbosh'})
@@ -425,7 +424,7 @@ class NonBlockingBOSH(NonBlockingTransport):
'route': 'xmpp:%s:%s' % (self.route_host, self.route_port),
'to': self.bosh_to,
'wait': str(self.bosh_wait),
- 'xml:lang': self.bosh_xml_lang,
+ 'xml:lang': self._owner.lang,
'xmpp:version': '1.0',
'ver': '1.6',
'xmlns:xmpp': 'urn:xmpp:xbosh'})
=====================================
nbxmpp/dispatcher_nb.py
=====================================
@@ -55,6 +55,7 @@ from nbxmpp.modules.signed import Signed
from nbxmpp.modules.vcard_avatar import VCardAvatar
from nbxmpp.modules.captcha import Captcha
from nbxmpp.modules.entity_caps import EntityCaps
+from nbxmpp.modules.blocking import Blocking
from nbxmpp.modules.misc import unwrap_carbon
from nbxmpp.modules.misc import unwrap_mam
from nbxmpp.util import get_properties_struct
@@ -177,6 +178,7 @@ class XMPPDispatcher(PlugIn):
self._modules['Signed'] = Signed(self._owner)
self._modules['VCardAvatar'] = VCardAvatar(self._owner)
self._modules['EntityCaps'] = EntityCaps(self._owner)
+ self._modules['Blocking'] = Blocking(self._owner)
for instance in self._modules.values():
for handler in instance.handlers:
=====================================
nbxmpp/modules/blocking.py
=====================================
@@ -0,0 +1,81 @@
+# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
+#
+# This file is part of nbxmpp.
+#
+# This program 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; either version 3
+# of the License, or (at your option) any later version.
+#
+# This program 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 this program; If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+
+from nbxmpp.protocol import NS_BLOCKING
+from nbxmpp.protocol import Iq
+from nbxmpp.protocol import isResultNode
+from nbxmpp.structs import BlockingListResult
+from nbxmpp.structs import CommonResult
+from nbxmpp.util import call_on_response
+from nbxmpp.util import callback
+
+log = logging.getLogger('nbxmpp.m.blocking')
+
+
+class Blocking:
+ def __init__(self, client):
+ self._client = client
+ self.handlers = []
+
+ @call_on_response('_blocking_list_received')
+ def get_blocking_list(self):
+ iq = Iq('get', NS_BLOCKING)
+ iq.setQuery('blocklist')
+ return iq
+
+ @callback
+ def _blocking_list_received(self, stanza):
+ blocked = []
+ if not isResultNode(stanza):
+ log.info('Error: %s', stanza.getErrorMsg())
+ return BlockingListResult(blocking_list=blocked,
+ error=stanza.getErrorMsg())
+
+ blocklist = stanza.getTag('blocklist', namespace=NS_BLOCKING)
+ for item in blocklist.getTags('item'):
+ blocked.append(item.getAttr('jid'))
+
+ log.info('Received blocking list: %s', blocked)
+ return BlockingListResult(blocking_list=blocked)
+
+ @call_on_response('_default_response')
+ def block(self, jids):
+ log.info('Block: %s', jids)
+ iq = Iq('set', NS_BLOCKING)
+ query = iq.setQuery(name='block')
+ for jid in jids:
+ query.addChild(name='item', attrs={'jid': jid})
+ return iq
+
+ @call_on_response('_default_response')
+ def unblock(self, jids):
+ log.info('Unblock: %s', jids)
+ iq = Iq('set', NS_BLOCKING)
+ query = iq.setQuery(name='unblock')
+ for jid in jids:
+ query.addChild(name='item', attrs={'jid': jid})
+ return iq
+
+ @callback
+ def _default_response(self, stanza):
+ if not isResultNode(stanza):
+ log.info('Error: %s', stanza.getErrorMsg())
+ return CommonResult(jid=stanza.getFrom(),
+ error=stanza.getErrorMsg())
+ return CommonResult(jid=stanza.getFrom())
=====================================
nbxmpp/structs.py
=====================================
@@ -294,14 +294,23 @@ class CommonResult(BaseResult, namedtuple('CommonResult', 'jid error')):
CommonResult.__new__.__defaults__ = (None,)
+
class AffiliationResult(BaseResult, namedtuple('AffiliationResult',
'jid affiliation users error')):
pass
AffiliationResult.__new__.__defaults__ = (None, None)
+
class MucConfigResult(BaseResult, namedtuple('MucConfigResult',
'jid form error')):
pass
MucConfigResult.__new__.__defaults__ = (None, None)
+
+
+class BlockingListResult(BaseResult, namedtuple('BlockingListResult',
+ 'blocking_list error')):
+ pass
+
+BlockingListResult.__new__.__defaults__ = (None,)
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/00189cbbcfd51063c2bb3ebe0…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/00189cbbcfd51063c2bb3ebe0…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits:
eb820d0e by André Apitzsch at 2019-01-20T16:10:12Z
Drop support for TLS 1.1 and older
- - - - -
00189cbb by Philipp Hörist at 2019-01-20T17:15:07Z
Merge branch 'tls' into 'master'
Drop support for TLS 1.1 and older
Closes #61
See merge request gajim/python-nbxmpp!26
- - - - -
1 changed file:
- nbxmpp/tls_nb.py
Changes:
=====================================
nbxmpp/tls_nb.py
=====================================
@@ -255,10 +255,10 @@ class NonBlockingTLS(PlugIn):
:param mycerts: path to pem file with certificates of user trusted
servers
:param tls_version: The lowest supported TLS version. If None is
- provided, version 1.0 is used. For example setting to 1.1 will
- enable TLS 1.1, TLS 1.2 and all further protocols
+ provided, version 1.2 is used. For example setting to 1.3 will
+ enable TLS 1.3 and all further protocols
:param cipher_list: list of ciphers to use when connection to server. If
- None is provided, a default list is used: HIGH:!aNULL:RC4-SHA
+ None is provided, a default list is used: HIGH:!aNULL
"""
PlugIn.__init__(self)
self.cacerts = cacerts
@@ -287,10 +287,7 @@ class NonBlockingTLS(PlugIn):
return res
def _dumpX509(self, cert, stream=sys.stderr):
- try:
- print("Digest (SHA-2 256):" + cert.digest("sha256"), file=stream)
- except ValueError: # Old OpenSSL version
- pass
+ print("Digest (SHA-2 256):" + cert.digest("sha256"), file=stream)
print("Digest (SHA-1):" + cert.digest("sha1"), file=stream)
print("Digest (MD5):" + cert.digest("md5"), file=stream)
print("Serial #:" + cert.get_serial_number(), file=stream)
@@ -368,40 +365,17 @@ class NonBlockingTLS(PlugIn):
# See http://docs.python.org/dev/library/ssl.html
tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
flags = OpenSSL.SSL.OP_NO_SSLv2 | OpenSSL.SSL.OP_NO_SSLv3 | \
- OpenSSL.SSL.OP_SINGLE_DH_USE
- try:
- flags |= OpenSSL.SSL.OP_NO_TICKET
- except AttributeError as e:
- # py-OpenSSL < 0.9 or old OpenSSL
- flags |= 16384
+ OpenSSL.SSL.OP_NO_TLSv1 | OpenSSL.SSL.OP_NO_TLSv1_1 | \
+ OpenSSL.SSL.OP_SINGLE_DH_USE | OpenSSL.SSL.OP_NO_TICKET
if self.alpn:
# XEP-0368 set ALPN Protocol
tcpsock._sslContext.set_alpn_protos([b'xmpp-client'])
- try:
- # OpenSSL 1.0.1d supports TLS 1.1 and TLS 1.2 and
- # fixes renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
- if OpenSSL.SSL.OPENSSL_VERSION_NUMBER >= 0x1000104f:
- if self.tls_version != '1.0':
- flags |= OpenSSL.SSL.OP_NO_TLSv1
- if self.tls_version not in ('1.0', '1.1'):
- try:
- flags |= OpenSSL.SSL.OP_NO_TLSv1_1
- except AttributeError as e:
- # older py-OpenSSL
- flags |= 0x10000000
- except AttributeError as e:
- pass # much older py-OpenSSL
-
-
tcpsock._sslContext.set_options(flags)
- try: # Supported only pyOpenSSL >= 0.14
- # Disable session resumption, protection against Triple Handshakes TLS attack
- tcpsock._sslContext.set_session_cache_mode(OpenSSL.SSL.SESS_CACHE_OFF)
- except AttributeError as e:
- pass
+ # Disable session resumption, protection against Triple Handshakes TLS attack
+ tcpsock._sslContext.set_session_cache_mode(OpenSSL.SSL.SESS_CACHE_OFF)
# NonBlockingHTTPBOSH instance has no attribute _owner
if hasattr(tcpsock, '_owner') and tcpsock._owner._caller.client_cert \
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/97f5f4a2ecbbe3390f4e111a9…
--
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/97f5f4a2ecbbe3390f4e111a9…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
31d9b397 by Philipp Hörist at 2019-01-19T20:35:58Z
Deal with stanza-id not added by a mam archive
Fixes #9550
- - - - -
1 changed file:
- gajim/common/modules/message.py
Changes:
=====================================
gajim/common/modules/message.py
=====================================
@@ -331,6 +331,8 @@ class Message:
if archive.bareMatch(properties.stanza_id.by):
return properties.stanza_id.id, None
+ # stanza-id not added by the archive, ignore it.
+ return None, None
class MessageReceivedEvent(NetworkIncomingEvent):
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/31d9b397441b8c239d4094022827b514aa…
--
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/31d9b397441b8c239d4094022827b514aa…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
7c7df9d4 by Philipp Hörist at 2019-01-19T20:21:16Z
Detect invalid user mood
Fixes #9546, #9547
- - - - -
3e362874 by Philipp Hörist at 2019-01-19T20:21:20Z
Detect invalid user activity
- - - - -
2 changed files:
- gajim/common/modules/user_activity.py
- gajim/common/modules/user_mood.py
Changes:
=====================================
gajim/common/modules/user_activity.py
=====================================
@@ -65,6 +65,9 @@ class UserActivity(AbstractPEPModule):
if activity_tag is None:
raise StanzaMalformed('No activity node')
+ if not activity_tag.getChildren():
+ return None
+
for child in activity_tag.getChildren():
name = child.getName().strip()
data = child.getData().strip()
@@ -76,17 +79,22 @@ class UserActivity(AbstractPEPModule):
subactivity_name = subactivity.getName().strip()
activity_dict['subactivity'] = subactivity_name
- return activity_dict or None
+ if 'activity' not in activity_dict:
+ raise StanzaMalformed('No activity value found')
+ return activity_dict
def _build_node(self, data):
item = nbxmpp.Node('activity', {'xmlns': self.namespace})
if data is None:
return item
+
activity, subactivity, message = data
- if activity:
- i = item.addChild(activity)
- if subactivity:
- i.addChild(subactivity)
+ if not activity:
+ return item
+
+ i = item.addChild(activity)
+ if subactivity:
+ i.addChild(subactivity)
if message:
i = item.addChild('text')
i.addData(message)
=====================================
gajim/common/modules/user_mood.py
=====================================
@@ -67,6 +67,9 @@ class UserMood(AbstractPEPModule):
if mood_tag is None:
raise StanzaMalformed('No mood node')
+ if not mood_tag.getChildren():
+ return None
+
for child in mood_tag.getChildren():
name = child.getName().strip()
if name == 'text':
@@ -74,15 +77,20 @@ class UserMood(AbstractPEPModule):
else:
mood_dict['mood'] = name
- return mood_dict or None
+ if 'mood' not in mood_dict:
+ raise StanzaMalformed('No mood value found')
+ return mood_dict
def _build_node(self, data: Optional[Tuple[str, str]]) -> nbxmpp.Node:
item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD})
if data is None:
return item
+
mood, text = data
- if mood:
- item.addChild(mood)
+ if not mood:
+ return item
+ item.addChild(mood)
+
if text:
item.addChild('text', payload=text)
return item
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/cf8eafffb28fa4acb48e4eda44be35b7d…
--
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/cf8eafffb28fa4acb48e4eda44be35b7d…
You're receiving this email because of your account on dev.gajim.org.
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
cf8eafff by Philipp Hörist at 2019-01-19T19:40:06Z
Detect full language code
Previously we only used short language codes (en, de, fr)
- Add conversion method to rfc5646 format
- - - - -
3 changed files:
- gajim/common/connection.py
- gajim/common/i18n.py
- gajim/conversation_textview.py
Changes:
=====================================
gajim/common/connection.py
=====================================
@@ -1059,11 +1059,14 @@ class Connection(CommonConnection, ConnectionHandlers):
secure_tuple = (self._current_type, cacerts, mycerts, tls_version,
cipher_list, self._current_host['alpn'])
+ lang = i18n.get_rfc5646_lang()
+ log.info('Set stream language: %s', lang)
+
con = nbxmpp.NonBlockingClient(
domain=self._hostname,
caller=self,
idlequeue=app.idlequeue,
- lang=i18n.LANG)
+ lang=lang)
if self._sm_resume_data:
con.set_resume_data(self._sm_resume_data)
=====================================
gajim/common/i18n.py
=====================================
@@ -69,21 +69,33 @@ def iter_locale_dirs():
if locale_dir.is_dir():
yield str(locale_dir)
+
def get_default_lang():
if os.name == "nt":
import ctypes
windll = ctypes.windll.kernel32
- lang = locale.windows_locale[windll.GetUserDefaultUILanguage()]
- return lang[:2]
+ return locale.windows_locale[windll.GetUserDefaultUILanguage()]
if sys.platform == "darwin":
from AppKit import NSLocale
+ # FIXME: This returns a two letter language code (en, de, fr)
+ # We need a way to get en_US, de_DE etc.
return NSLocale.currentLocale().languageCode()
- default = locale.getdefaultlocale()[0]
- if default is not None:
- return default[:2]
- return 'en'
+ return locale.getdefaultlocale()[0] or 'en'
+
+
+def get_rfc5646_lang(lang=None):
+ if lang is None:
+ lang = LANG
+ return lang.replace('_', '-')
+
+
+def get_short_lang_code(lang=None):
+ if lang is None:
+ lang = LANG
+ return lang[:2]
+
def initialize_direction_mark():
from gi.repository import Gtk
=====================================
gajim/conversation_textview.py
=====================================
@@ -553,7 +553,7 @@ class ConversationTextview(GObject.GObject):
% phrase_for_url
else:
link = 'http://%s.wikipedia.org/wiki/Special:Search?search=%s'\
- % (i18n.LANG, phrase_for_url)
+ % (i18n.get_short_lang_code(), phrase_for_url)
item = Gtk.MenuItem.new_with_mnemonic(_('Read _Wikipedia Article'))
id_ = item.connect('activate', self.visit_url_from_menuitem, link)
self.handlers[id_] = item
@@ -569,7 +569,7 @@ class ConversationTextview(GObject.GObject):
% phrase_for_url
else:
link = 'http://%s.wiktionary.org/wiki/Special:Search?search=%s'\
- % (i18n.LANG, phrase_for_url)
+ % (i18n.get_short_lang_code(), phrase_for_url)
id_ = item.connect('activate', self.visit_url_from_menuitem, link)
self.handlers[id_] = item
else:
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/cf8eafffb28fa4acb48e4eda44be35b7db…
--
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/cf8eafffb28fa4acb48e4eda44be35b7db…
You're receiving this email because of your account on dev.gajim.org.