diff --git a/Extensions/XMPPMUCLight/XMPPRoomLight.h b/Extensions/XMPPMUCLight/XMPPRoomLight.h index 95229d6685..bc763b9150 100644 --- a/Extensions/XMPPMUCLight/XMPPRoomLight.h +++ b/Extensions/XMPPMUCLight/XMPPRoomLight.h @@ -22,6 +22,7 @@ @property (readonly, nonatomic, strong, nonnull) XMPPJID *roomJID; @property (readonly, nonatomic, strong, nonnull) NSString *domain; @property (nonatomic, assign) BOOL shouldStoreAffiliationChangeMessages; +@property (assign) BOOL shouldHandleMemberMessagesWithoutBody; - (nonnull NSString *)roomname; - (nonnull NSString *)subject; diff --git a/Extensions/XMPPMUCLight/XMPPRoomLight.m b/Extensions/XMPPMUCLight/XMPPRoomLight.m index c12f527380..ab9183bf4d 100644 --- a/Extensions/XMPPMUCLight/XMPPRoomLight.m +++ b/Extensions/XMPPMUCLight/XMPPRoomLight.m @@ -15,6 +15,7 @@ @interface XMPPRoomLight() { BOOL shouldStoreAffiliationChangeMessages; + BOOL shouldHandleMemberMessagesWithoutBody; NSString *roomname; NSString *subject; NSArray *knownMembersList; @@ -105,6 +106,33 @@ - (void)setShouldStoreAffiliationChangeMessages:(BOOL)newValue dispatch_async(moduleQueue, block); } +- (BOOL)shouldHandleMemberMessagesWithoutBody +{ + __block BOOL result; + dispatch_block_t block = ^{ @autoreleasepool { + result = shouldHandleMemberMessagesWithoutBody; + }}; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_sync(moduleQueue, block); + + return result; +} + +- (void)setShouldHandleMemberMessagesWithoutBody:(BOOL)newValue +{ + dispatch_block_t block = ^{ @autoreleasepool { + shouldHandleMemberMessagesWithoutBody = newValue; + }}; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + - (nonnull NSString *)roomname { @synchronized(roomname) { return [roomname copy]; @@ -668,9 +696,9 @@ - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message // Is this a message we need to store (a chat message)? // // We store messages that from is full room-id@domain/user-who-sends-message - // and that have something in the body + // and that have something in the body (unless empty messages are allowed) - if ([from isFull] && [message isGroupChatMessageWithBody]) { + if ([from isFull] && [message isGroupChatMessage] && (self.shouldHandleMemberMessagesWithoutBody || [message isMessageWithBody])) { [xmppRoomLightStorage handleIncomingMessage:message room:self]; [multicastDelegate xmppRoomLight:self didReceiveMessage:message]; }else if(destroyRoom){ @@ -700,7 +728,7 @@ - (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message // A message to all recipients MUST be of type groupchat. // A message to an individual recipient would have a . - if ([message isGroupChatMessageWithBody]){ + if ([message isGroupChatMessage] && (self.shouldHandleMemberMessagesWithoutBody || [message isMessageWithBody])) { [xmppRoomLightStorage handleOutgoingMessage:message room:self]; } } diff --git a/Xcode/Testing-Shared/XMPPRoomLightCoreDataStorageTests.m b/Xcode/Testing-Shared/XMPPRoomLightCoreDataStorageTests.m index d686085465..14bca99631 100644 --- a/Xcode/Testing-Shared/XMPPRoomLightCoreDataStorageTests.m +++ b/Xcode/Testing-Shared/XMPPRoomLightCoreDataStorageTests.m @@ -31,7 +31,7 @@ - (void)testReceiveMessageWithoutStorage{ [roomLight addDelegate:self delegateQueue:dispatch_get_main_queue()]; [roomLight activate:streamTest]; - [streamTest fakeMessageResponse:[self fakeIncomingMessage]]; + [streamTest fakeMessageResponse:[self fakeIncomingMessageWithBody:YES]]; [self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) { if(error){ XCTFail(@"Expectation Failed with error: %@", error); @@ -53,7 +53,7 @@ - (void)testReceiveMessageWithStorage{ [roomLight addDelegate:self delegateQueue:dispatch_get_main_queue()]; [roomLight activate:streamTest]; - [streamTest fakeMessageResponse:[self fakeIncomingMessage]]; + [streamTest fakeMessageResponse:[self fakeIncomingMessageWithBody:YES]]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSManagedObjectContext *context = [storage mainThreadManagedObjectContext]; @@ -135,6 +135,52 @@ - (void)testReceiveAffiliationMessageWithStorage { }]; } +- (void)testReceiveMessageWithoutBody { + self.checkDelegate = false; + + XCTestExpectation *expectation = [self expectationWithDescription:@"receive message without body and correctly stored"]; + + XMPPRoomLightCoreDataStorage *storage = [[XMPPRoomLightCoreDataStorage alloc] initWithDatabaseFilename:@"testReceiveMessageWithoutBody.sqlite" + storeOptions:nil]; + storage.autoRemovePreviousDatabaseFile = YES; + + XMPPMockStream *streamTest = [[XMPPMockStream alloc] init]; + streamTest.myJID = [XMPPJID jidWithString:@"myUser@domain.com"]; + XMPPJID *jid = [XMPPJID jidWithString:@"room@domain.com"]; + XMPPRoomLight *roomLight = [[XMPPRoomLight alloc] initWithRoomLightStorage:storage jid:jid roomname:@"test" dispatchQueue:nil]; + roomLight.shouldHandleMemberMessagesWithoutBody = YES; + [roomLight activate:streamTest]; + + [streamTest fakeMessageResponse:[self fakeIncomingMessageWithBody:NO]]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NSManagedObjectContext *context = [storage mainThreadManagedObjectContext]; + NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPRoomLightMessageCoreDataStorageObject" + inManagedObjectContext:context]; + + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"roomJIDStr = %@", jid.full]; + + NSFetchRequest *request = [[NSFetchRequest alloc] init]; + request.entity = entity; + request.predicate = predicate; + + NSError *error; + XMPPRoomLightMessageCoreDataStorageObject *roomMessage = [[context executeFetchRequest:request error:&error] firstObject]; + XCTAssertNil(error); + XCTAssertEqualObjects(roomMessage.jid.full, @"room@domain.com/test.user@erlang-solutions.com"); + XCTAssertNil(roomMessage.body); + XCTAssertEqualObjects(roomMessage.nickname, @"test.user@erlang-solutions.com"); + + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:3 handler:^(NSError * _Nullable error) { + if(error){ + XCTFail(@"Expectation Failed with error: %@", error); + } + }]; +} + - (void)testImportMessage { self.checkDelegate = false; @@ -148,7 +194,10 @@ - (void)testImportMessage { XMPPJID *jid = [XMPPJID jidWithString:@"room@domain.com"]; XMPPRoomLight *roomLight = [[XMPPRoomLight alloc] initWithRoomLightStorage:storage jid:jid roomname:@"test" dispatchQueue:nil]; - [storage importRemoteArchiveMessage:[self fakeIncomingMessage] withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] inRoom:roomLight fromStream:streamTest]; + [storage importRemoteArchiveMessage:[self fakeIncomingMessageWithBody:YES] + withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] + inRoom:roomLight + fromStream:streamTest]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSManagedObjectContext *context = [storage mainThreadManagedObjectContext]; @@ -194,8 +243,14 @@ - (void)testImportMessageUniquing { XMPPJID *jid = [XMPPJID jidWithString:@"room@domain.com"]; XMPPRoomLight *roomLight = [[XMPPRoomLight alloc] initWithRoomLightStorage:storage jid:jid roomname:@"test" dispatchQueue:nil]; - [storage importRemoteArchiveMessage:[self fakeIncomingMessage] withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] inRoom:roomLight fromStream:streamTest]; - [storage importRemoteArchiveMessage:[self fakeIncomingMessage] withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] inRoom:roomLight fromStream:streamTest]; + [storage importRemoteArchiveMessage:[self fakeIncomingMessageWithBody:YES] + withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] + inRoom:roomLight + fromStream:streamTest]; + [storage importRemoteArchiveMessage:[self fakeIncomingMessageWithBody:YES] + withTimestamp:[NSDate dateWithTimeIntervalSinceReferenceDate:0] + inRoom:roomLight + fromStream:streamTest]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSManagedObjectContext *context = [storage mainThreadManagedObjectContext]; @@ -231,14 +286,16 @@ - (void)xmppRoomLight:(XMPPRoomLight *)sender didReceiveMessage:(XMPPMessage *)m } } -- (XMPPMessage *)fakeIncomingMessage{ +- (XMPPMessage *)fakeIncomingMessageWithBody:(BOOL)shouldIncludeBody { NSMutableString *s = [NSMutableString string]; [s appendString: @""]; - [s appendString: @" Yo! 13'"]; + if (shouldIncludeBody) { + [s appendString: @"Yo! 13'"]; + } [s appendString: @""]; NSError *error;