Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nbxmpp for openSUSE:Factory checked in at 2025-09-22 16:39:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nbxmpp (Old) and /work/SRC/openSUSE:Factory/.python-nbxmpp.new.27445 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nbxmpp" Mon Sep 22 16:39:45 2025 rev:55 rq:1306363 version:6.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nbxmpp/python-nbxmpp.changes 2025-05-30 17:26:17.257638867 +0200 +++ /work/SRC/openSUSE:Factory/.python-nbxmpp.new.27445/python-nbxmpp.changes 2025-09-22 16:40:34.823681889 +0200 @@ -1,0 +2,10 @@ +Sun Sep 21 19:36:01 UTC 2025 - Dirk Müller <[email protected]> + +- update to 6.3.0: + * Allow to set stream language + * Better cache invalid xml regex + * HTTP: Log warning on cancel instead of raising exception + * SASL: Apply SASLPrep for PLAIN and SCRAM + * VCard4: Preserve unsupported elements + +------------------------------------------------------------------- Old: ---- python-nbxmpp-6.2.0.tar.bz2 New: ---- python-nbxmpp-6.3.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nbxmpp.spec ++++++ --- /var/tmp/diff_new_pack.lRjfNj/_old 2025-09-22 16:40:35.399706091 +0200 +++ /var/tmp/diff_new_pack.lRjfNj/_new 2025-09-22 16:40:35.403706259 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-nbxmpp # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?sle15_python_module_pythons} %define _name nbxmpp Name: python-nbxmpp -Version: 6.2.0 +Version: 6.3.0 Release: 0 Summary: XMPP library by Gajim team License: GPL-3.0-or-later ++++++ python-nbxmpp-6.2.0.tar.bz2 -> python-nbxmpp-6.3.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/ChangeLog new/python-nbxmpp-6.3.0/ChangeLog --- old/python-nbxmpp-6.2.0/ChangeLog 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/ChangeLog 2025-08-11 20:29:51.000000000 +0200 @@ -1,3 +1,19 @@ +nbxmpp 6.3.0 (07 Aug 2025) + + New + + * Allow to set stream language + + Improvements + + * Better cache invalid xml regex + * HTTP: Log warning on cancel instead of raising exception + + Bug Fixes + + * SASL: Apply SASLPrep for PLAIN and SCRAM + * VCard4: Preserve unsupported elements + nbxmpp 6.2.0 (19 Apr 2025) Change diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/__init__.py new/python-nbxmpp-6.3.0/nbxmpp/__init__.py --- old/python-nbxmpp-6.2.0/nbxmpp/__init__.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/__init__.py 2025-08-11 20:29:51.000000000 +0200 @@ -4,4 +4,4 @@ from .protocol import * # noqa: F403, E402 -__version__: str = "6.2.0" +__version__: str = "6.3.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/client.py new/python-nbxmpp-6.3.0/nbxmpp/client.py --- old/python-nbxmpp-6.2.0/nbxmpp/client.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/client.py 2025-08-11 20:29:51.000000000 +0200 @@ -237,6 +237,9 @@ def lang(self) -> str: return self._lang + def set_lang(self, lang: str) -> None: + self._lang = lang + @property def username(self) -> str | None: return self._username diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/dispatcher.py new/python-nbxmpp-6.3.0/nbxmpp/dispatcher.py --- old/python-nbxmpp-6.2.0/nbxmpp/dispatcher.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/dispatcher.py 2025-08-11 20:29:51.000000000 +0200 @@ -12,7 +12,6 @@ from typing import TYPE_CHECKING import logging -import re import time from collections.abc import Callable from xml.parsers.expat import ExpatError @@ -91,8 +90,8 @@ from nbxmpp.simplexml import Node from nbxmpp.simplexml import NodeBuilder from nbxmpp.structs import StanzaHandler -from nbxmpp.util import get_invalid_xml_regex from nbxmpp.util import get_properties_struct +from nbxmpp.util import INVALID_XML_RX from nbxmpp.util import is_websocket_close from nbxmpp.util import is_websocket_stream_error from nbxmpp.util import LogAdapter @@ -251,8 +250,6 @@ "error": StreamErrorNode, } - self.invalid_chars_re = get_invalid_xml_regex() - self._register_namespace("unknown") self._register_namespace(Namespace.STREAMS) self._register_namespace(Namespace.CLIENT) @@ -449,7 +446,7 @@ self._parser.dispatch = self.dispatch def replace_non_character(self, data: str) -> str: - return re.sub(self.invalid_chars_re, "\ufffd", data) + return INVALID_XML_RX.sub("\ufffd", data) def process_data(self, data: str) -> None: # Parse incoming data diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/http.py new/python-nbxmpp-6.3.0/nbxmpp/http.py --- old/python-nbxmpp-6.2.0/nbxmpp/http.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/http.py 2025-08-11 20:29:51.000000000 +0200 @@ -160,7 +160,8 @@ def cancel(self) -> None: if self._is_finished: - raise ValueError("Session already finished") + self._log.warning("Cancel requested after download has already finished") + return self._log.info("Cancel requested") self._cancellable.cancel() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/modules/vcard4.py new/python-nbxmpp-6.3.0/nbxmpp/modules/vcard4.py --- old/python-nbxmpp-6.2.0/nbxmpp/modules/vcard4.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/modules/vcard4.py 2025-08-11 20:29:51.000000000 +0200 @@ -11,6 +11,7 @@ from typing import TYPE_CHECKING import logging +from collections import defaultdict from collections.abc import ValuesView from dataclasses import dataclass from dataclasses import field @@ -1067,18 +1068,31 @@ VCardPropertiesT = list[tuple[str | None, PropertyT | list[PropertyT]]] +NotSupportedNodesT = dict[str | None, list[Node]] class VCard: - def __init__(self, properties: VCardPropertiesT | None = None) -> None: + def __init__( + self, + properties: VCardPropertiesT | None = None, + not_supported_nodes: NotSupportedNodesT | None = None, + ) -> None: if properties is None: properties = [] + if not_supported_nodes is None: + not_supported_nodes = defaultdict(list) + self._properties = properties + self._no_supported_nodes = not_supported_nodes @classmethod def from_node(cls, node: Node) -> VCard: properties: VCardPropertiesT = [] + not_supported_nodes: NotSupportedNodesT = defaultdict(list) + for child in node.getChildren(): + if isinstance(child, str): + continue child_name = child.getName() if child_name == "group": @@ -1088,9 +1102,13 @@ group_properties: list[PropertyT] = [] for group_child in child.getChildren(): + if isinstance(group_child, str): + continue + group_child_name = group_child.getName() property_ = get_property_from_name(group_child_name, group_child) if property_ is None: + not_supported_nodes[group_name].append(group_child) continue group_properties.append(property_) @@ -1100,10 +1118,11 @@ property_ = get_property_from_name(child_name, child) if property_ is None: + not_supported_nodes[None].append(child) continue properties.append((None, property_)) - return cls(properties) + return cls(properties, not_supported_nodes) def to_node(self) -> Node: vcard = Node(f"{Namespace.VCARD4} vcard") @@ -1112,11 +1131,19 @@ assert not isinstance(props, list) vcard.addChild(node=props.to_node()) else: - group = Node(group) + group_node = Node(group) assert isinstance(props, list) for prop in props: - group.addChild(node=prop.to_node()) - vcard.addChild(node=group) + group_node.addChild(node=prop.to_node()) + + for node in self._no_supported_nodes.get(group, []): + group_node.addChild(node=node) + + vcard.addChild(node=group_node) + + for node in self._no_supported_nodes.get(None, []): + vcard.addChild(node=node) + return vcard def get_properties(self) -> list[PropertyT]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/old_dispatcher.py new/python-nbxmpp-6.3.0/nbxmpp/old_dispatcher.py --- old/python-nbxmpp-6.2.0/nbxmpp/old_dispatcher.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/old_dispatcher.py 2025-08-11 20:29:51.000000000 +0200 @@ -10,7 +10,6 @@ import inspect import logging -import re import sys import uuid from xml.parsers.expat import ExpatError @@ -69,6 +68,7 @@ from nbxmpp.protocol import Protocol from nbxmpp.simplexml import NodeBuilder from nbxmpp.util import get_properties_struct +from nbxmpp.util import INVALID_XML_RX log = logging.getLogger("nbxmpp.dispatcher") @@ -145,24 +145,6 @@ self.get_module, ] - # \ufddo -> \ufdef range - c = "\ufdd0" - r = c - while c < "\ufdef": - c = chr(ord(c) + 1) - r += "|" + c - - # \ufffe-\uffff, \u1fffe-\u1ffff, ..., \u10fffe-\u10ffff - c = "\ufffe" - r += "|" + c - r += "|" + chr(ord(c) + 1) - while c < "\U0010fffe": - c = chr(ord(c) + 0x10000) - r += "|" + c - r += "|" + chr(ord(c) + 1) - - self.invalid_chars_re = re.compile(r) - def getAnID(self): return str(uuid.uuid4()) @@ -293,7 +275,7 @@ ) def replace_non_character(self, data): - return re.sub(self.invalid_chars_re, "\ufffd", data) + return INVALID_XML_RX.sub("\ufffd", data) def ProcessNonBlocking(self, data): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/sasl.py new/python-nbxmpp-6.3.0/nbxmpp/sasl.py --- old/python-nbxmpp-6.2.0/nbxmpp/sasl.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/sasl.py 2025-08-11 20:29:51.000000000 +0200 @@ -25,6 +25,7 @@ from nbxmpp.protocol import Protocol from nbxmpp.protocol import SASL_AUTH_MECHS from nbxmpp.protocol import SASL_ERROR_CONDITIONS +from nbxmpp.stringprep import saslprep from nbxmpp.structs import ChannelBindingData from nbxmpp.util import b64decode from nbxmpp.util import b64encode @@ -315,7 +316,12 @@ name = "PLAIN" def get_initiate_data(self) -> str: - return b64encode("\x00%s\x00%s" % (self._username, self._password)) + try: + password = saslprep(self._password) + except Exception: + password = "" + + return b64encode("\x00%s\x00%s" % (self._username, password)) class EXTERNAL(BaseMechanism): @@ -431,8 +437,13 @@ if iteration_count < 4096: raise AuthFail("Salt iteration count to low: %s" % iteration_count) + try: + password = saslprep(self._password) + except Exception: + password = "" + salted_password = pbkdf2_hmac( - self._hash_method, self._password.encode("utf8"), salt, iteration_count + self._hash_method, password.encode("utf8"), salt, iteration_count ) client_final_message_wo_proof = "c=%s,r=%s" % ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/structs.py new/python-nbxmpp-6.3.0/nbxmpp/structs.py --- old/python-nbxmpp-6.2.0/nbxmpp/structs.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/structs.py 2025-08-11 20:29:51.000000000 +0200 @@ -922,33 +922,6 @@ return self._error_node.getTagAttr("stamp") -class StanzaMalformedError(CommonError): - def __init__(self, stanza: Protocol, text: str | None) -> None: - self._error_node = None - self.condition = "stanza-malformed" - self.condition_data = None - self.app_condition = None - self.type = None - self.jid = stanza.getFrom() - self.id = stanza.getID() - self._text: dict[str, str] = {} - if text: - self._text["en"] = text - - @classmethod - def from_string(cls, node_string: str) -> Any: - raise NotImplementedError - - def __str__(self) -> str: - text = self.get_text("en") - if text: - text = ": %s" % text - return "Received malformed stanza from %s%s" % (self.jid, text) - - def serialize(self) -> str: - raise NotImplementedError - - class StreamError(CommonError): def __init__(self, stanza: Protocol) -> None: self.condition = stanza.getError() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/task.py new/python-nbxmpp-6.3.0/nbxmpp/task.py --- old/python-nbxmpp-6.2.0/nbxmpp/task.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/task.py 2025-08-11 20:29:51.000000000 +0200 @@ -88,7 +88,7 @@ return task -def iq_request_task(func: Callable[P, T]) -> Callable[P, T]: +def iq_request_task(func: Callable[..., T]) -> Callable[..., T]: @wraps(func) def func_wrapper( self: NBXMPPModuleT, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/nbxmpp/util.py new/python-nbxmpp-6.3.0/nbxmpp/util.py --- old/python-nbxmpp-6.2.0/nbxmpp/util.py 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/nbxmpp/util.py 2025-08-11 20:29:51.000000000 +0200 @@ -47,7 +47,6 @@ from nbxmpp.structs import MessageProperties from nbxmpp.structs import PresenceProperties from nbxmpp.structs import Properties -from nbxmpp.structs import StanzaMalformedError from nbxmpp.third_party import hsluv if TYPE_CHECKING: @@ -117,11 +116,7 @@ error_classes = {Namespace.HTTPUPLOAD_0: HTTPUploadError} -def error_factory( - stanza: Protocol, condition: str | None = None, text: str | None = None -) -> Any: - if condition == "stanza-malformed": - return StanzaMalformedError(stanza, text) +def error_factory(stanza: Protocol) -> Any: app_namespace = stanza.getAppErrorNamespace() return error_classes.get(app_namespace, CommonError)(stanza) @@ -381,6 +376,9 @@ return re.compile(r) +INVALID_XML_RX = get_invalid_xml_regex() + + def get_tls_error_phrase(tls_error: Gio.TlsCertificateFlags) -> str | None: phrase = GIO_TLS_ERRORS.get(tls_error) if phrase is None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/python-nbxmpp.doap new/python-nbxmpp-6.3.0/python-nbxmpp.doap --- old/python-nbxmpp-6.2.0/python-nbxmpp.doap 2025-05-15 12:05:06.000000000 +0200 +++ new/python-nbxmpp-6.3.0/python-nbxmpp.doap 2025-08-11 20:29:51.000000000 +0200 @@ -383,7 +383,7 @@ <xmpp:SupportedXep> <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html"/> <xmpp:status>complete</xmpp:status> - <xmpp:version>0.1</xmpp:version> + <xmpp:version>0.3.0</xmpp:version> </xmpp:SupportedXep> </implements> <implements> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-nbxmpp-6.2.0/test/unit/test_vcard4.py new/python-nbxmpp-6.3.0/test/unit/test_vcard4.py --- old/python-nbxmpp-6.2.0/test/unit/test_vcard4.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-nbxmpp-6.3.0/test/unit/test_vcard4.py 2025-08-11 20:29:51.000000000 +0200 @@ -0,0 +1,115 @@ +import unittest + +from nbxmpp.modules.vcard4 import VCard +from nbxmpp.simplexml import Node + + +class TestVCard4(unittest.TestCase): + + def test_vard4_parsing(self): + vcard_node = Node( + node=""" + <vcard xmlns="urn:ietf:params:xml:ns:vcard-4.0"> + <fn><text>Peter Saint-Andre</text></fn> + <n><surname>Saint-Andre</surname><given>Peter</given><additional></additional></n> + <nickname><text>stpeter</text></nickname> + <nickname><text>psa</text></nickname> + <photo><uri>https://stpeter.im/images/stpeter_oscon.jpg</uri></photo> + <bday><date>1966-08-06</date></bday> + <adr> + <parameters> + <type><text>work</text><text>voice</text></type> + <pref><integer>1</integer></pref> + </parameters> + <ext>Suite 600</ext> + <street>1899 Wynkoop Street</street> + <locality>Denver</locality> + <region>CO</region> + <code>80202</code> + <country>USA</country> + </adr> + <adr> + <parameters><type><text>home</text></type></parameters> + <ext></ext> + <street></street> + <locality>Parker</locality> + <region>CO</region> + <code>80138</code> + <country>USA</country> + </adr> + <tel> + <parameters> + <type><text>work</text><text>voice</text></type> + <pref><integer>1</integer></pref> + </parameters> + <uri>tel:+1-303-308-3282</uri> + </tel> + <tel> + <parameters><type><text>work</text><text>fax</text></type></parameters> + <uri>tel:+1-303-308-3219</uri> + </tel> + <tel> + <parameters> + <type><text>cell</text><text>voice</text><text>text</text></type> + </parameters> + <uri>tel:+1-720-256-6756</uri> + </tel> + <tel> + <parameters><type><text>home</text><text>voice</text></type></parameters> + <uri>tel:+1-303-555-1212</uri> + </tel> + <geo><uri>geo:39.59,-105.01</uri></geo> + <title><text>Executive Director</text></title> + <role><text>Patron Saint</text></role> + <org> + <parameters><type><text>work</text></type></parameters> + <text>XMPP Standards Foundation</text> + </org> + <url><uri>https://stpeter.im/</uri></url> + <note> + <text> + More information about me is located on my + personal website: https://stpeter.im/ + </text> + </note> + <gender><sex><text>M</text></sex></gender> + <lang> + <parameters><pref>1</pref></parameters> + <language-tag>en</language-tag> + </lang> + <email> + <parameters><type><text>work</text></type></parameters> + <text>[email protected]</text> + </email> + <email> + <parameters><type><text>home</text></type></parameters> + <text>[email protected]</text> + </email> + <impp> + <parameters><type><text>work</text></type></parameters> + <uri>xmpp:[email protected]</uri> + </impp> + <impp> + <parameters><type><text>home</text></type></parameters> + <uri>xmpp:[email protected]</uri> + </impp> + <key> + <uri>https://stpeter.im/stpeter.asc</uri> + </key> + <unsupported-element>unsupported</unsupported-element> + </vcard> + """ + ) + + vcard = VCard.from_node(vcard_node) + props = vcard.get_properties() + + email_props = list(filter(lambda p: p.name == "email", props)) + self.assertEqual(len(email_props), 2) + + nickname_props = list(filter(lambda p: p.name == "nickname", props)) + self.assertEqual(len(nickname_props), 2) + + # Preserve unsupported elements + node = vcard.to_node() + self.assertEqual(node.getTagData("unsupported-element"), "unsupported")
