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