pEpObjCAdapter/PEPInternalSession.m
author Dirk Zimmermann <dirk@pep-project.org>
Thu, 17 May 2018 09:33:33 +0200
changeset 616 9e50cc7cd612
parent 614 f1bf3f2761dc
child 622 5c5d267a32a0
permissions -rw-r--r--
IOSAD-93 consistently using precomposedStringWithCanonicalMapping, stringWithUTF8String
andreas@269
     1
//
andreas@269
     2
//  PEPSession.m
andreas@269
     3
//  pEpiOSAdapter
andreas@269
     4
//
andreas@269
     5
//  Created by Volker Birk on 08.07.15.
andreas@269
     6
//  Copyright (c) 2015 p≡p. All rights reserved.
andreas@269
     7
//
andreas@269
     8
andreas@269
     9
#import "PEPInternalSession.h"
andreas@269
    10
#import "PEPObjCAdapter.h"
andreas@269
    11
#import "PEPObjCAdapter+Internal.h"
dirk@367
    12
#import "PEPMessageUtil.h"
andreas@269
    13
#import "PEPLanguage.h"
andreas@269
    14
#import "PEPCSVScanner.h"
andreas@269
    15
#import "NSArray+Extension.h"
andreas@269
    16
#import "NSDictionary+Extension.h"
dirk@312
    17
#import "PEPIdentity.h"
dirk@379
    18
#import "PEPMessage.h"
dirk@501
    19
#import "NSError+PEP.h"
dirk@564
    20
#import "PEPAutoPointer.h"
dirk@573
    21
#import "NSNumber+PEPRating.h"
dirk@598
    22
#import "NSMutableDictionary+PEP.h"
andreas@269
    23
andreas@269
    24
@implementation PEPInternalSession
andreas@269
    25
andreas@297
    26
- (instancetype)init
andreas@269
    27
{
andreas@274
    28
    self = [super init];
andreas@274
    29
    if (self) {
andreas@274
    30
        [PEPInternalSession setupTrustWordsDB];
andreas@269
    31
dirk@469
    32
        [self lockWrite];
andreas@274
    33
        PEP_STATUS status = init(&_session);
dirk@469
    34
        [self unlockWrite];
andreas@269
    35
andreas@274
    36
        if (status != PEP_STATUS_OK) {
andreas@274
    37
            return nil;
andreas@274
    38
        }
dirk@331
    39
dirk@331
    40
        [PEPObjCAdapter bindSession:self];
andreas@269
    41
    }
andreas@269
    42
    return self;
andreas@269
    43
}
andreas@269
    44
andreas@269
    45
- (void)dealloc
andreas@269
    46
{
dirk@331
    47
    [PEPObjCAdapter unbindSession:self];
dirk@331
    48
dirk@504
    49
    [self lockWrite];
andreas@269
    50
    release(_session);
dirk@504
    51
    [self unlockWrite];
andreas@269
    52
}
andreas@269
    53
andreas@416
    54
#pragma mark - CONFIG
andreas@416
    55
dirk@601
    56
- (void)configUnEncryptedSubjectEnabled:(BOOL)enabled;
andreas@416
    57
{
andreas@416
    58
    config_unencrypted_subject(self.session, enabled);
andreas@416
    59
}
andreas@416
    60
andreas@416
    61
#pragma mark - INTERNAL
andreas@416
    62
dirk@504
    63
- (void)lockWrite
dirk@504
    64
{
dirk@504
    65
    [PEPObjCAdapter lockWrite];
dirk@504
    66
}
dirk@504
    67
dirk@504
    68
- (void)unlockWrite
dirk@504
    69
{
dirk@504
    70
    [PEPObjCAdapter unlockWrite];
dirk@504
    71
}
dirk@504
    72
andreas@416
    73
+ (void)setupTrustWordsDB
andreas@416
    74
{
andreas@416
    75
    static dispatch_once_t once;
andreas@416
    76
    dispatch_once(&once, ^{
andreas@416
    77
        [PEPObjCAdapter setupTrustWordsDB:[NSBundle bundleForClass:[self class]]];
andreas@416
    78
    });
andreas@416
    79
}
andreas@416
    80
andreas@416
    81
#pragma mark - DEBUG UTILS
andreas@416
    82
andreas@269
    83
/**
andreas@269
    84
 Saves the given message dict as a plist to the local filesystem
andreas@269
    85
 (directly under NSApplicationSupportDirectory).
andreas@269
    86
 Since the complete output file will be logged by `debugSaveToFilePath`,
andreas@269
    87
 you can get access to the files easily when it's the simulator.
andreas@269
    88
 */
dirk@535
    89
- (void)debugOutPutMessageDict:(PEPDict * _Nonnull)src
andreas@269
    90
{
andreas@269
    91
    NSString *from = src[kPepFrom][kPepAddress];
andreas@269
    92
    NSArray *tos = src[kPepTo];
andreas@269
    93
    NSString *to = tos[0][kPepAddress];
andreas@269
    94
    NSString *msgID = src[kPepID];
andreas@269
    95
    NSString *fileName = [NSString stringWithFormat:@"%@_from(%@)_%@",
andreas@269
    96
                          to, from, msgID];
andreas@269
    97
    [src debugSaveToFilePath:fileName];
andreas@269
    98
}
andreas@269
    99
andreas@416
   100
#pragma mark - PEPSessionProtocol
andreas@416
   101
dirk@588
   102
void decryptMessageDictFree(message *src, message *dst, stringlist_t *extraKeys)
dirk@588
   103
{
dirk@588
   104
    free_message(src);
dirk@588
   105
    free_message(dst);
dirk@588
   106
    free_stringlist(extraKeys);
dirk@588
   107
}
dirk@588
   108
dirk@596
   109
- (PEPDict * _Nullable)decryptMessageDict:(PEPMutableDict * _Nonnull)messageDict
dirk@583
   110
                                    flags:(PEP_decrypt_flags * _Nullable)flags
dirk@517
   111
                                   rating:(PEP_rating * _Nullable)rating
dirk@523
   112
                                extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
dirk@524
   113
                                   status:(PEP_STATUS * _Nullable)status
dirk@517
   114
                                    error:(NSError * _Nullable * _Nullable)error
andreas@269
   115
{
dirk@514
   116
    if (rating) {
dirk@514
   117
        *rating = PEP_rating_undefined;
dirk@514
   118
    }
dirk@514
   119
dirk@522
   120
    message *_src = PEP_messageDictToStruct(messageDict);
dirk@467
   121
    message *_dst = NULL;
dirk@605
   122
    stringlist_t *theKeys = NULL;
dirk@583
   123
    PEP_decrypt_flags theFlags = 0;
dirk@583
   124
dirk@583
   125
    if (flags) {
dirk@583
   126
        theFlags = *flags;
dirk@583
   127
    }
andreas@269
   128
dirk@605
   129
    if (extraKeys && [*extraKeys count]) {
dirk@605
   130
        theKeys = PEP_arrayToStringlist(*extraKeys);
dirk@605
   131
    }
dirk@605
   132
dirk@514
   133
    PEP_rating internalRating = PEP_rating_undefined;
dirk@514
   134
dirk@469
   135
    [self lockWrite];
dirk@583
   136
    PEP_STATUS theStatus = decrypt_message(_session,
dirk@583
   137
                                           _src,
dirk@583
   138
                                           &_dst,
dirk@605
   139
                                           &theKeys,
dirk@583
   140
                                           &internalRating,
dirk@583
   141
                                           &theFlags);
dirk@469
   142
    [self unlockWrite];
andreas@269
   143
dirk@524
   144
    if (status) {
dirk@524
   145
        *status = theStatus;
dirk@524
   146
    }
dirk@524
   147
dirk@524
   148
    if ([NSError setError:error fromPEPStatus:theStatus]) {
dirk@605
   149
        decryptMessageDictFree(_src, _dst, theKeys);
dirk@517
   150
        return nil;
dirk@514
   151
    }
dirk@514
   152
dirk@583
   153
    if (flags) {
dirk@583
   154
        *flags = theFlags;
dirk@583
   155
    }
dirk@583
   156
dirk@467
   157
    NSDictionary *dst_;
andreas@269
   158
andreas@269
   159
    if (_dst) {
andreas@269
   160
        dst_ = PEP_messageDictFromStruct(_dst);
dirk@514
   161
    } else {
andreas@269
   162
        dst_ = PEP_messageDictFromStruct(_src);
andreas@269
   163
    }
andreas@269
   164
dirk@598
   165
    if (theFlags & PEP_decrypt_flag_untrusted_server) {
dirk@598
   166
        [messageDict replaceWithMessage:_src];
dirk@598
   167
    }
dirk@583
   168
dirk@605
   169
    if (extraKeys) {
dirk@605
   170
        *extraKeys = PEP_arrayFromStringlist(theKeys);
dirk@605
   171
    }
andreas@269
   172
dirk@605
   173
    decryptMessageDictFree(_src, _dst, theKeys);
dirk@514
   174
dirk@514
   175
    if (rating) {
dirk@514
   176
        *rating = internalRating;
dirk@514
   177
    }
dirk@514
   178
dirk@517
   179
    return dst_;
andreas@269
   180
}
andreas@269
   181
dirk@535
   182
- (PEPMessage * _Nullable)decryptMessage:(PEPMessage * _Nonnull)message
dirk@583
   183
                                   flags:(PEP_decrypt_flags * _Nullable)flags
dirk@517
   184
                                  rating:(PEP_rating * _Nullable)rating
dirk@523
   185
                               extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
dirk@524
   186
                                  status:(PEP_STATUS * _Nullable)status
dirk@517
   187
                                   error:(NSError * _Nullable * _Nullable)error
dirk@383
   188
{
dirk@583
   189
    PEPDict *destDict = [self
dirk@609
   190
                         decryptMessageDict:message.mutableDictionary
dirk@583
   191
                         flags:flags
dirk@583
   192
                         rating:rating
dirk@583
   193
                         extraKeys:extraKeys
dirk@583
   194
                         status:status
dirk@583
   195
                         error:error];
dirk@514
   196
dirk@614
   197
    if (destDict) {
dirk@383
   198
        PEPMessage *msg = [PEPMessage new];
dirk@383
   199
        [msg setValuesForKeysWithDictionary:destDict];
dirk@517
   200
        return msg;
dirk@614
   201
    } else {
dirk@614
   202
        return nil;
dirk@383
   203
    }
dirk@383
   204
}
dirk@383
   205
dirk@535
   206
- (BOOL)reEvaluateMessageDict:(PEPDict * _Nonnull)messageDict
dirk@516
   207
                       rating:(PEP_rating * _Nullable)rating
dirk@524
   208
                       status:(PEP_STATUS * _Nullable)status
dirk@516
   209
                        error:(NSError * _Nullable * _Nullable)error
andreas@269
   210
{
dirk@516
   211
    message *_src = PEP_messageDictToStruct(messageDict);
dirk@515
   212
    PEP_rating ratingByEngine = PEP_rating_undefined;
andreas@269
   213
dirk@469
   214
    [self lockWrite];
dirk@524
   215
    PEP_STATUS theStatus = re_evaluate_message_rating(_session,
dirk@524
   216
                                                      _src,
dirk@524
   217
                                                      NULL,
dirk@524
   218
                                                      PEP_rating_undefined,
dirk@524
   219
                                                      &ratingByEngine);
dirk@469
   220
    [self unlockWrite];
andreas@269
   221
andreas@269
   222
    free_message(_src);
andreas@269
   223
dirk@524
   224
    if (status) {
dirk@524
   225
        *status = theStatus;
dirk@524
   226
    }
dirk@524
   227
dirk@524
   228
    if ([NSError setError:error fromPEPStatus:theStatus]) {
dirk@515
   229
        return NO;
dirk@515
   230
    } else {
dirk@515
   231
        if (rating) {
dirk@515
   232
            *rating = ratingByEngine;
dirk@515
   233
        }
dirk@515
   234
        return YES;
dirk@515
   235
    }
andreas@269
   236
}
andreas@269
   237
dirk@535
   238
- (BOOL)reEvaluateMessage:(PEPMessage * _Nonnull)message
dirk@516
   239
                   rating:(PEP_rating * _Nullable)rating
dirk@524
   240
                   status:(PEP_STATUS * _Nullable)status
dirk@516
   241
                    error:(NSError * _Nullable * _Nullable)error
dirk@384
   242
{
dirk@524
   243
    return [self reEvaluateMessageDict:(PEPDict *) message
dirk@524
   244
                                rating:rating
dirk@524
   245
                                status:status
dirk@524
   246
                                 error:error];
dirk@384
   247
}
dirk@384
   248
andreas@269
   249
- (void)removeEmptyArrayKey:(NSString *)key inDict:(PEPMutableDict *)dict
andreas@269
   250
{
andreas@269
   251
    if ([[dict objectForKey:key] count] == 0) {
andreas@269
   252
        [dict removeObjectForKey:key];
andreas@269
   253
    }
andreas@269
   254
}
andreas@269
   255
andreas@269
   256
- (NSDictionary *)removeEmptyRecipients:(PEPDict *)src
andreas@269
   257
{
andreas@269
   258
    NSMutableDictionary *dest = src.mutableCopy;
andreas@269
   259
andreas@269
   260
    [self removeEmptyArrayKey:kPepTo inDict:dest];
andreas@269
   261
    [self removeEmptyArrayKey:kPepCC inDict:dest];
andreas@269
   262
    [self removeEmptyArrayKey:kPepBCC inDict:dest];
andreas@269
   263
dirk@370
   264
    return dest;
andreas@269
   265
}
andreas@269
   266
dirk@535
   267
- (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
dirk@535
   268
                                extraKeys:(PEPStringList * _Nullable)extraKeys
dirk@522
   269
                                encFormat:(PEP_enc_format)encFormat
dirk@524
   270
                                   status:(PEP_STATUS * _Nullable)status
dirk@522
   271
                                    error:(NSError * _Nullable * _Nullable)error
andreas@269
   272
{
andreas@269
   273
    PEP_encrypt_flags_t flags = 0;
andreas@269
   274
dirk@522
   275
    message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
dirk@467
   276
    message *_dst = NULL;
dirk@522
   277
    stringlist_t *_keys = PEP_arrayToStringlist(extraKeys);
andreas@269
   278
dirk@469
   279
    [self lockWrite];
dirk@524
   280
    PEP_STATUS theStatus = encrypt_message(_session, _src, _keys, &_dst, encFormat, flags);
dirk@469
   281
    [self unlockWrite];
andreas@269
   282
dirk@524
   283
    if (status) {
dirk@524
   284
        *status = theStatus;
dirk@524
   285
    }
dirk@524
   286
dirk@524
   287
    if ([NSError setError:error fromPEPStatus:theStatus]) {
dirk@522
   288
        return nil;
dirk@522
   289
    }
dirk@522
   290
dirk@467
   291
    NSDictionary *dst_;
andreas@269
   292
andreas@269
   293
    if (_dst) {
andreas@269
   294
        dst_ = PEP_messageDictFromStruct(_dst);
andreas@269
   295
    }
andreas@269
   296
    else {
andreas@269
   297
        dst_ = PEP_messageDictFromStruct(_src);
andreas@269
   298
    }
andreas@269
   299
andreas@269
   300
    free_message(_src);
andreas@269
   301
    free_message(_dst);
andreas@269
   302
    free_stringlist(_keys);
andreas@269
   303
dirk@522
   304
    return dst_;
andreas@269
   305
}
andreas@269
   306
dirk@535
   307
- (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
dirk@535
   308
                                   extraKeys:(PEPStringList * _Nullable)extraKeys
dirk@522
   309
                               encFormat:(PEP_enc_format)encFormat
dirk@524
   310
                                  status:(PEP_STATUS * _Nullable)status
dirk@522
   311
                                   error:(NSError * _Nullable * _Nullable)error
dirk@386
   312
{
dirk@522
   313
    PEPDict *encryptedDict = [self encryptMessageDict:(NSDictionary *) message
dirk@524
   314
                                            extraKeys:extraKeys
dirk@522
   315
                                            encFormat:encFormat
dirk@524
   316
                                               status:status
dirk@522
   317
                                                error:error];
dirk@614
   318
    if (encryptedDict) {
dirk@614
   319
        PEPMessage *encrypted = [PEPMessage new];
dirk@614
   320
        [encrypted setValuesForKeysWithDictionary:encryptedDict];
dirk@614
   321
        return encrypted;
dirk@614
   322
    } else {
dirk@614
   323
        return nil;
dirk@614
   324
    }
dirk@379
   325
}
dirk@379
   326
dirk@535
   327
- (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
dirk@535
   328
                                   extraKeys:(PEPStringList * _Nullable)extraKeys
dirk@524
   329
                                  status:(PEP_STATUS * _Nullable)status
dirk@522
   330
                                   error:(NSError * _Nullable * _Nullable)error
dirk@518
   331
{
dirk@524
   332
    return [self
dirk@524
   333
            encryptMessage:message
dirk@524
   334
            extraKeys:extraKeys
dirk@524
   335
            encFormat:PEP_enc_PEP
dirk@524
   336
            status:status
dirk@524
   337
            error:error];
dirk@518
   338
}
dirk@518
   339
dirk@535
   340
- (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
dirk@557
   341
                                  forSelf:(PEPIdentity * _Nonnull)ownIdentity
dirk@556
   342
                                extraKeys:(PEPStringList * _Nullable)extraKeys
dirk@526
   343
                                   status:(PEP_STATUS * _Nullable)status
dirk@526
   344
                                    error:(NSError * _Nullable * _Nullable)error
andreas@269
   345
{
andreas@269
   346
    PEP_encrypt_flags_t flags = 0;
andreas@269
   347
dirk@526
   348
    message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
dirk@557
   349
    pEp_identity *ident = PEP_identityToStruct(ownIdentity);
dirk@467
   350
    message *_dst = NULL;
andreas@269
   351
dirk@556
   352
    stringlist_t *keysStringList = PEP_arrayToStringlist(extraKeys);
dirk@556
   353
dirk@469
   354
    [self lockWrite];
dirk@526
   355
    PEP_STATUS theStatus = encrypt_message_for_self(_session,
dirk@526
   356
                                                    ident,
dirk@526
   357
                                                    _src,
dirk@556
   358
                                                    keysStringList,
dirk@526
   359
                                                    &_dst,
dirk@526
   360
                                                    PEP_enc_PGP_MIME,
dirk@526
   361
                                                    flags);
dirk@469
   362
    [self unlockWrite];
andreas@269
   363
dirk@556
   364
    free_stringlist(keysStringList);
dirk@556
   365
dirk@526
   366
    if (status) {
dirk@526
   367
        *status = theStatus;
dirk@526
   368
    }
dirk@526
   369
dirk@526
   370
    if ([NSError setError:error fromPEPStatus:theStatus]) {
dirk@526
   371
        return nil;
dirk@526
   372
    }
dirk@526
   373
dirk@467
   374
    NSDictionary *dst_;
andreas@269
   375
andreas@269
   376
    if (_dst) {
andreas@269
   377
        dst_ = PEP_messageDictFromStruct(_dst);
andreas@269
   378
    }
andreas@269
   379
    else {
andreas@269
   380
        dst_ = PEP_messageDictFromStruct(_src);
andreas@269
   381
    }
andreas@269
   382
andreas@269
   383
    free_message(_src);
andreas@269
   384
    free_message(_dst);
andreas@269
   385
    free_identity(ident);
andreas@269
   386
dirk@526
   387
    return dst_;
andreas@269
   388
}
andreas@269
   389
dirk@535
   390
- (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
dirk@557
   391
                                 forSelf:(PEPIdentity * _Nonnull)ownIdentity
dirk@556
   392
                               extraKeys:(PEPStringList * _Nullable)extraKeys
dirk@526
   393
                                  status:(PEP_STATUS * _Nullable)status
dirk@526
   394
                                   error:(NSError * _Nullable * _Nullable)error
dirk@381
   395
{
dirk@526
   396
    PEPDict *target = [self
dirk@526
   397
                       encryptMessageDict:message.dictionary
dirk@557
   398
                       forSelf:ownIdentity
dirk@556
   399
                       extraKeys:extraKeys
dirk@526
   400
                       status:status
dirk@526
   401
                       error:error];
dirk@526
   402
dirk@614
   403
    if (target) {
dirk@614
   404
        PEPMessage *encrypted = [PEPMessage new];
dirk@614
   405
        [encrypted setValuesForKeysWithDictionary:target];
dirk@614
   406
        return encrypted;
dirk@614
   407
    } else {
dirk@614
   408
        return nil;
dirk@614
   409
    }
dirk@381
   410
}
dirk@381
   411
dirk@608
   412
dirk@608
   413
- (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
dirk@608
   414
                                    toFpr:(NSString * _Nonnull)toFpr
dirk@608
   415
                                encFormat:(PEP_enc_format)encFormat
dirk@608
   416
                                    flags:(PEP_decrypt_flags)flags
dirk@608
   417
                                   status:(PEP_STATUS * _Nullable)status
dirk@608
   418
                                    error:(NSError * _Nullable * _Nullable)error __deprecated
dirk@608
   419
{
dirk@608
   420
    message *src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
dirk@608
   421
    message *dst = NULL;
dirk@608
   422
dirk@608
   423
    [self lockWrite];
dirk@610
   424
    PEP_STATUS theStatus =
dirk@610
   425
    encrypt_message_and_add_priv_key(_session, src, &dst,
dirk@610
   426
                                     [[toFpr precomposedStringWithCanonicalMapping] UTF8String],
dirk@610
   427
                                     encFormat, flags);
dirk@608
   428
    [self unlockWrite];
dirk@608
   429
dirk@608
   430
    if (status) {
dirk@608
   431
        *status = theStatus;
dirk@608
   432
    }
dirk@608
   433
dirk@608
   434
    if ([NSError setError:error fromPEPStatus:theStatus]) {
dirk@608
   435
        return nil;
dirk@608
   436
    }
dirk@608
   437
dirk@608
   438
    if (dst) {
dirk@608
   439
        return PEP_messageDictFromStruct(dst);
dirk@608
   440
    }
dirk@608
   441
dirk@608
   442
    return nil;
dirk@608
   443
}
dirk@608
   444
dirk@608
   445
- (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
dirk@608
   446
                                   toFpr:(NSString * _Nonnull)toFpr
dirk@608
   447
                               encFormat:(PEP_enc_format)encFormat
dirk@608
   448
                                   flags:(PEP_decrypt_flags)flags
dirk@608
   449
                                  status:(PEP_STATUS * _Nullable)status
dirk@608
   450
                                   error:(NSError * _Nullable * _Nullable)error
dirk@608
   451
{
dirk@608
   452
    PEPDict *target = [self
dirk@608
   453
                       encryptMessageDict:message.dictionary
dirk@608
   454
                       toFpr:toFpr
dirk@608
   455
                       encFormat:encFormat
dirk@608
   456
                       flags:flags
dirk@608
   457
                       status:status
dirk@608
   458
                       error:error];
dirk@608
   459
dirk@614
   460
    if (target) {
dirk@614
   461
        PEPMessage *encrypted = [PEPMessage new];
dirk@614
   462
        [encrypted setValuesForKeysWithDictionary:target];
dirk@614
   463
        return encrypted;
dirk@614
   464
    } else {
dirk@614
   465
        return nil;
dirk@614
   466
    }
dirk@608
   467
}
dirk@608
   468
dirk@573
   469
- (NSNumber * _Nullable)outgoingRatingForMessageDict:(PEPDict * _Nonnull)messageDict
dirk@573
   470
                                               error:(NSError * _Nullable * _Nullable)error
andreas@269
   471
{
dirk@528
   472
    message *_msg = PEP_messageDictToStruct(messageDict);
dirk@600
   473
    PEP_rating rating = PEP_rating_undefined;
andreas@269
   474
dirk@469
   475
    [self lockWrite];
dirk@573
   476
    PEP_STATUS status = outgoing_message_rating(_session, _msg, &rating);
dirk@469
   477
    [self unlockWrite];
andreas@269
   478
andreas@269
   479
    free_message(_msg);
andreas@269
   480
dirk@528
   481
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@573
   482
        return nil;
dirk@528
   483
    }
dirk@528
   484
dirk@573
   485
    return [NSNumber numberWithPEPRating:rating];
andreas@269
   486
}
andreas@269
   487
dirk@573
   488
- (NSNumber * _Nullable)outgoingRatingForMessage:(PEPMessage * _Nonnull)message
dirk@573
   489
                                           error:(NSError * _Nullable * _Nullable)error
dirk@377
   490
{
dirk@573
   491
    return [self outgoingRatingForMessageDict:(NSDictionary *) message error:error];
dirk@377
   492
}
dirk@377
   493
dirk@574
   494
- (NSNumber * _Nullable)ratingForIdentity:(PEPIdentity * _Nonnull)identity
dirk@574
   495
                                    error:(NSError * _Nullable * _Nullable)error
andreas@269
   496
{
dirk@364
   497
    pEp_identity *ident = PEP_identityToStruct(identity);
dirk@574
   498
    PEP_rating rating = PEP_rating_undefined;
andreas@269
   499
dirk@469
   500
    [self lockWrite];
dirk@574
   501
    PEP_STATUS status = identity_rating(_session, ident, &rating);
dirk@469
   502
    [self unlockWrite];
andreas@269
   503
andreas@269
   504
    free_identity(ident);
andreas@269
   505
dirk@529
   506
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@574
   507
        return nil;
dirk@529
   508
    }
dirk@529
   509
dirk@574
   510
    return [NSNumber numberWithPEPRating:rating];
andreas@269
   511
}
andreas@269
   512
dirk@531
   513
- (NSArray * _Nullable)trustwordsForFingerprint:(NSString * _Nonnull)fingerprint
dirk@531
   514
                                     languageID:(NSString * _Nonnull)languageID
dirk@531
   515
                                      shortened:(BOOL)shortened
dirk@531
   516
                                          error:(NSError * _Nullable * _Nullable)error
andreas@269
   517
{
andreas@269
   518
    NSMutableArray *array = [NSMutableArray array];
andreas@269
   519
dirk@531
   520
    for (int i = 0; i < [fingerprint length]; i += 4) {
andreas@269
   521
        if (shortened && i >= 20)
andreas@269
   522
            break;
andreas@269
   523
dirk@531
   524
        NSString *str = [fingerprint substringWithRange:NSMakeRange(i, 4)];
andreas@269
   525
andreas@269
   526
        unsigned int value;
andreas@269
   527
        [[NSScanner scannerWithString:str] scanHexInt:&value];
andreas@269
   528
dirk@564
   529
        PEPAutoPointer *word = [PEPAutoPointer new];
andreas@269
   530
        size_t size;
andreas@269
   531
dirk@563
   532
        PEP_STATUS status = trustword(_session,
dirk@563
   533
                                      value,
dirk@616
   534
                                      [[languageID precomposedStringWithCanonicalMapping]
dirk@616
   535
                                       UTF8String],
dirk@563
   536
                                      word.charPointerPointer,
dirk@563
   537
                                      &size);
dirk@531
   538
dirk@531
   539
        if ([NSError setError:error fromPEPStatus:status]) {
dirk@531
   540
            return nil;
andreas@269
   541
        }
andreas@269
   542
dirk@563
   543
        [array addObject:[NSString stringWithUTF8String:word.charPointer]];
andreas@269
   544
    }
andreas@269
   545
andreas@269
   546
    return array;
andreas@269
   547
}
andreas@269
   548
dirk@535
   549
- (BOOL)mySelf:(PEPIdentity * _Nonnull)identity error:(NSError * _Nullable * _Nullable)error
andreas@269
   550
{
dirk@312
   551
    pEp_identity *ident = PEP_identityToStruct(identity);
andreas@269
   552
dirk@469
   553
    [self lockWrite];
dirk@532
   554
    PEP_STATUS status = myself(_session, ident);
dirk@469
   555
    [self unlockWrite];
andreas@269
   556
dirk@532
   557
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@532
   558
        free_identity(ident);
dirk@532
   559
        return NO;
dirk@532
   560
    }
dirk@532
   561
dirk@477
   562
    [identity reset];
andreas@269
   563
    [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
andreas@269
   564
    free_identity(ident);
dirk@312
   565
dirk@532
   566
    return YES;
andreas@269
   567
}
andreas@269
   568
dirk@535
   569
- (BOOL)updateIdentity:(PEPIdentity * _Nonnull)identity error:(NSError * _Nullable * _Nullable)error
andreas@269
   570
{
dirk@520
   571
    if (identity.isOwn) {
dirk@532
   572
        return [self mySelf:identity error:error];
dirk@520
   573
    } else {
dirk@520
   574
        pEp_identity *ident = PEP_identityToStruct(identity);
andreas@269
   575
dirk@520
   576
        [self lockWrite];
dirk@532
   577
        PEP_STATUS status = update_identity(_session, ident);
dirk@520
   578
        [self unlockWrite];
andreas@269
   579
dirk@532
   580
        if ([NSError setError:error fromPEPStatus:status]) {
dirk@532
   581
            free_identity(ident);
dirk@532
   582
            return NO;
dirk@532
   583
        }
dirk@532
   584
dirk@520
   585
        [identity reset];
dirk@520
   586
        [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
dirk@520
   587
        free_identity(ident);
dirk@532
   588
dirk@532
   589
        return YES;
dirk@520
   590
    }
andreas@269
   591
}
andreas@269
   592
dirk@535
   593
- (BOOL)trustPersonalKey:(PEPIdentity * _Nonnull)identity
dirk@534
   594
                   error:(NSError * _Nullable * _Nullable)error
andreas@269
   595
{
dirk@360
   596
    pEp_identity *ident = PEP_identityToStruct(identity);
andreas@269
   597
dirk@469
   598
    [self lockWrite];
dirk@534
   599
    PEP_STATUS status = trust_personal_key(_session, ident);
dirk@469
   600
    [self unlockWrite];
andreas@269
   601
dirk@534
   602
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@534
   603
        free_identity(ident);
dirk@534
   604
        return NO;
dirk@534
   605
    }
dirk@534
   606
dirk@477
   607
    [identity reset];
andreas@269
   608
    [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
andreas@269
   609
    free_identity(ident);
dirk@534
   610
    return YES;
andreas@269
   611
}
andreas@269
   612
dirk@536
   613
- (BOOL)keyMistrusted:(PEPIdentity *)identity error:(NSError * _Nullable * _Nullable)error
dirk@536
   614
{
dirk@536
   615
    pEp_identity *ident = PEP_identityToStruct(identity);
dirk@536
   616
dirk@536
   617
    [self lockWrite];
dirk@536
   618
    PEP_STATUS status = key_mistrusted(_session, ident);
dirk@536
   619
    [self unlockWrite];
dirk@536
   620
dirk@536
   621
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@536
   622
        free_identity(ident);
dirk@536
   623
        return NO;
dirk@536
   624
    }
dirk@536
   625
dirk@536
   626
    [identity reset];
dirk@536
   627
    [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
dirk@536
   628
    free_identity(ident);
dirk@536
   629
dirk@536
   630
    return YES;
dirk@536
   631
}
dirk@536
   632
dirk@545
   633
- (BOOL)keyResetTrust:(PEPIdentity * _Nonnull)identity
dirk@545
   634
                error:(NSError * _Nullable * _Nullable)error
andreas@269
   635
{
dirk@361
   636
    pEp_identity *ident = PEP_identityToStruct(identity);
andreas@269
   637
dirk@469
   638
    [self lockWrite];
dirk@545
   639
    PEP_STATUS status = key_reset_trust(_session, ident);
dirk@469
   640
    [self unlockWrite];
andreas@269
   641
dirk@545
   642
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@545
   643
        free_identity(ident);
dirk@545
   644
        return NO;
dirk@545
   645
    }
dirk@545
   646
dirk@477
   647
    [identity reset];
andreas@269
   648
    [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
andreas@269
   649
    free_identity(ident);
dirk@545
   650
dirk@545
   651
    return YES;
andreas@269
   652
}
andreas@269
   653
dirk@551
   654
- (BOOL)importKey:(NSString * _Nonnull)keydata error:(NSError * _Nullable * _Nullable)error
andreas@269
   655
{
dirk@469
   656
    [self lockWrite];
dirk@616
   657
    PEP_STATUS status = import_key(_session,
dirk@616
   658
                                   [[keydata precomposedStringWithCanonicalMapping] UTF8String],
dirk@616
   659
                                   [keydata length], NULL);
dirk@469
   660
    [self unlockWrite];
andreas@269
   661
dirk@551
   662
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@551
   663
        return NO;
dirk@551
   664
    }
dirk@551
   665
dirk@551
   666
    return YES;
andreas@269
   667
}
andreas@269
   668
dirk@553
   669
- (BOOL)logTitle:(NSString * _Nonnull)title
dirk@553
   670
          entity:(NSString * _Nonnull)entity
dirk@553
   671
     description:(NSString * _Nullable)description
dirk@553
   672
         comment:(NSString * _Nullable)comment
dirk@553
   673
           error:(NSError * _Nullable * _Nullable)error
andreas@269
   674
{
dirk@469
   675
    [self lockWrite];
dirk@553
   676
    PEP_STATUS status = log_event(_session,
dirk@553
   677
                                  [[title precomposedStringWithCanonicalMapping] UTF8String],
dirk@553
   678
                                  [[entity precomposedStringWithCanonicalMapping] UTF8String],
dirk@553
   679
                                  [[description precomposedStringWithCanonicalMapping] UTF8String],
dirk@553
   680
                                  [[comment precomposedStringWithCanonicalMapping] UTF8String]);
dirk@469
   681
    [self unlockWrite];
dirk@553
   682
dirk@553
   683
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@553
   684
        return NO;
dirk@553
   685
    } else {
dirk@553
   686
        return YES;
dirk@553
   687
    }
andreas@269
   688
}
andreas@269
   689
dirk@552
   690
- (NSString * _Nullable)getLogWithError:(NSError * _Nullable * _Nullable)error
andreas@269
   691
{
dirk@475
   692
    char *theChars = NULL;
dirk@552
   693
    PEP_STATUS status = get_crashdump_log(_session, 0, &theChars);
dirk@552
   694
dirk@552
   695
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@552
   696
        return nil;
andreas@269
   697
    }
dirk@475
   698
dirk@475
   699
    if (theChars) {
dirk@475
   700
        return [NSString stringWithUTF8String:theChars];
dirk@475
   701
    } else {
dirk@552
   702
        [NSError setError:error fromPEPStatus:PEP_UNKNOWN_ERROR];
dirk@475
   703
        return nil;
dirk@475
   704
    }
andreas@269
   705
}
andreas@269
   706
dirk@535
   707
- (NSString * _Nullable)getTrustwordsIdentity1:(PEPIdentity * _Nonnull)identity1
dirk@535
   708
                                     identity2:(PEPIdentity * _Nonnull)identity2
dirk@535
   709
                                      language:(NSString * _Nullable)language
dirk@535
   710
                                          full:(BOOL)full
dirk@558
   711
                                         error:(NSError * _Nullable * _Nullable)error
andreas@269
   712
{
dirk@365
   713
    pEp_identity *ident1 = PEP_identityToStruct(identity1);
dirk@365
   714
    pEp_identity *ident2 = PEP_identityToStruct(identity2);
andreas@269
   715
    PEP_STATUS status;
andreas@269
   716
dirk@564
   717
    PEPAutoPointer *trustwords = [PEPAutoPointer new];
dirk@558
   718
    size_t sizeWritten = 0;
dirk@558
   719
dirk@469
   720
    [self lockWrite];
dirk@469
   721
    status = get_trustwords(_session, ident1, ident2,
dirk@469
   722
                            [[language precomposedStringWithCanonicalMapping]
dirk@469
   723
                             UTF8String],
dirk@563
   724
                            trustwords.charPointerPointer, &sizeWritten, full);
dirk@469
   725
    [self unlockWrite];
dirk@469
   726
dirk@558
   727
    NSString *result = nil;
dirk@558
   728
dirk@558
   729
    if (![NSError setError:error fromPEPStatus:status]) {
dirk@616
   730
        result = [NSString stringWithUTF8String:trustwords.charPointer];
andreas@269
   731
    }
dirk@558
   732
andreas@269
   733
    return result;
andreas@269
   734
}
andreas@269
   735
dirk@560
   736
- (NSArray<PEPLanguage *> * _Nullable)languageListWithError:(NSError * _Nullable * _Nullable)error
andreas@269
   737
{
dirk@564
   738
    PEPAutoPointer *chLangs = [PEPAutoPointer new];
dirk@563
   739
    PEP_STATUS status = get_languagelist(_session, chLangs.charPointerPointer);
dirk@560
   740
dirk@560
   741
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@560
   742
        return nil;
dirk@560
   743
    }
dirk@560
   744
dirk@563
   745
    NSString *parserInput = [NSString stringWithUTF8String:chLangs.charPointer];
andreas@269
   746
andreas@269
   747
    NSMutableArray<NSString *> *tokens = [NSMutableArray array];
andreas@269
   748
    PEPCSVScanner *scanner = [[PEPCSVScanner alloc] initWithString:parserInput];
andreas@269
   749
    while (YES) {
andreas@269
   750
        NSString *token = [scanner nextString];
andreas@269
   751
        if (!token) {
andreas@269
   752
            break;
andreas@269
   753
        }
andreas@269
   754
        [tokens addObject:token];
andreas@269
   755
    }
andreas@269
   756
    
andreas@269
   757
    NSArray *theTokens = [NSArray arrayWithArray:tokens];
andreas@269
   758
    NSMutableArray<PEPLanguage *> *langs = [NSMutableArray new];
andreas@269
   759
    while (YES) {
andreas@269
   760
        ArrayTake *take = [theTokens takeOrNil:3];
andreas@269
   761
        if (!take) {
andreas@269
   762
            break;
andreas@269
   763
        }
andreas@269
   764
        NSArray *elements = take.elements;
andreas@269
   765
        PEPLanguage *lang = [[PEPLanguage alloc]
andreas@269
   766
                             initWithCode:[elements objectAtIndex:0]
andreas@269
   767
                             name:[elements objectAtIndex:1]
andreas@269
   768
                             sentence:[elements objectAtIndex:2]];
andreas@269
   769
        [langs addObject:lang];
andreas@269
   770
        theTokens = take.rest;
andreas@269
   771
    }
andreas@269
   772
    
andreas@269
   773
    return [NSArray arrayWithArray:langs];
andreas@269
   774
}
andreas@269
   775
dirk@565
   776
- (BOOL)undoLastMistrustWithError:(NSError * _Nullable * _Nullable)error;
andreas@269
   777
{
dirk@469
   778
    [self lockWrite];
dirk@469
   779
    PEP_STATUS status = undo_last_mistrust(_session);
dirk@469
   780
    [self unlockWrite];
dirk@469
   781
dirk@565
   782
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@565
   783
        return NO;
dirk@565
   784
    }
dirk@565
   785
dirk@565
   786
    return YES;
andreas@269
   787
}
andreas@269
   788
dirk@417
   789
static NSDictionary *ratingToString;
dirk@417
   790
static NSDictionary *stringToRating;
dirk@417
   791
dirk@417
   792
+ (void)initialize
dirk@417
   793
{
dirk@417
   794
    NSDictionary *ratingToStringIntern =
dirk@417
   795
    @{
dirk@417
   796
      [NSNumber numberWithInteger:PEP_rating_cannot_decrypt]: @"cannot_decrypt",
dirk@417
   797
      [NSNumber numberWithInteger:PEP_rating_have_no_key]: @"have_no_key",
dirk@417
   798
      [NSNumber numberWithInteger:PEP_rating_unencrypted]: @"unencrypted",
dirk@417
   799
      [NSNumber numberWithInteger:PEP_rating_unencrypted_for_some]: @"unencrypted_for_some",
dirk@417
   800
      [NSNumber numberWithInteger:PEP_rating_unreliable]: @"unreliable",
dirk@417
   801
      [NSNumber numberWithInteger:PEP_rating_reliable]: @"reliable",
dirk@417
   802
      [NSNumber numberWithInteger:PEP_rating_trusted]: @"trusted",
dirk@417
   803
      [NSNumber numberWithInteger:PEP_rating_trusted_and_anonymized]: @"trusted_and_anonymized",
dirk@417
   804
      [NSNumber numberWithInteger:PEP_rating_fully_anonymous]: @"fully_anonymous",
dirk@417
   805
      [NSNumber numberWithInteger:PEP_rating_mistrust]: @"mistrust",
dirk@417
   806
      [NSNumber numberWithInteger:PEP_rating_b0rken]: @"b0rken",
dirk@417
   807
      [NSNumber numberWithInteger:PEP_rating_under_attack]: @"under_attack",
dirk@417
   808
      [NSNumber numberWithInteger:PEP_rating_undefined]: @"undefined",
dirk@417
   809
      };
dirk@417
   810
    NSMutableDictionary *stringToRatingMutable = [NSMutableDictionary
dirk@417
   811
                                                  dictionaryWithCapacity:
dirk@417
   812
                                                  ratingToStringIntern.count];
dirk@417
   813
    for (NSNumber *ratingNumber in ratingToStringIntern.allKeys) {
dirk@417
   814
        NSString *ratingName = [ratingToStringIntern objectForKey:ratingNumber];
dirk@417
   815
        [stringToRatingMutable setObject:ratingNumber forKey:ratingName];
dirk@417
   816
    }
dirk@417
   817
    ratingToString = ratingToStringIntern;
dirk@417
   818
    stringToRating = [NSDictionary dictionaryWithDictionary:stringToRatingMutable];
dirk@417
   819
}
dirk@417
   820
dirk@417
   821
- (PEP_rating)ratingFromString:(NSString * _Nonnull)string
dirk@417
   822
{
dirk@417
   823
    NSNumber *num = [stringToRating objectForKey:string];
dirk@417
   824
    if (num) {
dirk@417
   825
        return (PEP_rating) [num integerValue];
dirk@417
   826
    } else {
dirk@417
   827
        return PEP_rating_undefined;
dirk@417
   828
    }
dirk@417
   829
}
dirk@417
   830
dirk@417
   831
- (NSString * _Nonnull)stringFromRating:(PEP_rating)rating
dirk@417
   832
{
dirk@417
   833
    NSString *stringRating = [ratingToString objectForKey:[NSNumber numberWithInteger:rating]];
dirk@417
   834
    if (stringRating) {
dirk@417
   835
        return stringRating;
dirk@417
   836
    } else {
dirk@417
   837
        return @"undefined";
dirk@417
   838
    }
dirk@417
   839
}
dirk@417
   840
dirk@567
   841
- (NSNumber * _Nullable)isPEPUser:(PEPIdentity * _Nonnull)identity
dirk@567
   842
                            error:(NSError * _Nullable * _Nullable)error
dirk@427
   843
{
dirk@428
   844
    pEp_identity *ident = PEP_identityToStruct(identity);
dirk@428
   845
    bool isPEP;
dirk@428
   846
    PEP_STATUS status = is_pep_user(self.session, ident, &isPEP);
dirk@567
   847
dirk@567
   848
    if ([NSError setError:error fromPEPStatus:status]) {
dirk@567
   849
        return nil;
dirk@428
   850
    } else {
dirk@567
   851
        return [NSNumber numberWithBool:isPEP];
dirk@428
   852
    }
dirk@427
   853
}
dirk@427
   854
dirk@501
   855
- (BOOL)setOwnKey:(PEPIdentity * _Nonnull)identity fingerprint:(NSString * _Nonnull)fingerprint
dirk@501
   856
            error:(NSError * _Nullable * _Nullable)error
dirk@501
   857
{
dirk@501
   858
    pEp_identity *ident = PEP_identityToStruct(identity);
dirk@501
   859
    PEP_STATUS status = set_own_key(self.session, ident,
dirk@501
   860
                                    [[fingerprint precomposedStringWithCanonicalMapping]
dirk@501
   861
                                     UTF8String]);
dirk@501
   862
    if (status == PEP_STATUS_OK) {
dirk@501
   863
        return YES;
dirk@501
   864
    } else {
dirk@501
   865
        if (error) {
dirk@501
   866
            *error = [NSError errorWithPEPStatus:status];
dirk@501
   867
        }
dirk@501
   868
        return NO;
dirk@501
   869
    }
dirk@501
   870
}
dirk@501
   871
andreas@269
   872
@end