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;