From c7087a394e60112357b343d22abe53f3c7153c02 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Wed, 3 Aug 2022 16:52:39 -0700 Subject: [PATCH] MessagesList: Add support for beforeMessageGUID and beforeDate --- Dumped Classes/IMCore_ClassDump.h | 1 + MessagesBridge.xcodeproj/project.pbxproj | 10 ++++ .../Operations/MBIMMessagesListOperation.m | 55 ++++++++++++++++--- .../Operations/Utilities/MBIMErrorResponse.h | 18 ++++++ .../Operations/Utilities/MBIMErrorResponse.m | 38 +++++++++++++ .../Operations/Utilities/MBIMHTTPUtilities.h | 10 ++++ .../Operations/Utilities/MBIMHTTPUtilities.m | 28 ++++++++++ kordophone/kordophoned-Entitlements.plist | 16 ++++++ 8 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.h create mode 100644 kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.m create mode 100644 kordophone/kordophoned-Entitlements.plist diff --git a/Dumped Classes/IMCore_ClassDump.h b/Dumped Classes/IMCore_ClassDump.h index 16bee13..dfb2356 100644 --- a/Dumped Classes/IMCore_ClassDump.h +++ b/Dumped Classes/IMCore_ClassDump.h @@ -3457,6 +3457,7 @@ __attribute__((visibility("default"))) @interface IMService : NSObject { } - (id)loadUnreadMessagesWithLimit:(unsigned long long)arg1 fallbackToMessagesUpToGUID:(id)arg2; - (id)loadFrequentRepliesLimit:(unsigned long long)arg1 loadImmediately:(BOOL)arg2; - (id)loadMessagesBeforeAndAfterGUID:(id)arg1 numberOfMessagesToLoadBeforeGUID:(unsigned long long)arg2 numberOfMessagesToLoadAfterGUID:(unsigned long long)arg3 loadImmediately:(BOOL)arg4; +- (id)loadMessagesBeforeAndAfterGUID:(id)arg1 numberOfMessagesToLoadBeforeGUID:(unsigned long long)arg2 numberOfMessagesToLoadAfterGUID:(unsigned long long)arg3 loadImmediately:(BOOL)arg4 threadIdentifier:(id)tid; - (id)loadMessagesUpToGUID:(id)arg1 date:(id)arg2 limit:(unsigned long long)arg3 loadImmediately:(BOOL)arg4; - (id)loadMessagesBeforeDate:(id)arg1 limit:(unsigned long long)arg2 loadImmediately:(BOOL)arg3; - (id)loadMessagesBeforeDate:(id)arg1 limit:(unsigned long long)arg2; diff --git a/MessagesBridge.xcodeproj/project.pbxproj b/MessagesBridge.xcodeproj/project.pbxproj index 0655252..c7f26ac 100644 --- a/MessagesBridge.xcodeproj/project.pbxproj +++ b/MessagesBridge.xcodeproj/project.pbxproj @@ -81,6 +81,7 @@ CD602062219B68950024D9C5 /* MBIMSendMessageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CD602061219B68950024D9C5 /* MBIMSendMessageOperation.m */; }; CD83E156219BE10A00F4CCEA /* hooking.m in Sources */ = {isa = PBXBuildFile; fileRef = CD83E155219BE10A00F4CCEA /* hooking.m */; }; CD83E166219BE91600F4CCEA /* agentHook.m in Sources */ = {isa = PBXBuildFile; fileRef = CD83E165219BE91600F4CCEA /* agentHook.m */; }; + CD936A32289B353F0093A1AC /* MBIMErrorResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CD936A31289B353F0093A1AC /* MBIMErrorResponse.m */; }; CDDCF78D283F398C0087ABDF /* MBIMDeleteConversationOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF78C283F398C0087ABDF /* MBIMDeleteConversationOperation.m */; }; CDE4556421A3578A0041F5DD /* IMChat+Encoded.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE4556321A3578A0041F5DD /* IMChat+Encoded.m */; }; CDE455A121A365AD0041F5DD /* MBIMMarkOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE455A021A365AD0041F5DD /* MBIMMarkOperation.m */; }; @@ -237,6 +238,9 @@ CD83E161219BE91500F4CCEA /* libagentHook.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libagentHook.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; CD83E165219BE91600F4CCEA /* agentHook.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = agentHook.m; sourceTree = ""; }; CD83E1B5219BF78E00F4CCEA /* hookAgent.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = hookAgent.sh; sourceTree = ""; }; + CD936A2F289B31740093A1AC /* kordophoned-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "kordophoned-Entitlements.plist"; sourceTree = ""; }; + CD936A30289B353F0093A1AC /* MBIMErrorResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBIMErrorResponse.h; sourceTree = ""; }; + CD936A31289B353F0093A1AC /* MBIMErrorResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBIMErrorResponse.m; sourceTree = ""; }; CDDCF78B283F398C0087ABDF /* MBIMDeleteConversationOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBIMDeleteConversationOperation.h; sourceTree = ""; }; CDDCF78C283F398C0087ABDF /* MBIMDeleteConversationOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBIMDeleteConversationOperation.m; sourceTree = ""; }; CDE4556221A3578A0041F5DD /* IMChat+Encoded.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IMChat+Encoded.h"; sourceTree = ""; }; @@ -356,6 +360,8 @@ 1AA43E8E219EBB2D00EDF1A7 /* MBIMJSONDataResponse.m */, CDE455A521A531ED0041F5DD /* MBIMDataResponse.h */, CDE455A621A531ED0041F5DD /* MBIMDataResponse.m */, + CD936A30289B353F0093A1AC /* MBIMErrorResponse.h */, + CD936A31289B353F0093A1AC /* MBIMErrorResponse.m */, 1AA43E93219EC38E00EDF1A7 /* MBIMHTTPUtilities.h */, 1AA43E94219EC38E00EDF1A7 /* MBIMHTTPUtilities.m */, ); @@ -574,6 +580,7 @@ 1A0C446D219A4BCD00F2AC00 /* Bridge */, CDF62334219A895D00690038 /* main.m */, 1AAB32B221F835BD004A2A72 /* KPServer.pch */, + CD936A2F289B31740093A1AC /* kordophoned-Entitlements.plist */, ); path = kordophone; sourceTree = ""; @@ -856,6 +863,7 @@ CD60205F219B674B0024D9C5 /* MBIMConversationListOperation.m in Sources */, CDE4556421A3578A0041F5DD /* IMChat+Encoded.m in Sources */, 1AA43E8F219EBB2D00EDF1A7 /* MBIMJSONDataResponse.m in Sources */, + CD936A32289B353F0093A1AC /* MBIMErrorResponse.m in Sources */, CD2ECEC2269539100055E302 /* MBIMAuthenticateOperation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1124,6 +1132,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = NO; + CODE_SIGN_ENTITLEMENTS = "kordophone/kordophoned-Entitlements.plist"; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; GCC_PREFIX_HEADER = kordophone/KPServer.pch; @@ -1140,6 +1149,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = NO; + CODE_SIGN_ENTITLEMENTS = "kordophone/kordophoned-Entitlements.plist"; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; GCC_PREFIX_HEADER = kordophone/KPServer.pch; diff --git a/kordophone/Bridge/Operations/MBIMMessagesListOperation.m b/kordophone/Bridge/Operations/MBIMMessagesListOperation.m index 73c66b2..4b24271 100644 --- a/kordophone/Bridge/Operations/MBIMMessagesListOperation.m +++ b/kordophone/Bridge/Operations/MBIMMessagesListOperation.m @@ -9,9 +9,12 @@ #import "MBIMMessagesListOperation.h" #import "MBIMHTTPUtilities.h" #import "IMMessageItem+Encoded.h" +#import "MBIMErrorResponse.h" #import "IMCore_ClassDump.h" +#define kDefaultMessagesLimit 75 + @implementation MBIMMessagesListOperation + (void)load { [super load]; } @@ -25,11 +28,26 @@ { __block NSObject *response = nil; do { + // Required parameters NSString *guid = [self valueForQueryItemWithName:@"guid"]; + // Optional + NSString *limitValue = [self valueForQueryItemWithName:@"limit"]; + + NSDate *beforeDate = nil; + NSString *beforeDateValue = [self valueForQueryItemWithName:@"beforeDate"]; + if (beforeDateValue) { + beforeDate = [beforeDateValue ISO8601Date]; + if (!beforeDate) { + response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"Unable to decode ISO8601 beforeDate value"]; + break; + } + } + + NSString *beforeMessageGUID = [self valueForQueryItemWithName:@"beforeMessageGUID"]; + if (!guid) { - MBIMLogInfo(@"No query item provided"); - response = [[HTTPErrorResponse alloc] initWithErrorCode:500]; + response = [[MBIMErrorResponse alloc] initWithErrorCode:500 message:@"No GUID provided."]; break; } @@ -41,12 +59,33 @@ response = [[HTTPErrorResponse alloc] initWithErrorCode:500]; } else { // Load messages - [chat loadMessagesBeforeDate:[NSDate date] limit:50 loadImmediately:YES]; - - [[chat chatItems] enumerateMessagesWithOptions:0 usingBlock:^(IMMessage *message, BOOL *stop) { - NSDictionary *messageDict = [message mbim_dictionaryRepresentation]; - [messages addObject:messageDict]; - }]; + // (Must be done on main queue for some reason) + dispatch_sync(dispatch_get_main_queue(), ^{ + NSUInteger limit = kDefaultMessagesLimit; + if (limitValue) { + limit = [limitValue integerValue]; + } + + if (beforeMessageGUID) { + if ([chat respondsToSelector:@selector(loadMessagesBeforeAndAfterGUID:numberOfMessagesToLoadBeforeGUID:numberOfMessagesToLoadAfterGUID:loadImmediately:threadIdentifier:)]) { + [chat loadMessagesBeforeAndAfterGUID:beforeMessageGUID numberOfMessagesToLoadBeforeGUID:limit numberOfMessagesToLoadAfterGUID:0 loadImmediately:YES threadIdentifier:nil]; + } else { + [chat loadMessagesBeforeAndAfterGUID:beforeMessageGUID numberOfMessagesToLoadBeforeGUID:limit numberOfMessagesToLoadAfterGUID:0 loadImmediately:YES]; + } + } else { + [chat loadMessagesBeforeDate:beforeDate limit:limit loadImmediately:YES]; + } + + [[chat chatItems] enumerateMessagesWithOptions:0 usingBlock:^(IMMessage *message, BOOL *stop) { + if ([[message guid] isEqual:beforeMessageGUID]) { + *stop = YES; + return; + } + + NSDictionary *messageDict = [message mbim_dictionaryRepresentation]; + [messages addObject:messageDict]; + }]; + }); } }); diff --git a/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.h b/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.h new file mode 100644 index 0000000..6893d37 --- /dev/null +++ b/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.h @@ -0,0 +1,18 @@ +// +// MBIMErrorResponse.h +// kordophoned +// +// Created by James Magahern on 8/3/22. +// Copyright © 2022 James Magahern. All rights reserved. +// + +#import "HTTPDataResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MBIMErrorResponse : HTTPDataResponse +- (instancetype)initWithErrorCode:(int)httpErrorCode; +- (instancetype)initWithErrorCode:(int)httpErrorCode message:(NSString *)message; +@end + +NS_ASSUME_NONNULL_END diff --git a/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.m b/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.m new file mode 100644 index 0000000..92424a0 --- /dev/null +++ b/kordophone/Bridge/Operations/Utilities/MBIMErrorResponse.m @@ -0,0 +1,38 @@ +// +// MBIMErrorResponse.m +// kordophoned +// +// Created by James Magahern on 8/3/22. +// Copyright © 2022 James Magahern. All rights reserved. +// + +#import "MBIMErrorResponse.h" + +@implementation MBIMErrorResponse { + int _status; +} + +- (instancetype)initWithErrorCode:(int)httpErrorCode +{ + if (self = [super initWithData:nil]) { + _status = httpErrorCode; + } + + return self; +} + +- (instancetype)initWithErrorCode:(int)httpErrorCode message:(NSString *)message +{ + if (self = [super initWithData:[message dataUsingEncoding:NSUTF8StringEncoding]]) { + _status = httpErrorCode; + } + + return self; +} + +- (NSInteger)status +{ + return _status; +} + +@end diff --git a/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.h b/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.h index 7ffc249..de6b8a1 100644 --- a/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.h +++ b/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.h @@ -10,3 +10,13 @@ NSString* MBIMWebServerFormatRFC822(NSDate *date); NSString* MBIMWebServerFormatISO8601(NSDate *date); + +@interface NSDate (MBIMWebServerFormat) +- (NSString *)RFC822StringValue; +- (NSString *)ISO8601StringValue; +@end + +@interface NSString (MBIMWebServerFormat) +- (NSDate *)RFC822Date; +- (NSDate *)ISO8601Date; +@end diff --git a/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.m b/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.m index 00e0663..58e4174 100644 --- a/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.m +++ b/kordophone/Bridge/Operations/Utilities/MBIMHTTPUtilities.m @@ -47,3 +47,31 @@ NSString* MBIMWebServerFormatISO8601(NSDate *date) return string; } + +@implementation NSDate (MBIMWebServerFormat) + +- (NSString *)RFC822StringValue +{ + return MBIMWebServerFormatRFC822(self); +} + +- (NSString *)ISO8601StringValue +{ + return MBIMWebServerFormatISO8601(self); +} + +@end + +@implementation NSString (MBIMWebServerFormat) + +- (NSDate *)RFC822Date +{ + return [_dateFormatterRFC822 dateFromString:self]; +} + +- (NSDate *)ISO8601Date +{ + return [_dateFormatterISO8601 dateFromString:self]; +} + +@end diff --git a/kordophone/kordophoned-Entitlements.plist b/kordophone/kordophoned-Entitlements.plist new file mode 100644 index 0000000..e519577 --- /dev/null +++ b/kordophone/kordophoned-Entitlements.plist @@ -0,0 +1,16 @@ + + + + + com.apple.imagent + + com.apple.private.imagent + + com.apple.private.imcore.imagent + + com.apple.imagent.av + + com.apple.imagent.chat + + +