pEpObjCAdapter/PEPSession.m
author Dirk Zimmermann <dirk@pep-project.org>
Wed, 27 Sep 2017 14:38:33 +0200
changeset 248 a7b17433ebc2
parent 247 58df8f277afc
child 249 08abeb4fb445
permissions -rw-r--r--
IOS-714 rm unused method
     1 //
     2 //  PEPSession.m
     3 //  pEpiOSAdapter
     4 //
     5 //  Created by Volker Birk on 08.07.15.
     6 //  Copyright (c) 2015 p≡p. All rights reserved.
     7 //
     8 
     9 #import "PEPSession.h"
    10 #import "PEPSession+Internal.h"
    11 #import "PEPObjCAdapter.h"
    12 #import "PEPObjCAdapter+Internal.h"
    13 #import "PEPMessage.h"
    14 #import "PEPLanguage.h"
    15 #import "PEPCSVScanner.h"
    16 #import "NSArray+Extension.h"
    17 #import "NSDictionary+Extension.h"
    18 
    19 @implementation PEPSession
    20 
    21 // serialize all session access
    22 + (dispatch_queue_t)sharedSessionQueue
    23 {
    24     static dispatch_once_t once;
    25     static dispatch_queue_t sharedSessionQueue;
    26     dispatch_once(&once, ^{
    27         sharedSessionQueue = dispatch_queue_create("pEp session queue", DISPATCH_QUEUE_CONCURRENT);
    28     });
    29     return sharedSessionQueue;
    30 }
    31 
    32 + (PEPSession *)session
    33 {
    34     PEPSession *_session = [[PEPSession alloc] init];
    35     return _session;
    36 }
    37 
    38 + (void)dispatchAsyncOnSession:(PEPSessionBlock)block
    39 {
    40     dispatch_async([self sharedSessionQueue], ^{
    41         PEPSession *pepSession = [[PEPSession alloc] init];
    42         block(pepSession);
    43     });
    44 }
    45 
    46 + (void)dispatchSyncOnSession:(PEPSessionBlock)block
    47 {
    48     PEPSession *pepSession = [[PEPSession alloc] init];
    49     block(pepSession);
    50 }
    51 
    52 + (void)setupTrustWordsDB
    53 {
    54     static dispatch_once_t once;
    55     dispatch_once(&once, ^{
    56         [PEPObjCAdapter setupTrustWordsDB:[NSBundle bundleForClass:[self class]]];
    57     });
    58 }
    59 
    60 static NSString *threadCountKey = @"PEPSession.threadCount";
    61 static NSObject *sessionInitLock = nil;
    62 static dispatch_once_t sessionInitLockOnce;
    63 
    64 - (id)init
    65 {
    66     [PEPSession setupTrustWordsDB];
    67     
    68     dispatch_once(&sessionInitLockOnce, ^{
    69         sessionInitLock = [[NSObject alloc] init];
    70     });
    71     @synchronized (sessionInitLock) {
    72 
    73         PEP_STATUS status = init(&_session);
    74 
    75         if (status != PEP_STATUS_OK) {
    76             return nil;
    77         }
    78 
    79         [PEPObjCAdapter bindSession:self];
    80     }
    81     return self;
    82 }
    83 
    84 - (void)dealloc
    85 {
    86     [PEPObjCAdapter unbindSession:self];
    87 
    88     @synchronized (sessionInitLock) {
    89         release(_session);
    90     }
    91 }
    92 
    93 /**
    94  Saves the given message dict as a plist to the local filesystem
    95  (directly under NSApplicationSupportDirectory).
    96  Since the complete output file will be logged by `debugSaveToFilePath`,
    97  you can get access to the files easily when it's the simulator.
    98  */
    99 - (void)debugOutPutMessageDict:(nonnull PEPDict *)src
   100 {
   101     NSString *from = src[kPepFrom][kPepAddress];
   102     NSArray *tos = src[kPepTo];
   103     NSString *to = tos[0][kPepAddress];
   104     NSString *msgID = src[kPepID];
   105     NSString *fileName = [NSString stringWithFormat:@"%@_from(%@)_%@",
   106                           to, from, msgID];
   107     [src debugSaveToFilePath:fileName];
   108 }
   109 
   110 - (PEP_rating)decryptMessageDict:(nonnull PEPDict *)src
   111                             dest:(PEPDict * _Nullable * _Nullable)dst
   112                             keys:(PEPStringList * _Nullable * _Nullable)keys
   113 {
   114     message * _src = PEP_messageDictToStruct(src);
   115     message * _dst = NULL;
   116     stringlist_t * _keys = NULL;
   117     PEP_rating color = PEP_rating_undefined;
   118     PEP_decrypt_flags_t flags = 0;
   119 
   120     @synchronized (self) {
   121         decrypt_message(_session, _src, &_dst, &_keys, &color, &flags);
   122     }
   123 
   124     NSDictionary * dst_;
   125 
   126     if (_dst) {
   127         dst_ = PEP_messageDictFromStruct(_dst);
   128     }
   129     else {
   130         dst_ = PEP_messageDictFromStruct(_src);
   131     }
   132 
   133     NSArray * keys_ = nil;
   134     if (_keys)
   135         keys_ = PEP_arrayFromStringlist(_keys);
   136 
   137     free_message(_src);
   138     free_message(_dst);
   139     free_stringlist(_keys);
   140 
   141     if (dst) {
   142         *dst = dst_;
   143     }
   144     if (keys) {
   145         *keys = keys_;
   146     }
   147     return color;
   148 }
   149 
   150 - (PEP_rating)reEvaluateMessageRating:(nonnull PEPDict *)src
   151 {
   152     message * _src = PEP_messageDictToStruct(src);
   153     PEP_rating color = PEP_rating_undefined;
   154 
   155     @synchronized (self) {
   156         re_evaluate_message_rating(_session, _src, NULL, PEP_rating_undefined, &color);
   157     }
   158 
   159     free_message(_src);
   160 
   161     return color;
   162 }
   163 
   164 - (void)removeEmptyArrayKey:(NSString *)key inDict:(PEPMutableDict *)dict
   165 {
   166     if ([[dict objectForKey:key] count] == 0) {
   167         [dict removeObjectForKey:key];
   168     }
   169 }
   170 
   171 - (NSDictionary *)removeEmptyRecipients:(PEPDict *)src
   172 {
   173     NSMutableDictionary *dest = src.mutableCopy;
   174 
   175     [self removeEmptyArrayKey:kPepTo inDict:dest];
   176     [self removeEmptyArrayKey:kPepCC inDict:dest];
   177     [self removeEmptyArrayKey:kPepBCC inDict:dest];
   178 
   179     return [NSDictionary dictionaryWithDictionary:dest];
   180 }
   181 
   182 - (PEP_STATUS)encryptMessageDict:(nonnull PEPDict *)src
   183                            extra:(nullable NSArray *)keys
   184                             dest:(PEPDict * _Nullable * _Nullable)dst
   185 {
   186     PEP_STATUS status;
   187     PEP_encrypt_flags_t flags = 0;
   188 
   189     message * _src = PEP_messageDictToStruct([self removeEmptyRecipients:src]);
   190     message * _dst = NULL;
   191     stringlist_t * _keys = PEP_arrayToStringlist(keys);
   192 
   193     @synchronized (self) {
   194         status = encrypt_message(_session, _src, _keys, &_dst, PEP_enc_PGP_MIME, flags);
   195     }
   196 
   197     NSDictionary * dst_;
   198 
   199     if (_dst) {
   200         dst_ = PEP_messageDictFromStruct(_dst);
   201     }
   202     else {
   203         dst_ = PEP_messageDictFromStruct(_src);
   204     }
   205     if (dst) {
   206         *dst = dst_;
   207     }
   208 
   209     free_message(_src);
   210     free_message(_dst);
   211     free_stringlist(_keys);
   212 
   213     return status;
   214 }
   215 
   216 - (PEP_STATUS)encryptMessageDict:(nonnull PEPDict *)src
   217                         identity:(nonnull PEPDict *)identity
   218                             dest:(PEPDict * _Nullable * _Nullable)dst
   219 {
   220     PEP_STATUS status;
   221     PEP_encrypt_flags_t flags = 0;
   222 
   223     message * _src = PEP_messageDictToStruct([self removeEmptyRecipients:src]);
   224     pEp_identity *ident = PEP_identityDictToStruct(identity);
   225     message * _dst = NULL;
   226 
   227     @synchronized (self) {
   228         status = encrypt_message_for_self(_session, ident, _src, &_dst, PEP_enc_PGP_MIME, flags);
   229     }
   230 
   231     NSDictionary * dst_;
   232 
   233     if (_dst) {
   234         dst_ = PEP_messageDictFromStruct(_dst);
   235     }
   236     else {
   237         dst_ = PEP_messageDictFromStruct(_src);
   238     }
   239 
   240     if (dst) {
   241         *dst = dst_;
   242     }
   243 
   244     free_message(_src);
   245     free_message(_dst);
   246     free_identity(ident);
   247 
   248     return status;
   249 }
   250 
   251 - (PEP_rating)outgoingMessageColor:(PEPDict *)msg
   252 {
   253     message * _msg = PEP_messageDictToStruct(msg);
   254     PEP_rating color = PEP_rating_undefined;
   255 
   256     @synchronized (self) {
   257         outgoing_message_rating(_session, _msg, &color);
   258     }
   259 
   260     free_message(_msg);
   261 
   262     return color;
   263 }
   264 
   265 - (PEP_rating)identityRating:(nonnull PEPDict *)identity
   266 {
   267     pEp_identity *ident = PEP_identityDictToStruct(identity);
   268     PEP_rating color = PEP_rating_undefined;
   269 
   270     @synchronized (self) {
   271         identity_rating(_session, ident, &color);
   272     }
   273 
   274     free_identity(ident);
   275 
   276     return color;
   277 }
   278 
   279 DYNAMIC_API PEP_STATUS identity_rating(PEP_SESSION session, pEp_identity *ident, PEP_rating *color);
   280 
   281 
   282 - (NSArray *)trustwords:(NSString *)fpr forLanguage:(NSString *)languageID shortened:(BOOL)shortened
   283 {
   284     NSMutableArray *array = [NSMutableArray array];
   285 
   286     for (int i = 0; i < [fpr length]; i += 4) {
   287         if (shortened && i >= 20)
   288             break;
   289 
   290         NSString *str = [fpr substringWithRange:NSMakeRange(i, 4)];
   291 
   292         unsigned int value;
   293         [[NSScanner scannerWithString:str] scanHexInt:&value];
   294 
   295         char *word;
   296         size_t size;
   297 
   298         @synchronized (self) {
   299             trustword(_session, value, [languageID UTF8String], &word, &size);
   300         }
   301 
   302         [array addObject:[NSString stringWithUTF8String:word]];
   303         free(word);
   304     }
   305 
   306     return array;
   307 }
   308 
   309 - (void)mySelf:(PEPMutableDict *)identity
   310 {
   311     [identity removeObjectForKey:kPepUserID];
   312 
   313     pEp_identity *ident = PEP_identityDictToStruct(identity);
   314 
   315     @synchronized(self) {
   316         myself(_session, ident);
   317     }
   318 
   319     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   320     free_identity(ident);
   321 }
   322 
   323 - (void)updateIdentity:(PEPMutableDict *)identity
   324 {
   325     pEp_identity *ident = PEP_identityDictToStruct(identity);
   326 
   327     @synchronized(self) {
   328         update_identity(_session, ident);
   329     }
   330 
   331     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   332     free_identity(ident);
   333 }
   334 
   335 - (void)trustPersonalKey:(PEPMutableDict *)identity
   336 {
   337     pEp_identity *ident = PEP_identityDictToStruct(identity);
   338 
   339     @synchronized(self) {
   340         trust_personal_key(_session, ident);
   341     }
   342 
   343     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   344     free_identity(ident);
   345 }
   346 
   347 - (void)keyResetTrust:(PEPMutableDict *)identity
   348 {
   349     pEp_identity *ident = PEP_identityDictToStruct(identity);
   350 
   351     @synchronized(self) {
   352         key_reset_trust(_session, ident);
   353     }
   354 
   355     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   356     free_identity(ident);
   357 }
   358 
   359 - (void)keyMistrusted:(PEPMutableDict *)identity
   360 {
   361     pEp_identity *ident = PEP_identityDictToStruct(identity);
   362 
   363     @synchronized(self) {
   364         key_mistrusted(_session, ident);
   365     }
   366 
   367     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   368     free_identity(ident);
   369 }
   370 
   371 - (void)importKey:(NSString *)keydata
   372 {
   373     @synchronized(self) {
   374         import_key(_session, [keydata UTF8String], [keydata length], NULL);
   375     }
   376 
   377 }
   378 
   379 - (void)logTitle:(nonnull NSString *)title entity:(nonnull NSString *)entity
   380      description:(nullable NSString *)description comment:(nullable NSString *)comment
   381 {
   382     @synchronized(self) {
   383 
   384         log_event(_session, [[title precomposedStringWithCanonicalMapping] UTF8String],
   385                   [[entity precomposedStringWithCanonicalMapping] UTF8String],
   386                   [[description precomposedStringWithCanonicalMapping] UTF8String],
   387                   [[comment precomposedStringWithCanonicalMapping] UTF8String]);
   388 
   389     }
   390 }
   391 
   392 - (nonnull NSString *)getLog
   393 {
   394     char *data;
   395     get_crashdump_log(self.session, 0, &data);
   396     NSString *logString = [NSString stringWithUTF8String:data];
   397     return logString;
   398 }
   399 
   400 - (nullable NSString *)getTrustwordsIdentity1:(nonnull PEPDict *)identity1
   401                                     identity2:(nonnull PEPDict *)identity2
   402                                      language:(nullable NSString *)language
   403                                          full:(BOOL)full
   404 {
   405     NSString *result = nil;
   406     char *trustwords = nil;
   407     size_t sizeWritten = 0;
   408 
   409     pEp_identity *ident1 = PEP_identityDictToStruct(identity1);
   410     pEp_identity *ident2 = PEP_identityDictToStruct(identity2);
   411     PEP_STATUS status;
   412     @synchronized(self) {
   413 
   414         status = get_trustwords(_session, ident1, ident2,
   415                                            [[language precomposedStringWithCanonicalMapping]
   416                                             UTF8String],
   417                                            &trustwords, &sizeWritten, full);
   418     }
   419     if (status == PEP_STATUS_OK) {
   420         result = [NSString stringWithCString:trustwords
   421                                     encoding:NSUTF8StringEncoding];
   422     }
   423     if (trustwords) {
   424         free(trustwords);
   425     }
   426     return result;
   427 }
   428 
   429 - (nullable NSString *)getTrustwordsMessageDict:(nonnull PEPDict *)messageDict
   430                                    receiverDict:(nonnull PEPDict *)receiverDict
   431                                       keysArray:(PEPStringList * _Nullable)keysArray
   432                                        language:(nullable NSString *)language
   433                                            full:(BOOL)full
   434                                 resultingStatus:(PEP_STATUS * _Nullable)resultingStatus
   435 {
   436     NSString *result = nil;
   437     char *trustwords = nil;
   438 
   439     message *theMessage = PEP_messageDictToStruct(messageDict);
   440 
   441     stringlist_t *keyList = nil;
   442     if (keysArray) {
   443         keyList = PEP_arrayToStringlist(keysArray);
   444     }
   445 
   446     pEp_identity *receiver = PEP_identityDictToStruct(receiverDict);
   447     PEP_STATUS status;
   448     @synchronized(self) {
   449         status = get_message_trustwords(_session, theMessage, keyList, receiver,
   450                                         [[language
   451                                           precomposedStringWithCanonicalMapping] UTF8String],
   452                                         &trustwords, full);
   453     }
   454     
   455     if (resultingStatus) {
   456         *resultingStatus = status;
   457     }
   458 
   459     if (status == PEP_STATUS_OK) {
   460         result = [NSString stringWithCString:trustwords
   461                                     encoding:NSUTF8StringEncoding];
   462     }
   463     if (trustwords) {
   464         free(trustwords);
   465     }
   466     return result;
   467 }
   468 
   469 - (NSArray<PEPLanguage *> * _Nonnull)languageList
   470 {
   471     char *chLangs;
   472     get_languagelist(self.session, &chLangs);
   473     NSString *parserInput = [NSString stringWithUTF8String:chLangs];
   474 
   475     NSMutableArray<NSString *> *tokens = [NSMutableArray array];
   476     PEPCSVScanner *scanner = [[PEPCSVScanner alloc] initWithString:parserInput];
   477     while (YES) {
   478         NSString *token = [scanner nextString];
   479         if (!token) {
   480             break;
   481         }
   482         [tokens addObject:token];
   483     }
   484 
   485     NSArray *theTokens = [NSArray arrayWithArray:tokens];
   486     NSMutableArray<PEPLanguage *> *langs = [NSMutableArray new];
   487     while (YES) {
   488         ArrayTake *take = [theTokens takeOrNil:3];
   489         if (!take) {
   490             break;
   491         }
   492         NSArray *elements = take.elements;
   493         PEPLanguage *lang = [[PEPLanguage alloc]
   494                              initWithCode:[elements objectAtIndex:0]
   495                              name:[elements objectAtIndex:1]
   496                              sentence:[elements objectAtIndex:2]];
   497         [langs addObject:lang];
   498         theTokens = take.rest;
   499     }
   500     
   501     return [NSArray arrayWithArray:langs];
   502 }
   503 
   504 @end