Further config util logic

Removed the usage of the OWSAES256Key (using CryptoKit and raw data instead)
Removed the pre-compiled headers to speed up builds with minor changes (explicit imports instead)

# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	SessionMessagingKit/Database/Models/ClosedGroup.swift
#	SessionMessagingKit/Protos/Generated/SNProto.swift
#	SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift
#	SessionMessagingKit/Protos/SessionProtos.proto
#	SessionMessagingKit/Sending & Receiving/MessageSender.swift
#	SessionMessagingKit/Sending & Receiving/Pollers/CurrentUserPoller.swift
#	SessionMessagingKit/Utilities/ProfileManager.swift
#	SessionSnodeKit/Models/DeleteAllMessagesRequest.swift
#	SessionSnodeKit/Models/GetMessagesRequest.swift
#	SessionSnodeKit/Models/SendMessageRequest.swift
#	SessionSnodeKit/Types/SnodeAPINamespace.swift
This commit is contained in:
Morgan Pretty 2022-12-02 14:00:10 +11:00
parent f12191f85e
commit 1345e89809
153 changed files with 1481 additions and 806 deletions

View File

@ -320,7 +320,6 @@
C33FDC29255A581F00E217F9 /* ReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA6F255A57FA00E217F9 /* ReachabilityManager.swift */; };
C33FDC45255A581F00E217F9 /* AppVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA8B255A57FD00E217F9 /* AppVersion.m */; };
C33FDC50255A582000E217F9 /* OWSDispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA96255A57FE00E217F9 /* OWSDispatch.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC53255A582000E217F9 /* OutageDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA99255A57FE00E217F9 /* OutageDetection.swift */; };
C33FDC58255A582000E217F9 /* ReverseDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA9E255A57FF00E217F9 /* ReverseDispatchQueue.swift */; };
C33FDC78255A582000E217F9 /* TSConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDABE255A580100E217F9 /* TSConstants.m */; };
C33FDC7D255A582000E217F9 /* OWSDispatch.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAC3255A580200E217F9 /* OWSDispatch.m */; };
@ -524,7 +523,6 @@
FD09797927FAB7E800936362 /* ImageFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09797827FAB7E800936362 /* ImageFormat.swift */; };
FD09797B27FBB25900936362 /* Updatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09797A27FBB25900936362 /* Updatable.swift */; };
FD09797D27FBDB2000936362 /* Notification+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09797C27FBDB2000936362 /* Notification+Utilities.swift */; };
FD09797F27FCFBFF00936362 /* OWSAES256Key+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09797E27FCFBFF00936362 /* OWSAES256Key+Utilities.swift */; };
FD09798127FCFEE800936362 /* SessionThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09798027FCFEE800936362 /* SessionThread.swift */; };
FD09798327FD1A1500936362 /* ClosedGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09798227FD1A1500936362 /* ClosedGroup.swift */; };
FD09798527FD1A6500936362 /* ClosedGroupKeyPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD09798427FD1A6500936362 /* ClosedGroupKeyPair.swift */; };
@ -786,6 +784,10 @@
FD8ECF8629346DA100C0D1BB /* HeaderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906127E411AF00CD579F /* HeaderSpec.swift */; };
FD8ECF8729346DB500C0D1BB /* RequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906327E4122F00CD579F /* RequestSpec.swift */; };
FD8ECF892935AB7200C0D1BB /* SessionUtilError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */; };
FD8ECF8B2935DB4B00C0D1BB /* SharedConfigMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF8A2935DB4B00C0D1BB /* SharedConfigMessage.swift */; };
FD8ECF9029381FC200C0D1BB /* SessionUtil+UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF8F29381FC200C0D1BB /* SessionUtil+UserProfile.swift */; };
FD8ECF922938552800C0D1BB /* Threading.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF912938552800C0D1BB /* Threading.swift */; };
FD8ECF94293856AF00C0D1BB /* Randomness.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF93293856AF00C0D1BB /* Randomness.swift */; };
FD90040F2818AB6D00ABAAF6 /* GetSnodePoolJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */; };
FD9004122818ABDC00ABAAF6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73F280402C4004C14C5 /* Job.swift */; };
FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */; };
@ -1094,7 +1096,6 @@
3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageTimerView.m; sourceTree = "<group>"; };
3430FE171F7751D4000EC51B /* GiphyAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiphyAPI.swift; sourceTree = "<group>"; };
34480B371FD092A900BC14EF /* SignalShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SignalShareExtension-Bridging-Header.h"; sourceTree = "<group>"; };
34480B381FD092E300BC14EF /* SessionShareExtension-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SessionShareExtension-Prefix.pch"; sourceTree = "<group>"; };
34661FB720C1C0D60056EDD6 /* message_sent.aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = message_sent.aiff; path = Session/Meta/AudioFiles/message_sent.aiff; sourceTree = SOURCE_ROOT; };
346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = "<group>"; };
3488F9352191CC4000E524CC /* MediaView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaView.swift; sourceTree = "<group>"; };
@ -1410,7 +1411,6 @@
C33FDA8B255A57FD00E217F9 /* AppVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppVersion.m; sourceTree = "<group>"; };
C33FDA8E255A57FD00E217F9 /* OWSFileSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSFileSystem.m; sourceTree = "<group>"; };
C33FDA96255A57FE00E217F9 /* OWSDispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDispatch.h; sourceTree = "<group>"; };
C33FDA99255A57FE00E217F9 /* OutageDetection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutageDetection.swift; sourceTree = "<group>"; };
C33FDA9E255A57FF00E217F9 /* ReverseDispatchQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseDispatchQueue.swift; sourceTree = "<group>"; };
C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildConfiguration.swift; sourceTree = "<group>"; };
C33FDABE255A580100E217F9 /* TSConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSConstants.m; sourceTree = "<group>"; };
@ -1564,7 +1564,6 @@
C38EF3E9255B6DF6007E1867 /* Toast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Toast.swift; path = "SignalUtilitiesKit/Shared Views/Toast.swift"; sourceTree = SOURCE_ROOT; };
C38EF3ED255B6DF6007E1867 /* TappableStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TappableStackView.swift; path = "SignalUtilitiesKit/Shared Views/TappableStackView.swift"; sourceTree = SOURCE_ROOT; };
C38EF3EE255B6DF6007E1867 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = SessionUIKit/Components/GradientView.swift; sourceTree = SOURCE_ROOT; };
C38EF458255B710A007E1867 /* SignalUtilitiesKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SignalUtilitiesKit-Prefix.pch"; sourceTree = "<group>"; };
C396469C2509D3ED00B0B9F5 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
C396469D2509D3F400B0B9F5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
C396469E2509D40400B0B9F5 /* vi-VN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "vi-VN"; path = "vi-VN.lproj/Localizable.strings"; sourceTree = "<group>"; };
@ -1646,7 +1645,6 @@
D221A08F169C9E5E00537ABF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D221A091169C9E5E00537ABF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
D221A095169C9E5E00537ABF /* Session-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Session-Info.plist"; sourceTree = "<group>"; };
D221A09B169C9E5E00537ABF /* Session-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Session-Prefix.pch"; sourceTree = "<group>"; };
D221A0E7169DFFC500537ABF /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = ../../../../../../System/Library/Frameworks/AVFoundation.framework; sourceTree = "<group>"; };
D24B5BD4169F568C00681372 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = ../../../../../../System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<group>"; };
D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
@ -1674,7 +1672,6 @@
FD09797827FAB7E800936362 /* ImageFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageFormat.swift; sourceTree = "<group>"; };
FD09797A27FBB25900936362 /* Updatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Updatable.swift; sourceTree = "<group>"; };
FD09797C27FBDB2000936362 /* Notification+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+Utilities.swift"; sourceTree = "<group>"; };
FD09797E27FCFBFF00936362 /* OWSAES256Key+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OWSAES256Key+Utilities.swift"; sourceTree = "<group>"; };
FD09798027FCFEE800936362 /* SessionThread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionThread.swift; sourceTree = "<group>"; };
FD09798227FD1A1500936362 /* ClosedGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroup.swift; sourceTree = "<group>"; };
FD09798427FD1A6500936362 /* ClosedGroupKeyPair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupKeyPair.swift; sourceTree = "<group>"; };
@ -1907,6 +1904,10 @@
FD8ECF812934387A00C0D1BB /* ConfigUserProfileSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigUserProfileSpec.swift; sourceTree = "<group>"; };
FD8ECF842934508B00C0D1BB /* BatchResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchResponseSpec.swift; sourceTree = "<group>"; };
FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionUtilError.swift; sourceTree = "<group>"; };
FD8ECF8A2935DB4B00C0D1BB /* SharedConfigMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedConfigMessage.swift; sourceTree = "<group>"; };
FD8ECF8F29381FC200C0D1BB /* SessionUtil+UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+UserProfile.swift"; sourceTree = "<group>"; };
FD8ECF912938552800C0D1BB /* Threading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Threading.swift; sourceTree = "<group>"; };
FD8ECF93293856AF00C0D1BB /* Randomness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Randomness.swift; sourceTree = "<group>"; };
FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetSnodePoolJob.swift; sourceTree = "<group>"; };
FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; };
FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessageSendsJob.swift; sourceTree = "<group>"; };
@ -2710,6 +2711,8 @@
C3C2A7702553A41E00C340D1 /* ControlMessage.swift */,
B8DE1FB526C22FCB0079C9CE /* CallMessage.swift */,
C34A977325A3E34A00852C71 /* ClosedGroupControlMessage.swift */,
C34A977325A3E34A00852C71 /* LegacyClosedGroupControlMessage.swift */,
FD8ECF8A2935DB4B00C0D1BB /* SharedConfigMessage.swift */,
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */,
7B93D06E27CF194000811CB6 /* ConfigurationMessage+Convenience.swift */,
B8F5F60225EDE16F003BF8D4 /* DataExtractionNotification.swift */,
@ -2770,7 +2773,6 @@
4535186F1FC635DD00210559 /* Info.plist */,
34B0796E1FD07B1E00E248C2 /* SignalShareExtension.entitlements */,
34480B371FD092A900BC14EF /* SignalShareExtension-Bridging-Header.h */,
34480B381FD092E300BC14EF /* SessionShareExtension-Prefix.pch */,
);
path = Meta;
sourceTree = "<group>";
@ -2926,7 +2928,6 @@
isa = PBXGroup;
children = (
C33FD9AD255A548A00E217F9 /* SignalUtilitiesKit.h */,
C38EF458255B710A007E1867 /* SignalUtilitiesKit-Prefix.pch */,
C33FD9AE255A548A00E217F9 /* Info.plist */,
);
path = Meta;
@ -3202,7 +3203,6 @@
C38EF309255B6DBE007E1867 /* DeviceSleepManager.swift */,
C3BBE0C62554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift */,
C3A71D0A2558989C0043A11F /* MessageWrapper.swift */,
FD09797E27FCFBFF00936362 /* OWSAES256Key+Utilities.swift */,
C38EF2F5255B6DBC007E1867 /* OWSAudioPlayer.h */,
C38EF2F7255B6DBC007E1867 /* OWSAudioPlayer.m */,
C38EF281255B6D84007E1867 /* OWSAudioSession.swift */,
@ -3382,7 +3382,6 @@
C3F0A52F255C80BC007BE2A3 /* NoopNotificationsManager.swift */,
C33FDA8B255A57FD00E217F9 /* AppVersion.m */,
C33FDB69255A580F00E217F9 /* FeatureFlags.swift */,
C33FDA99255A57FE00E217F9 /* OutageDetection.swift */,
C33FDB80255A581100E217F9 /* Notification+Loki.swift */,
C33FDC16255A581E00E217F9 /* FunctionalUtil.h */,
C33FDB17255A580800E217F9 /* FunctionalUtil.m */,
@ -3436,7 +3435,6 @@
FDF2220A2818F38D000A4995 /* SessionApp.swift */,
45B201741DAECBFD00C461E0 /* Signal-Bridging-Header.h */,
D221A095169C9E5E00537ABF /* Session-Info.plist */,
D221A09B169C9E5E00537ABF /* Session-Prefix.pch */,
4C63CBFF210A620B003AE45C /* SignalTSan.supp */,
4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */,
34074F54203D0722004596AE /* Sounds */,
@ -3568,6 +3566,8 @@
FD09797127FAA2F500936362 /* Optional+Utilities.swift */,
FD09797C27FBDB2000936362 /* Notification+Utilities.swift */,
FDF222082818D2B0000A4995 /* NSAttributedString+Utilities.swift */,
FD8ECF912938552800C0D1BB /* Threading.swift */,
FD8ECF93293856AF00C0D1BB /* Randomness.swift */,
C33FDB38255A580B00E217F9 /* OWSBackgroundTask.h */,
C33FDC1B255A581F00E217F9 /* OWSBackgroundTask.m */,
);
@ -4027,9 +4027,10 @@
FD8ECF7529340F4800C0D1BB /* LibSessionUtil */ = {
isa = PBXGroup;
children = (
FD8ECF8E29381FB200C0D1BB /* Config Handling */,
FD8ECF7829340F7100C0D1BB /* libsession-util.xcframework */,
FD8ECF7A29340FFD00C0D1BB /* SessionUtil.swift */,
FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */,
FD8ECF7A29340FFD00C0D1BB /* SessionUtil.swift */,
);
path = LibSessionUtil;
sourceTree = "<group>";
@ -4052,6 +4053,14 @@
path = Networking;
sourceTree = "<group>";
};
FD8ECF8E29381FB200C0D1BB /* Config Handling */ = {
isa = PBXGroup;
children = (
FD8ECF8F29381FC200C0D1BB /* SessionUtil+UserProfile.swift */,
);
path = "Config Handling";
sourceTree = "<group>";
};
FD9004102818ABB000ABAAF6 /* JobRunner */ = {
isa = PBXGroup;
children = (
@ -5279,7 +5288,6 @@
C38EF245255B6D67007E1867 /* UIFont+OWS.m in Sources */,
C38EF36F255B6DCC007E1867 /* OWSViewController.m in Sources */,
C38EF3FB255B6DF7007E1867 /* UIAlertController+OWS.swift in Sources */,
C33FDC53255A582000E217F9 /* OutageDetection.swift in Sources */,
C38EF30C255B6DBF007E1867 /* ScreenLock.swift in Sources */,
C38EF363255B6DCC007E1867 /* ModalActivityIndicatorViewController.swift in Sources */,
C38EF38A255B6DD2007E1867 /* AttachmentCaptionToolbar.swift in Sources */,
@ -5437,6 +5445,7 @@
FD17D7BA27F51F2100122BE0 /* TargetMigrations.swift in Sources */,
FD17D7C327F5204C00122BE0 /* Database+Utilities.swift in Sources */,
FD17D7C527F5206300122BE0 /* ColumnDefinition+Utilities.swift in Sources */,
FD8ECF94293856AF00C0D1BB /* Randomness.swift in Sources */,
FDC438CD27BC641200C60D73 /* Set+Utilities.swift in Sources */,
FD77289E284EF1C50018502F /* Sodium+Utilities.swift in Sources */,
B8856DE6256F15F2001CE70E /* String+SSK.swift in Sources */,
@ -5458,6 +5467,7 @@
FD5D201E27B0D87C00FEA984 /* SessionId.swift in Sources */,
C32C5A24256DB7DB003C73A2 /* SNUserDefaults.swift in Sources */,
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
FD8ECF922938552800C0D1BB /* Threading.swift in Sources */,
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */,
FDF22211281B5E0B000A4995 /* TableRecord+Utilities.swift in Sources */,
B88FA7FB26114EA70049422F /* Hex.swift in Sources */,
@ -5534,6 +5544,8 @@
FD245C6A2850666F00B966DD /* FileServerAPI.swift in Sources */,
FDC4386927B4E6B800C60D73 /* String+Utlities.swift in Sources */,
FD716E6628502EE200C96BF4 /* CurrentCallProtocol.swift in Sources */,
FD26FA512919F9CE005801D8 /* GroupDeleteMessage.swift in Sources */,
FD8ECF9029381FC200C0D1BB /* SessionUtil+UserProfile.swift in Sources */,
FD09B7E5288670BB00ED0B66 /* _008_EmojiReacts.swift in Sources */,
FDC4385F27B4C4A200C60D73 /* PinnedMessage.swift in Sources */,
7BFD1A8C2747150E00FB91B9 /* TurnServerInfo.swift in Sources */,
@ -5550,10 +5562,10 @@
FDC4386727B4E10E00C60D73 /* Capabilities.swift in Sources */,
FDC438A427BB107F00C60D73 /* UserBanRequest.swift in Sources */,
C379DCF4256735770002D4EB /* VisibleMessage+Attachment.swift in Sources */,
FD09797F27FCFBFF00936362 /* OWSAES256Key+Utilities.swift in Sources */,
FDB4BBC72838B91E00B7C95D /* LinkPreviewError.swift in Sources */,
FD09798327FD1A1500936362 /* ClosedGroup.swift in Sources */,
B8B320B7258C30D70020074B /* HTMLMetadata.swift in Sources */,
FD8ECF8B2935DB4B00C0D1BB /* SharedConfigMessage.swift in Sources */,
FD09798727FD1B7800936362 /* GroupMember.swift in Sources */,
FDB4BBC92839BEF000B7C95D /* ProfileManagerError.swift in Sources */,
FD3E0C84283B5835002A425C /* SessionThreadViewModel.swift in Sources */,
@ -6153,7 +6165,6 @@
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SessionShareExtension/Meta/SessionShareExtension-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
@ -6227,7 +6238,6 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SessionShareExtension/Meta/SessionShareExtension-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
@ -6569,7 +6579,6 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREFIX_HEADER = "SignalUtilitiesKit/Meta/SignalUtilitiesKit-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
@ -6651,7 +6660,6 @@
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "SignalUtilitiesKit/Meta/SignalUtilitiesKit-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
@ -7296,7 +7304,6 @@
);
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Session/Meta/Session-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@ -7368,7 +7375,6 @@
);
GCC_OPTIMIZATION_LEVEL = 3;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Session/Meta/Session-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
HAVE_CONFIG_H,

View File

@ -2,8 +2,8 @@
import Foundation
import CallKit
import SignalCoreKit
import SessionUtilitiesKit
import SignalCoreKit
extension SessionCallManager: CXProviderDelegate {
public func providerDidReset(_ provider: CXProvider) {

View File

@ -4,6 +4,7 @@ import UIKit
import CallKit
import GRDB
import SessionMessagingKit
import SignalCoreKit
public final class SessionCallManager: NSObject, CallManagerProtocol {
let provider: CXProvider?

View File

@ -1,6 +1,8 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import WebRTC
import Foundation
import SessionUtilitiesKit
#if targetEnvironment(simulator)
// Note: 'RTCMTLVideoView' doesn't seem to work on the simulator so use 'RTCEAGLVideoView' instead
@ -27,7 +29,7 @@ class RemoteVideoView: TargetView {
return
}
DispatchMainThreadSafe {
Threading.dispatchMainThreadSafe {
let frameRatio = Double(frame.height) / Double(frame.width)
let frameRotation = frame.rotation
let deviceRotation = UIDevice.current.orientation
@ -93,7 +95,8 @@ class LocalVideoView: TargetView {
override func renderFrame(_ frame: RTCVideoFrame?) {
super.renderFrame(frame)
DispatchMainThreadSafe {
Threading.dispatchMainThreadSafe {
// This is a workaround for a weird issue that
// sometimes the rotationOverride is not working
// if it is only set once on initialization

View File

@ -3,6 +3,7 @@
import UIKit
import GRDB
import SignalUtilitiesKit
import SignalCoreKit
public class StyledSearchController: UISearchController {
public override var preferredStatusBarStyle: UIStatusBarStyle {

View File

@ -4,7 +4,6 @@ import UIKit
import CoreServices
import Photos
import PhotosUI
import Sodium
import PromiseKit
import GRDB
import SessionMessagingKit
@ -1799,7 +1798,7 @@ extension ConversationVC:
message: unsendRequest,
threadId: threadId,
interactionId: nil,
to: .contact(publicKey: userPublicKey)
to: .contact(publicKey: userPublicKey, namespace: .default)
)
}
return
@ -1818,7 +1817,7 @@ extension ConversationVC:
message: unsendRequest,
threadId: threadId,
interactionId: nil,
to: .contact(publicKey: userPublicKey)
to: .contact(publicKey: userPublicKey, namespace: .default)
)
}
self?.showInputAccessoryView()

View File

@ -3,6 +3,7 @@
import UIKit
import SessionUIKit
import SessionUtilitiesKit
import SignalCoreKit
protocol EmojiPickerCollectionViewDelegate: AnyObject {
func emojiPicker(_ emojiPicker: EmojiPickerCollectionView?, didSelectEmoji emoji: EmojiWithSkinTones)

View File

@ -2,6 +2,7 @@
import UIKit
import SessionUIKit
import SignalCoreKit
class EmojiSkinTonePicker: UIView {
let emoji: Emoji

View File

@ -2,6 +2,7 @@
import UIKit
import SessionMessagingKit
import SignalCoreKit
protocol LinkPreviewState {
var isLoaded: Bool { get }

View File

@ -2,6 +2,7 @@
import UIKit
import SessionMessagingKit
import SignalCoreKit
public class MediaAlbumView: UIStackView {
private let items: [Attachment]

View File

@ -4,6 +4,7 @@ import UIKit
import YYImage
import SessionUIKit
import SessionMessagingKit
import SignalCoreKit
public class MediaView: UIView {
static let contentMode: UIView.ContentMode = .scaleAspectFill

View File

@ -2,6 +2,7 @@
import UIKit
import SessionUIKit
import SignalCoreKit
@objc class TypingIndicatorView: UIStackView {
// This represents the spacing between the dots

View File

@ -6,6 +6,7 @@
#import "OWSMath.h"
#import "UIView+OWS.h"
#import <QuartzCore/QuartzCore.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalCoreKit/NSDate+OWS.h>
#import <SessionUtilitiesKit/NSTimer+Proxying.h>

View File

@ -1,4 +1,5 @@
import Foundation
import SignalCoreKit
extension Emoji {
private static let availableCache: Atomic<[Emoji:Bool]> = Atomic([:])

View File

@ -5,6 +5,7 @@ import PureLayout
import SessionUIKit
import SessionUtilitiesKit
import NVActivityIndicatorView
import SignalCoreKit
class EmptySearchResultCell: UITableViewCell {
private lazy var messageLabel: UILabel = {

View File

@ -7,6 +7,7 @@ import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalUtilitiesKit
import SignalCoreKit
class GlobalSearchViewController: BaseVC, UITableViewDelegate, UITableViewDataSource {
fileprivate typealias SectionModel = ArraySection<SearchSection, SessionThreadViewModel>

View File

@ -6,6 +6,7 @@ import GRDB
import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
public class AllMediaViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
private let pageVC = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)

View File

@ -1,11 +1,10 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import MediaPlayer
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
// This kind of view is tricky. I've tried to organize things in the
// simplest possible way.

View File

@ -6,6 +6,7 @@ import GRDB
import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
public class DocumentTileViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

View File

@ -7,6 +7,7 @@ import PromiseKit
import SignalUtilitiesKit
import SignalUtilitiesKit
import YYImage
import SignalCoreKit
class GifPickerCell: UICollectionViewCell {

View File

@ -1,8 +1,7 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalCoreKit
protocol GifPickerLayoutDelegate: AnyObject {
func imageInfosForLayout() -> [GiphyImageInfo]

View File

@ -7,6 +7,7 @@ import Reachability
import SignalUtilitiesKit
import PromiseKit
import SessionUIKit
import SignalCoreKit
class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegate, GifPickerLayoutDelegate {

View File

@ -1,11 +1,10 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import AFNetworking
import Foundation
import PromiseKit
import CoreServices
import SignalCoreKit
// There's no UTI type for webp!
enum GiphyFormat {

View File

@ -7,6 +7,7 @@ import Photos
import PromiseKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
protocol ImagePickerGridControllerDelegate: AnyObject {
func imagePickerDidCompleteSelection(_ imagePicker: ImagePickerGridController)

View File

@ -5,6 +5,7 @@ import YYImage
import SessionUIKit
import SignalUtilitiesKit
import SessionMessagingKit
import SignalCoreKit
public enum MediaGalleryOption {
case sliderEnabled

View File

@ -6,6 +6,7 @@ import PromiseKit
import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SignalCoreKit
class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, MediaDetailViewControllerDelegate, InteractivelyDismissableViewController {
class DynamicallySizedView: UIView {

View File

@ -6,6 +6,7 @@ import GRDB
import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
public class MediaTileViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

View File

@ -1,11 +1,10 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import AVFoundation
import PromiseKit
import CoreServices
import SignalCoreKit
protocol PhotoCaptureDelegate: AnyObject {
func photoCapture(_ photoCapture: PhotoCapture, didFinishProcessingAttachment attachment: SignalAttachment)

View File

@ -5,6 +5,7 @@ import AVFoundation
import PromiseKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
protocol PhotoCaptureViewControllerDelegate: AnyObject {
func photoCaptureViewController(_ photoCaptureViewController: PhotoCaptureViewController, didFinishProcessingAttachment attachment: SignalAttachment)

View File

@ -4,6 +4,7 @@
import UIKit
import SessionUIKit
import SignalCoreKit
public enum PhotoGridItemType {
case photo, animated, video

View File

@ -6,6 +6,8 @@ import Foundation
import Photos
import PromiseKit
import CoreServices
import SignalUtilitiesKit
import SignalCoreKit
protocol PhotoLibraryDelegate: AnyObject {
func photoLibraryDidChange(_ photoLibrary: PhotoLibrary)
@ -53,7 +55,7 @@ class PhotoPickerAssetItem: PhotoGridItem {
// Surprisingly, iOS will opportunistically run the completion block sync if the image is
// already available.
photoCollectionContents.requestThumbnail(for: self.asset, thumbnailSize: photoMediaSize.thumbnailSize) { image, _ in
DispatchMainThreadSafe({
Threading.dispatchMainThreadSafe {
// Once we've _successfully_ completed (e.g. invoked the completion with
// a non-nil image), don't invoke the completion again with a nil argument.
if !hasLoadedImage || image != nil {
@ -63,7 +65,7 @@ class PhotoPickerAssetItem: PhotoGridItem {
hasLoadedImage = true
}
}
})
}
}
}
}

View File

@ -4,6 +4,7 @@ import UIKit
import Photos
import PromiseKit
import SignalUtilitiesKit
import SignalCoreKit
class SendMediaNavigationController: UINavigationController {
public override var preferredStatusBarStyle: UIStatusBarStyle {

View File

@ -12,6 +12,7 @@ import SessionUIKit
import UserNotifications
import UIKit
import SignalUtilitiesKit
import SignalCoreKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

View File

@ -2,6 +2,7 @@
import Foundation
import SignalUtilitiesKit
import SignalCoreKit
public class AppEnvironment {

View File

@ -4,7 +4,7 @@
#import "MainAppContext.h"
#import "Session-Swift.h"
#import <SignalCoreKit/Threading.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -259,7 +259,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
{
OWSAssertDebug(block);
DispatchMainThreadSafe(^{
[Threading dispatchMainThreadSafe:^{
if (self.isMainAppAndActive) {
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
@ -273,7 +273,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
}
[self.appActiveBlocks addObject:block];
});
}];
}
- (void)runAppActiveBlocks

View File

@ -1,15 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <Availability.h>
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalUtilitiesKit/SSKAsserts.h>
#import <SessionUIKit/SessionUIKit.h>
#endif

View File

@ -3,6 +3,7 @@
import Foundation
import SessionUtilitiesKit
import SessionMessagingKit
import SignalCoreKit
public struct SessionApp {
static let homeViewController: Atomic<HomeVC?> = Atomic(nil)

View File

@ -16,11 +16,6 @@
#import <PureLayout/PureLayout.h>
#import <Reachability/Reachability.h>
#import <SignalCoreKit/Cryptography.h>
#import <SignalCoreKit/NSData+OWS.h>
#import <SignalCoreKit/NSDate+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalCoreKit/OWSLogs.h>
#import <SignalCoreKit/Threading.h>
#import <SessionMessagingKit/OWSAudioPlayer.h>
#import <SignalUtilitiesKit/OWSFormat.h>
#import <SignalUtilitiesKit/OWSViewController.h>

View File

@ -5,6 +5,7 @@ import GRDB
import PromiseKit
import SessionMessagingKit
import SignalUtilitiesKit
import SignalCoreKit
/// There are two primary components in our system notification integration:
///

View File

@ -7,6 +7,7 @@ import PromiseKit
import PushKit
import SignalUtilitiesKit
import GRDB
import SignalCoreKit
public enum PushRegistrationError: Error {
case assertionError(description: String)

View File

@ -3,9 +3,9 @@
import Foundation
import GRDB
import PromiseKit
import SignalCoreKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalCoreKit
public enum SyncPushTokensJob: JobExecutor {
public static let maxFailureCount: Int = -1

View File

@ -1,11 +1,10 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import UserNotifications
import PromiseKit
import SessionMessagingKit
import SignalCoreKit
class UserNotificationConfig {

View File

@ -6,6 +6,7 @@ import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalCoreKit
class HelpViewModel: SessionTableViewModel<NoNav, HelpViewModel.Section, HelpViewModel.Section> {
// MARK: - Section

View File

@ -2,7 +2,9 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "OWSBezierPathView.h"
#import <SignalCoreKit/OWSAsserts.h>
NS_ASSUME_NONNULL_BEGIN

View File

@ -4,6 +4,7 @@ import UIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalUtilitiesKit
import SignalCoreKit
class ScreenLockUI {
public static let shared: ScreenLockUI = ScreenLockUI()

View File

@ -2,7 +2,6 @@
import Foundation
import GRDB
import Sodium
import Curve25519Kit
import SessionMessagingKit

View File

@ -3,6 +3,7 @@
import Foundation
import SessionUtilitiesKit
import UIKit
import SignalCoreKit
@objc public extension UIApplication {

View File

@ -3,7 +3,6 @@
import Foundation
import Sodium
import YapDatabase
import SignalCoreKit
import SessionUtilitiesKit
public enum SMKLegacy {
@ -89,10 +88,23 @@ public enum SMKLegacy {
@objc(SNContact)
public class _Contact: NSObject, NSCoding {
@objc(SNLegacyProfileKey)
public class _LegacyProfileKey: NSObject, NSCoding {
let keyData: Data
public required init?(coder: NSCoder) {
keyData = coder.decodeObject(forKey: "keyData") as! Data
}
public func encode(with coder: NSCoder) {
fatalError("encode(with:) should never be called for legacy types")
}
}
public let sessionID: String
public var profilePictureURL: String?
public var profilePictureFileName: String?
public var profileEncryptionKey: OWSAES256Key?
public var profileEncryptionKey: _LegacyProfileKey?
public var threadID: String?
public var isTrusted = false
public var isApproved = false
@ -112,7 +124,7 @@ public enum SMKLegacy {
if let nickname = coder.decodeObject(forKey: "nickname") as! String? { self.nickname = nickname }
if let profilePictureURL = coder.decodeObject(forKey: "profilePictureURL") as! String? { self.profilePictureURL = profilePictureURL }
if let profilePictureFileName = coder.decodeObject(forKey: "profilePictureFileName") as! String? { self.profilePictureFileName = profilePictureFileName }
if let profileEncryptionKey = coder.decodeObject(forKey: "profilePictureEncryptionKey") as! OWSAES256Key? { self.profileEncryptionKey = profileEncryptionKey }
if let profileEncryptionKey = coder.decodeObject(forKey: "profilePictureEncryptionKey") as! _LegacyProfileKey? { self.profileEncryptionKey = profileEncryptionKey }
if let threadID = coder.decodeObject(forKey: "threadID") as! String? { self.threadID = threadID }
let isBlockedFlag: Bool = coder.decodeBool(forKey: "isBlocked")
@ -1627,10 +1639,10 @@ public enum SMKLegacy {
self.message = message
if let destString: String = _MessageSendJob.process(rawDestination, type: "contact") {
destination = .contact(publicKey: destString)
destination = .contact(publicKey: destString, namespace: .default)
}
else if let destString: String = _MessageSendJob.process(rawDestination, type: "closedGroup") {
destination = .closedGroup(groupPublicKey: destString)
destination = .closedGroup(groupPublicKey: destString, namespace: .legacyClosedGroup)
}
else if _MessageSendJob.process(rawDestination, type: "openGroup") != nil {
// We can no longer support sending messages to legacy open groups

View File

@ -421,7 +421,7 @@ enum _003_YDBToGRDBMigration: Migration {
nickname: legacyContact.nickname,
profilePictureUrl: legacyContact.profilePictureURL,
profilePictureFileName: legacyContact.profilePictureFileName,
profileEncryptionKey: legacyContact.profileEncryptionKey
profileEncryptionKey: legacyContact.profileEncryptionKey?.keyData
).migrationSafeInsert(db)
/// **Note:** The blow "shouldForce" flags are here to allow us to avoid having to run legacy migrations they
@ -526,7 +526,7 @@ enum _003_YDBToGRDBMigration: Migration {
let recipientString: String = {
if let destination: Message.Destination = destination {
switch destination {
case .contact(let publicKey): return publicKey
case .contact(let publicKey, _): return publicKey
default: break
}
}
@ -974,7 +974,10 @@ enum _003_YDBToGRDBMigration: Migration {
.keys
.map { $0 })
.defaulting(to: []),
destination: (threadVariant == .contact ? .contact(publicKey: threadId) : nil),
destination: (threadVariant == .contact ?
.contact(publicKey: threadId, namespace: .default) :
nil
),
variant: variant,
useFallback: false
)
@ -986,7 +989,10 @@ enum _003_YDBToGRDBMigration: Migration {
.keys
.map { $0 })
.defaulting(to: []),
destination: (threadVariant == .contact ? .contact(publicKey: threadId) : nil),
destination: (threadVariant == .contact ?
.contact(publicKey: threadId, namespace: .default) :
nil
),
variant: variant,
useFallback: true
)
@ -1273,8 +1279,8 @@ enum _003_YDBToGRDBMigration: Migration {
// Fetch the threadId and interactionId this job should be associated with
let threadId: String = {
switch legacyJob.destination {
case .contact(let publicKey): return publicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .contact(let publicKey, _): return publicKey
case .closedGroup(let groupPublicKey, _): return groupPublicKey
case .openGroup(let roomToken, let server, _, _, _):
return OpenGroup.idFor(roomToken: roomToken, server: server)
@ -1430,7 +1436,7 @@ enum _003_YDBToGRDBMigration: Migration {
behaviour: .recurring,
threadId: threadId,
details: SendReadReceiptsJob.Details(
destination: .contact(publicKey: threadId),
destination: .contact(publicKey: threadId, namespace: .default),
timestampMsValues: timestampsMs
)
)?.migrationSafeInserted(db)
@ -1856,6 +1862,10 @@ enum _003_YDBToGRDBMigration: Migration {
SMKLegacy._MessageRequestResponse.self,
forClassName: "SNMessageRequestResponse"
)
NSKeyedUnarchiver.setClass(
SMKLegacy._Contact._LegacyProfileKey.self,
forClassName: "OWSAES256Key"
)
}
}

View File

@ -27,8 +27,8 @@ enum _011_SharedUtilChanges: Migration {
for: .userProfile
)
let confResult: SessionUtil.ConfResult = try SessionUtil.update(
conf: userProfileConf,
with: Profile.fetchOrCreateCurrentUser(db)
profile: Profile.fetchOrCreateCurrentUser(db),
in: .custom(conf: Atomic(userProfileConf))
)
if confResult.needsDump {

View File

@ -2,6 +2,7 @@
import Foundation
import GRDB
import DifferenceKit
import SessionUtilitiesKit
public struct ClosedGroup: Codable, Identifiable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import DifferenceKit
import SignalCoreKit
import SessionUtilitiesKit
public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible, CustomStringConvertible, Differentiable {
@ -42,7 +41,7 @@ public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableReco
public let profilePictureFileName: String?
/// The key with which the profile is encrypted.
public let profileEncryptionKey: OWSAES256Key?
public let profileEncryptionKey: Data?
// MARK: - Initialization
@ -52,7 +51,7 @@ public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableReco
nickname: String? = nil,
profilePictureUrl: String? = nil,
profilePictureFileName: String? = nil,
profileEncryptionKey: OWSAES256Key? = nil
profileEncryptionKey: Data? = nil
) {
self.id = id
self.name = name
@ -68,7 +67,7 @@ public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableReco
"""
Profile(
name: \(name),
profileKey: \(profileEncryptionKey?.keyData.description ?? "null"),
profileKey: \(profileEncryptionKey?.description ?? "null"),
profilePictureUrl: \(profilePictureUrl ?? "null")
)
"""
@ -81,7 +80,7 @@ public extension Profile {
init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
var profileKey: OWSAES256Key?
var profileKey: Data?
var profilePictureUrl: String?
// If we have both a `profileKey` and a `profilePicture` then the key MUST be valid
@ -89,12 +88,7 @@ public extension Profile {
let profileKeyData: Data = try? container.decode(Data.self, forKey: .profileEncryptionKey),
let profilePictureUrlValue: String = try? container.decode(String.self, forKey: .profilePictureUrl)
{
guard let validProfileKey: OWSAES256Key = OWSAES256Key(data: profileKeyData) else {
owsFailDebug("Failed to make profile key for key data")
throw StorageError.decodingFailed
}
profileKey = validProfileKey
profileKey = profileKeyData
profilePictureUrl = profilePictureUrlValue
}
@ -113,10 +107,10 @@ public extension Profile {
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(nickname, forKey: .nickname)
try container.encode(profilePictureUrl, forKey: .profilePictureUrl)
try container.encode(profilePictureFileName, forKey: .profilePictureFileName)
try container.encode(profileEncryptionKey?.keyData, forKey: .profileEncryptionKey)
try container.encodeIfPresent(nickname, forKey: .nickname)
try container.encodeIfPresent(profilePictureUrl, forKey: .profilePictureUrl)
try container.encodeIfPresent(profilePictureFileName, forKey: .profilePictureFileName)
try container.encodeIfPresent(profileEncryptionKey, forKey: .profileEncryptionKey)
}
}
@ -126,17 +120,12 @@ public extension Profile {
static func fromProto(_ proto: SNProtoDataMessage, id: String) -> Profile? {
guard let profileProto = proto.profile, let displayName = profileProto.displayName else { return nil }
var profileKey: OWSAES256Key?
var profileKey: Data?
var profilePictureUrl: String?
// If we have both a `profileKey` and a `profilePicture` then the key MUST be valid
if let profileKeyData: Data = proto.profileKey, profileProto.profilePicture != nil {
guard let validProfileKey: OWSAES256Key = OWSAES256Key(data: profileKeyData) else {
owsFailDebug("Failed to make profile key for key data")
return nil
}
profileKey = validProfileKey
profileKey = profileKeyData
profilePictureUrl = profileProto.profilePicture
}
@ -155,8 +144,8 @@ public extension Profile {
let profileProto = SNProtoLokiProfile.builder()
profileProto.setDisplayName(name)
if let profileKey: OWSAES256Key = profileEncryptionKey, let profilePictureUrl: String = profilePictureUrl {
dataMessageProto.setProfileKey(profileKey.keyData)
if let profileKey: Data = profileEncryptionKey, let profilePictureUrl: String = profilePictureUrl {
dataMessageProto.setProfileKey(profileKey)
profileProto.setProfilePicture(profilePictureUrl)
}
@ -178,7 +167,7 @@ public extension Profile {
name: String? = nil,
profilePictureUrl: Updatable<String?> = .existing,
profilePictureFileName: Updatable<String?> = .existing,
profileEncryptionKey: Updatable<OWSAES256Key> = .existing
profileEncryptionKey: Updatable<Data?> = .existing
) -> Profile {
return Profile(
id: id,

View File

@ -4,7 +4,7 @@ import Foundation
import GRDB
import SessionUtilitiesKit
internal struct ConfigDump: Codable, Equatable, Hashable, Identifiable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {
public struct ConfigDump: Codable, Equatable, Hashable, Identifiable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {
public static var databaseTableName: String { "configDump" }
public typealias Columns = CodingKeys
@ -13,11 +13,11 @@ internal struct ConfigDump: Codable, Equatable, Hashable, Identifiable, Fetchabl
case data
}
enum Variant: String, Codable, DatabaseValueConvertible, CaseIterable {
public enum Variant: String, Codable, DatabaseValueConvertible, CaseIterable {
case userProfile
}
var id: Variant { variant }
public var id: Variant { variant }
/// The type of config this dump is for
public let variant: Variant
@ -25,3 +25,13 @@ internal struct ConfigDump: Codable, Equatable, Hashable, Identifiable, Fetchabl
/// The data for this dump
public let data: Data
}
// MARK: - Convenience
public extension ConfigDump.Variant {
var configMessageKind: SharedConfigMessage.Kind {
switch self {
case .userProfile: return .userProfile
}
}
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import PromiseKit
import SignalCoreKit
import SessionUtilitiesKit
public enum AttachmentUploadJob: JobExecutor {

View File

@ -2,7 +2,7 @@
import Foundation
import GRDB
import SignalCoreKit
//import SignalCoreKit
import SessionUtilitiesKit
public enum FailedMessageSendsJob: JobExecutor {

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import PromiseKit
import SignalCoreKit
import SessionUtilitiesKit
import SessionSnodeKit

View File

@ -27,11 +27,19 @@ public enum MessageReceiveJob: JobExecutor {
var updatedJob: Job = job
var leastSevereError: Error?
let nonConfigMessages: [Details.MessageInfo] = details.messages
.filter { $0.variant != .sharedConfigMessage }
let sharedConfigMessages: [SharedConfigMessage] = details.messages
.compactMap { $0.message as? SharedConfigMessage }
Storage.shared.write { db in
// Send any SharedConfigMessages to the SessionUtil to handle it
try SessionUtil.handleConfigMessages(db, messages: sharedConfigMessages)
// Handle the remaining messages
var remainingMessagesToProcess: [Details.MessageInfo] = []
for messageInfo in details.messages {
for messageInfo in nonConfigMessages {
do {
try MessageReceiver.handle(
db,
@ -100,6 +108,8 @@ public enum MessageReceiveJob: JobExecutor {
extension MessageReceiveJob {
public struct Details: Codable {
typealias SharedConfigInfo = (message: SharedConfigMessage, serializedProtoData: Data)
public struct MessageInfo: Codable {
private enum CodingKeys: String, CodingKey {
case message

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import PromiseKit
import SignalCoreKit
import SessionUtilitiesKit
import SessionSnodeKit

View File

@ -2,7 +2,6 @@
import Foundation
import GRDB
import SignalCoreKit
import SessionUtilitiesKit
public enum RetrieveDefaultOpenGroupRoomsJob: JobExecutor {

View File

@ -156,7 +156,7 @@ public extension SendReadReceiptsJob {
behaviour: .recurring,
threadId: threadId,
details: Details(
destination: .contact(publicKey: threadId),
destination: .contact(publicKey: threadId, namespace: .default),
timestampMsValues: timestampMsValues.asSet()
)
)

View File

@ -2,7 +2,6 @@
import Foundation
import GRDB
import SignalCoreKit
import SessionUtilitiesKit
public enum UpdateProfilePictureJob: JobExecutor {
@ -37,6 +36,7 @@ public enum UpdateProfilePictureJob: JobExecutor {
.updateAll(db, Job.Columns.nextRunTimestamp.set(to: 0))
}
}
SNLog("[UpdateProfilePictureJob] Deferred as not enough time has passed since the last update")
deferred(job)
return
}

View File

@ -0,0 +1,112 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtil
import SessionUtilitiesKit
internal extension SessionUtil {
static func handleUserProfileUpdate(
_ db: Database,
in target: Target,
needsDump: Bool,
latestConfigUpdateSentTimestamp: TimeInterval
) throws {
typealias ProfileData = (profileName: String, profilePictureUrl: String?, profilePictureKey: Data?)
guard needsDump else { return }
guard target.conf.wrappedValue != nil else { throw SessionUtilError.nilConfigObject }
let userPublicKey: String = getUserHexEncodedPublicKey(db)
// Since we are doing direct memory manipulation we are using an `Atomic` type which has
// blocking access in it's `mutate` closure
let maybeProfileData: ProfileData? = target.conf.mutate { conf -> ProfileData? in
// A profile must have a name so if this is null then it's invalid and can be ignored
guard let profileNamePtr: UnsafePointer<CChar> = user_profile_get_name(conf) else {
return nil
}
let profileName: String = String(cString: profileNamePtr)
let profilePic: user_profile_pic = user_profile_get_pic(conf)
var profilePictureUrl: String? = nil
var profilePictureKey: Data? = nil
// Make sure the url and key exist before reading the memory
if
profilePic.keylen > 0,
let profilePictureUrlPtr: UnsafePointer<CChar> = profilePic.url,
let profilePictureKeyPtr: UnsafePointer<CChar> = profilePic.key
{
profilePictureUrl = String(cString: profilePictureUrlPtr)
profilePictureKey = Data(bytes: profilePictureKeyPtr, count: profilePic.keylen)
}
return (
profileName: profileName,
profilePictureUrl: profilePictureUrl,
profilePictureKey: profilePictureKey
)
}
// Only save the data in the database if it's valid
guard let profileData: ProfileData = maybeProfileData else { return }
// Profile (also force-approve the current user in case the account got into a weird state or
// restored directly from a migration)
try MessageReceiver.updateProfileIfNeeded(
db,
publicKey: userPublicKey,
name: profileData.profileName,
profilePictureUrl: profileData.profilePictureUrl,
profileKey: profileData.profilePictureKey,
sentTimestamp: latestConfigUpdateSentTimestamp
)
try Contact(id: userPublicKey)
.with(
isApproved: true,
didApproveMe: true
)
.save(db)
}
@discardableResult static func update(
profile: Profile,
in target: Target
) throws -> ConfResult {
guard target.conf.wrappedValue != nil else { throw SessionUtilError.nilConfigObject }
// Since we are doing direct memory manipulation we are using an `Atomic` type which has
// blocking access in it's `mutate` closure
return target.conf.mutate { conf in
// Update the name
user_profile_set_name(conf, profile.name)
let profilePic: user_profile_pic? = profile.profilePictureUrl?
.bytes
.map { CChar(bitPattern: $0) }
.withUnsafeBufferPointer { profileUrlPtr in
let profileKey: [CChar]? = profile.profileEncryptionKey?
.bytes
.map { CChar(bitPattern: $0) }
return profileKey?.withUnsafeBufferPointer { profileKeyPtr in
user_profile_pic(
url: profileUrlPtr.baseAddress,
key: profileKeyPtr.baseAddress,
keylen: (profileKey?.count ?? 0)
)
}
}
if let profilePic: user_profile_pic = profilePic {
user_profile_set_pic(conf, profilePic)
}
return (
needsPush: config_needs_push(conf),
needsDump: config_needs_dump(conf)
)
}
}
}

View File

@ -6,7 +6,20 @@ import SessionUtil
import SessionUtilitiesKit
/*internal*/public enum SessionUtil {
typealias ConfResult = (needsPush: Bool, needsDump: Bool)
public typealias ConfResult = (needsPush: Bool, needsDump: Bool)
public typealias IncomingConfResult = (needsPush: Bool, needsDump: Bool, latestSentTimestamp: TimeInterval)
enum Target {
case global(variant: ConfigDump.Variant)
case custom(conf: Atomic<UnsafeMutablePointer<config_object>?>)
var conf: Atomic<UnsafeMutablePointer<config_object>?> {
switch self {
case .global(let variant): return SessionUtil.config(for: variant)
case .custom(let conf): return conf
}
}
}
// MARK: - Configs
@ -23,6 +36,13 @@ import SessionUtilitiesKit
}
}
// MARK: - Convenience
private static func config(for variant: ConfigDump.Variant) -> Atomic<UnsafeMutablePointer<config_object>?> {
switch variant {
case .userProfile: return SessionUtil.userProfileConfig
}
}
// MARK: - Loading
/*internal*/public static func loadState() {
@ -103,42 +123,104 @@ import SessionUtilitiesKit
.save(db)
}
// MARK: - UserProfile
// MARK: - Pushes
internal static func update(
conf: UnsafeMutablePointer<config_object>?,
with profile: Profile
) throws -> ConfResult {
guard conf != nil else { throw SessionUtilError.nilConfigObject }
public static func getChanges(
for variants: [ConfigDump.Variant] = ConfigDump.Variant.allCases
) -> [SharedConfigMessage] {
return variants
.compactMap { variant -> SharedConfigMessage? in
let conf = SessionUtil.config(for: variant)
// Check if the config needs to be pushed
guard config_needs_push(conf.wrappedValue) else { return nil }
var toPush: UnsafeMutablePointer<CChar>? = nil
var toPushLen: Int = 0
let seqNo: Int64 = conf.mutate { config_push($0, &toPush, &toPushLen) }
guard let toPush: UnsafeMutablePointer<CChar> = toPush else { return nil }
let pushData: Data = Data(bytes: toPush, count: toPushLen)
toPush.deallocate()
return SharedConfigMessage(
kind: variant.configMessageKind,
seqNo: seqNo,
data: pushData
)
}
}
public static func markAsPushed(messages: [SharedConfigMessage]) -> [ConfigDump.Variant: Bool] {
messages.reduce(into: [:]) { result, message in
let conf = SessionUtil.config(for: message.kind.configDumpVariant)
// Mark the config as pushed
config_confirm_pushed(conf.wrappedValue, message.seqNo)
// Update the result to indicate whether the config needs to be dumped
result[message.kind.configDumpVariant] = config_needs_dump(conf.wrappedValue)
}
}
// MARK: - Receiving
public static func handleConfigMessages(
_ db: Database,
messages: [SharedConfigMessage]
) throws {
let groupedMessages: [SharedConfigMessage.Kind: [SharedConfigMessage]] = messages
.grouped(by: \.kind)
// Update the name
user_profile_set_name(conf, profile.name)
let profilePic: user_profile_pic? = profile.profilePictureUrl?
.bytes
.map { CChar(bitPattern: $0) }
.withUnsafeBufferPointer { profileUrlPtr in
let profileKey: [CChar]? = profile.profileEncryptionKey?
.keyData
.bytes
.map { CChar(bitPattern: $0) }
// Merge the config messages into the current state
let results: [ConfigDump.Variant: IncomingConfResult] = groupedMessages
.reduce(into: [:]) { result, next in
let atomicConf = SessionUtil.config(for: next.key.configDumpVariant)
var needsPush: Bool = false
var needsDump: Bool = false
let messageSentTimestamp: TimeInterval = TimeInterval(
(next.value.compactMap { $0.sentTimestamp }.max() ?? 0) / 1000
)
// Block the config while we are merging
atomicConf.mutate { conf in
var mergeData: [UnsafePointer<CChar>?] = next.value
.map { message -> [CChar] in
message.data
.bytes
.map { CChar(bitPattern: $0) }
}
.unsafeCopy()
var mergeSize: [Int] = messages.map { $0.data.count }
config_merge(conf, &mergeData, &mergeSize, messages.count)
mergeData.forEach { $0?.deallocate() }
return profileKey?.withUnsafeBufferPointer { profileKeyPtr in
user_profile_pic(
url: profileUrlPtr.baseAddress,
key: profileKeyPtr.baseAddress,
keylen: (profileKey?.count ?? 0)
)
// Get the state of this variant
needsPush = config_needs_push(conf)
needsDump = config_needs_dump(conf)
}
// Return the current state of the config
result[next.key.configDumpVariant] = (
needsPush: needsPush,
needsDump: needsDump,
latestSentTimestamp: messageSentTimestamp
)
}
if let profilePic: user_profile_pic = profilePic {
user_profile_set_pic(conf, profilePic)
// If the data needs to be dumped then apply the relevant local changes
try results.forEach { variant, result in
switch variant {
case .userProfile:
try SessionUtil.handleUserProfileUpdate(
db,
in: .global(variant: variant),
needsDump: result.needsDump,
latestConfigUpdateSentTimestamp: result.latestSentTimestamp
)
}
}
return (
needsPush: config_needs_push(conf),
needsDump: config_needs_dump(conf)
)
}
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import Sodium
import Curve25519Kit
import SessionUtilitiesKit
public final class ClosedGroupControlMessage: ControlMessage {

View File

@ -9,7 +9,7 @@ extension ConfigurationMessage {
let currentUserProfile: Profile = Profile.fetchOrCreateCurrentUser(db)
let displayName: String = currentUserProfile.name
let profilePictureUrl: String? = currentUserProfile.profilePictureUrl
let profileKey: Data? = currentUserProfile.profileEncryptionKey?.keyData
let profileKey: Data? = currentUserProfile.profileEncryptionKey
let closedGroups: Set<CMClosedGroup> = try ClosedGroup.fetchAll(db)
.compactMap { closedGroup -> CMClosedGroup? in
guard let latestKeyPair: ClosedGroupKeyPair = try closedGroup.fetchLatestKeyPair(db) else {
@ -62,7 +62,7 @@ extension ConfigurationMessage {
publicKey: contact.id,
displayName: (profile?.name ?? contact.id),
profilePictureUrl: profile?.profilePictureUrl,
profileKey: profile?.profileEncryptionKey?.keyData,
profileKey: profile?.profileEncryptionKey,
hasIsApproved: true,
isApproved: contact.isApproved,
hasIsBlocked: true,

View File

@ -1,9 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Sodium
import GRDB
import Curve25519Kit
import SessionUtilitiesKit
public final class ConfigurationMessage: ControlMessage {

View File

@ -0,0 +1,126 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
public final class SharedConfigMessage: ControlMessage {
private enum CodingKeys: String, CodingKey {
case kind
case seqNo
case data
}
public var kind: Kind
public var seqNo: Int64
public var data: Data
public override var isSelfSendValid: Bool { true }
// MARK: - Kind
public enum Kind: CustomStringConvertible, Codable {
case userProfile
public var description: String {
switch self {
case .userProfile: return "userProfile"
}
}
}
// MARK: - Initialization
public init(
kind: Kind,
seqNo: Int64,
data: Data
) {
self.kind = kind
self.seqNo = seqNo
self.data = data
super.init()
}
// MARK: - Codable
required init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
kind = try container.decode(Kind.self, forKey: .kind)
seqNo = try container.decode(Int64.self, forKey: .seqNo)
data = try container.decode(Data.self, forKey: .data)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try container.encode(kind, forKey: .kind)
try container.encode(seqNo, forKey: .seqNo)
try container.encode(data, forKey: .data)
}
// MARK: - Proto Conversion
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> SharedConfigMessage? {
guard let sharedConfigMessage = proto.sharedConfigMessage else { return nil }
return SharedConfigMessage(
kind: {
switch sharedConfigMessage.kind {
case .userProfile: return .userProfile
}
}(),
seqNo: sharedConfigMessage.seqno,
data: sharedConfigMessage.data
)
}
public override func toProto(_ db: Database) -> SNProtoContent? {
do {
let sharedConfigMessage: SNProtoSharedConfigMessage.SNProtoSharedConfigMessageBuilder = SNProtoSharedConfigMessage.builder(
kind: {
switch self.kind {
case .userProfile: return .userProfile
}
}(),
seqno: self.seqNo,
data: self.data
)
let contentProto = SNProtoContent.builder()
contentProto.setSharedConfigMessage(try sharedConfigMessage.build())
return try contentProto.build()
} catch {
SNLog("Couldn't construct data extraction notification proto from: \(self).")
return nil
}
}
// MARK: - Description
public var description: String {
"""
SharedConfigMessage(
kind: \(kind.description),
seqNo: \(seqNo),
data: \(data.count) bytes
)
"""
}
}
// MARK: - Convenience
public extension SharedConfigMessage.Kind {
var configDumpVariant: ConfigDump.Variant {
switch self {
case .userProfile: return .userProfile
}
}
}

View File

@ -2,12 +2,19 @@
import Foundation
import GRDB
import SessionSnodeKit
import SessionUtilitiesKit
public extension Message {
enum Destination: Codable {
case contact(publicKey: String)
case closedGroup(groupPublicKey: String)
case contact(
publicKey: String,
namespace: SnodeAPI.Namespace
)
case closedGroup(
groupPublicKey: String,
namespace: SnodeAPI.Namespace
)
case openGroup(
roomToken: String,
server: String,
@ -36,10 +43,10 @@ public extension Message {
)
}
return .contact(publicKey: thread.id)
return .contact(publicKey: thread.id, namespace: .default)
case .closedGroup:
return .closedGroup(groupPublicKey: thread.id)
return .closedGroup(groupPublicKey: thread.id, namespace: .legacyClosedGroup)
case .openGroup:
guard let openGroup: OpenGroup = try thread.openGroup.fetchOne(db) else {
@ -65,5 +72,59 @@ public extension Message {
default: return self
}
}
// MARK: - Codable
// FIXME: Remove this custom implementation after enough time has passed (added the 'namespace' properties)
public init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
// Should only have a single root key so we can just switch on it to have cleaner code
switch container.allKeys.first {
case .contact:
let childContainer: KeyedDecodingContainer<ContactCodingKeys> = try container.nestedContainer(keyedBy: ContactCodingKeys.self, forKey: .contact)
self = .contact(
publicKey: try childContainer.decode(String.self, forKey: .publicKey),
namespace: (
(try? childContainer.decode(SnodeAPI.Namespace.self, forKey: .namespace)) ??
.default
)
)
case .closedGroup:
let childContainer: KeyedDecodingContainer<ClosedGroupCodingKeys> = try container.nestedContainer(keyedBy: ClosedGroupCodingKeys.self, forKey: .closedGroup)
self = .closedGroup(
groupPublicKey: try childContainer.decode(String.self, forKey: .groupPublicKey),
namespace: (
(try? childContainer.decode(SnodeAPI.Namespace.self, forKey: .namespace)) ??
.legacyClosedGroup
)
)
case .openGroup:
let childContainer: KeyedDecodingContainer<OpenGroupCodingKeys> = try container.nestedContainer(keyedBy: OpenGroupCodingKeys.self, forKey: .openGroup)
self = .openGroup(
roomToken: try childContainer.decode(String.self, forKey: .roomToken),
server: try childContainer.decode(String.self, forKey: .server),
whisperTo: try? childContainer.decode(String.self, forKey: .whisperTo),
whisperMods: try childContainer.decode(Bool.self, forKey: .whisperMods),
fileIds: try? childContainer.decode([String].self, forKey: .fileIds)
)
case .openGroupInbox:
let childContainer: KeyedDecodingContainer<OpenGroupInboxCodingKeys> = try container.nestedContainer(keyedBy: OpenGroupInboxCodingKeys.self, forKey: .openGroupInbox)
self = .openGroupInbox(
server: try childContainer.decode(String.self, forKey: .server),
openGroupPublicKey: try childContainer.decode(String.self, forKey: .openGroupPublicKey),
blindedPublicKey: try childContainer.decode(String.self, forKey: .blindedPublicKey)
)
default: throw MessageReceiverError.invalidMessage
}
}
}
}

View File

@ -99,6 +99,7 @@ public extension Message {
case messageRequestResponse
case visibleMessage
case callMessage
case sharedConfigMessage
init?(from type: Message) {
switch type {
@ -112,6 +113,7 @@ public extension Message {
case is MessageRequestResponse: self = .messageRequestResponse
case is VisibleMessage: self = .visibleMessage
case is CallMessage: self = .callMessage
case is SharedConfigMessage: self = .sharedConfigMessage
default: return nil
}
}
@ -128,6 +130,7 @@ public extension Message {
case .messageRequestResponse: return MessageRequestResponse.self
case .visibleMessage: return VisibleMessage.self
case .callMessage: return CallMessage.self
case .sharedConfigMessage: return SharedConfigMessage.self
}
}
@ -148,6 +151,7 @@ public extension Message {
case .messageRequestResponse: return try container.decode(MessageRequestResponse.self, forKey: key)
case .visibleMessage: return try container.decode(VisibleMessage.self, forKey: key)
case .callMessage: return try container.decode(CallMessage.self, forKey: key)
case .sharedConfigMessage: return try container.decode(SharedConfigMessage.self, forKey: key)
}
}
}
@ -165,7 +169,8 @@ public extension Message {
.unsendRequest,
.messageRequestResponse,
.visibleMessage,
.callMessage
.callMessage,
.sharedConfigMessage
]
return prioritisedVariants

View File

@ -114,7 +114,7 @@ public extension VisibleMessage {
extension VisibleMessage.VMProfile {
init(profile: Profile) {
self.displayName = profile.name
self.profileKey = profile.profileEncryptionKey?.keyData
self.profileKey = profile.profileEncryptionKey
self.profilePictureUrl = profile.profilePictureUrl
}
}

View File

@ -618,6 +618,9 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
if let _value = messageRequestResponse {
builder.setMessageRequestResponse(_value)
}
if let _value = sharedConfigMessage {
builder.setSharedConfigMessage(_value)
}
return builder
}
@ -659,6 +662,10 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
proto.messageRequestResponse = valueParam.proto
}
@objc public func setSharedConfigMessage(_ valueParam: SNProtoSharedConfigMessage) {
proto.sharedConfigMessage = valueParam.proto
}
@objc public func build() throws -> SNProtoContent {
return try SNProtoContent.parseProto(proto)
}
@ -686,6 +693,8 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
@objc public let messageRequestResponse: SNProtoMessageRequestResponse?
@objc public let sharedConfigMessage: SNProtoSharedConfigMessage?
private init(proto: SessionProtos_Content,
dataMessage: SNProtoDataMessage?,
callMessage: SNProtoCallMessage?,
@ -694,7 +703,8 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
configurationMessage: SNProtoConfigurationMessage?,
dataExtractionNotification: SNProtoDataExtractionNotification?,
unsendRequest: SNProtoUnsendRequest?,
messageRequestResponse: SNProtoMessageRequestResponse?) {
messageRequestResponse: SNProtoMessageRequestResponse?,
sharedConfigMessage: SNProtoSharedConfigMessage?) {
self.proto = proto
self.dataMessage = dataMessage
self.callMessage = callMessage
@ -704,6 +714,7 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
self.dataExtractionNotification = dataExtractionNotification
self.unsendRequest = unsendRequest
self.messageRequestResponse = messageRequestResponse
self.sharedConfigMessage = sharedConfigMessage
}
@objc
@ -757,6 +768,11 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
messageRequestResponse = try SNProtoMessageRequestResponse.parseProto(proto.messageRequestResponse)
}
var sharedConfigMessage: SNProtoSharedConfigMessage? = nil
if proto.hasSharedConfigMessage {
sharedConfigMessage = try SNProtoSharedConfigMessage.parseProto(proto.sharedConfigMessage)
}
// MARK: - Begin Validation Logic for SNProtoContent -
// MARK: - End Validation Logic for SNProtoContent -
@ -769,7 +785,8 @@ extension SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder {
configurationMessage: configurationMessage,
dataExtractionNotification: dataExtractionNotification,
unsendRequest: unsendRequest,
messageRequestResponse: messageRequestResponse)
messageRequestResponse: messageRequestResponse,
sharedConfigMessage: sharedConfigMessage)
return result
}
@ -2449,9 +2466,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
builder.setBody(_value)
}
builder.setAttachments(attachments)
if let _value = group {
builder.setGroup(_value)
}
if hasFlags {
builder.setFlags(flags)
}
@ -2506,10 +2520,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
proto.attachments = wrappedItems.map { $0.proto }
}
@objc public func setGroup(_ valueParam: SNProtoGroupContext) {
proto.group = valueParam.proto
}
@objc public func setFlags(_ valueParam: UInt32) {
proto.flags = valueParam
}
@ -2573,8 +2583,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
@objc public let attachments: [SNProtoAttachmentPointer]
@objc public let group: SNProtoGroupContext?
@objc public let quote: SNProtoDataMessageQuote?
@objc public let preview: [SNProtoDataMessagePreview]
@ -2640,7 +2648,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
private init(proto: SessionProtos_DataMessage,
attachments: [SNProtoAttachmentPointer],
group: SNProtoGroupContext?,
quote: SNProtoDataMessageQuote?,
preview: [SNProtoDataMessagePreview],
reaction: SNProtoDataMessageReaction?,
@ -2649,7 +2656,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
closedGroupControlMessage: SNProtoDataMessageClosedGroupControlMessage?) {
self.proto = proto
self.attachments = attachments
self.group = group
self.quote = quote
self.preview = preview
self.reaction = reaction
@ -2672,11 +2678,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
var attachments: [SNProtoAttachmentPointer] = []
attachments = try proto.attachments.map { try SNProtoAttachmentPointer.parseProto($0) }
var group: SNProtoGroupContext? = nil
if proto.hasGroup {
group = try SNProtoGroupContext.parseProto(proto.group)
}
var quote: SNProtoDataMessageQuote? = nil
if proto.hasQuote {
quote = try SNProtoDataMessageQuote.parseProto(proto.quote)
@ -2711,7 +2712,6 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
let result = SNProtoDataMessage(proto: proto,
attachments: attachments,
group: group,
quote: quote,
preview: preview,
reaction: reaction,
@ -3706,152 +3706,91 @@ extension SNProtoAttachmentPointer.SNProtoAttachmentPointerBuilder {
#endif
// MARK: - SNProtoGroupContext
// MARK: - SNProtoSharedConfigMessage
@objc public class SNProtoGroupContext: NSObject {
@objc public class SNProtoSharedConfigMessage: NSObject {
// MARK: - SNProtoGroupContextType
// MARK: - SNProtoSharedConfigMessageKind
@objc public enum SNProtoGroupContextType: Int32 {
case unknown = 0
case update = 1
case deliver = 2
case quit = 3
case requestInfo = 4
@objc public enum SNProtoSharedConfigMessageKind: Int32 {
case userProfile = 1
}
private class func SNProtoGroupContextTypeWrap(_ value: SessionProtos_GroupContext.TypeEnum) -> SNProtoGroupContextType {
private class func SNProtoSharedConfigMessageKindWrap(_ value: SessionProtos_SharedConfigMessage.Kind) -> SNProtoSharedConfigMessageKind {
switch value {
case .unknown: return .unknown
case .update: return .update
case .deliver: return .deliver
case .quit: return .quit
case .requestInfo: return .requestInfo
case .userProfile: return .userProfile
}
}
private class func SNProtoGroupContextTypeUnwrap(_ value: SNProtoGroupContextType) -> SessionProtos_GroupContext.TypeEnum {
private class func SNProtoSharedConfigMessageKindUnwrap(_ value: SNProtoSharedConfigMessageKind) -> SessionProtos_SharedConfigMessage.Kind {
switch value {
case .unknown: return .unknown
case .update: return .update
case .deliver: return .deliver
case .quit: return .quit
case .requestInfo: return .requestInfo
case .userProfile: return .userProfile
}
}
// MARK: - SNProtoGroupContextBuilder
// MARK: - SNProtoSharedConfigMessageBuilder
@objc public class func builder(id: Data, type: SNProtoGroupContextType) -> SNProtoGroupContextBuilder {
return SNProtoGroupContextBuilder(id: id, type: type)
@objc public class func builder(kind: SNProtoSharedConfigMessageKind, seqno: Int64, data: Data) -> SNProtoSharedConfigMessageBuilder {
return SNProtoSharedConfigMessageBuilder(kind: kind, seqno: seqno, data: data)
}
// asBuilder() constructs a builder that reflects the proto's contents.
@objc public func asBuilder() -> SNProtoGroupContextBuilder {
let builder = SNProtoGroupContextBuilder(id: id, type: type)
if let _value = name {
builder.setName(_value)
}
builder.setMembers(members)
if let _value = avatar {
builder.setAvatar(_value)
}
builder.setAdmins(admins)
@objc public func asBuilder() -> SNProtoSharedConfigMessageBuilder {
let builder = SNProtoSharedConfigMessageBuilder(kind: kind, seqno: seqno, data: data)
return builder
}
@objc public class SNProtoGroupContextBuilder: NSObject {
@objc public class SNProtoSharedConfigMessageBuilder: NSObject {
private var proto = SessionProtos_GroupContext()
private var proto = SessionProtos_SharedConfigMessage()
@objc fileprivate override init() {}
@objc fileprivate init(id: Data, type: SNProtoGroupContextType) {
@objc fileprivate init(kind: SNProtoSharedConfigMessageKind, seqno: Int64, data: Data) {
super.init()
setId(id)
setType(type)
setKind(kind)
setSeqno(seqno)
setData(data)
}
@objc public func setId(_ valueParam: Data) {
proto.id = valueParam
@objc public func setKind(_ valueParam: SNProtoSharedConfigMessageKind) {
proto.kind = SNProtoSharedConfigMessageKindUnwrap(valueParam)
}
@objc public func setType(_ valueParam: SNProtoGroupContextType) {
proto.type = SNProtoGroupContextTypeUnwrap(valueParam)
@objc public func setSeqno(_ valueParam: Int64) {
proto.seqno = valueParam
}
@objc public func setName(_ valueParam: String) {
proto.name = valueParam
@objc public func setData(_ valueParam: Data) {
proto.data = valueParam
}
@objc public func addMembers(_ valueParam: String) {
var items = proto.members
items.append(valueParam)
proto.members = items
}
@objc public func setMembers(_ wrappedItems: [String]) {
proto.members = wrappedItems
}
@objc public func setAvatar(_ valueParam: SNProtoAttachmentPointer) {
proto.avatar = valueParam.proto
}
@objc public func addAdmins(_ valueParam: String) {
var items = proto.admins
items.append(valueParam)
proto.admins = items
}
@objc public func setAdmins(_ wrappedItems: [String]) {
proto.admins = wrappedItems
}
@objc public func build() throws -> SNProtoGroupContext {
return try SNProtoGroupContext.parseProto(proto)
@objc public func build() throws -> SNProtoSharedConfigMessage {
return try SNProtoSharedConfigMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SNProtoGroupContext.parseProto(proto).serializedData()
return try SNProtoSharedConfigMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SessionProtos_GroupContext
fileprivate let proto: SessionProtos_SharedConfigMessage
@objc public let id: Data
@objc public let kind: SNProtoSharedConfigMessageKind
@objc public let type: SNProtoGroupContextType
@objc public let seqno: Int64
@objc public let avatar: SNProtoAttachmentPointer?
@objc public let data: Data
@objc public var name: String? {
guard proto.hasName else {
return nil
}
return proto.name
}
@objc public var hasName: Bool {
return proto.hasName
}
@objc public var members: [String] {
return proto.members
}
@objc public var admins: [String] {
return proto.admins
}
private init(proto: SessionProtos_GroupContext,
id: Data,
type: SNProtoGroupContextType,
avatar: SNProtoAttachmentPointer?) {
private init(proto: SessionProtos_SharedConfigMessage,
kind: SNProtoSharedConfigMessageKind,
seqno: Int64,
data: Data) {
self.proto = proto
self.id = id
self.type = type
self.avatar = avatar
self.kind = kind
self.seqno = seqno
self.data = data
}
@objc
@ -3859,35 +3798,35 @@ extension SNProtoAttachmentPointer.SNProtoAttachmentPointerBuilder {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoGroupContext {
let proto = try SessionProtos_GroupContext(serializedData: serializedData)
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoSharedConfigMessage {
let proto = try SessionProtos_SharedConfigMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SessionProtos_GroupContext) throws -> SNProtoGroupContext {
guard proto.hasID else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: id")
fileprivate class func parseProto(_ proto: SessionProtos_SharedConfigMessage) throws -> SNProtoSharedConfigMessage {
guard proto.hasKind else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: kind")
}
let id = proto.id
let kind = SNProtoSharedConfigMessageKindWrap(proto.kind)
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
guard proto.hasSeqno else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: seqno")
}
let type = SNProtoGroupContextTypeWrap(proto.type)
let seqno = proto.seqno
var avatar: SNProtoAttachmentPointer? = nil
if proto.hasAvatar {
avatar = try SNProtoAttachmentPointer.parseProto(proto.avatar)
guard proto.hasData else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: data")
}
let data = proto.data
// MARK: - Begin Validation Logic for SNProtoGroupContext -
// MARK: - Begin Validation Logic for SNProtoSharedConfigMessage -
// MARK: - End Validation Logic for SNProtoGroupContext -
// MARK: - End Validation Logic for SNProtoSharedConfigMessage -
let result = SNProtoGroupContext(proto: proto,
id: id,
type: type,
avatar: avatar)
let result = SNProtoSharedConfigMessage(proto: proto,
kind: kind,
seqno: seqno,
data: data)
return result
}
@ -3898,14 +3837,14 @@ extension SNProtoAttachmentPointer.SNProtoAttachmentPointerBuilder {
#if DEBUG
extension SNProtoGroupContext {
extension SNProtoSharedConfigMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SNProtoGroupContext.SNProtoGroupContextBuilder {
@objc public func buildIgnoringErrors() -> SNProtoGroupContext? {
extension SNProtoSharedConfigMessage.SNProtoSharedConfigMessageBuilder {
@objc public func buildIgnoringErrors() -> SNProtoSharedConfigMessage? {
return try! self.build()
}
}

View File

@ -348,6 +348,15 @@ struct SessionProtos_Content {
/// Clears the value of `messageRequestResponse`. Subsequent reads from it will return its default value.
mutating func clearMessageRequestResponse() {_uniqueStorage()._messageRequestResponse = nil}
var sharedConfigMessage: SessionProtos_SharedConfigMessage {
get {return _storage._sharedConfigMessage ?? SessionProtos_SharedConfigMessage()}
set {_uniqueStorage()._sharedConfigMessage = newValue}
}
/// Returns true if `sharedConfigMessage` has been explicitly set.
var hasSharedConfigMessage: Bool {return _storage._sharedConfigMessage != nil}
/// Clears the value of `sharedConfigMessage`. Subsequent reads from it will return its default value.
mutating func clearSharedConfigMessage() {_uniqueStorage()._sharedConfigMessage = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@ -591,15 +600,7 @@ struct SessionProtos_DataMessage {
set {_uniqueStorage()._attachments = newValue}
}
var group: SessionProtos_GroupContext {
get {return _storage._group ?? SessionProtos_GroupContext()}
set {_uniqueStorage()._group = newValue}
}
/// Returns true if `group` has been explicitly set.
var hasGroup: Bool {return _storage._group != nil}
/// Clears the value of `group`. Subsequent reads from it will return its default value.
mutating func clearGroup() {_uniqueStorage()._group = nil}
/// optional GroupContext group = 3; // No longer used
var flags: UInt32 {
get {return _storage._flags ?? 0}
set {_uniqueStorage()._flags = newValue}
@ -1580,91 +1581,61 @@ extension SessionProtos_AttachmentPointer.Flags: CaseIterable {
#endif // swift(>=4.2)
struct SessionProtos_GroupContext {
struct SessionProtos_SharedConfigMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// @required
var id: Data {
get {return _storage._id ?? Data()}
set {_uniqueStorage()._id = newValue}
var kind: SessionProtos_SharedConfigMessage.Kind {
get {return _kind ?? .userProfile}
set {_kind = newValue}
}
/// Returns true if `id` has been explicitly set.
var hasID: Bool {return _storage._id != nil}
/// Clears the value of `id`. Subsequent reads from it will return its default value.
mutating func clearID() {_uniqueStorage()._id = nil}
/// Returns true if `kind` has been explicitly set.
var hasKind: Bool {return self._kind != nil}
/// Clears the value of `kind`. Subsequent reads from it will return its default value.
mutating func clearKind() {self._kind = nil}
/// @required
var type: SessionProtos_GroupContext.TypeEnum {
get {return _storage._type ?? .unknown}
set {_uniqueStorage()._type = newValue}
var seqno: Int64 {
get {return _seqno ?? 0}
set {_seqno = newValue}
}
/// Returns true if `type` has been explicitly set.
var hasType: Bool {return _storage._type != nil}
/// Clears the value of `type`. Subsequent reads from it will return its default value.
mutating func clearType() {_uniqueStorage()._type = nil}
/// Returns true if `seqno` has been explicitly set.
var hasSeqno: Bool {return self._seqno != nil}
/// Clears the value of `seqno`. Subsequent reads from it will return its default value.
mutating func clearSeqno() {self._seqno = nil}
var name: String {
get {return _storage._name ?? String()}
set {_uniqueStorage()._name = newValue}
}
/// Returns true if `name` has been explicitly set.
var hasName: Bool {return _storage._name != nil}
/// Clears the value of `name`. Subsequent reads from it will return its default value.
mutating func clearName() {_uniqueStorage()._name = nil}
var members: [String] {
get {return _storage._members}
set {_uniqueStorage()._members = newValue}
}
var avatar: SessionProtos_AttachmentPointer {
get {return _storage._avatar ?? SessionProtos_AttachmentPointer()}
set {_uniqueStorage()._avatar = newValue}
}
/// Returns true if `avatar` has been explicitly set.
var hasAvatar: Bool {return _storage._avatar != nil}
/// Clears the value of `avatar`. Subsequent reads from it will return its default value.
mutating func clearAvatar() {_uniqueStorage()._avatar = nil}
var admins: [String] {
get {return _storage._admins}
set {_uniqueStorage()._admins = newValue}
/// @required
var data: Data {
get {return _data ?? Data()}
set {_data = newValue}
}
/// Returns true if `data` has been explicitly set.
var hasData: Bool {return self._data != nil}
/// Clears the value of `data`. Subsequent reads from it will return its default value.
mutating func clearData() {self._data = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
enum TypeEnum: SwiftProtobuf.Enum {
enum Kind: SwiftProtobuf.Enum {
typealias RawValue = Int
case unknown // = 0
case update // = 1
case deliver // = 2
case quit // = 3
case requestInfo // = 4
case userProfile // = 1
init() {
self = .unknown
self = .userProfile
}
init?(rawValue: Int) {
switch rawValue {
case 0: self = .unknown
case 1: self = .update
case 2: self = .deliver
case 3: self = .quit
case 4: self = .requestInfo
case 1: self = .userProfile
default: return nil
}
}
var rawValue: Int {
switch self {
case .unknown: return 0
case .update: return 1
case .deliver: return 2
case .quit: return 3
case .requestInfo: return 4
case .userProfile: return 1
}
}
@ -1672,12 +1643,14 @@ struct SessionProtos_GroupContext {
init() {}
fileprivate var _storage = _StorageClass.defaultInstance
fileprivate var _kind: SessionProtos_SharedConfigMessage.Kind? = nil
fileprivate var _seqno: Int64? = nil
fileprivate var _data: Data? = nil
}
#if swift(>=4.2)
extension SessionProtos_GroupContext.TypeEnum: CaseIterable {
extension SessionProtos_SharedConfigMessage.Kind: CaseIterable {
// Support synthesized by the compiler.
}
@ -1933,6 +1906,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
8: .same(proto: "dataExtractionNotification"),
9: .same(proto: "unsendRequest"),
10: .same(proto: "messageRequestResponse"),
11: .same(proto: "sharedConfigMessage"),
]
fileprivate class _StorageClass {
@ -1944,6 +1918,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
var _dataExtractionNotification: SessionProtos_DataExtractionNotification? = nil
var _unsendRequest: SessionProtos_UnsendRequest? = nil
var _messageRequestResponse: SessionProtos_MessageRequestResponse? = nil
var _sharedConfigMessage: SessionProtos_SharedConfigMessage? = nil
static let defaultInstance = _StorageClass()
@ -1958,6 +1933,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
_dataExtractionNotification = source._dataExtractionNotification
_unsendRequest = source._unsendRequest
_messageRequestResponse = source._messageRequestResponse
_sharedConfigMessage = source._sharedConfigMessage
}
}
@ -1978,6 +1954,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
if let v = _storage._dataExtractionNotification, !v.isInitialized {return false}
if let v = _storage._unsendRequest, !v.isInitialized {return false}
if let v = _storage._messageRequestResponse, !v.isInitialized {return false}
if let v = _storage._sharedConfigMessage, !v.isInitialized {return false}
return true
}
}
@ -1998,6 +1975,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
case 8: try { try decoder.decodeSingularMessageField(value: &_storage._dataExtractionNotification) }()
case 9: try { try decoder.decodeSingularMessageField(value: &_storage._unsendRequest) }()
case 10: try { try decoder.decodeSingularMessageField(value: &_storage._messageRequestResponse) }()
case 11: try { try decoder.decodeSingularMessageField(value: &_storage._sharedConfigMessage) }()
default: break
}
}
@ -2034,6 +2012,9 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
try { if let v = _storage._messageRequestResponse {
try visitor.visitSingularMessageField(value: v, fieldNumber: 10)
} }()
try { if let v = _storage._sharedConfigMessage {
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
} }()
}
try unknownFields.traverse(visitor: &visitor)
}
@ -2051,6 +2032,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
if _storage._dataExtractionNotification != rhs_storage._dataExtractionNotification {return false}
if _storage._unsendRequest != rhs_storage._unsendRequest {return false}
if _storage._messageRequestResponse != rhs_storage._messageRequestResponse {return false}
if _storage._sharedConfigMessage != rhs_storage._sharedConfigMessage {return false}
return true
}
if !storagesAreEqual {return false}
@ -2286,7 +2268,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "body"),
2: .same(proto: "attachments"),
3: .same(proto: "group"),
4: .same(proto: "flags"),
5: .same(proto: "expireTimer"),
6: .same(proto: "profileKey"),
@ -2303,7 +2284,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
fileprivate class _StorageClass {
var _body: String? = nil
var _attachments: [SessionProtos_AttachmentPointer] = []
var _group: SessionProtos_GroupContext? = nil
var _flags: UInt32? = nil
var _expireTimer: UInt32? = nil
var _profileKey: Data? = nil
@ -2323,7 +2303,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
init(copying source: _StorageClass) {
_body = source._body
_attachments = source._attachments
_group = source._group
_flags = source._flags
_expireTimer = source._expireTimer
_profileKey = source._profileKey
@ -2348,7 +2327,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
public var isInitialized: Bool {
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
if !SwiftProtobuf.Internal.areAllInitialized(_storage._attachments) {return false}
if let v = _storage._group, !v.isInitialized {return false}
if let v = _storage._quote, !v.isInitialized {return false}
if !SwiftProtobuf.Internal.areAllInitialized(_storage._preview) {return false}
if let v = _storage._reaction, !v.isInitialized {return false}
@ -2368,7 +2346,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &_storage._body) }()
case 2: try { try decoder.decodeRepeatedMessageField(value: &_storage._attachments) }()
case 3: try { try decoder.decodeSingularMessageField(value: &_storage._group) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &_storage._flags) }()
case 5: try { try decoder.decodeSingularUInt32Field(value: &_storage._expireTimer) }()
case 6: try { try decoder.decodeSingularBytesField(value: &_storage._profileKey) }()
@ -2398,9 +2375,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
if !_storage._attachments.isEmpty {
try visitor.visitRepeatedMessageField(value: _storage._attachments, fieldNumber: 2)
}
try { if let v = _storage._group {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try { if let v = _storage._flags {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4)
} }()
@ -2445,7 +2419,6 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
let rhs_storage = _args.1
if _storage._body != rhs_storage._body {return false}
if _storage._attachments != rhs_storage._attachments {return false}
if _storage._group != rhs_storage._group {return false}
if _storage._flags != rhs_storage._flags {return false}
if _storage._expireTimer != rhs_storage._expireTimer {return false}
if _storage._profileKey != rhs_storage._profileKey {return false}
@ -3301,127 +3274,63 @@ extension SessionProtos_AttachmentPointer.Flags: SwiftProtobuf._ProtoNameProvidi
]
}
extension SessionProtos_GroupContext: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".GroupContext"
extension SessionProtos_SharedConfigMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".SharedConfigMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "type"),
3: .same(proto: "name"),
4: .same(proto: "members"),
5: .same(proto: "avatar"),
6: .same(proto: "admins"),
1: .same(proto: "kind"),
2: .same(proto: "seqno"),
3: .same(proto: "data"),
]
fileprivate class _StorageClass {
var _id: Data? = nil
var _type: SessionProtos_GroupContext.TypeEnum? = nil
var _name: String? = nil
var _members: [String] = []
var _avatar: SessionProtos_AttachmentPointer? = nil
var _admins: [String] = []
static let defaultInstance = _StorageClass()
private init() {}
init(copying source: _StorageClass) {
_id = source._id
_type = source._type
_name = source._name
_members = source._members
_avatar = source._avatar
_admins = source._admins
}
}
fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
public var isInitialized: Bool {
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
if let v = _storage._avatar, !v.isInitialized {return false}
return true
}
if self._kind == nil {return false}
if self._seqno == nil {return false}
if self._data == nil {return false}
return true
}
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularBytesField(value: &_storage._id) }()
case 2: try { try decoder.decodeSingularEnumField(value: &_storage._type) }()
case 3: try { try decoder.decodeSingularStringField(value: &_storage._name) }()
case 4: try { try decoder.decodeRepeatedStringField(value: &_storage._members) }()
case 5: try { try decoder.decodeSingularMessageField(value: &_storage._avatar) }()
case 6: try { try decoder.decodeRepeatedStringField(value: &_storage._admins) }()
default: break
}
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularEnumField(value: &self._kind) }()
case 2: try { try decoder.decodeSingularInt64Field(value: &self._seqno) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self._data) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = _storage._id {
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
} }()
try { if let v = _storage._type {
try visitor.visitSingularEnumField(value: v, fieldNumber: 2)
} }()
try { if let v = _storage._name {
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
} }()
if !_storage._members.isEmpty {
try visitor.visitRepeatedStringField(value: _storage._members, fieldNumber: 4)
}
try { if let v = _storage._avatar {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
} }()
if !_storage._admins.isEmpty {
try visitor.visitRepeatedStringField(value: _storage._admins, fieldNumber: 6)
}
}
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = self._kind {
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
} }()
try { if let v = self._seqno {
try visitor.visitSingularInt64Field(value: v, fieldNumber: 2)
} }()
try { if let v = self._data {
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: SessionProtos_GroupContext, rhs: SessionProtos_GroupContext) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._id != rhs_storage._id {return false}
if _storage._type != rhs_storage._type {return false}
if _storage._name != rhs_storage._name {return false}
if _storage._members != rhs_storage._members {return false}
if _storage._avatar != rhs_storage._avatar {return false}
if _storage._admins != rhs_storage._admins {return false}
return true
}
if !storagesAreEqual {return false}
}
static func ==(lhs: SessionProtos_SharedConfigMessage, rhs: SessionProtos_SharedConfigMessage) -> Bool {
if lhs._kind != rhs._kind {return false}
if lhs._seqno != rhs._seqno {return false}
if lhs._data != rhs._data {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension SessionProtos_GroupContext.TypeEnum: SwiftProtobuf._ProtoNameProviding {
extension SessionProtos_SharedConfigMessage.Kind: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "UNKNOWN"),
1: .same(proto: "UPDATE"),
2: .same(proto: "DELIVER"),
3: .same(proto: "QUIT"),
4: .same(proto: "REQUEST_INFO"),
1: .same(proto: "USER_PROFILE"),
]
}

View File

@ -57,6 +57,7 @@ message Content {
optional DataExtractionNotification dataExtractionNotification = 8;
optional UnsendRequest unsendRequest = 9;
optional MessageRequestResponse messageRequestResponse = 10;
optional SharedConfigMessage sharedConfigMessage = 11;
}
message CallMessage {
@ -193,7 +194,7 @@ message DataMessage {
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
// optional GroupContext group = 3; // No longer used
optional uint32 flags = 4;
optional uint32 expireTimer = 5;
optional bytes profileKey = 6;
@ -271,22 +272,15 @@ message AttachmentPointer {
optional string url = 101;
}
message GroupContext {
message SharedConfigMessage {
enum Kind {
USER_PROFILE = 1;
}
enum Type {
UNKNOWN = 0;
UPDATE = 1;
DELIVER = 2;
QUIT = 3;
REQUEST_INFO = 4;
}
// @required
optional bytes id = 1;
// @required
optional Type type = 2;
optional string name = 3;
repeated string members = 4;
optional AttachmentPointer avatar = 5;
repeated string admins = 6;
// @required
required Kind kind = 1;
// @required
required int64 seqno = 2;
// @required
required bytes data = 3;
}

View File

@ -19,12 +19,14 @@ public enum MessageReceiverError: LocalizedError {
case decryptionFailed
case invalidGroupPublicKey
case noGroupKeyPair
case invalidSharedConfigMessageHandling
public var isRetryable: Bool {
switch self {
case .duplicateMessage, .duplicateMessageNewSnode, .duplicateControlMessage,
.invalidMessage, .unknownMessage, .unknownEnvelopeType, .invalidSignature,
.noData, .senderBlocked, .noThread, .selfSend, .decryptionFailed:
.noData, .senderBlocked, .noThread, .selfSend, .decryptionFailed,
.invalidSharedConfigMessageHandling:
return false
default: return true
@ -51,6 +53,8 @@ public enum MessageReceiverError: LocalizedError {
// Shared sender keys
case .invalidGroupPublicKey: return "Invalid group public key."
case .noGroupKeyPair: return "Missing group key pair."
case .invalidSharedConfigMessageHandling: return "Invalid handling of a shared config message"
}
}
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import Sodium
import SignalCoreKit
import SessionUtilitiesKit
extension MessageReceiver {
@ -29,7 +28,7 @@ extension MessageReceiver {
publicKey: userPublicKey,
name: message.displayName,
profilePictureUrl: message.profilePictureUrl,
profileKey: OWSAES256Key(data: message.profileKey),
profileKey: message.profileKey,
sentTimestamp: messageSentTimestamp
)
try Contact(id: userPublicKey)
@ -73,15 +72,13 @@ extension MessageReceiver {
if
profile.name != contactInfo.displayName ||
profile.profilePictureUrl != contactInfo.profilePictureUrl ||
profile.profileEncryptionKey != contactInfo.profileKey.map({ OWSAES256Key(data: $0) })
profile.profileEncryptionKey != contactInfo.profileKey
{
try profile
.with(
name: contactInfo.displayName,
profilePictureUrl: .updateIf(contactInfo.profilePictureUrl),
profileEncryptionKey: .updateIf(
contactInfo.profileKey.map { OWSAES256Key(data: $0) }
)
profileEncryptionKey: .updateIf(contactInfo.profileKey)
)
.save(db)
}

View File

@ -2,7 +2,6 @@
import Foundation
import GRDB
import SignalCoreKit
import SessionUtilitiesKit
extension MessageReceiver {
@ -21,17 +20,14 @@ extension MessageReceiver {
// Update profile if needed (want to do this regardless of whether the message exists or
// not to ensure the profile info gets sync between a users devices at every chance)
if let profile = message.profile {
var contactProfileKey: OWSAES256Key? = nil
let messageSentTimestamp: TimeInterval = (TimeInterval(message.sentTimestamp ?? 0) / 1000)
if let profileKey = profile.profileKey { contactProfileKey = OWSAES256Key(data: profileKey) }
try MessageReceiver.updateProfileIfNeeded(
db,
publicKey: senderId,
name: profile.displayName,
profilePictureUrl: profile.profilePictureUrl,
profileKey: contactProfileKey,
profileKey: profile.profileKey,
sentTimestamp: messageSentTimestamp
)
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import Sodium
import SignalCoreKit
import SessionUtilitiesKit
extension MessageReceiver {
@ -26,15 +25,12 @@ extension MessageReceiver {
// Update profile if needed (want to do this regardless of whether the message exists or
// not to ensure the profile info gets sync between a users devices at every chance)
if let profile = message.profile {
var contactProfileKey: OWSAES256Key? = nil
if let profileKey = profile.profileKey { contactProfileKey = OWSAES256Key(data: profileKey) }
try MessageReceiver.updateProfileIfNeeded(
db,
publicKey: sender,
name: profile.displayName,
profilePictureUrl: profile.profilePictureUrl,
profileKey: contactProfileKey,
profileKey: profile.profileKey,
sentTimestamp: messageSentTimestamp
)
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import Sodium
import SignalCoreKit
import SessionUtilitiesKit
public enum MessageReceiver {
@ -218,6 +217,9 @@ public enum MessageReceiver {
openGroupId: openGroupId
)
// SharedConfigMessages should be handled by the 'SharedUtil' instead of this
case is SharedConfigMessage: throw MessageReceiverError.invalidSharedConfigMessageHandling
default: fatalError()
}
@ -309,7 +311,7 @@ public enum MessageReceiver {
publicKey: String,
name: String?,
profilePictureUrl: String?,
profileKey: OWSAES256Key?,
profileKey: Data?,
sentTimestamp: TimeInterval,
dependencies: Dependencies = Dependencies()
) throws {
@ -341,9 +343,9 @@ public enum MessageReceiver {
// Profile picture & profile key
if
let profileKey: OWSAES256Key = profileKey,
let profileKey: Data = profileKey,
let profilePictureUrl: String = profilePictureUrl,
profileKey.keyData.count == kAES256_KeyByteLength,
profileKey.count == ProfileManager.avatarAES256KeyByteLength,
profileKey != profile.profileEncryptionKey
{
let shouldUpdate: Bool

View File

@ -106,8 +106,8 @@ extension MessageSender {
if let interactionId: Int64 = interactionId {
let threadId: String = {
switch destination {
case .contact(let publicKey): return publicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .contact(let publicKey, _): return publicKey
case .closedGroup(let groupPublicKey, _): return groupPublicKey
case .openGroup(let roomToken, let server, _, _, _):
return OpenGroup.idFor(roomToken: roomToken, server: server)
@ -194,16 +194,53 @@ extension MessageSender {
guard Identity.userExists(db) else { return Promise(error: StorageError.generic) }
let publicKey: String = getUserHexEncodedPublicKey(db)
let destination: Message.Destination = Message.Destination.contact(publicKey: publicKey)
let configurationMessage = try ConfigurationMessage.getCurrent(db)
let legacyDestination: Message.Destination = Message.Destination.contact(
publicKey: publicKey,
namespace: .default
)
let legacyConfigurationMessage = try ConfigurationMessage.getCurrent(db)
let (promise, seal) = Promise<Void>.pending()
let userConfigMessageChanges: [SharedConfigMessage] = SessionUtil.getChanges()
let destination: Message.Destination = Message.Destination.contact(
publicKey: publicKey,
namespace: .userProfileConfig
)
if forceSyncNow {
try MessageSender
.sendImmediate(db, message: configurationMessage, to: destination, interactionId: nil)
.sendImmediate(db, message: legacyConfigurationMessage, to: legacyDestination, interactionId: nil)
.done { seal.fulfill(()) }
.catch { _ in seal.reject(StorageError.generic) }
.retainUntilComplete()
when(
resolved: try userConfigMessageChanges.map { message in
try MessageSender
.sendImmediate(
db,
message: message,
to: destination,
interactionId: nil
)
}
)
.done { results in
let hadError: Bool = results.contains { result in
switch result {
case .fulfilled: return false
case .rejected: return true
}
}
guard !hadError else {
seal.reject(StorageError.generic)
return
}
seal.fulfill(())
}
.catch { _ in seal.reject(StorageError.generic) }
.retainUntilComplete()
}
else {
JobRunner.add(
@ -212,8 +249,8 @@ extension MessageSender {
variant: .messageSend,
threadId: publicKey,
details: MessageSendJob.Details(
destination: destination,
message: configurationMessage
destination: legacyDestination,
message: legacyConfigurationMessage
)
)
)

View File

@ -77,8 +77,8 @@ public final class MessageSender {
message.sender = userPublicKey
message.recipient = {
switch destination {
case .contact(let publicKey): return publicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .contact(let publicKey, _): return publicKey
case .closedGroup(let groupPublicKey, _): return groupPublicKey
case .openGroup, .openGroupInbox: preconditionFailure()
}
}()
@ -112,7 +112,7 @@ public final class MessageSender {
if var messageWithProfile: MessageWithProfile = message as? MessageWithProfile {
let profile: Profile = Profile.fetchOrCreateCurrentUser(db)
if let profileKey: Data = profile.profileEncryptionKey?.keyData, let profilePictureUrl: String = profile.profilePictureUrl {
if let profileKey: Data = profile.profileEncryptionKey, let profilePictureUrl: String = profile.profilePictureUrl {
messageWithProfile.profile = VisibleMessage.VMProfile(
displayName: profile.name,
profileKey: profileKey,
@ -146,10 +146,10 @@ public final class MessageSender {
let ciphertext: Data
do {
switch destination {
case .contact(let publicKey):
case .contact(let publicKey, _):
ciphertext = try encryptWithSessionProtocol(plaintext, for: publicKey)
case .closedGroup(let groupPublicKey):
case .closedGroup(let groupPublicKey, _):
guard let encryptionKeyPair: ClosedGroupKeyPair = try? ClosedGroupKeyPair.fetchLatestKeyPair(db, threadId: groupPublicKey) else {
throw MessageSenderError.noKeyPair
}
@ -171,15 +171,18 @@ public final class MessageSender {
// Wrap the result
let kind: SNProtoEnvelope.SNProtoEnvelopeType
let senderPublicKey: String
let namespace: SnodeAPI.Namespace
switch destination {
case .contact:
case .contact(_, let targetNamespace):
kind = .sessionMessage
senderPublicKey = ""
namespace = targetNamespace
case .closedGroup(let groupPublicKey):
case .closedGroup(let groupPublicKey, let targetNamespace):
kind = .closedGroupMessage
senderPublicKey = groupPublicKey
namespace = targetNamespace
case .openGroup, .openGroupInbox: preconditionFailure()
}
@ -208,8 +211,7 @@ public final class MessageSender {
SnodeAPI
.sendMessage(
snodeMessage,
isClosedGroupMessage: (kind == .closedGroupMessage),
isConfigMessage: (message is ConfigurationMessage)
in: namespace
)
.done(on: DispatchQueue.global(qos: .default)) { promises in
let promiseCount = promises.count
@ -488,7 +490,7 @@ public final class MessageSender {
if let message: VisibleMessage = message as? VisibleMessage {
let profile: Profile = Profile.fetchOrCreateCurrentUser(db)
if let profileKey: Data = profile.profileEncryptionKey?.keyData, let profilePictureUrl: String = profile.profilePictureUrl {
if let profileKey: Data = profile.profileEncryptionKey, let profilePictureUrl: String = profile.profilePictureUrl {
message.profile = VisibleMessage.VMProfile(
displayName: profile.name,
profileKey: profileKey,
@ -627,8 +629,8 @@ public final class MessageSender {
try? ControlMessageProcessRecord(
threadId: {
switch destination {
case .contact(let publicKey): return publicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .contact(let publicKey, _): return publicKey
case .closedGroup(let groupPublicKey, _): return groupPublicKey
case .openGroup(let roomToken, let server, _, _, _):
return OpenGroup.idFor(roomToken: roomToken, server: server)
@ -644,7 +646,7 @@ public final class MessageSender {
// the destination was a contact
// we didn't sync it already
let userPublicKey = getUserHexEncodedPublicKey(db)
if case .contact(let publicKey) = destination, !isSyncMessage {
if case .contact(let publicKey, let namespace) = destination, !isSyncMessage {
if let message = message as? VisibleMessage { message.syncTarget = publicKey }
if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey }
@ -652,7 +654,7 @@ public final class MessageSender {
try sendToSnodeDestination(
db,
message: message,
to: .contact(publicKey: userPublicKey),
to: .contact(publicKey: userPublicKey, namespace: namespace),
interactionId: interactionId,
isSyncMessage: true
).retainUntilComplete()

View File

@ -0,0 +1,114 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import PromiseKit
import SessionSnodeKit
import SessionUtilitiesKit
public final class CurrentUserPoller: Poller {
public static var namespaces: [SnodeAPI.Namespace] = [.default, .userProfileConfig]
private var targetSnode: Atomic<Snode?> = Atomic(nil)
private var usedSnodes: Atomic<Set<Snode>> = Atomic([])
// MARK: - Settings
override var namespaces: [SnodeAPI.Namespace] { CurrentUserPoller.namespaces }
/// After polling a given snode this many times we always switch to a new one.
///
/// The reason for doing this is that sometimes a snode will be giving us successful responses while
/// it isn't actually getting messages from other snodes.
override var maxNodePollCount: UInt { 6 }
private let pollInterval: TimeInterval = 1.5
private let retryInterval: TimeInterval = 0.25
private let maxRetryInterval: TimeInterval = 15
// MARK: - Convenience Functions
public func start() {
let publicKey: String = getUserHexEncodedPublicKey()
guard isPolling.wrappedValue[publicKey] != true else { return }
SNLog("Started polling.")
super.startIfNeeded(for: publicKey)
}
public func stop() {
SNLog("Stopped polling.")
super.stopAllPollers()
}
// MARK: - Abstract Methods
override func pollerName(for publicKey: String) -> String {
return "Main Poller"
}
override func nextPollDelay(for publicKey: String) -> TimeInterval {
let failureCount: TimeInterval = TimeInterval(failureCount.wrappedValue[publicKey] ?? 0)
// If there have been no failures then just use the 'minPollInterval'
guard failureCount > 0 else { return pollInterval }
// Otherwise use a simple back-off with the 'retryInterval'
let nextDelay: TimeInterval = (retryInterval * (failureCount * 1.2))
return min(maxRetryInterval, nextDelay)
}
override func getSnodeForPolling(
for publicKey: String,
on queue: DispatchQueue
) -> Promise<Snode> {
if let targetSnode: Snode = self.targetSnode.wrappedValue {
return Promise.value(targetSnode)
}
// Used the cached swarm for the given key and update the list of unusedSnodes
let swarm: Set<Snode> = (SnodeAPI.swarmCache.wrappedValue[publicKey] ?? [])
let unusedSnodes: Set<Snode> = swarm.subtracting(usedSnodes.wrappedValue)
// randomElement() uses the system's default random generator, which is cryptographically secure
if let nextSnode: Snode = unusedSnodes.randomElement() {
self.targetSnode.mutate { $0 = nextSnode }
self.usedSnodes.mutate { $0.insert(nextSnode) }
return Promise.value(nextSnode)
}
// If we haven't retrieved a target snode at this point then either the cache
// is empty or we have used all of the snodes and need to start from scratch
return SnodeAPI.getSwarm(for: publicKey)
.then(on: queue) { [weak self] _ -> Promise<Snode> in
guard let strongSelf = self else { return Promise(error: SnodeAPIError.generic) }
self?.targetSnode.mutate { $0 = nil }
self?.usedSnodes.mutate { $0.removeAll() }
return strongSelf.getSnodeForPolling(for: publicKey, on: queue)
}
}
override func handlePollError(_ error: Error, for publicKey: String) {
if UserDefaults.sharedLokiProject?[.isMainAppActive] != true {
// Do nothing when an error gets throws right after returning from the background (happens frequently)
}
else if let targetSnode: Snode = targetSnode.wrappedValue {
SNLog("Polling \(targetSnode) failed; dropping it and switching to next snode.")
self.targetSnode.mutate { $0 = nil }
SnodeAPI.dropSnodeFromSwarmIfNeeded(targetSnode, publicKey: publicKey)
}
else {
SNLog("Polling failed due to having no target service node.")
}
// Try to restart the poller from scratch
Threading.pollerQueue.async { [weak self] in
self?.setUpPolling(for: publicKey)
}
}
}

View File

@ -3,7 +3,6 @@
import Foundation
import GRDB
import PromiseKit
import Sodium
import SessionSnodeKit
import SessionUtilitiesKit

View File

@ -4,8 +4,6 @@
#import "AppReadiness.h"
#import "AppContext.h"
#import <SignalCoreKit/SignalCoreKit.h>
#import <SignalCoreKit/Threading.h>
NS_ASSUME_NONNULL_BEGIN
@ -53,9 +51,14 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block
{
DispatchMainThreadSafe(^{
if ([NSThread isMainThread]) {
[self.sharedManager runNowOrWhenAppWillBecomeReady:block];
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.sharedManager runNowOrWhenAppWillBecomeReady:block];
});
}
}
- (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block
@ -75,9 +78,14 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block
{
DispatchMainThreadSafe(^{
if ([NSThread isMainThread]) {
[self.sharedManager runNowOrWhenAppDidBecomeReady:block];
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.sharedManager runNowOrWhenAppDidBecomeReady:block];
});
}
}
- (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block

View File

@ -1,12 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SignalCoreKit
public extension OWSAES256Key {
convenience init?(data: Data?) {
guard let existingData: Data = data else { return nil }
self.init(data: existingData)
}
}

View File

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import CryptoKit
import GRDB
import PromiseKit
import SignalCoreKit
@ -11,6 +12,9 @@ public struct ProfileManager {
// Before encrypting and submitting we NULL pad the name data to this length.
private static let nameDataLength: UInt = 64
public static let maxAvatarDiameter: CGFloat = 640
internal static let avatarAES256KeyByteLength: Int = 32
private static let avatarNonceLength: Int = 12
private static let avatarTagLength: Int = 16
private static var profileAvatarCache: Atomic<[String: Data]> = Atomic([:])
private static var currentAvatarDownloads: Atomic<Set<String>> = Atomic([])
@ -82,16 +86,40 @@ public struct ProfileManager {
// MARK: - Profile Encryption
private static func encryptProfileData(data: Data, key: OWSAES256Key) -> Data? {
guard key.keyData.count == kAES256_KeyByteLength else { return nil }
private static func encryptData(data: Data, key: Data) -> Data? {
// The key structure is: nonce || ciphertext || authTag
guard
key.count == ProfileManager.avatarAES256KeyByteLength,
let nonceData: Data = try? Randomness.generateRandomBytes(numberBytes: ProfileManager.avatarNonceLength),
let nonce: AES.GCM.Nonce = try? AES.GCM.Nonce(data: nonceData),
let sealedData: AES.GCM.SealedBox = try? AES.GCM.seal(
data,
using: SymmetricKey(data: key),
nonce: nonce
),
let encryptedContent: Data = sealedData.combined
else { return nil }
return Cryptography.encryptAESGCMProfileData(plainTextData: data, key: key)
return encryptedContent
}
private static func decryptProfileData(data: Data, key: OWSAES256Key) -> Data? {
guard key.keyData.count == kAES256_KeyByteLength else { return nil }
private static func decryptData(data: Data, key: Data) -> Data? {
guard key.count == ProfileManager.avatarAES256KeyByteLength else { return nil }
return Cryptography.decryptAESGCMProfileData(encryptedData: data, key: key)
// The key structure is: nonce || ciphertext || authTag
let cipherTextLength: Int = (data.count - (ProfileManager.avatarNonceLength + ProfileManager.avatarTagLength))
guard
cipherTextLength > 0,
let sealedData: AES.GCM.SealedBox = try? AES.GCM.SealedBox(
nonce: AES.GCM.Nonce(data: data.subdata(in: 0..<ProfileManager.avatarNonceLength)),
ciphertext: data.subdata(in: ProfileManager.avatarNonceLength..<(ProfileManager.avatarNonceLength + cipherTextLength)),
tag: data.subdata(in: (data.count - ProfileManager.avatarTagLength)..<data.count)
),
let decryptedData: Data = try? AES.GCM.open(sealedData, using: SymmetricKey(data: key))
else { return nil }
return decryptedData
}
// MARK: - File Paths
@ -151,8 +179,8 @@ public struct ProfileManager {
}
guard
let fileId: String = Attachment.fileId(for: profileUrlStringAtStart),
let profileKeyAtStart: OWSAES256Key = profile.profileEncryptionKey,
profileKeyAtStart.keyData.count > 0
let profileKeyAtStart: Data = profile.profileEncryptionKey,
profileKeyAtStart.count > 0
else {
return
}
@ -178,8 +206,8 @@ public struct ProfileManager {
}
guard
let latestProfileKey: OWSAES256Key = latestProfile.profileEncryptionKey,
!latestProfileKey.keyData.isEmpty,
let latestProfileKey: Data = latestProfile.profileEncryptionKey,
!latestProfileKey.isEmpty,
latestProfileKey == profileKeyAtStart
else {
OWSLogger.warn("Ignoring avatar download for obsolete user profile.")
@ -239,15 +267,85 @@ public struct ProfileManager {
imageFilePath: String?,
success: ((Database, Profile) throws -> ())? = nil,
failure: ((ProfileManagerError) -> ())? = nil
) {
prepareAndUploadAvatarImage(
queue: queue,
image: image,
imageFilePath: imageFilePath,
success: { fileInfo, newProfileKey in
// If we have no download url the we are removing the profile image
guard let (downloadUrl, fileName): (String, String) = fileInfo else {
Storage.shared.writeAsync { db in
let existingProfile: Profile = Profile.fetchOrCreateCurrentUser(db)
OWSLogger.verbose(existingProfile.profilePictureUrl != nil ?
"Updating local profile on service with cleared avatar." :
"Updating local profile on service with no avatar."
)
let updatedProfile: Profile = try existingProfile
.with(
name: profileName,
profilePictureUrl: nil,
profilePictureFileName: nil,
profileEncryptionKey: (existingProfile.profilePictureUrl != nil ?
.update(newProfileKey) :
.existing
)
)
.saved(db)
try SessionUtil.update(
profile: updatedProfile,
in: .global(variant: .userProfile)
)
SNLog("Successfully updated service with profile.")
try success?(db, updatedProfile)
}
return
}
// Update user defaults
UserDefaults.standard[.lastProfilePictureUpload] = Date()
// Update the profile
Storage.shared.writeAsync { db in
let profile: Profile = try Profile
.fetchOrCreateCurrentUser(db)
.with(
name: profileName,
profilePictureUrl: .update(downloadUrl),
profilePictureFileName: .update(fileName),
profileEncryptionKey: .update(newProfileKey)
)
.saved(db)
SNLog("Successfully updated service with profile.")
try success?(db, profile)
}
},
failure: failure
)
}
public static func prepareAndUploadAvatarImage(
queue: DispatchQueue,
image: UIImage?,
imageFilePath: String?,
success: @escaping ((downloadUrl: String, fileName: String)?, Data) -> (),
failure: ((ProfileManagerError) -> ())? = nil
) {
queue.async {
// If the profile avatar was updated or removed then encrypt with a new profile key
// to ensure that other users know that our profile picture was updated
let newProfileKey: OWSAES256Key = OWSAES256Key.generateRandom()
let newProfileKey: Data
let maxAvatarBytes: UInt = (5 * 1000 * 1000)
let avatarImageData: Data?
do {
newProfileKey = try Randomness.generateRandomBytes(numberBytes: ProfileManager.avatarAES256KeyByteLength)
avatarImageData = try {
guard var image: UIImage = image else {
guard let imageFilePath: String = imageFilePath else { return nil }

View File

@ -8,6 +8,7 @@ import BackgroundTasks
import PromiseKit
import SessionMessagingKit
import SignalUtilitiesKit
import SignalCoreKit
public final class NotificationServiceExtension: UNNotificationServiceExtension {
private var didPerformSetup = false
@ -137,6 +138,9 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
self.handleSuccessForIncomingCall(db, for: callMessage)
case let sharedConfigMessage as SharedConfigMessage:
try SessionUtil.handleConfigMessages(db, messages: [sharedConfigMessage])
default: break
}

View File

@ -1,14 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <Availability.h>
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalCoreKit/NSObject+OWS.h>
#import <SessionUIKit/SessionUIKit.h>
#endif

View File

@ -6,9 +6,6 @@
#import <UIKit/UIKit.h>
// Separate iOS Frameworks from other imports.
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalCoreKit/OWSLogs.h>
#import <SignalUtilitiesKit/UIFont+OWS.h>
#import <SessionUtilitiesKit/UIView+OWS.h>
#import <SessionUtilitiesKit/AppContext.h>

View File

@ -2,10 +2,10 @@
import UIKit
import PromiseKit
import SignalCoreKit
import SignalUtilitiesKit
import SessionUIKit
import SessionUtilitiesKit
import SignalCoreKit
final class SAEScreenLockViewController: ScreenLockViewController {
private var hasShownAuthUIOnce: Bool = false

View File

@ -4,6 +4,7 @@ import UIKit
import SignalUtilitiesKit
import SessionUtilitiesKit
import SessionMessagingKit
import SignalCoreKit
/// This is _NOT_ a singleton and will be instantiated each time that the SAE is used.
final class ShareAppExtensionContext: NSObject, AppContext {

View File

@ -5,6 +5,7 @@ import CoreServices
import PromiseKit
import SignalUtilitiesKit
import SessionUIKit
import SignalCoreKit
final class ShareVC: UINavigationController, ShareViewDelegate {
private var areVersionMigrationsComplete = false

View File

@ -4,7 +4,6 @@ import UIKit
import GRDB
import PromiseKit
import DifferenceKit
import Sodium
import SessionUIKit
import SignalUtilitiesKit
import SessionMessagingKit

View File

@ -2,7 +2,6 @@
import Foundation
import GRDB
import SignalCoreKit
import SessionUtilitiesKit
public enum GetSnodePoolJob: JobExecutor {

View File

@ -0,0 +1,81 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
extension SnodeAPI {
public class DeleteAllMessagesRequest: SnodeAuthenticatedRequestBody {
enum CodingKeys: String, CodingKey {
case namespace
}
/// The message namespace from which to delete messages. The request will delete all messages
/// from the specific namespace, or from all namespaces when not provided
///
/// **Note:** If omitted when sending the request, messages are deleted from the default namespace
/// only (namespace 0)
let namespace: SnodeAPI.Namespace?
// MARK: - Init
public init(
namespace: SnodeAPI.Namespace?,
pubkey: String,
timestampMs: UInt64,
ed25519PublicKey: [UInt8],
ed25519SecretKey: [UInt8]
) {
self.namespace = namespace
super.init(
pubkey: pubkey,
ed25519PublicKey: ed25519PublicKey,
ed25519SecretKey: ed25519SecretKey,
timestampMs: timestampMs
)
}
// MARK: - Coding
override public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
// If no namespace is specified it defaults to the default namespace only (namespace
// 0), so instead in this case we want to explicitly delete from `all` namespaces
switch namespace {
case .some(let namespace): try container.encode(namespace, forKey: .namespace)
case .none: try container.encode("all", forKey: .namespace)
}
try super.encode(to: encoder)
}
// MARK: - Abstract Methods
override func generateSignature() throws -> [UInt8] {
/// Ed25519 signature of `( "delete_all" || namespace || timestamp )`, where
/// `namespace` is the empty string for the default namespace (whether explicitly specified or
/// not), and otherwise the stringified version of the namespace parameter (i.e. "99" or "-42" or "all").
/// The signature must be signed by the ed25519 pubkey in `pubkey` (omitting the leading prefix).
/// Must be base64 encoded for json requests; binary for OMQ requests.
let verificationBytes: [UInt8] = SnodeAPI.Endpoint.deleteAll.rawValue.bytes
.appending(
contentsOf: (namespace == nil ?
"all" :
namespace?.verificationString
)?.bytes
)
.appending(contentsOf: timestampMs.map { "\($0)" }?.data(using: .utf8)?.bytes)
guard
let signatureBytes: [UInt8] = sodium.wrappedValue.sign.signature(
message: verificationBytes,
secretKey: ed25519SecretKey
)
else {
throw SnodeAPIError.signingFailed
}
return signatureBytes
}
}
}

View File

@ -0,0 +1,72 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
extension SnodeAPI {
public class GetMessagesRequest: SnodeAuthenticatedRequestBody {
enum CodingKeys: String, CodingKey {
case lastHash = "last_hash"
case namespace
}
let lastHash: String
let namespace: SnodeAPI.Namespace?
// MARK: - Init
public init(
lastHash: String,
namespace: SnodeAPI.Namespace?,
pubkey: String,
subkey: String?,
timestampMs: UInt64,
ed25519PublicKey: [UInt8],
ed25519SecretKey: [UInt8]
) {
self.lastHash = lastHash
self.namespace = namespace
super.init(
pubkey: pubkey,
ed25519PublicKey: ed25519PublicKey,
ed25519SecretKey: ed25519SecretKey,
subkey: subkey,
timestampMs: timestampMs
)
}
// MARK: - Coding
override public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try container.encode(lastHash, forKey: .lastHash)
try container.encodeIfPresent(namespace, forKey: .namespace)
try super.encode(to: encoder)
}
// MARK: - Abstract Methods
override func generateSignature() throws -> [UInt8] {
/// Ed25519 signature of `("retrieve" || namespace || timestamp)` (if using a non-0
/// namespace), or `("retrieve" || timestamp)` when fetching from the default namespace. Both
/// namespace and timestamp are the base10 expressions of the relevant values. Must be base64
/// encoded for json requests; binary for OMQ requests.
let verificationBytes: [UInt8] = SnodeAPI.Endpoint.getMessages.rawValue.bytes
.appending(contentsOf: namespace?.verificationString.bytes)
.appending(contentsOf: timestampMs.map { "\($0)" }?.data(using: .utf8)?.bytes)
guard
let signatureBytes: [UInt8] = sodium.wrappedValue.sign.signature(
message: verificationBytes,
secretKey: ed25519SecretKey
)
else {
throw SnodeAPIError.signingFailed
}
return signatureBytes
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
extension SnodeAPI {
public class SendMessageRequest: SnodeAuthenticatedRequestBody {
enum CodingKeys: String, CodingKey {
case namespace
case signatureTimestamp = "sig_timestamp"
}
let message: SnodeMessage
let namespace: SnodeAPI.Namespace
// MARK: - Init
public init(
message: SnodeMessage,
namespace: SnodeAPI.Namespace,
subkey: String?,
timestampMs: UInt64,
ed25519PublicKey: [UInt8],
ed25519SecretKey: [UInt8]
) {
self.message = message
self.namespace = namespace
super.init(
pubkey: message.recipient,
ed25519PublicKey: ed25519PublicKey,
ed25519SecretKey: ed25519SecretKey,
subkey: subkey,
timestampMs: timestampMs
)
}
// MARK: - Coding
override public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try super.encode(to: encoder)
/// **Note:** We **MUST** do the `message.encode` after we call `super.encode` because it will
/// override the `timestampMs` value with the value in the message (if we do it the other way around then
/// the the API call timestamp will be sent instead which is incorrect. For this specific request type we have a
/// separate `signatureTimestamp` value to store the timestamp used to generate the signature
try message.encode(to: encoder)
try container.encode(namespace, forKey: .namespace)
try container.encode(timestampMs, forKey: .signatureTimestamp)
}
// MARK: - Abstract Methods
override func generateSignature() throws -> [UInt8] {
/// Ed25519 signature of `("store" || namespace || sig_timestamp)`, where namespace and
/// `sig_timestamp` are the base10 expression of the namespace and `sig_timestamp` values. Must be
/// base64 encoded for json requests; binary for OMQ requests. For non-05 type pubkeys (i.e. non
/// session ids) the signature will be verified using `pubkey`. For 05 pubkeys, see the following
/// option.
let verificationBytes: [UInt8] = SnodeAPI.Endpoint.sendMessage.rawValue.bytes
.appending(contentsOf: namespace.verificationString.bytes)
.appending(contentsOf: timestampMs.map { "\($0)" }?.data(using: .utf8)?.bytes)
guard
let signatureBytes: [UInt8] = sodium.wrappedValue.sign.signature(
message: verificationBytes,
secretKey: ed25519SecretKey
)
else {
throw SnodeAPIError.signingFailed
}
return signatureBytes
}
}
}

View File

@ -0,0 +1,37 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
public extension SnodeAPI {
enum Namespace: Int, Codable {
case `default` = 0
case userProfileConfig = 2
case legacyClosedGroup = -10
// MARK: Variables
var requiresReadAuthentication: Bool {
switch self {
case .legacyClosedGroup: return false
default: return true
}
}
var requiresWriteAuthentication: Bool {
switch self {
// Not in use until we can batch delete and store config messages
case .default, .legacyClosedGroup: return false
default: return true
}
}
var verificationString: String {
switch self {
case .`default`: return ""
default: return "\(self.rawValue)"
}
}
}
}

View File

@ -4,13 +4,12 @@ import Foundation
import Combine
import GRDB
import PromiseKit
import SignalCoreKit
open class Storage {
private static let dbFileName: String = "Session.sqlite"
private static let keychainService: String = "TSKeyChainService"
private static let dbCipherKeySpecKey: String = "GRDBDatabaseCipherKeySpec"
private static let kSQLCipherKeySpecLength: Int32 = 48
private static let kSQLCipherKeySpecLength: Int = 48
private static var sharedDatabaseDirectoryPath: String { "\(OWSFileSystem.appSharedDataDirectoryPath())/database" }
private static var databasePath: String { "\(Storage.sharedDatabaseDirectoryPath)/\(Storage.dbFileName)" }
@ -103,7 +102,7 @@ open class Storage {
migrations: [TargetMigrations],
async: Bool = true,
onProgressUpdate: ((CGFloat, TimeInterval) -> ())?,
onComplete: @escaping (Swift.Result<Database, Error>, Bool) -> ()
onComplete: @escaping (Swift.Result<Void, Error>, Bool) -> ()
) {
guard isValid, let dbWriter: DatabaseWriter = dbWriter else { return }
@ -179,7 +178,7 @@ open class Storage {
}
// Store the logic to run when the migration completes
let migrationCompleted: (Swift.Result<Database, Error>) -> () = { [weak self] result in
let migrationCompleted: (Swift.Result<Void, Error>) -> () = { [weak self] result in
self?.hasCompletedMigrations = true
self?.migrationProgressUpdater = nil
SUKLegacy.clearLegacyDatabaseInstance()
@ -194,16 +193,23 @@ open class Storage {
// Note: The non-async migration should only be used for unit tests
guard async else {
do { try self.migrator?.migrate(dbWriter) }
catch {
try? dbWriter.read { db in
migrationCompleted(Swift.Result<Database, Error>.failure(error))
}
}
catch { migrationCompleted(Swift.Result<Void, Error>.failure(error)) }
return
}
self.migrator?.asyncMigrate(dbWriter) { result in
migrationCompleted(result)
let finalResult: Swift.Result<Void, Error> = {
switch result {
case .failure(let error): return .failure(error)
case .success: return .success(())
}
}()
// Note: We need to dispatch this to the next run toop to prevent any potential re-entrancy
// issues since the 'asyncMigrate' returns a result containing a DB instance
DispatchQueue.global(qos: .userInitiated).async {
migrationCompleted(finalResult)
}
}
}
@ -251,7 +257,7 @@ open class Storage {
case (_, errSecItemNotFound):
// No keySpec was found so we need to generate a new one
do {
var keySpec: Data = Randomness.generateRandomBytes(kSQLCipherKeySpecLength)
var keySpec: Data = try Randomness.generateRandomBytes(numberBytes: kSQLCipherKeySpecLength)
defer { keySpec.resetBytes(in: 0..<keySpec.count) } // Reset content immediately after use
try SSKDefaultKeychainStorage.shared.set(data: keySpec, service: keychainService, key: dbCipherKeySpecKey)

View File

@ -43,6 +43,12 @@ public class Atomic<Value> {
return mutation(&value)
}
}
@discardableResult public func mutate<T>(_ mutation: (inout Value) throws -> T) throws -> T {
return try queue.sync {
return try mutation(&value)
}
}
}
extension Atomic where Value: CustomDebugStringConvertible {

View File

@ -20,6 +20,7 @@ public enum General {
public enum GeneralError: Error {
case keyGenerationFailed
case randomGenerationFailed
}
public func getUserHexEncodedPublicKey(_ db: Database? = nil, dependencies: Dependencies = Dependencies()) -> String {

Some files were not shown because too many files have changed in this diff Show More