pEpObjCAdapter/PEPSession.m
author Dirk Zimmermann <dirk@pep-project.org>
Mon, 04 Sep 2017 18:48:17 +0200
changeset 216 f3f9abeb7c2b
parent 213 959a115bc0f7
child 218 fcc791d5b1fe
permissions -rw-r--r--
NETPGP-20 decrypt outputs plist of original message
     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 - (id)init
    61 {
    62     [PEPSession setupTrustWordsDB];
    63 
    64     PEP_STATUS status = init(&_session);
    65 
    66     if (status != PEP_STATUS_OK) {
    67         return nil;
    68     }
    69 
    70     [PEPObjCAdapter bindSession:self];
    71 
    72     return self;
    73 }
    74 
    75 - (void)dealloc
    76 {
    77     [PEPObjCAdapter unbindSession:self];
    78 
    79     release(_session);
    80 }
    81 
    82 - (void)debugOutPutMessageDict:(nonnull PEPDict *)src
    83 {
    84     NSString *from = src[kPepFrom][kPepAddress];
    85     NSArray *tos = src[kPepTo];
    86     NSString *to = tos[0][kPepAddress];
    87     NSString *msgID = src[kPepID];
    88     NSString *fileName = [NSString stringWithFormat:@"from(%@)_to(%@)_(%@)",
    89                           from, to, msgID];
    90     [src debugSaveToFilePath:fileName];
    91 }
    92 
    93 - (PEP_rating)decryptMessageDict:(nonnull PEPDict *)src
    94                             dest:(PEPDict * _Nullable * _Nullable)dst
    95                             keys:(PEPStringList * _Nullable * _Nullable)keys
    96 {
    97     [self debugOutPutMessageDict:src];
    98 
    99     message * _src = PEP_messageDictToStruct(src);
   100     message * _dst = NULL;
   101     stringlist_t * _keys = NULL;
   102     PEP_rating color = PEP_rating_undefined;
   103     PEP_decrypt_flags_t flags = 0;
   104 
   105     @synchronized (self) {
   106         decrypt_message(_session, _src, &_dst, &_keys, &color, &flags);
   107     }
   108 
   109     NSDictionary * dst_;
   110 
   111     if (_dst) {
   112         dst_ = PEP_messageDictFromStruct(_dst);
   113     }
   114     else {
   115         dst_ = PEP_messageDictFromStruct(_src);
   116     }
   117 
   118     NSArray * keys_ = nil;
   119     if (_keys)
   120         keys_ = PEP_arrayFromStringlist(_keys);
   121 
   122     free_message(_src);
   123     free_message(_dst);
   124     free_stringlist(_keys);
   125 
   126     if (dst) {
   127         *dst = dst_;
   128     }
   129     if (keys) {
   130         *keys = keys_;
   131     }
   132     return color;
   133 }
   134 
   135 - (PEP_rating)reEvaluateMessageRating:(nonnull PEPDict *)src
   136 {
   137     message * _src = PEP_messageDictToStruct(src);
   138     PEP_rating color = PEP_rating_undefined;
   139 
   140     @synchronized (self) {
   141         re_evaluate_message_rating(_session, _src, NULL, PEP_rating_undefined, &color);
   142     }
   143 
   144     free_message(_src);
   145 
   146     return color;
   147 }
   148 
   149 - (void)removeEmptyArrayKey:(NSString *)key inDict:(PEPMutableDict *)dict
   150 {
   151     if ([[dict objectForKey:key] count] == 0) {
   152         [dict removeObjectForKey:key];
   153     }
   154 }
   155 
   156 - (NSDictionary *)removeEmptyRecipients:(PEPDict *)src
   157 {
   158     NSMutableDictionary *dest = src.mutableCopy;
   159 
   160     [self removeEmptyArrayKey:kPepTo inDict:dest];
   161     [self removeEmptyArrayKey:kPepCC inDict:dest];
   162     [self removeEmptyArrayKey:kPepBCC inDict:dest];
   163 
   164     return [NSDictionary dictionaryWithDictionary:dest];
   165 }
   166 
   167 - (PEP_STATUS)encryptMessageDict:(nonnull PEPDict *)src
   168                            extra:(nullable NSArray *)keys
   169                             dest:(PEPDict * _Nullable * _Nullable)dst
   170 {
   171     PEP_STATUS status;
   172     PEP_encrypt_flags_t flags = 0;
   173 
   174     message * _src = PEP_messageDictToStruct([self removeEmptyRecipients:src]);
   175     message * _dst = NULL;
   176     stringlist_t * _keys = PEP_arrayToStringlist(keys);
   177 
   178     @synchronized (self) {
   179         status = encrypt_message(_session, _src, _keys, &_dst, PEP_enc_PGP_MIME, flags);
   180     }
   181 
   182     NSDictionary * dst_;
   183 
   184     if (_dst) {
   185         dst_ = PEP_messageDictFromStruct(_dst);
   186     }
   187     else {
   188         dst_ = PEP_messageDictFromStruct(_src);
   189     }
   190     if (dst) {
   191         *dst = dst_;
   192     }
   193 
   194     free_message(_src);
   195     free_message(_dst);
   196     free_stringlist(_keys);
   197 
   198     return status;
   199 }
   200 
   201 - (PEP_STATUS)encryptMessageDict:(nonnull PEPDict *)src
   202                         identity:(nonnull PEPDict *)identity
   203                             dest:(PEPDict * _Nullable * _Nullable)dst
   204 {
   205     PEP_STATUS status;
   206     PEP_encrypt_flags_t flags = 0;
   207 
   208     message * _src = PEP_messageDictToStruct([self removeEmptyRecipients:src]);
   209     pEp_identity *ident = PEP_identityDictToStruct(identity);
   210     message * _dst = NULL;
   211 
   212     @synchronized (self) {
   213         status = encrypt_message_for_self(_session, ident, _src, &_dst, PEP_enc_PGP_MIME, flags);
   214     }
   215 
   216     NSDictionary * dst_;
   217 
   218     if (_dst) {
   219         dst_ = PEP_messageDictFromStruct(_dst);
   220     }
   221     else {
   222         dst_ = PEP_messageDictFromStruct(_src);
   223     }
   224 
   225     if (dst) {
   226         *dst = dst_;
   227     }
   228 
   229     free_message(_src);
   230     free_message(_dst);
   231     free_identity(ident);
   232 
   233     return status;
   234 }
   235 
   236 - (PEP_rating)outgoingMessageColor:(PEPDict *)msg
   237 {
   238     message * _msg = PEP_messageDictToStruct(msg);
   239     PEP_rating color = PEP_rating_undefined;
   240 
   241     @synchronized (self) {
   242         outgoing_message_rating(_session, _msg, &color);
   243     }
   244 
   245     free_message(_msg);
   246 
   247     return color;
   248 }
   249 
   250 - (PEP_rating)identityRating:(nonnull PEPDict *)identity
   251 {
   252     pEp_identity *ident = PEP_identityDictToStruct(identity);
   253     PEP_rating color = PEP_rating_undefined;
   254 
   255     @synchronized (self) {
   256         identity_rating(_session, ident, &color);
   257     }
   258 
   259     free_identity(ident);
   260 
   261     return color;
   262 }
   263 
   264 DYNAMIC_API PEP_STATUS identity_rating(PEP_SESSION session, pEp_identity *ident, PEP_rating *color);
   265 
   266 
   267 - (NSArray *)trustwords:(NSString *)fpr forLanguage:(NSString *)languageID shortened:(BOOL)shortened
   268 {
   269     NSMutableArray *array = [NSMutableArray array];
   270 
   271     for (int i = 0; i < [fpr length]; i += 4) {
   272         if (shortened && i >= 20)
   273             break;
   274 
   275         NSString *str = [fpr substringWithRange:NSMakeRange(i, 4)];
   276 
   277         unsigned int value;
   278         [[NSScanner scannerWithString:str] scanHexInt:&value];
   279 
   280         char *word;
   281         size_t size;
   282 
   283         @synchronized (self) {
   284             trustword(_session, value, [languageID UTF8String], &word, &size);
   285         }
   286 
   287         [array addObject:[NSString stringWithUTF8String:word]];
   288         free(word);
   289     }
   290 
   291     return array;
   292 }
   293 
   294 - (void)mySelf:(PEPMutableDict *)identity
   295 {
   296     [identity removeObjectForKey:kPepUserID];
   297 
   298     pEp_identity *ident = PEP_identityDictToStruct(identity);
   299 
   300     @synchronized(self) {
   301         myself(_session, ident);
   302     }
   303 
   304     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   305     free_identity(ident);
   306 }
   307 
   308 - (void)updateIdentity:(PEPMutableDict *)identity
   309 {
   310     pEp_identity *ident = PEP_identityDictToStruct(identity);
   311 
   312     @synchronized(self) {
   313         update_identity(_session, ident);
   314     }
   315 
   316     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   317     free_identity(ident);
   318 }
   319 
   320 - (void)trustPersonalKey:(PEPMutableDict *)identity
   321 {
   322     pEp_identity *ident = PEP_identityDictToStruct(identity);
   323 
   324     @synchronized(self) {
   325         trust_personal_key(_session, ident);
   326     }
   327 
   328     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   329     free_identity(ident);
   330 }
   331 
   332 - (void)keyResetTrust:(PEPMutableDict *)identity
   333 {
   334     pEp_identity *ident = PEP_identityDictToStruct(identity);
   335 
   336     @synchronized(self) {
   337         key_reset_trust(_session, ident);
   338     }
   339 
   340     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   341     free_identity(ident);
   342 }
   343 
   344 - (void)keyMistrusted:(PEPMutableDict *)identity
   345 {
   346     pEp_identity *ident = PEP_identityDictToStruct(identity);
   347 
   348     @synchronized(self) {
   349         key_mistrusted(_session, ident);
   350     }
   351 
   352     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   353     free_identity(ident);
   354 }
   355 
   356 - (void)importKey:(NSString *)keydata
   357 {
   358     @synchronized(self) {
   359         import_key(_session, [keydata UTF8String], [keydata length], NULL);
   360     }
   361 
   362 }
   363 
   364 - (void)logTitle:(nonnull NSString *)title entity:(nonnull NSString *)entity
   365      description:(nullable NSString *)description comment:(nullable NSString *)comment
   366 {
   367     log_event(self.session, [[title precomposedStringWithCanonicalMapping] UTF8String],
   368               [[entity precomposedStringWithCanonicalMapping] UTF8String],
   369               [[description precomposedStringWithCanonicalMapping] UTF8String],
   370               [[comment precomposedStringWithCanonicalMapping] UTF8String]);
   371 }
   372 
   373 - (nonnull NSString *)getLog
   374 {
   375     char *data;
   376     get_crashdump_log(self.session, 0, &data);
   377     NSString *logString = [NSString stringWithUTF8String:data];
   378     return logString;
   379 }
   380 
   381 - (nullable NSString *)getTrustwordsIdentity1:(nonnull PEPDict *)identity1
   382                                     identity2:(nonnull PEPDict *)identity2
   383                                      language:(nullable NSString *)language
   384                                          full:(BOOL)full
   385 {
   386     NSString *result = nil;
   387     char *trustwords = nil;
   388     size_t sizeWritten = 0;
   389 
   390     pEp_identity *ident1 = PEP_identityDictToStruct(identity1);
   391     pEp_identity *ident2 = PEP_identityDictToStruct(identity2);
   392     PEP_STATUS status = get_trustwords(_session, ident1, ident2,
   393                                        [[language precomposedStringWithCanonicalMapping]
   394                                         UTF8String],
   395                                        &trustwords, &sizeWritten, full);
   396     if (status == PEP_STATUS_OK) {
   397         result = [NSString stringWithCString:trustwords
   398                                     encoding:NSUTF8StringEncoding];
   399     }
   400     if (trustwords) {
   401         free(trustwords);
   402     }
   403     return result;
   404 }
   405 
   406 - (nullable NSString *)getTrustwordsMessageDict:(nonnull PEPDict *)messageDict
   407                                    receiverDict:(nonnull PEPDict *)receiverDict
   408                                       keysArray:(PEPStringList * _Nullable)keysArray
   409                                        language:(nullable NSString *)language
   410                                            full:(BOOL)full
   411                                 resultingStatus:(PEP_STATUS * _Nullable)resultingStatus
   412 {
   413     NSString *result = nil;
   414     char *trustwords = nil;
   415 
   416     message *theMessage = PEP_messageDictToStruct(messageDict);
   417 
   418     stringlist_t *keyList = nil;
   419     if (keysArray) {
   420         keyList = PEP_arrayToStringlist(keysArray);
   421     }
   422 
   423     pEp_identity *receiver = PEP_identityDictToStruct(receiverDict);
   424 
   425     PEP_STATUS status = get_message_trustwords(_session, theMessage, keyList, receiver,
   426                                                [[language
   427                                                  precomposedStringWithCanonicalMapping] UTF8String],
   428                                                &trustwords, full);
   429 
   430     if (resultingStatus) {
   431         *resultingStatus = status;
   432     }
   433 
   434     if (status == PEP_STATUS_OK) {
   435         result = [NSString stringWithCString:trustwords
   436                                     encoding:NSUTF8StringEncoding];
   437     }
   438     if (trustwords) {
   439         free(trustwords);
   440     }
   441     return result;
   442 }
   443 
   444 - (NSArray<PEPLanguage *> * _Nonnull)languageList
   445 {
   446     char *chLangs;
   447     get_languagelist(self.session, &chLangs);
   448     NSString *parserInput = [NSString stringWithUTF8String:chLangs];
   449 
   450     NSMutableArray<NSString *> *tokens = [NSMutableArray array];
   451     PEPCSVScanner *scanner = [[PEPCSVScanner alloc] initWithString:parserInput];
   452     while (YES) {
   453         NSString *token = [scanner nextString];
   454         if (!token) {
   455             break;
   456         }
   457         [tokens addObject:token];
   458     }
   459 
   460     NSArray *theTokens = [NSArray arrayWithArray:tokens];
   461     NSMutableArray<PEPLanguage *> *langs = [NSMutableArray new];
   462     while (YES) {
   463         ArrayTake *take = [theTokens takeOrNil:3];
   464         if (!take) {
   465             break;
   466         }
   467         NSArray *elements = take.elements;
   468         PEPLanguage *lang = [[PEPLanguage alloc]
   469                              initWithCode:[elements objectAtIndex:0]
   470                              name:[elements objectAtIndex:1]
   471                              sentence:[elements objectAtIndex:2]];
   472         [langs addObject:lang];
   473         theTokens = take.rest;
   474     }
   475     
   476     return [NSArray arrayWithArray:langs];
   477 }
   478 
   479 @end