diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index d90c0a1b..f2ac3ec3 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -20,6 +20,7 @@ library matrix_api_lite; export 'src/matrix_api.dart'; export 'src/utils/logs.dart'; +export 'src/utils/map_copy_extension.dart'; export 'src/utils/try_get_map_extension.dart'; export 'src/model/algorithm_types.dart'; export 'src/model/basic_event.dart'; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index fe28d1c8..6ae4df3f 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -17,6 +17,7 @@ */ import 'authentication_user_identifier.dart'; + import 'authentication_data.dart'; import 'authentication_identifier.dart'; import 'authentication_phone_identifier.dart'; diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 095b2b21..7a91f559 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class BasicEvent { String type; Map content; @@ -27,7 +29,7 @@ class BasicEvent { BasicEvent.fromJson(Map json) { type = json['type']; - content = Map.from(json['content']); + content = (json['content'] as Map).copy(); } Map toJson() { final data = {}; diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index b368b4f1..ed02e87d 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -17,6 +17,7 @@ */ import 'matrix_keys.dart'; +import '../utils/map_copy_extension.dart'; class KeysQueryResponse { Map failures; @@ -26,9 +27,7 @@ class KeysQueryResponse { Map userSigningKeys; KeysQueryResponse.fromJson(Map json) { - failures = json['failures'] != null - ? Map.from(json['failures']) - : null; + failures = (json['failures'] as Map)?.copy(); deviceKeys = json['device_keys'] != null ? (json['device_keys'] as Map).map( (k, v) => MapEntry( diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 2f5f35f0..83fe7596 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -17,6 +17,7 @@ */ import 'stripped_state_event.dart'; +import '../utils/map_copy_extension.dart'; class MatrixEvent extends StrippedStateEvent { String eventId; @@ -38,12 +39,8 @@ class MatrixEvent extends StrippedStateEvent { roomId = json['room_id']; originServerTs = DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']); - unsigned = json['unsigned'] != null - ? Map.from(json['unsigned']) - : null; - prevContent = json['prev_content'] != null - ? Map.from(json['prev_content']) - : null; + unsigned = (json['unsigned'] as Map)?.copy(); + prevContent = (json['prev_content'] as Map)?.copy(); redacts = json['redacts']; } diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index c0f00386..317ef390 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class MatrixSignableKey { String userId; String identifier; @@ -33,13 +35,12 @@ class MatrixSignableKey { _json = json; userId = json['user_id']; keys = Map.from(json['keys']); + // we need to manually copy to ensure that our map is Map> signatures = json['signatures'] is Map ? Map>.from((json['signatures'] as Map) .map((k, v) => MapEntry(k, Map.from(v)))) : null; - unsigned = json['unsigned'] is Map - ? Map.from(json['unsigned']) - : null; + unsigned = (json['unsigned'] as Map)?.copy(); } Map toJson() { diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index 7834211c..7607892b 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -16,13 +16,17 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class OneTimeKeysClaimResponse { Map failures; Map> oneTimeKeys; OneTimeKeysClaimResponse.fromJson(Map json) { - failures = Map.from(json['failures'] ?? {}); - oneTimeKeys = Map>.from(json['one_time_keys']); + failures = (json['failures'] as Map)?.copy() ?? {}; + // We still need a Map<...>.from(...) to ensure all second-level entries are also maps + oneTimeKeys = Map>.from( + (json['one_time_keys'] as Map).copy()); } Map toJson() { diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart index 2ac7ac3c..037b20e1 100644 --- a/lib/src/model/room_keys_info.dart +++ b/lib/src/model/room_keys_info.dart @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import 'algorithm_types.dart'; +import '../../matrix_api_lite.dart'; enum RoomKeysAlgorithmType { v1Curve25519AesSha2 } diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index 0e449e9d..0ae7c1ee 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + enum RoomVersionStability { stable, unstable } class ServerCapabilities { @@ -30,7 +32,7 @@ class ServerCapabilities { mRoomVersions = json['m.room_versions'] != null ? MRoomVersions.fromJson(json['m.room_versions']) : null; - customCapabilities = Map.from(json); + customCapabilities = json.copy(); customCapabilities.remove('m.change_password'); customCapabilities.remove('m.room_versions'); } diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index 14fe31d8..25d5b469 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import '../../matrix_api_lite.dart'; +import '../matrix_api.dart'; class ThirdPartyIdentifier { ThirdPartyIdentifierMedium medium; diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 68083805..39546099 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class ThirdPartyLocation { String alias; String protocol; @@ -24,7 +26,7 @@ class ThirdPartyLocation { ThirdPartyLocation.fromJson(Map json) { alias = json['alias']; protocol = json['protocol']; - fields = Map.from(json['fields']); + fields = (json['fields'] as Map).copy(); } Map toJson() { diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index fd84f907..e19818e8 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class ThirdPartyUser { String userId; String protocol; @@ -24,7 +26,7 @@ class ThirdPartyUser { ThirdPartyUser.fromJson(Map json) { userId = json['userid']; protocol = json['protocol']; - fields = Map.from(json['fields']); + fields = (json['fields'] as Map).copy(); } Map toJson() { diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart new file mode 100644 index 00000000..84ddc272 --- /dev/null +++ b/lib/src/utils/map_copy_extension.dart @@ -0,0 +1,33 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +extension MapCopyExtension on Map { + /// Deep-copies a given json map + Map copy() { + final copy = Map.from(this); + for (final entry in copy.entries) { + if (entry.value is Map) { + copy[entry.key] = (entry.value as Map).copy(); + } + if (entry.value is List) { + copy[entry.key] = List.from(entry.value); + } + } + return copy; + } +}