From c9c45baabc00a779ace90ebad08de4b0f26f8ecd Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Mon, 23 Jan 2023 12:47:30 +0100 Subject: [PATCH] feat: Allow easier responding to incoming stanzas Should fix #20. --- packages/moxxmpp/lib/src/connection.dart | 5 +- packages/moxxmpp/lib/src/iq.dart | 28 ++- .../moxxmpp/lib/src/managers/attributes.dart | 2 +- packages/moxxmpp/lib/src/managers/base.dart | 22 +++ packages/moxxmpp/lib/src/managers/data.dart | 5 + .../lib/src/managers/data.freezed.dart | 36 +++- packages/moxxmpp/lib/src/roster/roster.dart | 6 +- packages/moxxmpp/lib/src/stanza.dart | 59 +++--- .../lib/src/xeps/xep_0030/xep_0030.dart | 183 +++++++++--------- .../lib/src/xeps/xep_0384/xep_0384.dart | 7 +- packages/moxxmpp/test/stanza_test.dart | 50 ----- packages/moxxmpp/test/xeps/xep_0198_test.dart | 2 +- packages/moxxmpp/test/xeps/xep_0280_test.dart | 2 +- packages/moxxmpp/test/xeps/xep_0352_test.dart | 105 +++++----- packages/moxxmpp/test/xmpp_test.dart | 4 +- 15 files changed, 269 insertions(+), 247 deletions(-) delete mode 100644 packages/moxxmpp/test/stanza_test.dart diff --git a/packages/moxxmpp/lib/src/connection.dart b/packages/moxxmpp/lib/src/connection.dart index 99bed7d..cd19f18 100644 --- a/packages/moxxmpp/lib/src/connection.dart +++ b/packages/moxxmpp/lib/src/connection.dart @@ -459,7 +459,7 @@ class XmppConnection { /// If addId is true, then an 'id' attribute will be added to the stanza if [stanza] has /// none. // TODO(Unknown): if addId = false, the function crashes. - Future sendStanza(Stanza stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool awaitable = true, bool encrypted = false }) async { + Future sendStanza(Stanza stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async { assert(implies(addId == false && stanza.id == null, !awaitable), 'Cannot await a stanza with no id'); // Add extra data in case it was not set @@ -490,6 +490,7 @@ class XmppConnection { null, stanza_, encrypted: encrypted, + forceEncryption: forceEncryption, ), ); _log.fine('Done'); @@ -737,7 +738,7 @@ class XmppConnection { ), ); if (!incomingHandlers.done) { - handleUnhandledStanza(this, incomingPreHandlers.stanza); + await handleUnhandledStanza(this, incomingPreHandlers); } } diff --git a/packages/moxxmpp/lib/src/iq.dart b/packages/moxxmpp/lib/src/iq.dart index 961dd43..47cce7c 100644 --- a/packages/moxxmpp/lib/src/iq.dart +++ b/packages/moxxmpp/lib/src/iq.dart @@ -1,10 +1,28 @@ import 'package:moxxmpp/src/connection.dart'; +import 'package:moxxmpp/src/managers/data.dart'; import 'package:moxxmpp/src/stanza.dart'; -bool handleUnhandledStanza(XmppConnection conn, Stanza stanza) { - if (stanza.type != 'error' && stanza.type != 'result') { - conn.sendStanza(stanza.errorReply('cancel', 'feature-not-implemented')); - } +/// Bounce a stanza if it was not handled by any manager. [conn] is the connection object +/// to use for sending the stanza. [data] is the StanzaHandlerData of the unhandled +/// stanza. +Future handleUnhandledStanza(XmppConnection conn, StanzaHandlerData data) async { + if (data.stanza.type != 'error' && data.stanza.type != 'result') { + final stanza = data.stanza.copyWith( + to: data.stanza.from, + from: data.stanza.to, + type: 'error', + children: [ + buildErrorElement( + 'cancel', + 'feature-not-implemented', + ), + ], + ); - return true; + await conn.sendStanza( + stanza, + awaitable: false, + forceEncryption: data.encrypted, + ); + } } diff --git a/packages/moxxmpp/lib/src/managers/attributes.dart b/packages/moxxmpp/lib/src/managers/attributes.dart index 7630940..c4525be 100644 --- a/packages/moxxmpp/lib/src/managers/attributes.dart +++ b/packages/moxxmpp/lib/src/managers/attributes.dart @@ -23,7 +23,7 @@ class XmppManagerAttributes { required this.getNegotiatorById, }); /// Send a stanza whose response can be awaited. - final Future Function(Stanza stanza, { StanzaFromType addFrom, bool addId, bool awaitable, bool encrypted}) sendStanza; + final Future Function(Stanza stanza, { StanzaFromType addFrom, bool addId, bool awaitable, bool encrypted, bool forceEncryption}) sendStanza; /// Send a nonza. final void Function(XMLNode) sendNonza; diff --git a/packages/moxxmpp/lib/src/managers/base.dart b/packages/moxxmpp/lib/src/managers/base.dart index 9cdb5dd..11435ce 100644 --- a/packages/moxxmpp/lib/src/managers/base.dart +++ b/packages/moxxmpp/lib/src/managers/base.dart @@ -1,6 +1,7 @@ import 'package:logging/logging.dart'; import 'package:moxxmpp/src/events.dart'; import 'package:moxxmpp/src/managers/attributes.dart'; +import 'package:moxxmpp/src/managers/data.dart'; import 'package:moxxmpp/src/managers/handlers.dart'; import 'package:moxxmpp/src/stringxml.dart'; @@ -79,4 +80,25 @@ abstract class XmppManagerBase { return handled; } + + /// Sends a reply of the stanza in [data] with [type]. Replaces the original stanza's + /// children with [children]. + /// + /// Note that this function currently only accepts IQ stanzas. + Future reply(StanzaHandlerData data, String type, List children) async { + assert(data.stanza.tag == 'iq', 'Reply makes little sense for non-IQ stanzas'); + + final stanza = data.stanza.copyWith( + to: data.stanza.from, + from: data.stanza.to, + type: type, + children: children, + ); + + await getAttributes().sendStanza( + stanza, + awaitable: false, + forceEncryption: data.encrypted, + ); + } } diff --git a/packages/moxxmpp/lib/src/managers/data.dart b/packages/moxxmpp/lib/src/managers/data.dart index e964e6a..0a0b466 100644 --- a/packages/moxxmpp/lib/src/managers/data.dart +++ b/packages/moxxmpp/lib/src/managers/data.dart @@ -50,6 +50,11 @@ class StanzaHandlerData with _$StanzaHandlerData { String? funCancellation, // Whether the stanza was received encrypted @Default(false) bool encrypted, + // If true, forces the encryption manager to encrypt to the JID, even if it + // would not normally. In the case of OMEMO: If shouldEncrypt returns false + // but forceEncryption is true, then the OMEMO manager will try to encrypt + // to the JID anyway. + @Default(false) bool forceEncryption, // The stated type of encryption used, if any was used ExplicitEncryptionType? encryptionType, // Delayed Delivery diff --git a/packages/moxxmpp/lib/src/managers/data.freezed.dart b/packages/moxxmpp/lib/src/managers/data.freezed.dart index 8c72edf..d5a1c2b 100644 --- a/packages/moxxmpp/lib/src/managers/data.freezed.dart +++ b/packages/moxxmpp/lib/src/managers/data.freezed.dart @@ -48,6 +48,11 @@ mixin _$StanzaHandlerData { String? get funCancellation => throw _privateConstructorUsedError; // Whether the stanza was received encrypted bool get encrypted => + throw _privateConstructorUsedError; // If true, forces the encryption manager to encrypt to the JID, even if it +// would not normally. In the case of OMEMO: If shouldEncrypt returns false +// but forceEncryption is true, then the OMEMO manager will try to encrypt +// to the JID anyway. + bool get forceEncryption => throw _privateConstructorUsedError; // The stated type of encryption used, if any was used ExplicitEncryptionType? get encryptionType => throw _privateConstructorUsedError; // Delayed Delivery @@ -94,6 +99,7 @@ abstract class $StanzaHandlerDataCopyWith<$Res> { String? funReplacement, String? funCancellation, bool encrypted, + bool forceEncryption, ExplicitEncryptionType? encryptionType, DelayedDelivery? delayedDelivery, Map other, @@ -132,6 +138,7 @@ class _$StanzaHandlerDataCopyWithImpl<$Res> Object? funReplacement = freezed, Object? funCancellation = freezed, Object? encrypted = freezed, + Object? forceEncryption = freezed, Object? encryptionType = freezed, Object? delayedDelivery = freezed, Object? other = freezed, @@ -213,6 +220,10 @@ class _$StanzaHandlerDataCopyWithImpl<$Res> ? _value.encrypted : encrypted // ignore: cast_nullable_to_non_nullable as bool, + forceEncryption: forceEncryption == freezed + ? _value.forceEncryption + : forceEncryption // ignore: cast_nullable_to_non_nullable + as bool, encryptionType: encryptionType == freezed ? _value.encryptionType : encryptionType // ignore: cast_nullable_to_non_nullable @@ -271,6 +282,7 @@ abstract class _$$_StanzaHandlerDataCopyWith<$Res> String? funReplacement, String? funCancellation, bool encrypted, + bool forceEncryption, ExplicitEncryptionType? encryptionType, DelayedDelivery? delayedDelivery, Map other, @@ -311,6 +323,7 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res> Object? funReplacement = freezed, Object? funCancellation = freezed, Object? encrypted = freezed, + Object? forceEncryption = freezed, Object? encryptionType = freezed, Object? delayedDelivery = freezed, Object? other = freezed, @@ -392,6 +405,10 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res> ? _value.encrypted : encrypted // ignore: cast_nullable_to_non_nullable as bool, + forceEncryption: forceEncryption == freezed + ? _value.forceEncryption + : forceEncryption // ignore: cast_nullable_to_non_nullable + as bool, encryptionType: encryptionType == freezed ? _value.encryptionType : encryptionType // ignore: cast_nullable_to_non_nullable @@ -442,6 +459,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { this.funReplacement, this.funCancellation, this.encrypted = false, + this.forceEncryption = false, this.encryptionType, this.delayedDelivery, final Map other = const {}, @@ -506,6 +524,13 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { @override @JsonKey() final bool encrypted; +// If true, forces the encryption manager to encrypt to the JID, even if it +// would not normally. In the case of OMEMO: If shouldEncrypt returns false +// but forceEncryption is true, then the OMEMO manager will try to encrypt +// to the JID anyway. + @override + @JsonKey() + final bool forceEncryption; // The stated type of encryption used, if any was used @override final ExplicitEncryptionType? encryptionType; @@ -540,7 +565,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { @override String toString() { - return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, stableId: $stableId, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction, lastMessageCorrectionSid: $lastMessageCorrectionSid, messageReactions: $messageReactions, stickerPackId: $stickerPackId)'; + return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, stableId: $stableId, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, forceEncryption: $forceEncryption, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction, lastMessageCorrectionSid: $lastMessageCorrectionSid, messageReactions: $messageReactions, stickerPackId: $stickerPackId)'; } @override @@ -572,6 +597,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { const DeepCollectionEquality() .equals(other.funCancellation, funCancellation) && const DeepCollectionEquality().equals(other.encrypted, encrypted) && + const DeepCollectionEquality() + .equals(other.forceEncryption, forceEncryption) && const DeepCollectionEquality() .equals(other.encryptionType, encryptionType) && const DeepCollectionEquality() @@ -608,6 +635,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { const DeepCollectionEquality().hash(funReplacement), const DeepCollectionEquality().hash(funCancellation), const DeepCollectionEquality().hash(encrypted), + const DeepCollectionEquality().hash(forceEncryption), const DeepCollectionEquality().hash(encryptionType), const DeepCollectionEquality().hash(delayedDelivery), const DeepCollectionEquality().hash(_other), @@ -641,6 +669,7 @@ abstract class _StanzaHandlerData implements StanzaHandlerData { final String? funReplacement, final String? funCancellation, final bool encrypted, + final bool forceEncryption, final ExplicitEncryptionType? encryptionType, final DelayedDelivery? delayedDelivery, final Map other, @@ -690,6 +719,11 @@ abstract class _StanzaHandlerData implements StanzaHandlerData { String? get funCancellation; @override // Whether the stanza was received encrypted bool get encrypted; + @override // If true, forces the encryption manager to encrypt to the JID, even if it +// would not normally. In the case of OMEMO: If shouldEncrypt returns false +// but forceEncryption is true, then the OMEMO manager will try to encrypt +// to the JID anyway. + bool get forceEncryption; @override // The stated type of encryption used, if any was used ExplicitEncryptionType? get encryptionType; @override // Delayed Delivery diff --git a/packages/moxxmpp/lib/src/roster/roster.dart b/packages/moxxmpp/lib/src/roster/roster.dart index cc945be..e804a0f 100644 --- a/packages/moxxmpp/lib/src/roster/roster.dart +++ b/packages/moxxmpp/lib/src/roster/roster.dart @@ -161,7 +161,11 @@ class RosterManager extends XmppManagerBase { ), ); - await attrs.sendStanza(stanza.reply()); + await reply( + state, + 'result', + [], + ); return state.copyWith(done: true); } diff --git a/packages/moxxmpp/lib/src/stanza.dart b/packages/moxxmpp/lib/src/stanza.dart index f6993c1..37059f9 100644 --- a/packages/moxxmpp/lib/src/stanza.dart +++ b/packages/moxxmpp/lib/src/stanza.dart @@ -114,40 +114,27 @@ class Stanza extends XMLNode { children: children ?? this.children, ); } - - Stanza reply({ List children = const [] }) { - return copyWith( - from: attributes['to'] as String?, - to: attributes['from'] as String?, - type: tag == 'iq' ? 'result' : attributes['type'] as String?, - children: children, - ); - } - - Stanza errorReply(String type, String condition, { String? text }) { - return copyWith( - from: attributes['to'] as String?, - to: attributes['from'] as String?, - type: 'error', - children: [ - XMLNode( - tag: 'error', - attributes: { 'type': type }, - children: [ - XMLNode.xmlns( - tag: condition, - xmlns: fullStanzaXmlns, - children: text != null ?[ - XMLNode.xmlns( - tag: 'text', - xmlns: fullStanzaXmlns, - text: text, - ) - ] : [], - ) - ], - ) - ], - ); - } +} + +/// Build an element with a child <[condition] type="[type]" />. If [text] +/// is not null, then the condition element will contain a element with [text] +/// as the body. +XMLNode buildErrorElement(String type, String condition, { String? text }) { + return XMLNode( + tag: 'error', + attributes: { 'type': type }, + children: [ + XMLNode.xmlns( + tag: condition, + xmlns: fullStanzaXmlns, + children: text != null ? [ + XMLNode.xmlns( + tag: 'text', + xmlns: fullStanzaXmlns, + text: text, + ) + ] : [], + ), + ], + ); } diff --git a/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart b/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart index dcabd5e..e446db5 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart @@ -20,7 +20,6 @@ import 'package:synchronized/synchronized.dart'; @immutable class DiscoCacheKey { - const DiscoCacheKey(this.jid, this.node); final String jid; final String? node; @@ -35,7 +34,6 @@ class DiscoCacheKey { } class DiscoManager extends XmppManagerBase { - DiscoManager() : _features = List.empty(growable: true), _capHashCache = {}, @@ -47,15 +45,19 @@ class DiscoManager extends XmppManagerBase { /// Our features final List _features; - // Map full JID to Capability hashes + /// Map full JID to Capability hashes final Map _capHashCache; - // Map capability hash to the disco info + + /// Map capability hash to the disco info final Map _capHashInfoCache; - // Map full JID to Disco Info + + /// Map full JID to Disco Info final Map _discoInfoCache; - // Mapping the full JID to a list of running requests + + /// Mapping the full JID to a list of running requests final Map>>> _runningInfoQueries; - // Cache lock + + /// Cache lock final Lock _cacheLock; @visibleForTesting @@ -154,67 +156,65 @@ class DiscoManager extends XmppManagerBase { if (stanza.type != 'get') return state; final presence = getAttributes().getManagerById(presenceManager)! as PresenceManager; - final query = stanza.firstTag('query')!; + final query = stanza.firstTag('query', xmlns: discoInfoXmlns)!; final node = query.attributes['node'] as String?; final capHash = await presence.getCapabilityHash(); final isCapabilityNode = node == '${presence.capabilityHashNode}#$capHash'; if (!isCapabilityNode && node != null) { - await getAttributes().sendStanza(Stanza.iq( - to: stanza.from, - from: stanza.to, - id: stanza.id, - type: 'error', + await reply( + state, + 'error', + [ + XMLNode.xmlns( + tag: 'query', + xmlns: discoInfoXmlns, + attributes: { + 'node': node + }, + ), + XMLNode( + tag: 'error', + attributes: { + 'type': 'cancel' + }, children: [ XMLNode.xmlns( - tag: 'query', - // TODO(PapaTutuWawa): Why are we copying the xmlns? - xmlns: query.attributes['xmlns']! as String, - attributes: { - 'node': node - }, - ), - XMLNode( - tag: 'error', - attributes: { - 'type': 'cancel' - }, - children: [ - XMLNode.xmlns( - tag: 'not-allowed', - xmlns: fullStanzaXmlns, - ) - ], + tag: 'not-allowed', + xmlns: fullStanzaXmlns, ) ], - ) - ,); + ), + ], + ); return state.copyWith(done: true); } - await getAttributes().sendStanza(stanza.reply( - children: [ - XMLNode.xmlns( - tag: 'query', - xmlns: discoInfoXmlns, - attributes: { - ...!isCapabilityNode ? {} : { - 'node': '${presence.capabilityHashNode}#$capHash' - } - }, - children: [ - ...getIdentities().map((identity) => identity.toXMLNode()), - ..._features.map((feat) { - return XMLNode( - tag: 'feature', - attributes: { 'var': feat }, - ); - }), - ], - ), - ], - ),); + await reply( + state, + 'result', + [ + XMLNode.xmlns( + tag: 'query', + xmlns: discoInfoXmlns, + attributes: { + ...!isCapabilityNode ? {} : { + 'node': '${presence.capabilityHashNode}#$capHash' + } + }, + children: [ + ...getIdentities().map((identity) => identity.toXMLNode()), + ..._features.map((feat) { + return XMLNode( + tag: 'feature', + attributes: { 'var': feat }, + ); + }), + ], + ), + ], + ); return state.copyWith(done: true); } @@ -222,52 +222,49 @@ class DiscoManager extends XmppManagerBase { Future _onDiscoItemsRequest(Stanza stanza, StanzaHandlerData state) async { if (stanza.type != 'get') return state; - final query = stanza.firstTag('query')!; + final query = stanza.firstTag('query', xmlns: discoItemsXmlns)!; if (query.attributes['node'] != null) { // TODO(Unknown): Handle the node we specified for XEP-0115 - await getAttributes().sendStanza( - Stanza.iq( - to: stanza.from, - from: stanza.to, - id: stanza.id, - type: 'error', - children: [ - XMLNode.xmlns( - tag: 'query', - // TODO(PapaTutuWawa): Why copy the xmlns? - xmlns: query.attributes['xmlns']! as String, - attributes: { - 'node': query.attributes['node']! as String, - }, - ), - XMLNode( - tag: 'error', - attributes: { - 'type': 'cancel' - }, - children: [ - XMLNode.xmlns( - tag: 'not-allowed', - xmlns: fullStanzaXmlns, - ), - ], - ), - ], - ), - ); - return state.copyWith(done: true); - } - - await getAttributes().sendStanza( - stanza.reply( - children: [ + await reply( + state, + 'error', + [ XMLNode.xmlns( tag: 'query', xmlns: discoItemsXmlns, + attributes: { + 'node': query.attributes['node']! as String, + }, + ), + XMLNode( + tag: 'error', + attributes: { + 'type': 'cancel' + }, + children: [ + XMLNode.xmlns( + tag: 'not-allowed', + xmlns: fullStanzaXmlns, + ), + ], ), ], - ), + ); + + return state.copyWith(done: true); + } + + await reply( + state, + 'result', + [ + XMLNode.xmlns( + tag: 'query', + xmlns: discoItemsXmlns, + ), + ], ); + return state.copyWith(done: true); } diff --git a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart index dc10333..339a09c 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart @@ -318,11 +318,12 @@ abstract class BaseOmemoManager extends XmppManagerBase { } final toJid = JID.fromString(stanza.to!).toBare(); - if (!(await shouldEncryptStanza(toJid, stanza))) { - logger.finest('shouldEncryptStanza returned false for message to $toJid. Not encrypting.'); + final shouldEncryptResult = await shouldEncryptStanza(toJid, stanza); + if (!shouldEncryptResult && !state.forceEncryption) { + logger.finest('Not encrypting stanza for $toJid: Both shouldEncryptStanza and forceEncryption are false.'); return state; } else { - logger.finest('shouldEncryptStanza returned true for message to $toJid.'); + logger.finest('Encrypting stanza for $toJid: shouldEncryptResult=$shouldEncryptResult, forceEncryption=${state.forceEncryption}'); } final toEncrypt = List.empty(growable: true); diff --git a/packages/moxxmpp/test/stanza_test.dart b/packages/moxxmpp/test/stanza_test.dart deleted file mode 100644 index e54b8a8..0000000 --- a/packages/moxxmpp/test/stanza_test.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:moxxmpp/moxxmpp.dart'; -import 'package:test/test.dart'; - -void main() { - test('Make sure reply does not copy the children', () { - final stanza = Stanza.iq( - to: 'hallo', - from: 'world', - id: 'abc123', - type: 'get', - children: [ - XMLNode(tag: 'test-tag'), - XMLNode(tag: 'test-tag2') - ], - ); - - final reply = stanza.reply(); - - expect(reply.children, []); - expect(reply.type, 'result'); - expect(reply.from, stanza.to); - expect(reply.to, stanza.from); - expect(reply.id, stanza.id); - }); - - test('Make sure reply includes the new children', () { - final stanza = Stanza.iq( - to: 'hallo', - from: 'world', - id: 'abc123', - type: 'get', - children: [ - XMLNode(tag: 'test-tag'), - XMLNode(tag: 'test-tag2') - ], - ); - - final reply = stanza.reply( - children: [ - XMLNode.xmlns( - tag: 'test', - xmlns: 'test', - ) - ], - ); - - expect(reply.children.length, 1); - expect(reply.firstTag('test') != null, true); - }); -} diff --git a/packages/moxxmpp/test/xeps/xep_0198_test.dart b/packages/moxxmpp/test/xeps/xep_0198_test.dart index 22ad652..a468954 100644 --- a/packages/moxxmpp/test/xeps/xep_0198_test.dart +++ b/packages/moxxmpp/test/xeps/xep_0198_test.dart @@ -17,7 +17,7 @@ Future runOutgoingStanzaHandlers(StreamManagementManager man, Stanza stanz XmppManagerAttributes mkAttributes(void Function(Stanza) callback) { return XmppManagerAttributes( - sendStanza: (stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool awaitable = true, bool encrypted = false }) async { + sendStanza: (stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async { callback(stanza); return Stanza.message(); diff --git a/packages/moxxmpp/test/xeps/xep_0280_test.dart b/packages/moxxmpp/test/xeps/xep_0280_test.dart index 06727c6..3b5e932 100644 --- a/packages/moxxmpp/test/xeps/xep_0280_test.dart +++ b/packages/moxxmpp/test/xeps/xep_0280_test.dart @@ -5,7 +5,7 @@ import '../helpers/xmpp.dart'; void main() { test("Test if we're vulnerable against CVE-2020-26547 style vulnerabilities", () async { final attributes = XmppManagerAttributes( - sendStanza: (stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async { + sendStanza: (stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async { // ignore: avoid_print print('==> ${stanza.toXml()}'); return XMLNode(tag: 'iq', attributes: { 'type': 'result' }); diff --git a/packages/moxxmpp/test/xeps/xep_0352_test.dart b/packages/moxxmpp/test/xeps/xep_0352_test.dart index 24e0a12..592816f 100644 --- a/packages/moxxmpp/test/xeps/xep_0352_test.dart +++ b/packages/moxxmpp/test/xeps/xep_0352_test.dart @@ -29,59 +29,62 @@ T? getUnsupportedCSINegotiator(String id) { void main() { group('Test the XEP-0352 implementation', () { - test('Test setting the CSI state when CSI is unsupported', () { - var nonzaSent = false; - final csi = CSIManager(); - csi.register(XmppManagerAttributes( - sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'), - sendEvent: (event) {}, - sendNonza: (nonza) { - nonzaSent = true; - }, - getConnectionSettings: () => ConnectionSettings( - jid: JID.fromString('some.user@example.server'), - password: 'password', - useDirectTLS: true, - allowPlainAuth: false, - ), - getManagerById: getManagerNullStub, - getNegotiatorById: getUnsupportedCSINegotiator, - isFeatureSupported: (_) => false, - getFullJID: () => JID.fromString('some.user@example.server/aaaaa'), - getSocket: () => StubTCPSocket(play: []), - getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])), - ), - ); + test('Test setting the CSI state when CSI is unsupported', () { + var nonzaSent = false; + final csi = CSIManager(); + csi.register( + XmppManagerAttributes( + sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async => XMLNode(tag: 'hallo'), + sendEvent: (event) {}, + sendNonza: (nonza) { + nonzaSent = true; + }, + getConnectionSettings: () => ConnectionSettings( + jid: JID.fromString('some.user@example.server'), + password: 'password', + useDirectTLS: true, + allowPlainAuth: false, + ), + getManagerById: getManagerNullStub, + getNegotiatorById: getUnsupportedCSINegotiator, + isFeatureSupported: (_) => false, + getFullJID: () => JID.fromString('some.user@example.server/aaaaa'), + getSocket: () => StubTCPSocket(play: []), + getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])), + ), + ); - csi.setActive(); - csi.setInactive(); + csi.setActive(); + csi.setInactive(); - expect(nonzaSent, false, reason: 'Expected that no nonza is sent'); - }); - test('Test setting the CSI state when CSI is supported', () { - final csi = CSIManager(); - csi.register(XmppManagerAttributes( - sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'), - sendEvent: (event) {}, - sendNonza: (nonza) { - expect(nonza.attributes['xmlns'] == csiXmlns, true, reason: "Expected only nonzas with XMLNS '$csiXmlns'"); - }, - getConnectionSettings: () => ConnectionSettings( - jid: JID.fromString('some.user@example.server'), - password: 'password', - useDirectTLS: true, - allowPlainAuth: false, - ), - getManagerById: getManagerNullStub, - getNegotiatorById: getSupportedCSINegotiator, - isFeatureSupported: (_) => false, - getFullJID: () => JID.fromString('some.user@example.server/aaaaa'), - getSocket: () => StubTCPSocket(play: []), - getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])), - ),); + expect(nonzaSent, false, reason: 'Expected that no nonza is sent'); + }); + test('Test setting the CSI state when CSI is supported', () { + final csi = CSIManager(); + csi.register( + XmppManagerAttributes( + sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async => XMLNode(tag: 'hallo'), + sendEvent: (event) {}, + sendNonza: (nonza) { + expect(nonza.attributes['xmlns'] == csiXmlns, true, reason: "Expected only nonzas with XMLNS '$csiXmlns'"); + }, + getConnectionSettings: () => ConnectionSettings( + jid: JID.fromString('some.user@example.server'), + password: 'password', + useDirectTLS: true, + allowPlainAuth: false, + ), + getManagerById: getManagerNullStub, + getNegotiatorById: getSupportedCSINegotiator, + isFeatureSupported: (_) => false, + getFullJID: () => JID.fromString('some.user@example.server/aaaaa'), + getSocket: () => StubTCPSocket(play: []), + getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])), + ), + ); - csi.setActive(); - csi.setInactive(); - }); + csi.setActive(); + csi.setInactive(); + }); }); } diff --git a/packages/moxxmpp/test/xmpp_test.dart b/packages/moxxmpp/test/xmpp_test.dart index 3e1b3d7..bbad56e 100644 --- a/packages/moxxmpp/test/xmpp_test.dart +++ b/packages/moxxmpp/test/xmpp_test.dart @@ -9,7 +9,7 @@ Future testRosterManager(String bareJid, String resource, String stanzaStr var eventTriggered = false; final roster = RosterManager(TestingRosterStateManager('', [])); roster.register(XmppManagerAttributes( - sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'), + sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async => XMLNode(tag: 'hallo'), sendEvent: (event) { eventTriggered = true; }, @@ -310,7 +310,7 @@ void main() { var eventTriggered = false; final roster = RosterManager(TestingRosterStateManager('', [])); roster.register(XmppManagerAttributes( - sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'), + sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false, bool forceEncryption = false, }) async => XMLNode(tag: 'hallo'), sendEvent: (event) { eventTriggered = true; },