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