MessageDecoder.m 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. // _____ _
  2. // |_ _| |_ _ _ ___ ___ _ __ __ _
  3. // | | | ' \| '_/ -_) -_) ' \/ _` |_
  4. // |_| |_||_|_| \___\___|_|_|_\__,_(_)
  5. //
  6. // Threema iOS Client
  7. // Copyright (c) 2012-2020 Threema GmbH
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU Affero General Public License, version 3,
  11. // as published by the Free Software Foundation.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU Affero General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Affero General Public License
  19. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. #import "MessageDecoder.h"
  21. #import "NaClCrypto.h"
  22. #import "ContactStore.h"
  23. #import "MyIdentityStore.h"
  24. #import "BoxedMessage.h"
  25. #import "ProtocolDefines.h"
  26. #import "BoxTextMessage.h"
  27. #import "BoxImageMessage.h"
  28. #import "BoxVideoMessage.h"
  29. #import "BoxLocationMessage.h"
  30. #import "BoxAudioMessage.h"
  31. #import "DeliveryReceiptMessage.h"
  32. #import "TypingIndicatorMessage.h"
  33. #import "GroupCreateMessage.h"
  34. #import "GroupRenameMessage.h"
  35. #import "GroupLeaveMessage.h"
  36. #import "GroupTextMessage.h"
  37. #import "GroupLocationMessage.h"
  38. #import "GroupImageMessage.h"
  39. #import "GroupVideoMessage.h"
  40. #import "GroupAudioMessage.h"
  41. #import "GroupSetPhotoMessage.h"
  42. #import "GroupRequestSyncMessage.h"
  43. #import "UnknownTypeMessage.h"
  44. #import "BoxBallotCreateMessage.h"
  45. #import "BoxBallotVoteMessage.h"
  46. #import "GroupBallotCreateMessage.h"
  47. #import "GroupBallotVoteMessage.h"
  48. #import "BoxFileMessage.h"
  49. #import "GroupFileMessage.h"
  50. #import "ContactSetPhotoMessage.h"
  51. #import "ContactDeletePhotoMessage.h"
  52. #import "ContactRequestPhotoMessage.h"
  53. #import "BoxVoIPCallOfferMessage.h"
  54. #import "BoxVoIPCallAnswerMessage.h"
  55. #import "BoxVoIPCallIceCandidatesMessage.h"
  56. #import "BoxVoIPCallHangupMessage.h"
  57. #import "BoxVoIPCallRingingMessage.h"
  58. #import "ValidationLogger.h"
  59. #import "GroupDeletePhotoMessage.h"
  60. #import "QuoteParser.h"
  61. #ifdef DEBUG
  62. static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
  63. #else
  64. static const DDLogLevel ddLogLevel = DDLogLevelWarning;
  65. #endif
  66. @implementation MessageDecoder
  67. + (void)decodeFromBoxed:(BoxedMessage*)boxmsg isIncomming:(BOOL)isIncomming onCompletion:(void(^)(AbstractMessage *msg))onCompletion onError:(void(^)(NSError *err))onError {
  68. /* obtain sender's key, via API if necessary */
  69. [[ContactStore sharedContactStore] fetchPublicKeyForIdentity:boxmsg.fromIdentity onCompletion:^(NSData *publicKey) {
  70. AbstractMessage *msg = [MessageDecoder decodeFromBoxed:boxmsg isIncomming:isIncomming withPublicKey:publicKey];
  71. onCompletion(msg);
  72. } onError:^(NSError *error) {
  73. [[ValidationLogger sharedValidationLogger] logBoxedMessage:boxmsg isIncoming:isIncomming description:@"PublicKey from Threema-ID not found"];
  74. onError(error);
  75. }];
  76. }
  77. + (AbstractMessage*)decodeFromBoxed:(BoxedMessage*)boxmsg isIncomming:(BOOL)isIncomming withPublicKey:(NSData*)publicKey {
  78. if (![boxmsg.toIdentity isEqualToString:[MyIdentityStore sharedMyIdentityStore].identity]) {
  79. DDLogError(@"Message is not for my identity - cannot decode");
  80. [[ValidationLogger sharedValidationLogger] logBoxedMessage:boxmsg isIncoming:isIncomming description:@"Message is not for my identity - cannot decode"];
  81. return nil;
  82. }
  83. /* decrypt with our secret key */
  84. NSData *data = [[MyIdentityStore sharedMyIdentityStore] decryptData:boxmsg.box withNonce:boxmsg.nonce publicKey:publicKey];
  85. if (data == nil) {
  86. DDLogError(@"Decryption of message from %@ failed", boxmsg.fromIdentity);
  87. [[ValidationLogger sharedValidationLogger] logBoxedMessage:boxmsg isIncoming:isIncomming description:@"Decryption of message failed"];
  88. return nil;
  89. }
  90. if (data.length < 1) {
  91. DDLogError(@"Empty message received");
  92. [[ValidationLogger sharedValidationLogger] logBoxedMessage:boxmsg isIncoming:isIncomming description:@"Empty message received"];
  93. return nil;
  94. }
  95. /* remove padding */
  96. uint8_t padbytes = *((uint8_t*)data.bytes + data.length - 1);
  97. int realDataLength = (int)data.length - padbytes;
  98. if (realDataLength < 1) {
  99. DDLogError(@"Bad message padding");
  100. [[ValidationLogger sharedValidationLogger] logBoxedMessage:boxmsg isIncoming:isIncomming description:@"Bad message padding"];
  101. return nil;
  102. }
  103. DDLogVerbose(@"Effective data length is %d", realDataLength);
  104. uint8_t *type = (uint8_t*)data.bytes;
  105. AbstractMessage *msg = [MessageDecoder messageFromType: type data: data realDataLength: realDataLength fromIdentity: boxmsg.fromIdentity];
  106. if (msg != nil) {
  107. /* copy header attributes from boxed message */
  108. msg.fromIdentity = boxmsg.fromIdentity;
  109. msg.toIdentity = boxmsg.toIdentity;
  110. msg.messageId = boxmsg.messageId;
  111. msg.pushFromName = boxmsg.pushFromName;
  112. msg.date = boxmsg.date;
  113. msg.delivered = boxmsg.delivered;
  114. msg.deliveryDate = boxmsg.deliveryDate;
  115. msg.userAck = boxmsg.userAck;
  116. msg.sendUserAck = boxmsg.sendUserAck;
  117. msg.nonce = boxmsg.nonce;
  118. msg.flags = @(boxmsg.flags);
  119. }
  120. return msg;
  121. }
  122. + (AbstractMessage*)messageFromType:(uint8_t*)type data:(NSData *) data realDataLength: (int) realDataLength fromIdentity: (NSString*) fromIdentity{
  123. /* first byte of data is type */
  124. AbstractMessage *msg = nil;
  125. switch (*type) {
  126. case MSGTYPE_TEXT: {
  127. if (realDataLength < 1) {
  128. DDLogWarn(@"Wrong length %d for text message", realDataLength);
  129. break;
  130. }
  131. BoxTextMessage *textmsg = [[BoxTextMessage alloc] init];
  132. textmsg.text = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1) length:(realDataLength - 1)] encoding:NSUTF8StringEncoding];
  133. NSString *remainingBody = nil;
  134. NSData *quotedMessageId = [QuoteParser parseQuoteV2FromMessage:textmsg.text remainingBody:&remainingBody];
  135. if (quotedMessageId != nil) {
  136. textmsg.text = remainingBody;
  137. textmsg.quotedMessageId = quotedMessageId;
  138. }
  139. msg = textmsg;
  140. break;
  141. }
  142. case MSGTYPE_IMAGE: {
  143. if (realDataLength != (1 + kBlobIdLen + sizeof(uint32_t) + kNonceLen)) {
  144. DDLogWarn(@"Wrong length %d for image message", realDataLength);
  145. break;
  146. }
  147. BoxImageMessage *imgmsg = [[BoxImageMessage alloc] init];
  148. imgmsg.blobId = [NSData dataWithBytes:(data.bytes + 1) length:kBlobIdLen];
  149. imgmsg.size = *((uint32_t*)(data.bytes + 1 + kBlobIdLen));
  150. imgmsg.imageNonce = [NSData dataWithBytes:(data.bytes + 1 + kBlobIdLen + sizeof(uint32_t)) length:kNonceLen];
  151. msg = imgmsg;
  152. break;
  153. }
  154. case MSGTYPE_VIDEO: {
  155. if (realDataLength != (1 + sizeof(uint16_t) + 2*(kBlobIdLen + sizeof(uint32_t)) + kBlobKeyLen)) {
  156. DDLogWarn(@"Wrong length %d for video message", realDataLength);
  157. break;
  158. }
  159. BoxVideoMessage *videomsg = [[BoxVideoMessage alloc] init];
  160. int i = 1;
  161. videomsg.duration = *((uint16_t*)(data.bytes + i)); i += sizeof(uint16_t);
  162. videomsg.videoBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  163. videomsg.videoSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  164. videomsg.thumbnailBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  165. videomsg.thumbnailSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  166. videomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  167. msg = videomsg;
  168. break;
  169. }
  170. case MSGTYPE_LOCATION: {
  171. if (realDataLength < 4) {
  172. DDLogWarn(@"Wrong length %d for location message", realDataLength);
  173. break;
  174. }
  175. NSString *coordinateStr = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1) length:(realDataLength - 1)] encoding:NSUTF8StringEncoding];
  176. if (coordinateStr == nil) {
  177. DDLogWarn(@"Bad coordinate string");
  178. break;
  179. }
  180. NSArray *lines = [coordinateStr componentsSeparatedByString:@"\n"];
  181. if (lines.count < 1) {
  182. DDLogWarn(@"Bad coordinate string");
  183. break;
  184. }
  185. NSArray *components = [lines[0] componentsSeparatedByString:@","];
  186. if (components.count < 2 || components.count > 3) {
  187. DDLogWarn(@"Bad coordinate format in location message");
  188. break;
  189. }
  190. BoxLocationMessage *locationmsg = [[BoxLocationMessage alloc] init];
  191. locationmsg.latitude = [components[0] doubleValue];
  192. locationmsg.longitude = [components[1] doubleValue];
  193. if (components.count == 3)
  194. locationmsg.accuracy = [components[2] doubleValue];
  195. else
  196. locationmsg.accuracy = 0;
  197. if (lines.count >= 2) {
  198. locationmsg.poiName = lines[1];
  199. if (lines.count >= 3)
  200. locationmsg.poiAddress = [lines[2] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];
  201. }
  202. if (locationmsg.latitude < -90.0 || locationmsg.latitude > 90.0 || locationmsg.longitude < -180.0 || locationmsg.longitude > 180.0) {
  203. DDLogWarn(@"Invalid coordinate values in location message");
  204. break;
  205. }
  206. msg = locationmsg;
  207. break;
  208. }
  209. case MSGTYPE_AUDIO: {
  210. if (realDataLength != (1 + sizeof(uint16_t) + kBlobIdLen + sizeof(uint32_t)) + kBlobKeyLen) {
  211. DDLogWarn(@"Wrong length %d for audio message", realDataLength);
  212. break;
  213. }
  214. BoxAudioMessage *audiomsg = [[BoxAudioMessage alloc] init];
  215. int i = 1;
  216. audiomsg.duration = *((uint16_t*)(data.bytes + i)); i += sizeof(uint16_t);
  217. audiomsg.audioBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  218. audiomsg.audioSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  219. audiomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  220. msg = audiomsg;
  221. break;
  222. }
  223. case MSGTYPE_DELIVERY_RECEIPT: {
  224. if (realDataLength < kMessageIdLen + 2 || ((realDataLength - 2) % kMessageIdLen) != 0) {
  225. DDLogWarn(@"Wrong length %d for delivery receipt", realDataLength);
  226. break;
  227. }
  228. DeliveryReceiptMessage *receiptmsg = [[DeliveryReceiptMessage alloc] init];
  229. receiptmsg.receiptType = *((uint8_t*)(data.bytes + 1));
  230. int numMsgIds = ((realDataLength - 2) / kMessageIdLen);
  231. NSMutableArray *receiptMessageIds = [NSMutableArray arrayWithCapacity:numMsgIds];
  232. for (int i = 0; i < numMsgIds; i++) {
  233. NSData *receiptMessageId = [NSData dataWithBytes:(data.bytes + 2 + i*kMessageIdLen) length:kMessageIdLen];
  234. [receiptMessageIds addObject:receiptMessageId];
  235. }
  236. receiptmsg.receiptMessageIds = receiptMessageIds;
  237. msg = receiptmsg;
  238. break;
  239. }
  240. case MSGTYPE_TYPING_INDICATOR: {
  241. if (realDataLength != 2) {
  242. DDLogWarn(@"Wrong length %d for typing indicator", realDataLength);
  243. break;
  244. }
  245. TypingIndicatorMessage *typingmsg = [[TypingIndicatorMessage alloc] init];
  246. typingmsg.typing = *((uint8_t*)(data.bytes + 1)) ? YES : NO;
  247. msg = typingmsg;
  248. break;
  249. }
  250. case MSGTYPE_GROUP_CREATE: {
  251. if (realDataLength < (1 + kGroupIdLen) || ((realDataLength - 1 - kGroupIdLen) % kIdentityLen) != 0) {
  252. DDLogWarn(@"Wrong length %d for group create message", realDataLength);
  253. break;
  254. }
  255. GroupCreateMessage *groupcreatemsg = [[GroupCreateMessage alloc] init];
  256. groupcreatemsg.groupId = [NSData dataWithBytes:(data.bytes + 1) length:kGroupIdLen];
  257. int numMembers = ((realDataLength - kGroupIdLen - 1) / kIdentityLen);
  258. NSMutableArray *groupMembers = [NSMutableArray arrayWithCapacity:numMembers];
  259. for (int i = 0; i < numMembers; i++) {
  260. NSString *member = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1 + kGroupIdLen + i*kIdentityLen) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  261. if (member == nil) {
  262. DDLogWarn(@"Invalid group member ID");
  263. groupMembers = nil;
  264. break;
  265. }
  266. [groupMembers addObject:member];
  267. }
  268. if (groupMembers == nil)
  269. break;
  270. groupcreatemsg.groupMembers = groupMembers;
  271. groupcreatemsg.groupCreator = fromIdentity;
  272. msg = groupcreatemsg;
  273. break;
  274. }
  275. case MSGTYPE_GROUP_RENAME: {
  276. if (realDataLength < (1 + kGroupIdLen)) {
  277. DDLogWarn(@"Wrong length %d for group rename message", realDataLength);
  278. break;
  279. }
  280. GroupRenameMessage *renamemsg = [[GroupRenameMessage alloc] init];
  281. renamemsg.groupId = [NSData dataWithBytes:(data.bytes + 1) length:kGroupIdLen];
  282. renamemsg.name = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1 + kGroupIdLen) length:(realDataLength - 1 - kGroupIdLen)] encoding:NSUTF8StringEncoding];
  283. renamemsg.groupCreator = fromIdentity;
  284. msg = renamemsg;
  285. break;
  286. }
  287. case MSGTYPE_GROUP_LEAVE: {
  288. if (realDataLength != (1 + kIdentityLen + kGroupIdLen)) {
  289. DDLogWarn(@"Wrong length %d for group leave message", realDataLength);
  290. break;
  291. }
  292. GroupLeaveMessage *groupleavemsg = [[GroupLeaveMessage alloc] init];
  293. groupleavemsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  294. groupleavemsg.groupId = [NSData dataWithBytes:(data.bytes + 1 + kIdentityLen) length:kGroupIdLen];
  295. msg = groupleavemsg;
  296. break;
  297. }
  298. case MSGTYPE_GROUP_TEXT: {
  299. if (realDataLength < (1 + kIdentityLen + kGroupIdLen)) {
  300. DDLogWarn(@"Wrong length %d for group text message", realDataLength);
  301. break;
  302. }
  303. GroupTextMessage *textmsg = [[GroupTextMessage alloc] init];
  304. textmsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  305. textmsg.groupId = [NSData dataWithBytes:(data.bytes + 1 + kIdentityLen) length:kGroupIdLen];
  306. textmsg.text = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1 + kIdentityLen + kGroupIdLen) length:(realDataLength - 1 - kIdentityLen - kGroupIdLen)] encoding:NSUTF8StringEncoding];
  307. NSString *remainingBody = nil;
  308. NSData *quotedMessageId = [QuoteParser parseQuoteV2FromMessage:textmsg.text remainingBody:&remainingBody];
  309. if (quotedMessageId != nil) {
  310. textmsg.text = remainingBody;
  311. textmsg.quotedMessageId = quotedMessageId;
  312. }
  313. msg = textmsg;
  314. break;
  315. }
  316. case MSGTYPE_GROUP_LOCATION: {
  317. if (realDataLength < (kIdentityLen + kGroupIdLen + 4)) {
  318. DDLogWarn(@"Wrong length %d for group location message", realDataLength);
  319. break;
  320. }
  321. GroupLocationMessage *locationmsg = [[GroupLocationMessage alloc] init];
  322. locationmsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  323. locationmsg.groupId = [NSData dataWithBytes:(data.bytes + 1 + kIdentityLen) length:kGroupIdLen];
  324. NSString *coordinateStr = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + 1 + kIdentityLen + kGroupIdLen) length:(realDataLength - 1 - kIdentityLen - kGroupIdLen)] encoding:NSUTF8StringEncoding];
  325. if (coordinateStr == nil) {
  326. DDLogWarn(@"Bad coordinate string");
  327. break;
  328. }
  329. NSArray *lines = [coordinateStr componentsSeparatedByString:@"\n"];
  330. if (lines.count < 1) {
  331. DDLogWarn(@"Bad coordinate string");
  332. break;
  333. }
  334. NSArray *components = [lines[0] componentsSeparatedByString:@","];
  335. if (components.count < 2 || components.count > 3) {
  336. DDLogWarn(@"Bad coordinate format in location message");
  337. break;
  338. }
  339. locationmsg.latitude = [components[0] doubleValue];
  340. locationmsg.longitude = [components[1] doubleValue];
  341. if (components.count == 3)
  342. locationmsg.accuracy = [components[2] doubleValue];
  343. else
  344. locationmsg.accuracy = 0;
  345. if (lines.count >= 2) {
  346. locationmsg.poiName = lines[1];
  347. if (lines.count >= 3)
  348. locationmsg.poiAddress = [lines[2] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];
  349. }
  350. if (locationmsg.latitude < -90.0 || locationmsg.latitude > 90.0 || locationmsg.longitude < -180.0 || locationmsg.longitude > 180.0) {
  351. DDLogWarn(@"Invalid coordinate values in location message");
  352. break;
  353. }
  354. msg = locationmsg;
  355. break;
  356. }
  357. case MSGTYPE_GROUP_IMAGE: {
  358. if (realDataLength != (1 + kIdentityLen + kGroupIdLen + kBlobIdLen + sizeof(uint32_t) + kBlobKeyLen)) {
  359. DDLogWarn(@"Wrong length %d for group image message", realDataLength);
  360. break;
  361. }
  362. GroupImageMessage *imagemsg = [[GroupImageMessage alloc] init];
  363. int i = 1;
  364. imagemsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding]; i += kIdentityLen;
  365. imagemsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen]; i+= kGroupIdLen;
  366. imagemsg.blobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  367. imagemsg.size = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  368. imagemsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  369. msg = imagemsg;
  370. break;
  371. }
  372. case MSGTYPE_GROUP_VIDEO: {
  373. if (realDataLength != (1 + kIdentityLen + kGroupIdLen + sizeof(uint16_t) + 2*(kBlobIdLen + sizeof(uint32_t)) + kBlobKeyLen)) {
  374. DDLogWarn(@"Wrong length %d for group video message", realDataLength);
  375. break;
  376. }
  377. GroupVideoMessage *videomsg = [[GroupVideoMessage alloc] init];
  378. int i = 1;
  379. videomsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding]; i += kIdentityLen;
  380. videomsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen]; i+= kGroupIdLen;
  381. videomsg.duration = *((uint16_t*)(data.bytes + i)); i += sizeof(uint16_t);
  382. videomsg.videoBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  383. videomsg.videoSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  384. videomsg.thumbnailBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  385. videomsg.thumbnailSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  386. videomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  387. msg = videomsg;
  388. break;
  389. }
  390. case MSGTYPE_GROUP_AUDIO: {
  391. if (realDataLength != (1 + kIdentityLen + kGroupIdLen + sizeof(uint16_t) + kBlobIdLen + sizeof(uint32_t)) + kBlobKeyLen) {
  392. DDLogWarn(@"Wrong length %d for group audio message", realDataLength);
  393. break;
  394. }
  395. GroupAudioMessage *audiomsg = [[GroupAudioMessage alloc] init];
  396. int i = 1;
  397. audiomsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding]; i += kIdentityLen;
  398. audiomsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen]; i+= kGroupIdLen;
  399. audiomsg.duration = *((uint16_t*)(data.bytes + i)); i += sizeof(uint16_t);
  400. audiomsg.audioBlobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  401. audiomsg.audioSize = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  402. audiomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  403. msg = audiomsg;
  404. break;
  405. }
  406. case MSGTYPE_GROUP_SET_PHOTO: {
  407. if (realDataLength != (1 + kGroupIdLen + kBlobIdLen + sizeof(uint32_t) + kBlobKeyLen)) {
  408. DDLogWarn(@"Wrong length %d for group set photo message", realDataLength);
  409. break;
  410. }
  411. GroupSetPhotoMessage *setphotomsg = [[GroupSetPhotoMessage alloc] init];
  412. int i = 1;
  413. setphotomsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen]; i+= kGroupIdLen;
  414. setphotomsg.blobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  415. setphotomsg.size = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  416. setphotomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  417. setphotomsg.groupCreator = fromIdentity;
  418. msg = setphotomsg;
  419. break;
  420. }
  421. case MSGTYPE_GROUP_REQUEST_SYNC: {
  422. if (realDataLength != (1 + kGroupIdLen)) {
  423. DDLogWarn(@"Wrong length %d for group request sync message", realDataLength);
  424. break;
  425. }
  426. GroupRequestSyncMessage *groupsyncmsg = [[GroupRequestSyncMessage alloc] init];
  427. groupsyncmsg.groupId = [NSData dataWithBytes:(data.bytes + 1) length:kGroupIdLen];
  428. msg = groupsyncmsg;
  429. break;
  430. }
  431. case MSGTYPE_BALLOT_CREATE: {
  432. if (realDataLength < (1 + kBallotIdLen)) {
  433. DDLogWarn(@"Wrong length %d for ballot create message", realDataLength);
  434. break;
  435. }
  436. int i = 1;
  437. BoxBallotCreateMessage *ballotCreateMsg = [[BoxBallotCreateMessage alloc] init];
  438. ballotCreateMsg.ballotId = [NSData dataWithBytes:(data.bytes + i) length:kBallotIdLen];
  439. i+= kBallotIdLen;
  440. ballotCreateMsg.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  441. msg = ballotCreateMsg;
  442. break;
  443. }
  444. case MSGTYPE_BALLOT_VOTE: {
  445. if (realDataLength < (1 + kIdentityLen + kIdentityLen + kBallotIdLen)) {
  446. DDLogWarn(@"Wrong length %d for ballot vote message", realDataLength);
  447. break;
  448. }
  449. int i = 1;
  450. BoxBallotVoteMessage *ballotVoteMsg = [[BoxBallotVoteMessage alloc] init];
  451. ballotVoteMsg.ballotCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  452. i+= kIdentityLen;
  453. ballotVoteMsg.ballotId = [NSData dataWithBytes:(data.bytes + i) length:kBallotIdLen];
  454. i+= kBallotIdLen;
  455. ballotVoteMsg.jsonChoiceData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  456. msg = ballotVoteMsg;
  457. break;
  458. }
  459. case MSGTYPE_GROUP_BALLOT_CREATE: {
  460. if (realDataLength < (1 + kIdentityLen + kGroupIdLen + kBallotIdLen)) {
  461. DDLogWarn(@"Wrong length %d for group ballot create message", realDataLength);
  462. break;
  463. }
  464. int i = 1;
  465. GroupBallotCreateMessage *ballotCreateMsg = [[GroupBallotCreateMessage alloc] init];
  466. ballotCreateMsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  467. i+= kIdentityLen;
  468. ballotCreateMsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen];
  469. i+= kGroupIdLen;
  470. ballotCreateMsg.ballotId = [NSData dataWithBytes:(data.bytes + i) length:kBallotIdLen];
  471. i+= kBallotIdLen;
  472. ballotCreateMsg.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  473. msg = ballotCreateMsg;
  474. break;
  475. }
  476. case MSGTYPE_GROUP_BALLOT_VOTE: {
  477. if (realDataLength < (1 + kIdentityLen + kGroupIdLen + kIdentityLen + kBallotIdLen)) {
  478. DDLogWarn(@"Wrong length %d for group ballot vote message", realDataLength);
  479. break;
  480. }
  481. int i = 1;
  482. GroupBallotVoteMessage *ballotVoteMsg = [[GroupBallotVoteMessage alloc] init];
  483. ballotVoteMsg.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  484. i+= kIdentityLen;
  485. ballotVoteMsg.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen];
  486. i+= kGroupIdLen;
  487. ballotVoteMsg.ballotCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  488. i+= kIdentityLen;
  489. ballotVoteMsg.ballotId = [NSData dataWithBytes:(data.bytes + i) length:kBallotIdLen];
  490. i+= kBallotIdLen;
  491. ballotVoteMsg.jsonChoiceData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  492. msg = ballotVoteMsg;
  493. break;
  494. }
  495. case MSGTYPE_GROUP_DELETE_PHOTO: {
  496. if (realDataLength != (1 + kGroupIdLen)) {
  497. DDLogWarn(@"Wrong length %d for group delete photo message", realDataLength);
  498. break;
  499. }
  500. GroupDeletePhotoMessage *deletephotomsg = [[GroupDeletePhotoMessage alloc] init];
  501. deletephotomsg.groupId = [NSData dataWithBytes:(data.bytes + 1) length:kGroupIdLen];
  502. deletephotomsg.groupCreator = fromIdentity;
  503. msg = deletephotomsg;
  504. break;
  505. }
  506. case MSGTYPE_FILE: {
  507. if (realDataLength < 1) {
  508. DDLogWarn(@"Wrong length %d for file message", realDataLength);
  509. break;
  510. }
  511. int i = 1;
  512. BoxFileMessage *fileMessage = [[BoxFileMessage alloc] init];
  513. fileMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  514. msg = fileMessage;
  515. break;
  516. }
  517. case MSGTYPE_GROUP_FILE: {
  518. if (realDataLength < (1 + kIdentityLen + kGroupIdLen)) {
  519. DDLogWarn(@"Wrong length %d for group file message", realDataLength);
  520. break;
  521. }
  522. int i = 1;
  523. GroupFileMessage *fileMessage = [[GroupFileMessage alloc] init];
  524. fileMessage.groupCreator = [[NSString alloc] initWithData:[NSData dataWithBytes:(data.bytes + i) length:kIdentityLen] encoding:NSASCIIStringEncoding];
  525. i+= kIdentityLen;
  526. fileMessage.groupId = [NSData dataWithBytes:(data.bytes + i) length:kGroupIdLen];
  527. i+= kGroupIdLen;
  528. fileMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  529. msg = fileMessage;
  530. break;
  531. }
  532. case MSGTYPE_CONTACT_SET_PHOTO: {
  533. if (realDataLength != (1 + kBlobIdLen + sizeof(uint32_t) + kBlobKeyLen)) {
  534. DDLogWarn(@"Wrong length %d for contact set photo message", realDataLength);
  535. break;
  536. }
  537. ContactSetPhotoMessage *setphotomsg = [[ContactSetPhotoMessage alloc] init];
  538. int i = 1;
  539. setphotomsg.blobId = [NSData dataWithBytes:(data.bytes + i) length:kBlobIdLen]; i += kBlobIdLen;
  540. setphotomsg.size = *((uint32_t*)(data.bytes + i)); i += sizeof(uint32_t);
  541. setphotomsg.encryptionKey = [NSData dataWithBytes:(data.bytes + i) length:kBlobKeyLen];
  542. msg = setphotomsg;
  543. break;
  544. }
  545. case MSGTYPE_CONTACT_DELETE_PHOTO: {
  546. if (realDataLength != 1) {
  547. DDLogWarn(@"Wrong length %d for contact delete photo message", realDataLength);
  548. break;
  549. }
  550. ContactDeletePhotoMessage *deletephotomsg = [[ContactDeletePhotoMessage alloc] init];
  551. msg = deletephotomsg;
  552. break;
  553. }
  554. case MSGTYPE_CONTACT_REQUEST_PHOTO: {
  555. if (realDataLength != 1) {
  556. DDLogWarn(@"Wrong length %d for contact request photo message", realDataLength);
  557. break;
  558. }
  559. ContactRequestPhotoMessage *deletephotomsg = [[ContactRequestPhotoMessage alloc] init];
  560. msg = deletephotomsg;
  561. break;
  562. }
  563. case MSGTYPE_VOIP_CALL_OFFER: {
  564. if (realDataLength < 1) {
  565. DDLogWarn(@"Wrong length %d for call offer message", realDataLength);
  566. break;
  567. }
  568. int i = 1;
  569. BoxVoIPCallOfferMessage *offerMessage = [[BoxVoIPCallOfferMessage alloc] init];
  570. offerMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  571. msg = offerMessage;
  572. break;
  573. }
  574. case MSGTYPE_VOIP_CALL_ANSWER: {
  575. if (realDataLength < 1) {
  576. DDLogWarn(@"Wrong length %d for call answer message", realDataLength);
  577. break;
  578. }
  579. int i = 1;
  580. BoxVoIPCallAnswerMessage *answerMessage = [[BoxVoIPCallAnswerMessage alloc] init];
  581. answerMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  582. msg = answerMessage;
  583. break;
  584. }
  585. case MSGTYPE_VOIP_CALL_ICECANDIDATE: {
  586. if (realDataLength < 1) {
  587. DDLogWarn(@"Wrong length %d for call ice candidate message", realDataLength);
  588. break;
  589. }
  590. int i = 1;
  591. BoxVoIPCallIceCandidatesMessage *iceCandidateMessage = [[BoxVoIPCallIceCandidatesMessage alloc] init];
  592. iceCandidateMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  593. msg = iceCandidateMessage;
  594. break;
  595. }
  596. case MSGTYPE_VOIP_CALL_HANGUP: {
  597. int i = 1;
  598. BoxVoIPCallHangupMessage *hangupMessage = [[BoxVoIPCallHangupMessage alloc] init];
  599. hangupMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  600. msg = hangupMessage;
  601. break;
  602. }
  603. case MSGTYPE_VOIP_CALL_RINGING: {
  604. int i = 1;
  605. BoxVoIPCallRingingMessage *ringingMessage = [[BoxVoIPCallRingingMessage alloc] init];
  606. ringingMessage.jsonData = [NSData dataWithBytes:(data.bytes + i) length:(realDataLength - i)];
  607. msg = ringingMessage;
  608. break;
  609. }
  610. default:
  611. DDLogWarn(@"Unsupported message type %d", *type);
  612. msg = [[UnknownTypeMessage alloc] init];
  613. break;
  614. }
  615. return msg;
  616. }
  617. @end