IOSAD-93 consistently using precomposedStringWithCanonicalMapping, stringWithUTF8String
5 // Created by Volker Birk on 08.07.15.
6 // Copyright (c) 2015 p≡p. All rights reserved.
9 #import "PEPInternalSession.h"
10 #import "PEPObjCAdapter.h"
11 #import "PEPObjCAdapter+Internal.h"
12 #import "PEPMessageUtil.h"
13 #import "PEPLanguage.h"
14 #import "PEPCSVScanner.h"
15 #import "NSArray+Extension.h"
16 #import "NSDictionary+Extension.h"
17 #import "PEPIdentity.h"
18 #import "PEPMessage.h"
19 #import "NSError+PEP.h"
20 #import "PEPAutoPointer.h"
21 #import "NSNumber+PEPRating.h"
22 #import "NSMutableDictionary+PEP.h"
24 @implementation PEPInternalSession
30 [PEPInternalSession setupTrustWordsDB];
33 PEP_STATUS status = init(&_session);
36 if (status != PEP_STATUS_OK) {
40 [PEPObjCAdapter bindSession:self];
47 [PEPObjCAdapter unbindSession:self];
56 - (void)configUnEncryptedSubjectEnabled:(BOOL)enabled;
58 config_unencrypted_subject(self.session, enabled);
61 #pragma mark - INTERNAL
65 [PEPObjCAdapter lockWrite];
70 [PEPObjCAdapter unlockWrite];
73 + (void)setupTrustWordsDB
75 static dispatch_once_t once;
76 dispatch_once(&once, ^{
77 [PEPObjCAdapter setupTrustWordsDB:[NSBundle bundleForClass:[self class]]];
81 #pragma mark - DEBUG UTILS
84 Saves the given message dict as a plist to the local filesystem
85 (directly under NSApplicationSupportDirectory).
86 Since the complete output file will be logged by `debugSaveToFilePath`,
87 you can get access to the files easily when it's the simulator.
89 - (void)debugOutPutMessageDict:(PEPDict * _Nonnull)src
91 NSString *from = src[kPepFrom][kPepAddress];
92 NSArray *tos = src[kPepTo];
93 NSString *to = tos[0][kPepAddress];
94 NSString *msgID = src[kPepID];
95 NSString *fileName = [NSString stringWithFormat:@"%@_from(%@)_%@",
97 [src debugSaveToFilePath:fileName];
100 #pragma mark - PEPSessionProtocol
102 void decryptMessageDictFree(message *src, message *dst, stringlist_t *extraKeys)
106 free_stringlist(extraKeys);
109 - (PEPDict * _Nullable)decryptMessageDict:(PEPMutableDict * _Nonnull)messageDict
110 flags:(PEP_decrypt_flags * _Nullable)flags
111 rating:(PEP_rating * _Nullable)rating
112 extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
113 status:(PEP_STATUS * _Nullable)status
114 error:(NSError * _Nullable * _Nullable)error
117 *rating = PEP_rating_undefined;
120 message *_src = PEP_messageDictToStruct(messageDict);
121 message *_dst = NULL;
122 stringlist_t *theKeys = NULL;
123 PEP_decrypt_flags theFlags = 0;
129 if (extraKeys && [*extraKeys count]) {
130 theKeys = PEP_arrayToStringlist(*extraKeys);
133 PEP_rating internalRating = PEP_rating_undefined;
136 PEP_STATUS theStatus = decrypt_message(_session,
148 if ([NSError setError:error fromPEPStatus:theStatus]) {
149 decryptMessageDictFree(_src, _dst, theKeys);
160 dst_ = PEP_messageDictFromStruct(_dst);
162 dst_ = PEP_messageDictFromStruct(_src);
165 if (theFlags & PEP_decrypt_flag_untrusted_server) {
166 [messageDict replaceWithMessage:_src];
170 *extraKeys = PEP_arrayFromStringlist(theKeys);
173 decryptMessageDictFree(_src, _dst, theKeys);
176 *rating = internalRating;
182 - (PEPMessage * _Nullable)decryptMessage:(PEPMessage * _Nonnull)message
183 flags:(PEP_decrypt_flags * _Nullable)flags
184 rating:(PEP_rating * _Nullable)rating
185 extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
186 status:(PEP_STATUS * _Nullable)status
187 error:(NSError * _Nullable * _Nullable)error
189 PEPDict *destDict = [self
190 decryptMessageDict:message.mutableDictionary
198 PEPMessage *msg = [PEPMessage new];
199 [msg setValuesForKeysWithDictionary:destDict];
206 - (BOOL)reEvaluateMessageDict:(PEPDict * _Nonnull)messageDict
207 rating:(PEP_rating * _Nullable)rating
208 status:(PEP_STATUS * _Nullable)status
209 error:(NSError * _Nullable * _Nullable)error
211 message *_src = PEP_messageDictToStruct(messageDict);
212 PEP_rating ratingByEngine = PEP_rating_undefined;
215 PEP_STATUS theStatus = re_evaluate_message_rating(_session,
218 PEP_rating_undefined,
228 if ([NSError setError:error fromPEPStatus:theStatus]) {
232 *rating = ratingByEngine;
238 - (BOOL)reEvaluateMessage:(PEPMessage * _Nonnull)message
239 rating:(PEP_rating * _Nullable)rating
240 status:(PEP_STATUS * _Nullable)status
241 error:(NSError * _Nullable * _Nullable)error
243 return [self reEvaluateMessageDict:(PEPDict *) message
249 - (void)removeEmptyArrayKey:(NSString *)key inDict:(PEPMutableDict *)dict
251 if ([[dict objectForKey:key] count] == 0) {
252 [dict removeObjectForKey:key];
256 - (NSDictionary *)removeEmptyRecipients:(PEPDict *)src
258 NSMutableDictionary *dest = src.mutableCopy;
260 [self removeEmptyArrayKey:kPepTo inDict:dest];
261 [self removeEmptyArrayKey:kPepCC inDict:dest];
262 [self removeEmptyArrayKey:kPepBCC inDict:dest];
267 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
268 extraKeys:(PEPStringList * _Nullable)extraKeys
269 encFormat:(PEP_enc_format)encFormat
270 status:(PEP_STATUS * _Nullable)status
271 error:(NSError * _Nullable * _Nullable)error
273 PEP_encrypt_flags_t flags = 0;
275 message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
276 message *_dst = NULL;
277 stringlist_t *_keys = PEP_arrayToStringlist(extraKeys);
280 PEP_STATUS theStatus = encrypt_message(_session, _src, _keys, &_dst, encFormat, flags);
287 if ([NSError setError:error fromPEPStatus:theStatus]) {
294 dst_ = PEP_messageDictFromStruct(_dst);
297 dst_ = PEP_messageDictFromStruct(_src);
302 free_stringlist(_keys);
307 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
308 extraKeys:(PEPStringList * _Nullable)extraKeys
309 encFormat:(PEP_enc_format)encFormat
310 status:(PEP_STATUS * _Nullable)status
311 error:(NSError * _Nullable * _Nullable)error
313 PEPDict *encryptedDict = [self encryptMessageDict:(NSDictionary *) message
319 PEPMessage *encrypted = [PEPMessage new];
320 [encrypted setValuesForKeysWithDictionary:encryptedDict];
327 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
328 extraKeys:(PEPStringList * _Nullable)extraKeys
329 status:(PEP_STATUS * _Nullable)status
330 error:(NSError * _Nullable * _Nullable)error
333 encryptMessage:message
335 encFormat:PEP_enc_PEP
340 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
341 forSelf:(PEPIdentity * _Nonnull)ownIdentity
342 extraKeys:(PEPStringList * _Nullable)extraKeys
343 status:(PEP_STATUS * _Nullable)status
344 error:(NSError * _Nullable * _Nullable)error
346 PEP_encrypt_flags_t flags = 0;
348 message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
349 pEp_identity *ident = PEP_identityToStruct(ownIdentity);
350 message *_dst = NULL;
352 stringlist_t *keysStringList = PEP_arrayToStringlist(extraKeys);
355 PEP_STATUS theStatus = encrypt_message_for_self(_session,
364 free_stringlist(keysStringList);
370 if ([NSError setError:error fromPEPStatus:theStatus]) {
377 dst_ = PEP_messageDictFromStruct(_dst);
380 dst_ = PEP_messageDictFromStruct(_src);
385 free_identity(ident);
390 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
391 forSelf:(PEPIdentity * _Nonnull)ownIdentity
392 extraKeys:(PEPStringList * _Nullable)extraKeys
393 status:(PEP_STATUS * _Nullable)status
394 error:(NSError * _Nullable * _Nullable)error
396 PEPDict *target = [self
397 encryptMessageDict:message.dictionary
404 PEPMessage *encrypted = [PEPMessage new];
405 [encrypted setValuesForKeysWithDictionary:target];
413 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
414 toFpr:(NSString * _Nonnull)toFpr
415 encFormat:(PEP_enc_format)encFormat
416 flags:(PEP_decrypt_flags)flags
417 status:(PEP_STATUS * _Nullable)status
418 error:(NSError * _Nullable * _Nullable)error __deprecated
420 message *src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
424 PEP_STATUS theStatus =
425 encrypt_message_and_add_priv_key(_session, src, &dst,
426 [[toFpr precomposedStringWithCanonicalMapping] UTF8String],
434 if ([NSError setError:error fromPEPStatus:theStatus]) {
439 return PEP_messageDictFromStruct(dst);
445 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
446 toFpr:(NSString * _Nonnull)toFpr
447 encFormat:(PEP_enc_format)encFormat
448 flags:(PEP_decrypt_flags)flags
449 status:(PEP_STATUS * _Nullable)status
450 error:(NSError * _Nullable * _Nullable)error
452 PEPDict *target = [self
453 encryptMessageDict:message.dictionary
461 PEPMessage *encrypted = [PEPMessage new];
462 [encrypted setValuesForKeysWithDictionary:target];
469 - (NSNumber * _Nullable)outgoingRatingForMessageDict:(PEPDict * _Nonnull)messageDict
470 error:(NSError * _Nullable * _Nullable)error
472 message *_msg = PEP_messageDictToStruct(messageDict);
473 PEP_rating rating = PEP_rating_undefined;
476 PEP_STATUS status = outgoing_message_rating(_session, _msg, &rating);
481 if ([NSError setError:error fromPEPStatus:status]) {
485 return [NSNumber numberWithPEPRating:rating];
488 - (NSNumber * _Nullable)outgoingRatingForMessage:(PEPMessage * _Nonnull)message
489 error:(NSError * _Nullable * _Nullable)error
491 return [self outgoingRatingForMessageDict:(NSDictionary *) message error:error];
494 - (NSNumber * _Nullable)ratingForIdentity:(PEPIdentity * _Nonnull)identity
495 error:(NSError * _Nullable * _Nullable)error
497 pEp_identity *ident = PEP_identityToStruct(identity);
498 PEP_rating rating = PEP_rating_undefined;
501 PEP_STATUS status = identity_rating(_session, ident, &rating);
504 free_identity(ident);
506 if ([NSError setError:error fromPEPStatus:status]) {
510 return [NSNumber numberWithPEPRating:rating];
513 - (NSArray * _Nullable)trustwordsForFingerprint:(NSString * _Nonnull)fingerprint
514 languageID:(NSString * _Nonnull)languageID
515 shortened:(BOOL)shortened
516 error:(NSError * _Nullable * _Nullable)error
518 NSMutableArray *array = [NSMutableArray array];
520 for (int i = 0; i < [fingerprint length]; i += 4) {
521 if (shortened && i >= 20)
524 NSString *str = [fingerprint substringWithRange:NSMakeRange(i, 4)];
527 [[NSScanner scannerWithString:str] scanHexInt:&value];
529 PEPAutoPointer *word = [PEPAutoPointer new];
532 PEP_STATUS status = trustword(_session,
534 [[languageID precomposedStringWithCanonicalMapping]
536 word.charPointerPointer,
539 if ([NSError setError:error fromPEPStatus:status]) {
543 [array addObject:[NSString stringWithUTF8String:word.charPointer]];
549 - (BOOL)mySelf:(PEPIdentity * _Nonnull)identity error:(NSError * _Nullable * _Nullable)error
551 pEp_identity *ident = PEP_identityToStruct(identity);
554 PEP_STATUS status = myself(_session, ident);
557 if ([NSError setError:error fromPEPStatus:status]) {
558 free_identity(ident);
563 [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
564 free_identity(ident);
569 - (BOOL)updateIdentity:(PEPIdentity * _Nonnull)identity error:(NSError * _Nullable * _Nullable)error
571 if (identity.isOwn) {
572 return [self mySelf:identity error:error];
574 pEp_identity *ident = PEP_identityToStruct(identity);
577 PEP_STATUS status = update_identity(_session, ident);
580 if ([NSError setError:error fromPEPStatus:status]) {
581 free_identity(ident);
586 [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
587 free_identity(ident);
593 - (BOOL)trustPersonalKey:(PEPIdentity * _Nonnull)identity
594 error:(NSError * _Nullable * _Nullable)error
596 pEp_identity *ident = PEP_identityToStruct(identity);
599 PEP_STATUS status = trust_personal_key(_session, ident);
602 if ([NSError setError:error fromPEPStatus:status]) {
603 free_identity(ident);
608 [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
609 free_identity(ident);
613 - (BOOL)keyMistrusted:(PEPIdentity *)identity error:(NSError * _Nullable * _Nullable)error
615 pEp_identity *ident = PEP_identityToStruct(identity);
618 PEP_STATUS status = key_mistrusted(_session, ident);
621 if ([NSError setError:error fromPEPStatus:status]) {
622 free_identity(ident);
627 [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
628 free_identity(ident);
633 - (BOOL)keyResetTrust:(PEPIdentity * _Nonnull)identity
634 error:(NSError * _Nullable * _Nullable)error
636 pEp_identity *ident = PEP_identityToStruct(identity);
639 PEP_STATUS status = key_reset_trust(_session, ident);
642 if ([NSError setError:error fromPEPStatus:status]) {
643 free_identity(ident);
648 [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
649 free_identity(ident);
654 - (BOOL)importKey:(NSString * _Nonnull)keydata error:(NSError * _Nullable * _Nullable)error
657 PEP_STATUS status = import_key(_session,
658 [[keydata precomposedStringWithCanonicalMapping] UTF8String],
659 [keydata length], NULL);
662 if ([NSError setError:error fromPEPStatus:status]) {
669 - (BOOL)logTitle:(NSString * _Nonnull)title
670 entity:(NSString * _Nonnull)entity
671 description:(NSString * _Nullable)description
672 comment:(NSString * _Nullable)comment
673 error:(NSError * _Nullable * _Nullable)error
676 PEP_STATUS status = log_event(_session,
677 [[title precomposedStringWithCanonicalMapping] UTF8String],
678 [[entity precomposedStringWithCanonicalMapping] UTF8String],
679 [[description precomposedStringWithCanonicalMapping] UTF8String],
680 [[comment precomposedStringWithCanonicalMapping] UTF8String]);
683 if ([NSError setError:error fromPEPStatus:status]) {
690 - (NSString * _Nullable)getLogWithError:(NSError * _Nullable * _Nullable)error
692 char *theChars = NULL;
693 PEP_STATUS status = get_crashdump_log(_session, 0, &theChars);
695 if ([NSError setError:error fromPEPStatus:status]) {
700 return [NSString stringWithUTF8String:theChars];
702 [NSError setError:error fromPEPStatus:PEP_UNKNOWN_ERROR];
707 - (NSString * _Nullable)getTrustwordsIdentity1:(PEPIdentity * _Nonnull)identity1
708 identity2:(PEPIdentity * _Nonnull)identity2
709 language:(NSString * _Nullable)language
711 error:(NSError * _Nullable * _Nullable)error
713 pEp_identity *ident1 = PEP_identityToStruct(identity1);
714 pEp_identity *ident2 = PEP_identityToStruct(identity2);
717 PEPAutoPointer *trustwords = [PEPAutoPointer new];
718 size_t sizeWritten = 0;
721 status = get_trustwords(_session, ident1, ident2,
722 [[language precomposedStringWithCanonicalMapping]
724 trustwords.charPointerPointer, &sizeWritten, full);
727 NSString *result = nil;
729 if (![NSError setError:error fromPEPStatus:status]) {
730 result = [NSString stringWithUTF8String:trustwords.charPointer];
736 - (NSArray<PEPLanguage *> * _Nullable)languageListWithError:(NSError * _Nullable * _Nullable)error
738 PEPAutoPointer *chLangs = [PEPAutoPointer new];
739 PEP_STATUS status = get_languagelist(_session, chLangs.charPointerPointer);
741 if ([NSError setError:error fromPEPStatus:status]) {
745 NSString *parserInput = [NSString stringWithUTF8String:chLangs.charPointer];
747 NSMutableArray<NSString *> *tokens = [NSMutableArray array];
748 PEPCSVScanner *scanner = [[PEPCSVScanner alloc] initWithString:parserInput];
750 NSString *token = [scanner nextString];
754 [tokens addObject:token];
757 NSArray *theTokens = [NSArray arrayWithArray:tokens];
758 NSMutableArray<PEPLanguage *> *langs = [NSMutableArray new];
760 ArrayTake *take = [theTokens takeOrNil:3];
764 NSArray *elements = take.elements;
765 PEPLanguage *lang = [[PEPLanguage alloc]
766 initWithCode:[elements objectAtIndex:0]
767 name:[elements objectAtIndex:1]
768 sentence:[elements objectAtIndex:2]];
769 [langs addObject:lang];
770 theTokens = take.rest;
773 return [NSArray arrayWithArray:langs];
776 - (BOOL)undoLastMistrustWithError:(NSError * _Nullable * _Nullable)error;
779 PEP_STATUS status = undo_last_mistrust(_session);
782 if ([NSError setError:error fromPEPStatus:status]) {
789 static NSDictionary *ratingToString;
790 static NSDictionary *stringToRating;
794 NSDictionary *ratingToStringIntern =
796 [NSNumber numberWithInteger:PEP_rating_cannot_decrypt]: @"cannot_decrypt",
797 [NSNumber numberWithInteger:PEP_rating_have_no_key]: @"have_no_key",
798 [NSNumber numberWithInteger:PEP_rating_unencrypted]: @"unencrypted",
799 [NSNumber numberWithInteger:PEP_rating_unencrypted_for_some]: @"unencrypted_for_some",
800 [NSNumber numberWithInteger:PEP_rating_unreliable]: @"unreliable",
801 [NSNumber numberWithInteger:PEP_rating_reliable]: @"reliable",
802 [NSNumber numberWithInteger:PEP_rating_trusted]: @"trusted",
803 [NSNumber numberWithInteger:PEP_rating_trusted_and_anonymized]: @"trusted_and_anonymized",
804 [NSNumber numberWithInteger:PEP_rating_fully_anonymous]: @"fully_anonymous",
805 [NSNumber numberWithInteger:PEP_rating_mistrust]: @"mistrust",
806 [NSNumber numberWithInteger:PEP_rating_b0rken]: @"b0rken",
807 [NSNumber numberWithInteger:PEP_rating_under_attack]: @"under_attack",
808 [NSNumber numberWithInteger:PEP_rating_undefined]: @"undefined",
810 NSMutableDictionary *stringToRatingMutable = [NSMutableDictionary
811 dictionaryWithCapacity:
812 ratingToStringIntern.count];
813 for (NSNumber *ratingNumber in ratingToStringIntern.allKeys) {
814 NSString *ratingName = [ratingToStringIntern objectForKey:ratingNumber];
815 [stringToRatingMutable setObject:ratingNumber forKey:ratingName];
817 ratingToString = ratingToStringIntern;
818 stringToRating = [NSDictionary dictionaryWithDictionary:stringToRatingMutable];
821 - (PEP_rating)ratingFromString:(NSString * _Nonnull)string
823 NSNumber *num = [stringToRating objectForKey:string];
825 return (PEP_rating) [num integerValue];
827 return PEP_rating_undefined;
831 - (NSString * _Nonnull)stringFromRating:(PEP_rating)rating
833 NSString *stringRating = [ratingToString objectForKey:[NSNumber numberWithInteger:rating]];
841 - (NSNumber * _Nullable)isPEPUser:(PEPIdentity * _Nonnull)identity
842 error:(NSError * _Nullable * _Nullable)error
844 pEp_identity *ident = PEP_identityToStruct(identity);
846 PEP_STATUS status = is_pep_user(self.session, ident, &isPEP);
848 if ([NSError setError:error fromPEPStatus:status]) {
851 return [NSNumber numberWithBool:isPEP];
855 - (BOOL)setOwnKey:(PEPIdentity * _Nonnull)identity fingerprint:(NSString * _Nonnull)fingerprint
856 error:(NSError * _Nullable * _Nullable)error
858 pEp_identity *ident = PEP_identityToStruct(identity);
859 PEP_STATUS status = set_own_key(self.session, ident,
860 [[fingerprint precomposedStringWithCanonicalMapping]
862 if (status == PEP_STATUS_OK) {
866 *error = [NSError errorWithPEPStatus:status];