parent
a01022c217
commit
c9c45baabc
@ -459,7 +459,7 @@ class XmppConnection {
|
|||||||
/// If addId is true, then an 'id' attribute will be added to the stanza if [stanza] has
|
/// If addId is true, then an 'id' attribute will be added to the stanza if [stanza] has
|
||||||
/// none.
|
/// none.
|
||||||
// TODO(Unknown): if addId = false, the function crashes.
|
// TODO(Unknown): if addId = false, the function crashes.
|
||||||
Future<XMLNode> sendStanza(Stanza stanza, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool awaitable = true, bool encrypted = false }) async {
|
Future<XMLNode> 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');
|
assert(implies(addId == false && stanza.id == null, !awaitable), 'Cannot await a stanza with no id');
|
||||||
|
|
||||||
// Add extra data in case it was not set
|
// Add extra data in case it was not set
|
||||||
@ -490,6 +490,7 @@ class XmppConnection {
|
|||||||
null,
|
null,
|
||||||
stanza_,
|
stanza_,
|
||||||
encrypted: encrypted,
|
encrypted: encrypted,
|
||||||
|
forceEncryption: forceEncryption,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
_log.fine('Done');
|
_log.fine('Done');
|
||||||
@ -737,7 +738,7 @@ class XmppConnection {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!incomingHandlers.done) {
|
if (!incomingHandlers.done) {
|
||||||
handleUnhandledStanza(this, incomingPreHandlers.stanza);
|
await handleUnhandledStanza(this, incomingPreHandlers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
import 'package:moxxmpp/src/connection.dart';
|
import 'package:moxxmpp/src/connection.dart';
|
||||||
|
import 'package:moxxmpp/src/managers/data.dart';
|
||||||
import 'package:moxxmpp/src/stanza.dart';
|
import 'package:moxxmpp/src/stanza.dart';
|
||||||
|
|
||||||
bool handleUnhandledStanza(XmppConnection conn, Stanza stanza) {
|
/// Bounce a stanza if it was not handled by any manager. [conn] is the connection object
|
||||||
if (stanza.type != 'error' && stanza.type != 'result') {
|
/// to use for sending the stanza. [data] is the StanzaHandlerData of the unhandled
|
||||||
conn.sendStanza(stanza.errorReply('cancel', 'feature-not-implemented'));
|
/// stanza.
|
||||||
}
|
Future<void> 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class XmppManagerAttributes {
|
|||||||
required this.getNegotiatorById,
|
required this.getNegotiatorById,
|
||||||
});
|
});
|
||||||
/// Send a stanza whose response can be awaited.
|
/// Send a stanza whose response can be awaited.
|
||||||
final Future<XMLNode> Function(Stanza stanza, { StanzaFromType addFrom, bool addId, bool awaitable, bool encrypted}) sendStanza;
|
final Future<XMLNode> Function(Stanza stanza, { StanzaFromType addFrom, bool addId, bool awaitable, bool encrypted, bool forceEncryption}) sendStanza;
|
||||||
|
|
||||||
/// Send a nonza.
|
/// Send a nonza.
|
||||||
final void Function(XMLNode) sendNonza;
|
final void Function(XMLNode) sendNonza;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:moxxmpp/src/events.dart';
|
import 'package:moxxmpp/src/events.dart';
|
||||||
import 'package:moxxmpp/src/managers/attributes.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/managers/handlers.dart';
|
||||||
import 'package:moxxmpp/src/stringxml.dart';
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
|
|
||||||
@ -79,4 +80,25 @@ abstract class XmppManagerBase {
|
|||||||
|
|
||||||
return handled;
|
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<void> reply(StanzaHandlerData data, String type, List<XMLNode> 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,11 @@ class StanzaHandlerData with _$StanzaHandlerData {
|
|||||||
String? funCancellation,
|
String? funCancellation,
|
||||||
// Whether the stanza was received encrypted
|
// Whether the stanza was received encrypted
|
||||||
@Default(false) bool 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
|
// The stated type of encryption used, if any was used
|
||||||
ExplicitEncryptionType? encryptionType,
|
ExplicitEncryptionType? encryptionType,
|
||||||
// Delayed Delivery
|
// Delayed Delivery
|
||||||
|
@ -48,6 +48,11 @@ mixin _$StanzaHandlerData {
|
|||||||
String? get funCancellation =>
|
String? get funCancellation =>
|
||||||
throw _privateConstructorUsedError; // Whether the stanza was received encrypted
|
throw _privateConstructorUsedError; // Whether the stanza was received encrypted
|
||||||
bool get 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
|
throw _privateConstructorUsedError; // The stated type of encryption used, if any was used
|
||||||
ExplicitEncryptionType? get encryptionType =>
|
ExplicitEncryptionType? get encryptionType =>
|
||||||
throw _privateConstructorUsedError; // Delayed Delivery
|
throw _privateConstructorUsedError; // Delayed Delivery
|
||||||
@ -94,6 +99,7 @@ abstract class $StanzaHandlerDataCopyWith<$Res> {
|
|||||||
String? funReplacement,
|
String? funReplacement,
|
||||||
String? funCancellation,
|
String? funCancellation,
|
||||||
bool encrypted,
|
bool encrypted,
|
||||||
|
bool forceEncryption,
|
||||||
ExplicitEncryptionType? encryptionType,
|
ExplicitEncryptionType? encryptionType,
|
||||||
DelayedDelivery? delayedDelivery,
|
DelayedDelivery? delayedDelivery,
|
||||||
Map<String, dynamic> other,
|
Map<String, dynamic> other,
|
||||||
@ -132,6 +138,7 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
Object? funReplacement = freezed,
|
Object? funReplacement = freezed,
|
||||||
Object? funCancellation = freezed,
|
Object? funCancellation = freezed,
|
||||||
Object? encrypted = freezed,
|
Object? encrypted = freezed,
|
||||||
|
Object? forceEncryption = freezed,
|
||||||
Object? encryptionType = freezed,
|
Object? encryptionType = freezed,
|
||||||
Object? delayedDelivery = freezed,
|
Object? delayedDelivery = freezed,
|
||||||
Object? other = freezed,
|
Object? other = freezed,
|
||||||
@ -213,6 +220,10 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
? _value.encrypted
|
? _value.encrypted
|
||||||
: encrypted // ignore: cast_nullable_to_non_nullable
|
: encrypted // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
forceEncryption: forceEncryption == freezed
|
||||||
|
? _value.forceEncryption
|
||||||
|
: forceEncryption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
encryptionType: encryptionType == freezed
|
encryptionType: encryptionType == freezed
|
||||||
? _value.encryptionType
|
? _value.encryptionType
|
||||||
: encryptionType // ignore: cast_nullable_to_non_nullable
|
: encryptionType // ignore: cast_nullable_to_non_nullable
|
||||||
@ -271,6 +282,7 @@ abstract class _$$_StanzaHandlerDataCopyWith<$Res>
|
|||||||
String? funReplacement,
|
String? funReplacement,
|
||||||
String? funCancellation,
|
String? funCancellation,
|
||||||
bool encrypted,
|
bool encrypted,
|
||||||
|
bool forceEncryption,
|
||||||
ExplicitEncryptionType? encryptionType,
|
ExplicitEncryptionType? encryptionType,
|
||||||
DelayedDelivery? delayedDelivery,
|
DelayedDelivery? delayedDelivery,
|
||||||
Map<String, dynamic> other,
|
Map<String, dynamic> other,
|
||||||
@ -311,6 +323,7 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
Object? funReplacement = freezed,
|
Object? funReplacement = freezed,
|
||||||
Object? funCancellation = freezed,
|
Object? funCancellation = freezed,
|
||||||
Object? encrypted = freezed,
|
Object? encrypted = freezed,
|
||||||
|
Object? forceEncryption = freezed,
|
||||||
Object? encryptionType = freezed,
|
Object? encryptionType = freezed,
|
||||||
Object? delayedDelivery = freezed,
|
Object? delayedDelivery = freezed,
|
||||||
Object? other = freezed,
|
Object? other = freezed,
|
||||||
@ -392,6 +405,10 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
? _value.encrypted
|
? _value.encrypted
|
||||||
: encrypted // ignore: cast_nullable_to_non_nullable
|
: encrypted // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
forceEncryption: forceEncryption == freezed
|
||||||
|
? _value.forceEncryption
|
||||||
|
: forceEncryption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
encryptionType: encryptionType == freezed
|
encryptionType: encryptionType == freezed
|
||||||
? _value.encryptionType
|
? _value.encryptionType
|
||||||
: encryptionType // ignore: cast_nullable_to_non_nullable
|
: encryptionType // ignore: cast_nullable_to_non_nullable
|
||||||
@ -442,6 +459,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
this.funReplacement,
|
this.funReplacement,
|
||||||
this.funCancellation,
|
this.funCancellation,
|
||||||
this.encrypted = false,
|
this.encrypted = false,
|
||||||
|
this.forceEncryption = false,
|
||||||
this.encryptionType,
|
this.encryptionType,
|
||||||
this.delayedDelivery,
|
this.delayedDelivery,
|
||||||
final Map<String, dynamic> other = const <String, dynamic>{},
|
final Map<String, dynamic> other = const <String, dynamic>{},
|
||||||
@ -506,6 +524,13 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool encrypted;
|
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
|
// The stated type of encryption used, if any was used
|
||||||
@override
|
@override
|
||||||
final ExplicitEncryptionType? encryptionType;
|
final ExplicitEncryptionType? encryptionType;
|
||||||
@ -540,7 +565,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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
|
@override
|
||||||
@ -572,6 +597,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other.funCancellation, funCancellation) &&
|
.equals(other.funCancellation, funCancellation) &&
|
||||||
const DeepCollectionEquality().equals(other.encrypted, encrypted) &&
|
const DeepCollectionEquality().equals(other.encrypted, encrypted) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.forceEncryption, forceEncryption) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other.encryptionType, encryptionType) &&
|
.equals(other.encryptionType, encryptionType) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
@ -608,6 +635,7 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
const DeepCollectionEquality().hash(funReplacement),
|
const DeepCollectionEquality().hash(funReplacement),
|
||||||
const DeepCollectionEquality().hash(funCancellation),
|
const DeepCollectionEquality().hash(funCancellation),
|
||||||
const DeepCollectionEquality().hash(encrypted),
|
const DeepCollectionEquality().hash(encrypted),
|
||||||
|
const DeepCollectionEquality().hash(forceEncryption),
|
||||||
const DeepCollectionEquality().hash(encryptionType),
|
const DeepCollectionEquality().hash(encryptionType),
|
||||||
const DeepCollectionEquality().hash(delayedDelivery),
|
const DeepCollectionEquality().hash(delayedDelivery),
|
||||||
const DeepCollectionEquality().hash(_other),
|
const DeepCollectionEquality().hash(_other),
|
||||||
@ -641,6 +669,7 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
|
|||||||
final String? funReplacement,
|
final String? funReplacement,
|
||||||
final String? funCancellation,
|
final String? funCancellation,
|
||||||
final bool encrypted,
|
final bool encrypted,
|
||||||
|
final bool forceEncryption,
|
||||||
final ExplicitEncryptionType? encryptionType,
|
final ExplicitEncryptionType? encryptionType,
|
||||||
final DelayedDelivery? delayedDelivery,
|
final DelayedDelivery? delayedDelivery,
|
||||||
final Map<String, dynamic> other,
|
final Map<String, dynamic> other,
|
||||||
@ -690,6 +719,11 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
|
|||||||
String? get funCancellation;
|
String? get funCancellation;
|
||||||
@override // Whether the stanza was received encrypted
|
@override // Whether the stanza was received encrypted
|
||||||
bool get 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
|
@override // The stated type of encryption used, if any was used
|
||||||
ExplicitEncryptionType? get encryptionType;
|
ExplicitEncryptionType? get encryptionType;
|
||||||
@override // Delayed Delivery
|
@override // Delayed Delivery
|
||||||
|
@ -161,7 +161,11 @@ class RosterManager extends XmppManagerBase {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await attrs.sendStanza(stanza.reply());
|
await reply(
|
||||||
|
state,
|
||||||
|
'result',
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
return state.copyWith(done: true);
|
return state.copyWith(done: true);
|
||||||
}
|
}
|
||||||
|
@ -114,23 +114,13 @@ class Stanza extends XMLNode {
|
|||||||
children: children ?? this.children,
|
children: children ?? this.children,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stanza reply({ List<XMLNode> 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 }) {
|
/// Build an <error /> element with a child <[condition] type="[type]" />. If [text]
|
||||||
return copyWith(
|
/// is not null, then the condition element will contain a <text /> element with [text]
|
||||||
from: attributes['to'] as String?,
|
/// as the body.
|
||||||
to: attributes['from'] as String?,
|
XMLNode buildErrorElement(String type, String condition, { String? text }) {
|
||||||
type: 'error',
|
return XMLNode(
|
||||||
children: [
|
|
||||||
XMLNode(
|
|
||||||
tag: 'error',
|
tag: 'error',
|
||||||
attributes: <String, dynamic>{ 'type': type },
|
attributes: <String, dynamic>{ 'type': type },
|
||||||
children: [
|
children: [
|
||||||
@ -144,10 +134,7 @@ class Stanza extends XMLNode {
|
|||||||
text: text,
|
text: text,
|
||||||
)
|
)
|
||||||
] : [],
|
] : [],
|
||||||
)
|
),
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -20,7 +20,6 @@ import 'package:synchronized/synchronized.dart';
|
|||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class DiscoCacheKey {
|
class DiscoCacheKey {
|
||||||
|
|
||||||
const DiscoCacheKey(this.jid, this.node);
|
const DiscoCacheKey(this.jid, this.node);
|
||||||
final String jid;
|
final String jid;
|
||||||
final String? node;
|
final String? node;
|
||||||
@ -35,7 +34,6 @@ class DiscoCacheKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DiscoManager extends XmppManagerBase {
|
class DiscoManager extends XmppManagerBase {
|
||||||
|
|
||||||
DiscoManager()
|
DiscoManager()
|
||||||
: _features = List.empty(growable: true),
|
: _features = List.empty(growable: true),
|
||||||
_capHashCache = {},
|
_capHashCache = {},
|
||||||
@ -47,15 +45,19 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
/// Our features
|
/// Our features
|
||||||
final List<String> _features;
|
final List<String> _features;
|
||||||
|
|
||||||
// Map full JID to Capability hashes
|
/// Map full JID to Capability hashes
|
||||||
final Map<String, CapabilityHashInfo> _capHashCache;
|
final Map<String, CapabilityHashInfo> _capHashCache;
|
||||||
// Map capability hash to the disco info
|
|
||||||
|
/// Map capability hash to the disco info
|
||||||
final Map<String, DiscoInfo> _capHashInfoCache;
|
final Map<String, DiscoInfo> _capHashInfoCache;
|
||||||
// Map full JID to Disco Info
|
|
||||||
|
/// Map full JID to Disco Info
|
||||||
final Map<DiscoCacheKey, DiscoInfo> _discoInfoCache;
|
final Map<DiscoCacheKey, DiscoInfo> _discoInfoCache;
|
||||||
// Mapping the full JID to a list of running requests
|
|
||||||
|
/// Mapping the full JID to a list of running requests
|
||||||
final Map<DiscoCacheKey, List<Completer<Result<DiscoError, DiscoInfo>>>> _runningInfoQueries;
|
final Map<DiscoCacheKey, List<Completer<Result<DiscoError, DiscoInfo>>>> _runningInfoQueries;
|
||||||
// Cache lock
|
|
||||||
|
/// Cache lock
|
||||||
final Lock _cacheLock;
|
final Lock _cacheLock;
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
@ -154,22 +156,19 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
if (stanza.type != 'get') return state;
|
if (stanza.type != 'get') return state;
|
||||||
|
|
||||||
final presence = getAttributes().getManagerById(presenceManager)! as PresenceManager;
|
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 node = query.attributes['node'] as String?;
|
||||||
final capHash = await presence.getCapabilityHash();
|
final capHash = await presence.getCapabilityHash();
|
||||||
final isCapabilityNode = node == '${presence.capabilityHashNode}#$capHash';
|
final isCapabilityNode = node == '${presence.capabilityHashNode}#$capHash';
|
||||||
|
|
||||||
if (!isCapabilityNode && node != null) {
|
if (!isCapabilityNode && node != null) {
|
||||||
await getAttributes().sendStanza(Stanza.iq(
|
await reply(
|
||||||
to: stanza.from,
|
state,
|
||||||
from: stanza.to,
|
'error',
|
||||||
id: stanza.id,
|
[
|
||||||
type: 'error',
|
|
||||||
children: [
|
|
||||||
XMLNode.xmlns(
|
XMLNode.xmlns(
|
||||||
tag: 'query',
|
tag: 'query',
|
||||||
// TODO(PapaTutuWawa): Why are we copying the xmlns?
|
xmlns: discoInfoXmlns,
|
||||||
xmlns: query.attributes['xmlns']! as String,
|
|
||||||
attributes: <String, String>{
|
attributes: <String, String>{
|
||||||
'node': node
|
'node': node
|
||||||
},
|
},
|
||||||
@ -185,16 +184,17 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
xmlns: fullStanzaXmlns,
|
xmlns: fullStanzaXmlns,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
)
|
);
|
||||||
,);
|
|
||||||
|
|
||||||
return state.copyWith(done: true);
|
return state.copyWith(done: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await getAttributes().sendStanza(stanza.reply(
|
await reply(
|
||||||
children: [
|
state,
|
||||||
|
'result',
|
||||||
|
[
|
||||||
XMLNode.xmlns(
|
XMLNode.xmlns(
|
||||||
tag: 'query',
|
tag: 'query',
|
||||||
xmlns: discoInfoXmlns,
|
xmlns: discoInfoXmlns,
|
||||||
@ -214,7 +214,7 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),);
|
);
|
||||||
|
|
||||||
return state.copyWith(done: true);
|
return state.copyWith(done: true);
|
||||||
}
|
}
|
||||||
@ -222,20 +222,16 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
Future<StanzaHandlerData> _onDiscoItemsRequest(Stanza stanza, StanzaHandlerData state) async {
|
Future<StanzaHandlerData> _onDiscoItemsRequest(Stanza stanza, StanzaHandlerData state) async {
|
||||||
if (stanza.type != 'get') return state;
|
if (stanza.type != 'get') return state;
|
||||||
|
|
||||||
final query = stanza.firstTag('query')!;
|
final query = stanza.firstTag('query', xmlns: discoItemsXmlns)!;
|
||||||
if (query.attributes['node'] != null) {
|
if (query.attributes['node'] != null) {
|
||||||
// TODO(Unknown): Handle the node we specified for XEP-0115
|
// TODO(Unknown): Handle the node we specified for XEP-0115
|
||||||
await getAttributes().sendStanza(
|
await reply(
|
||||||
Stanza.iq(
|
state,
|
||||||
to: stanza.from,
|
'error',
|
||||||
from: stanza.to,
|
[
|
||||||
id: stanza.id,
|
|
||||||
type: 'error',
|
|
||||||
children: [
|
|
||||||
XMLNode.xmlns(
|
XMLNode.xmlns(
|
||||||
tag: 'query',
|
tag: 'query',
|
||||||
// TODO(PapaTutuWawa): Why copy the xmlns?
|
xmlns: discoItemsXmlns,
|
||||||
xmlns: query.attributes['xmlns']! as String,
|
|
||||||
attributes: <String, String>{
|
attributes: <String, String>{
|
||||||
'node': query.attributes['node']! as String,
|
'node': query.attributes['node']! as String,
|
||||||
},
|
},
|
||||||
@ -253,21 +249,22 @@ class DiscoManager extends XmppManagerBase {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return state.copyWith(done: true);
|
return state.copyWith(done: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await getAttributes().sendStanza(
|
await reply(
|
||||||
stanza.reply(
|
state,
|
||||||
children: [
|
'result',
|
||||||
|
[
|
||||||
XMLNode.xmlns(
|
XMLNode.xmlns(
|
||||||
tag: 'query',
|
tag: 'query',
|
||||||
xmlns: discoItemsXmlns,
|
xmlns: discoItemsXmlns,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return state.copyWith(done: true);
|
return state.copyWith(done: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,11 +318,12 @@ abstract class BaseOmemoManager extends XmppManagerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final toJid = JID.fromString(stanza.to!).toBare();
|
final toJid = JID.fromString(stanza.to!).toBare();
|
||||||
if (!(await shouldEncryptStanza(toJid, stanza))) {
|
final shouldEncryptResult = await shouldEncryptStanza(toJid, stanza);
|
||||||
logger.finest('shouldEncryptStanza returned false for message to $toJid. Not encrypting.');
|
if (!shouldEncryptResult && !state.forceEncryption) {
|
||||||
|
logger.finest('Not encrypting stanza for $toJid: Both shouldEncryptStanza and forceEncryption are false.');
|
||||||
return state;
|
return state;
|
||||||
} else {
|
} else {
|
||||||
logger.finest('shouldEncryptStanza returned true for message to $toJid.');
|
logger.finest('Encrypting stanza for $toJid: shouldEncryptResult=$shouldEncryptResult, forceEncryption=${state.forceEncryption}');
|
||||||
}
|
}
|
||||||
|
|
||||||
final toEncrypt = List<XMLNode>.empty(growable: true);
|
final toEncrypt = List<XMLNode>.empty(growable: true);
|
||||||
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ Future<void> runOutgoingStanzaHandlers(StreamManagementManager man, Stanza stanz
|
|||||||
|
|
||||||
XmppManagerAttributes mkAttributes(void Function(Stanza) callback) {
|
XmppManagerAttributes mkAttributes(void Function(Stanza) callback) {
|
||||||
return XmppManagerAttributes(
|
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);
|
callback(stanza);
|
||||||
|
|
||||||
return Stanza.message();
|
return Stanza.message();
|
||||||
|
@ -5,7 +5,7 @@ import '../helpers/xmpp.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
test("Test if we're vulnerable against CVE-2020-26547 style vulnerabilities", () async {
|
test("Test if we're vulnerable against CVE-2020-26547 style vulnerabilities", () async {
|
||||||
final attributes = XmppManagerAttributes(
|
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
|
// ignore: avoid_print
|
||||||
print('==> ${stanza.toXml()}');
|
print('==> ${stanza.toXml()}');
|
||||||
return XMLNode(tag: 'iq', attributes: { 'type': 'result' });
|
return XMLNode(tag: 'iq', attributes: { 'type': 'result' });
|
||||||
|
@ -32,8 +32,9 @@ void main() {
|
|||||||
test('Test setting the CSI state when CSI is unsupported', () {
|
test('Test setting the CSI state when CSI is unsupported', () {
|
||||||
var nonzaSent = false;
|
var nonzaSent = false;
|
||||||
final csi = CSIManager();
|
final csi = CSIManager();
|
||||||
csi.register(XmppManagerAttributes(
|
csi.register(
|
||||||
sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'),
|
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) {},
|
sendEvent: (event) {},
|
||||||
sendNonza: (nonza) {
|
sendNonza: (nonza) {
|
||||||
nonzaSent = true;
|
nonzaSent = true;
|
||||||
@ -60,8 +61,9 @@ void main() {
|
|||||||
});
|
});
|
||||||
test('Test setting the CSI state when CSI is supported', () {
|
test('Test setting the CSI state when CSI is supported', () {
|
||||||
final csi = CSIManager();
|
final csi = CSIManager();
|
||||||
csi.register(XmppManagerAttributes(
|
csi.register(
|
||||||
sendStanza: (_, { StanzaFromType addFrom = StanzaFromType.full, bool addId = true, bool retransmitted = false, bool awaitable = true, bool encrypted = false }) async => XMLNode(tag: 'hallo'),
|
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) {},
|
sendEvent: (event) {},
|
||||||
sendNonza: (nonza) {
|
sendNonza: (nonza) {
|
||||||
expect(nonza.attributes['xmlns'] == csiXmlns, true, reason: "Expected only nonzas with XMLNS '$csiXmlns'");
|
expect(nonza.attributes['xmlns'] == csiXmlns, true, reason: "Expected only nonzas with XMLNS '$csiXmlns'");
|
||||||
@ -78,7 +80,8 @@ void main() {
|
|||||||
getFullJID: () => JID.fromString('some.user@example.server/aaaaa'),
|
getFullJID: () => JID.fromString('some.user@example.server/aaaaa'),
|
||||||
getSocket: () => StubTCPSocket(play: []),
|
getSocket: () => StubTCPSocket(play: []),
|
||||||
getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])),
|
getConnection: () => XmppConnection(TestingReconnectionPolicy(), StubTCPSocket(play: [])),
|
||||||
),);
|
),
|
||||||
|
);
|
||||||
|
|
||||||
csi.setActive();
|
csi.setActive();
|
||||||
csi.setInactive();
|
csi.setInactive();
|
||||||
|
@ -9,7 +9,7 @@ Future<bool> testRosterManager(String bareJid, String resource, String stanzaStr
|
|||||||
var eventTriggered = false;
|
var eventTriggered = false;
|
||||||
final roster = RosterManager(TestingRosterStateManager('', []));
|
final roster = RosterManager(TestingRosterStateManager('', []));
|
||||||
roster.register(XmppManagerAttributes(
|
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) {
|
sendEvent: (event) {
|
||||||
eventTriggered = true;
|
eventTriggered = true;
|
||||||
},
|
},
|
||||||
@ -310,7 +310,7 @@ void main() {
|
|||||||
var eventTriggered = false;
|
var eventTriggered = false;
|
||||||
final roster = RosterManager(TestingRosterStateManager('', []));
|
final roster = RosterManager(TestingRosterStateManager('', []));
|
||||||
roster.register(XmppManagerAttributes(
|
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) {
|
sendEvent: (event) {
|
||||||
eventTriggered = true;
|
eventTriggered = true;
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user