Element -> Site WIP
This commit is contained in:
		@@ -16,8 +16,8 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPKey.h"
 | 
			
		||||
#import "MPElementStoredEntity.h"
 | 
			
		||||
#import "MPElementGeneratedEntity.h"
 | 
			
		||||
#import "MPSiteStoredEntity.h"
 | 
			
		||||
#import "MPSiteGeneratedEntity.h"
 | 
			
		||||
 | 
			
		||||
#define MPAlgorithmDefaultVersion 1
 | 
			
		||||
#define MPAlgorithmDefault MPAlgorithmForVersion(MPAlgorithmDefaultVersion)
 | 
			
		||||
@@ -44,48 +44,48 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
 | 
			
		||||
@required
 | 
			
		||||
- (NSUInteger)version;
 | 
			
		||||
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
 | 
			
		||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit;
 | 
			
		||||
- (BOOL)migrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit;
 | 
			
		||||
 | 
			
		||||
- (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName;
 | 
			
		||||
- (MPKey *)keyFromKeyData:(NSData *)keyData;
 | 
			
		||||
- (NSData *)keyIDForKeyData:(NSData *)keyData;
 | 
			
		||||
 | 
			
		||||
- (NSString *)scopeForVariant:(MPElementVariant)variant;
 | 
			
		||||
- (NSString *)nameOfType:(MPElementType)type;
 | 
			
		||||
- (NSString *)shortNameOfType:(MPElementType)type;
 | 
			
		||||
- (NSString *)classNameOfType:(MPElementType)type;
 | 
			
		||||
- (Class)classOfType:(MPElementType)type;
 | 
			
		||||
- (NSString *)scopeForVariant:(MPSiteVariant)variant;
 | 
			
		||||
- (NSString *)nameOfType:(MPSiteType)type;
 | 
			
		||||
- (NSString *)shortNameOfType:(MPSiteType)type;
 | 
			
		||||
- (NSString *)classNameOfType:(MPSiteType)type;
 | 
			
		||||
- (Class)classOfType:(MPSiteType)type;
 | 
			
		||||
- (NSArray *)allTypes;
 | 
			
		||||
- (NSArray *)allTypesStartingWith:(MPElementType)startingType;
 | 
			
		||||
- (MPElementType)nextType:(MPElementType)type;
 | 
			
		||||
- (MPElementType)previousType:(MPElementType)type;
 | 
			
		||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
 | 
			
		||||
- (MPSiteType)nextType:(MPSiteType)type;
 | 
			
		||||
- (MPSiteType)previousType:(MPSiteType)type;
 | 
			
		||||
 | 
			
		||||
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter
 | 
			
		||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  variant:(MPElementVariant)variant usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  variant:(MPSiteVariant)variant usingKey:(MPKey *)key;
 | 
			
		||||
 | 
			
		||||
- (NSString *)storedLoginForElement:(MPElementStoredEntity *)element usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)storedPasswordForElement:(MPElementStoredEntity *)element usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)storedLoginForSite:(MPSiteStoredEntity *)site usingKey:(MPKey *)key;
 | 
			
		||||
- (NSString *)storedPasswordForSite:(MPSiteStoredEntity *)site usingKey:(MPKey *)key;
 | 
			
		||||
 | 
			
		||||
- (BOOL)savePassword:(NSString *)clearPassword toElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
 | 
			
		||||
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
 | 
			
		||||
 | 
			
		||||
- (NSString *)resolveLoginForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
 | 
			
		||||
- (NSString *)resolvePasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
 | 
			
		||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
 | 
			
		||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
 | 
			
		||||
 | 
			
		||||
- (void)resolveLoginForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey
 | 
			
		||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey
 | 
			
		||||
                     result:(void ( ^ )(NSString *result))resultBlock;
 | 
			
		||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey
 | 
			
		||||
                        result:(void ( ^ )(NSString *result))resultBlock;
 | 
			
		||||
- (void)resolvePasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey
 | 
			
		||||
                           result:(void ( ^ )(NSString *result))resultBlock;
 | 
			
		||||
 | 
			
		||||
- (void)importProtectedPassword:(NSString *)protectedPassword protectedByKey:(MPKey *)importKey
 | 
			
		||||
                    intoElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
 | 
			
		||||
- (void)importClearTextPassword:(NSString *)clearPassword intoElement:(MPElementEntity *)element
 | 
			
		||||
                       usingKey:(MPKey *)elementKey;
 | 
			
		||||
- (NSString *)exportPasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
 | 
			
		||||
                       intoSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
 | 
			
		||||
- (void)importClearTextPassword:(NSString *)clearPassword intoSite:(MPSiteEntity *)site
 | 
			
		||||
                       usingKey:(MPKey *)siteKey;
 | 
			
		||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
 | 
			
		||||
 | 
			
		||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPElementType)type byAttacker:(MPAttacker)attacker;
 | 
			
		||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPSiteType)type byAttacker:(MPAttacker)attacker;
 | 
			
		||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordString:(NSString *)password byAttacker:(MPAttacker)attacker;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
@interface MPAlgorithmV0 : NSObject<MPAlgorithm>
 | 
			
		||||
 | 
			
		||||
- (NSDictionary *)allCiphers;
 | 
			
		||||
- (NSArray *)ciphersForType:(MPElementType)type;
 | 
			
		||||
- (NSArray *)ciphersForType:(MPSiteType)type;
 | 
			
		||||
- (NSArray *)cipherClasses;
 | 
			
		||||
- (NSArray *)cipherClassCharacters;
 | 
			
		||||
- (NSString *)charactersForCipherClass:(NSString *)cipherClass;
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,7 @@
 | 
			
		||||
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc {
 | 
			
		||||
 | 
			
		||||
    NSError *error = nil;
 | 
			
		||||
    NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
 | 
			
		||||
    NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
 | 
			
		||||
    migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user];
 | 
			
		||||
    NSArray *migrationElements = [moc executeFetchRequest:migrationRequest error:&error];
 | 
			
		||||
    if (!migrationElements) {
 | 
			
		||||
@@ -84,14 +84,14 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BOOL requiresExplicitMigration = NO;
 | 
			
		||||
    for (MPElementEntity *migrationElement in migrationElements)
 | 
			
		||||
    for (MPSiteEntity *migrationElement in migrationElements)
 | 
			
		||||
        if (![migrationElement migrateExplicitly:NO])
 | 
			
		||||
            requiresExplicitMigration = YES;
 | 
			
		||||
 | 
			
		||||
    return requiresExplicitMigration;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit {
 | 
			
		||||
- (BOOL)migrateSite:(MPSiteEntity *)element explicit:(BOOL)explicit {
 | 
			
		||||
 | 
			
		||||
    if (element.version != [self version] - 1)
 | 
			
		||||
        // Only migrate from previous version.
 | 
			
		||||
@@ -138,129 +138,138 @@
 | 
			
		||||
    return [keyData hashWith:MP_hash];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)scopeForVariant:(MPElementVariant)variant {
 | 
			
		||||
- (NSString *)scopeForVariant:(MPSiteVariant)variant {
 | 
			
		||||
 | 
			
		||||
    switch (variant) {
 | 
			
		||||
        case MPElementVariantPassword:
 | 
			
		||||
        case MPSiteVariantPassword:
 | 
			
		||||
            return @"com.lyndir.masterpassword";
 | 
			
		||||
        case MPElementVariantLogin:
 | 
			
		||||
        case MPSiteVariantLogin:
 | 
			
		||||
            return @"com.lyndir.masterpassword.login";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw( @"Unsupported variant: %ld", (long)variant );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)nameOfType:(MPElementType)type {
 | 
			
		||||
- (NSString *)nameOfType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    if (!type)
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
            return @"Maximum Security Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
            return @"Long Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
            return @"Medium Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
            return @"Basic Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
            return @"Short Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
            return @"PIN";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
            return @"Login Name";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase:
 | 
			
		||||
            return @"Phrase";
 | 
			
		||||
 | 
			
		||||
        case MPSiteTypeStoredPersonal:
 | 
			
		||||
            return @"Personal Password";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            return @"Device Private Password";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw( @"Type not supported: %lu", (long)type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)shortNameOfType:(MPElementType)type {
 | 
			
		||||
- (NSString *)shortNameOfType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    if (!type)
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
            return @"Maximum";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
            return @"Long";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
            return @"Medium";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
            return @"Basic";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
            return @"Short";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
            return @"PIN";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
            return @"Name";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase:
 | 
			
		||||
            return @"Phrase";
 | 
			
		||||
 | 
			
		||||
        case MPSiteTypeStoredPersonal:
 | 
			
		||||
            return @"Personal";
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            return @"Device";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw( @"Type not supported: %lu", (long)type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)classNameOfType:(MPElementType)type {
 | 
			
		||||
- (NSString *)classNameOfType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    return NSStringFromClass( [self classOfType:type] );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (Class)classOfType:(MPElementType)type {
 | 
			
		||||
- (Class)classOfType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    if (!type)
 | 
			
		||||
        Throw( @"No type given." );
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal:
 | 
			
		||||
            return [MPElementStoredEntity class];
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase:
 | 
			
		||||
            return [MPElementGeneratedEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
            return [MPElementStoredEntity class];
 | 
			
		||||
        case MPSiteTypeStoredPersonal:
 | 
			
		||||
            return [MPSiteStoredEntity class];
 | 
			
		||||
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            return [MPSiteStoredEntity class];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Throw( @"Type not supported: %lu", (long)type );
 | 
			
		||||
@@ -268,13 +277,13 @@
 | 
			
		||||
 | 
			
		||||
- (NSArray *)allTypes {
 | 
			
		||||
 | 
			
		||||
    return [self allTypesStartingWith:MPElementTypeGeneratedMaximum];
 | 
			
		||||
    return [self allTypesStartingWith:MPSiteTypeGeneratedMaximum];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSArray *)allTypesStartingWith:(MPElementType)startingType {
 | 
			
		||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType {
 | 
			
		||||
 | 
			
		||||
    NSMutableArray *allTypes = [[NSMutableArray alloc] initWithCapacity:8];
 | 
			
		||||
    MPElementType currentType = startingType;
 | 
			
		||||
    MPSiteType currentType = startingType;
 | 
			
		||||
    do {
 | 
			
		||||
        [allTypes addObject:@(currentType)];
 | 
			
		||||
    } while ((currentType = [self nextType:currentType]) != startingType);
 | 
			
		||||
@@ -282,33 +291,33 @@
 | 
			
		||||
    return allTypes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)nextType:(MPElementType)type {
 | 
			
		||||
- (MPSiteType)nextType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
            return MPElementTypeGeneratedLong;
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
            return MPElementTypeGeneratedMedium;
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
            return MPElementTypeGeneratedBasic;
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
            return MPElementTypeGeneratedShort;
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
            return MPElementTypeGeneratedPIN;
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
            return MPElementTypeStoredPersonal;
 | 
			
		||||
        case MPElementTypeStoredPersonal:
 | 
			
		||||
            return MPElementTypeStoredDevicePrivate;
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
            return MPElementTypeGeneratedMaximum;
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
            return MPSiteTypeGeneratedLong;
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
            return MPSiteTypeGeneratedMedium;
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
            return MPSiteTypeGeneratedBasic;
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
            return MPSiteTypeGeneratedShort;
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
            return MPSiteTypeGeneratedPIN;
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
            return MPSiteTypeStoredPersonal;
 | 
			
		||||
        case MPSiteTypeStoredPersonal:
 | 
			
		||||
            return MPSiteTypeStoredDevicePrivate;
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            return MPSiteTypeGeneratedMaximum;
 | 
			
		||||
        default:
 | 
			
		||||
            return MPElementTypeGeneratedLong;
 | 
			
		||||
            return MPSiteTypeGeneratedLong;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)previousType:(MPElementType)type {
 | 
			
		||||
- (MPSiteType)previousType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    MPElementType previousType = type, nextType = type;
 | 
			
		||||
    MPSiteType previousType = type, nextType = type;
 | 
			
		||||
    while ((nextType = [self nextType:nextType]) != type)
 | 
			
		||||
        previousType = nextType;
 | 
			
		||||
 | 
			
		||||
@@ -327,7 +336,7 @@
 | 
			
		||||
    return ciphers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSArray *)ciphersForType:(MPElementType)type {
 | 
			
		||||
- (NSArray *)ciphersForType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    NSString *typeClass = [self classNameOfType:type];
 | 
			
		||||
    NSString *typeName = [self nameOfType:type];
 | 
			
		||||
@@ -351,19 +360,19 @@
 | 
			
		||||
 | 
			
		||||
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return [self generateContentForSiteNamed:name ofType:MPElementTypeGeneratedName withCounter:1
 | 
			
		||||
                                     variant:MPElementVariantLogin usingKey:key];
 | 
			
		||||
    return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedName withCounter:1
 | 
			
		||||
                                                 variant:MPSiteVariantLogin usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  usingKey:(MPKey *)key {
 | 
			
		||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
 | 
			
		||||
              usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return [self generateContentForSiteNamed:name ofType:type withCounter:counter
 | 
			
		||||
                                     variant:MPElementVariantPassword usingKey:key];
 | 
			
		||||
                                     variant:MPSiteVariantPassword usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  variant:(MPElementVariant)variant usingKey:(MPKey *)key {
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
 | 
			
		||||
              variant:(MPSiteVariant)variant usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    // Determine the seed whose bytes will be used for calculating a password
 | 
			
		||||
    uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length );
 | 
			
		||||
@@ -404,49 +413,50 @@
 | 
			
		||||
    return content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)storedLoginForElement:(MPElementStoredEntity *)element usingKey:(MPKey *)key {
 | 
			
		||||
- (NSString *)storedLoginForSite:(MPSiteStoredEntity *)element usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)storedPasswordForElement:(MPElementStoredEntity *)element usingKey:(MPKey *)key {
 | 
			
		||||
- (NSString *)storedPasswordForSite:(MPSiteStoredEntity *)element usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return [self decryptContent:element.contentObject usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)savePassword:(NSString *)clearContent toElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
- (BOOL)savePassword:(NSString *)clearContent toSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    switch (element.type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPElementTypeGeneratedName: {
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase: {
 | 
			
		||||
            wrn( @"Cannot save content to element with generated type %lu.", (long)element.type );
 | 
			
		||||
            return NO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
 | 
			
		||||
        case MPSiteTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPSiteStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                return NO;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
 | 
			
		||||
                    encryptWithSymmetricKey:[elementKey subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
 | 
			
		||||
            if ([((MPElementStoredEntity *)element).contentObject isEqualToData:encryptedContent])
 | 
			
		||||
            if ([((MPSiteStoredEntity *)element).contentObject isEqualToData:encryptedContent])
 | 
			
		||||
                return NO;
 | 
			
		||||
 | 
			
		||||
            ((MPElementStoredEntity *)element).contentObject = encryptedContent;
 | 
			
		||||
            ((MPSiteStoredEntity *)element).contentObject = encryptedContent;
 | 
			
		||||
            return YES;
 | 
			
		||||
        }
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate: {
 | 
			
		||||
            if (![element isKindOfClass:[MPSiteStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                return NO;
 | 
			
		||||
            }
 | 
			
		||||
@@ -463,7 +473,7 @@
 | 
			
		||||
                        (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
 | 
			
		||||
#endif
 | 
			
		||||
                }];
 | 
			
		||||
            ((MPElementStoredEntity *)element).contentObject = nil;
 | 
			
		||||
            ((MPSiteStoredEntity *)element).contentObject = nil;
 | 
			
		||||
            return YES;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -471,12 +481,12 @@
 | 
			
		||||
    Throw( @"Unsupported type: %ld", (long)element.type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)resolveLoginForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    dispatch_group_t group = dispatch_group_create();
 | 
			
		||||
    dispatch_group_enter( group );
 | 
			
		||||
    __block NSString *result = nil;
 | 
			
		||||
    [self resolveLoginForElement:element usingKey:elementKey result:^(NSString *result_) {
 | 
			
		||||
    [self resolveLoginForSite:element usingKey:elementKey result:^(NSString *result_) {
 | 
			
		||||
        result = result_;
 | 
			
		||||
        dispatch_group_leave( group );
 | 
			
		||||
    }];
 | 
			
		||||
@@ -485,12 +495,12 @@
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)resolvePasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    dispatch_group_t group = dispatch_group_create();
 | 
			
		||||
    dispatch_group_enter( group );
 | 
			
		||||
    __block NSString *result = nil;
 | 
			
		||||
    [self resolvePasswordForElement:element usingKey:elementKey result:^(NSString *result_) {
 | 
			
		||||
    [self resolvePasswordForSite:element usingKey:elementKey result:^(NSString *result_) {
 | 
			
		||||
        result = result_;
 | 
			
		||||
        dispatch_group_leave( group );
 | 
			
		||||
    }];
 | 
			
		||||
@@ -499,7 +509,7 @@
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolveLoginForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey result:(void ( ^ )(NSString *result))resultBlock {
 | 
			
		||||
- (void)resolveLoginForSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey result:(void ( ^ )(NSString *result))resultBlock {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    NSString *name = element.name;
 | 
			
		||||
@@ -521,25 +531,26 @@
 | 
			
		||||
    } );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolvePasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey result:(void ( ^ )(NSString *result))resultBlock {
 | 
			
		||||
- (void)resolvePasswordForSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey result:(void ( ^ )(NSString *result))resultBlock {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    switch (element.type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPElementTypeGeneratedName: {
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementGeneratedEntity class]]) {
 | 
			
		||||
                wrn( @"Element with generated type %lu is not an MPElementGeneratedEntity, but a %@.",
 | 
			
		||||
                wrn( @"Element with generated type %lu is not an MPSiteGeneratedEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            NSString *name = element.name;
 | 
			
		||||
            MPElementType type = element.type;
 | 
			
		||||
            MPSiteType type = element.type;
 | 
			
		||||
            NSUInteger counter = ((MPElementGeneratedEntity *)element).counter;
 | 
			
		||||
            id<MPAlgorithm> algorithm = nil;
 | 
			
		||||
            if (!element.name.length)
 | 
			
		||||
@@ -556,14 +567,14 @@
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
 | 
			
		||||
        case MPSiteTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPSiteStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            NSData *encryptedContent = ((MPElementStoredEntity *)element).contentObject;
 | 
			
		||||
            NSData *encryptedContent = ((MPSiteStoredEntity *)element).contentObject;
 | 
			
		||||
 | 
			
		||||
            dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
 | 
			
		||||
                NSString *result = [self decryptContent:encryptedContent usingKey:elementKey];
 | 
			
		||||
@@ -571,9 +582,9 @@
 | 
			
		||||
            } );
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate: {
 | 
			
		||||
            NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
 | 
			
		||||
                    @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate: {
 | 
			
		||||
            NSAssert( [element isKindOfClass:[MPSiteStoredEntity class]],
 | 
			
		||||
                    @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.", (long)element.type,
 | 
			
		||||
                    [element class] );
 | 
			
		||||
 | 
			
		||||
            NSDictionary *elementQuery = [self queryForDevicePrivateElementNamed:element.name];
 | 
			
		||||
@@ -589,93 +600,96 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)importProtectedPassword:(NSString *)protectedContent protectedByKey:(MPKey *)importKey
 | 
			
		||||
                    intoElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
                                                                   intoSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    switch (element.type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPElementTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase:
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
 | 
			
		||||
        case MPSiteTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPSiteStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if ([importKey.keyID isEqualToData:elementKey.keyID])
 | 
			
		||||
                ((MPElementStoredEntity *)element).contentObject = [protectedContent decodeBase64];
 | 
			
		||||
                ((MPSiteStoredEntity *)element).contentObject = [protectedContent decodeBase64];
 | 
			
		||||
 | 
			
		||||
            else {
 | 
			
		||||
                NSString *clearContent = [self decryptContent:[protectedContent decodeBase64] usingKey:importKey];
 | 
			
		||||
                [self importClearTextPassword:clearContent intoElement:element usingKey:elementKey];
 | 
			
		||||
                [self importClearTextPassword:clearContent intoSite:element usingKey:elementKey];
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)importClearTextPassword:(NSString *)clearContent intoElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
- (void)importClearTextPassword:(NSString *)clearContent intoSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    switch (element.type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPElementTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase:
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal: {
 | 
			
		||||
            [self savePassword:clearContent toElement:element usingKey:elementKey];
 | 
			
		||||
        case MPSiteTypeStoredPersonal: {
 | 
			
		||||
            [self savePassword:clearContent toSite:element usingKey:elementKey];
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)exportPasswordForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)element usingKey:(MPKey *)elementKey {
 | 
			
		||||
 | 
			
		||||
    NSAssert( [elementKey.keyID isEqualToData:element.user.keyID], @"Element does not belong to current user." );
 | 
			
		||||
    if (!(element.type & MPElementFeatureExportContent))
 | 
			
		||||
    if (!(element.type & MPSiteFeatureExportContent))
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    NSString *result = nil;
 | 
			
		||||
    switch (element.type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPElementTypeGeneratedName: {
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedName:
 | 
			
		||||
        case MPSiteTypeGeneratedPhrase: {
 | 
			
		||||
            result = nil;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPElementStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
 | 
			
		||||
        case MPSiteTypeStoredPersonal: {
 | 
			
		||||
            if (![element isKindOfClass:[MPSiteStoredEntity class]]) {
 | 
			
		||||
                wrn( @"Element with stored type %lu is not an MPSiteStoredEntity, but a %@.",
 | 
			
		||||
                        (long)element.type, [element class] );
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            result = [((MPElementStoredEntity *)element).contentObject encodeBase64];
 | 
			
		||||
            result = [((MPSiteStoredEntity *)element).contentObject encodeBase64];
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate: {
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate: {
 | 
			
		||||
            result = nil;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -710,7 +724,7 @@
 | 
			
		||||
    return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPElementType)type byAttacker:(MPAttacker)attacker {
 | 
			
		||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPSiteType)type byAttacker:(MPAttacker)attacker {
 | 
			
		||||
 | 
			
		||||
    if (!type)
 | 
			
		||||
        return NO;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,14 +25,14 @@
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit {
 | 
			
		||||
- (BOOL)migrateSite:(MPSiteEntity *)element explicit:(BOOL)explicit {
 | 
			
		||||
 | 
			
		||||
    if (element.version != [self version] - 1)
 | 
			
		||||
        // Only migrate from previous version.
 | 
			
		||||
        return NO;
 | 
			
		||||
 | 
			
		||||
    if (!explicit) {
 | 
			
		||||
        if (element.type & MPElementTypeClassGenerated) {
 | 
			
		||||
        if (element.type & MPSiteTypeClassGenerated) {
 | 
			
		||||
            // This migration requires explicit permission for types of the generated class.
 | 
			
		||||
            element.requiresExplicitMigration = YES;
 | 
			
		||||
            return NO;
 | 
			
		||||
@@ -45,8 +45,8 @@
 | 
			
		||||
    return YES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  variant:(MPElementVariant)variant usingKey:(MPKey *)key {
 | 
			
		||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
 | 
			
		||||
                                  variant:(MPSiteVariant)variant usingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    // Determine the seed whose bytes will be used for calculating a password
 | 
			
		||||
    uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length );
 | 
			
		||||
 
 | 
			
		||||
@@ -176,10 +176,10 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
 | 
			
		||||
            (long)[user.elements count] )];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    for (MPElementEntity *element in user.elements) {
 | 
			
		||||
        if (element.type & MPElementTypeClassStored) {
 | 
			
		||||
    for (MPSiteEntity *element in user.elements) {
 | 
			
		||||
        if (element.type & MPSiteTypeClassStored) {
 | 
			
		||||
            NSString *content;
 | 
			
		||||
            while (!(content = [element.algorithm storedPasswordForElement:(MPElementStoredEntity *)element usingKey:recoverKey])) {
 | 
			
		||||
            while (!(content = [element.algorithm storedPasswordForSite:(MPElementStoredEntity *)element usingKey:recoverKey])) {
 | 
			
		||||
                // Failed to decrypt element with the current recoveryKey.  Ask user for a new one to use.
 | 
			
		||||
                __block NSString *masterPassword = nil;
 | 
			
		||||
 | 
			
		||||
@@ -216,7 +216,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            if (![recoverKey isEqualToKey:newKey])
 | 
			
		||||
                [element.algorithm savePassword:content toElement:element usingKey:newKey];
 | 
			
		||||
                [element.algorithm savePassword:content toSite:element usingKey:newKey];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,8 +29,8 @@ typedef NS_ENUM( NSUInteger, MPImportResult ) {
 | 
			
		||||
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
 | 
			
		||||
 | 
			
		||||
/** @param completion The block to execute after adding the element, executed from the main thread with the new element in the main MOC. */
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion;
 | 
			
		||||
- (MPElementEntity *)changeElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context toType:(MPElementType)type;
 | 
			
		||||
- (void)addSiteNamed:(NSString *)siteName completion:(void ( ^ )(MPSiteEntity *element, NSManagedObjectContext *context))completion;
 | 
			
		||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPSiteType)type;
 | 
			
		||||
- (MPImportResult)importSites:(NSString *)importedSitesString
 | 
			
		||||
            askImportPassword:(NSString *(^)(NSString *userName))importPassword
 | 
			
		||||
              askUserPassword:(NSString *(^)(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword;
 | 
			
		||||
 
 | 
			
		||||
@@ -333,7 +333,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
#pragma mark - Utilities
 | 
			
		||||
 | 
			
		||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion {
 | 
			
		||||
- (void)addSiteNamed:(NSString *)siteName completion:(void ( ^ )(MPSiteEntity *site, NSManagedObjectContext *context))completion {
 | 
			
		||||
 | 
			
		||||
    if (![siteName length]) {
 | 
			
		||||
        completion( nil, nil );
 | 
			
		||||
@@ -348,61 +348,61 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MPElementType type = activeUser.defaultType;
 | 
			
		||||
        MPSiteType type = activeUser.defaultType;
 | 
			
		||||
        NSString *typeEntityName = [MPAlgorithmDefault classNameOfType:type];
 | 
			
		||||
 | 
			
		||||
        MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        element.name = siteName;
 | 
			
		||||
        element.user = activeUser;
 | 
			
		||||
        element.type = type;
 | 
			
		||||
        element.lastUsed = [NSDate date];
 | 
			
		||||
        element.version = MPAlgorithmDefaultVersion;
 | 
			
		||||
        MPSiteEntity *site = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        site.name = siteName;
 | 
			
		||||
        site.user = activeUser;
 | 
			
		||||
        site.type = type;
 | 
			
		||||
        site.lastUsed = [NSDate date];
 | 
			
		||||
        site.version = MPAlgorithmDefaultVersion;
 | 
			
		||||
 | 
			
		||||
        NSError *error = nil;
 | 
			
		||||
        if (element.objectID.isTemporaryID && ![context obtainPermanentIDsForObjects:@[ element ] error:&error])
 | 
			
		||||
            err( @"Failed to obtain a permanent object ID after creating new element: %@", error );
 | 
			
		||||
        if (site.objectID.isTemporaryID && ![context obtainPermanentIDsForObjects:@[ site ] error:&error])
 | 
			
		||||
            err( @"Failed to obtain a permanent object ID after creating new site: %@", error );
 | 
			
		||||
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        completion( element, context );
 | 
			
		||||
        completion( site, context );
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)changeElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context toType:(MPElementType)type {
 | 
			
		||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    if (element.type == type)
 | 
			
		||||
        return element;
 | 
			
		||||
    if (site.type == type)
 | 
			
		||||
        return site;
 | 
			
		||||
 | 
			
		||||
    if ([element.algorithm classOfType:type] == element.typeClass) {
 | 
			
		||||
        element.type = type;
 | 
			
		||||
    if ([site.algorithm classOfType:type] == site.typeClass) {
 | 
			
		||||
        site.type = type;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else {
 | 
			
		||||
        // Type requires a different class of element.  Recreate the element.
 | 
			
		||||
        NSString *typeEntityName = [element.algorithm classNameOfType:type];
 | 
			
		||||
        MPElementEntity *newElement = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        newElement.type = type;
 | 
			
		||||
        newElement.name = element.name;
 | 
			
		||||
        newElement.user = element.user;
 | 
			
		||||
        newElement.uses = element.uses;
 | 
			
		||||
        newElement.lastUsed = element.lastUsed;
 | 
			
		||||
        newElement.version = element.version;
 | 
			
		||||
        newElement.loginName = element.loginName;
 | 
			
		||||
        // Type requires a different class of site.  Recreate the site.
 | 
			
		||||
        NSString *typeEntityName = [site.algorithm classNameOfType:type];
 | 
			
		||||
        MPSiteEntity *newSite = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        newSite.type = type;
 | 
			
		||||
        newSite.name = site.name;
 | 
			
		||||
        newSite.user = site.user;
 | 
			
		||||
        newSite.uses = site.uses;
 | 
			
		||||
        newSite.lastUsed = site.lastUsed;
 | 
			
		||||
        newSite.version = site.version;
 | 
			
		||||
        newSite.loginName = site.loginName;
 | 
			
		||||
 | 
			
		||||
        NSError *error = nil;
 | 
			
		||||
        if (![context obtainPermanentIDsForObjects:@[ newElement ] error:&error])
 | 
			
		||||
        if (![context obtainPermanentIDsForObjects:@[ newSite ] error:&error])
 | 
			
		||||
            err( @"Failed to obtain a permanent object ID after changing object type: %@", error );
 | 
			
		||||
 | 
			
		||||
        [context deleteObject:element];
 | 
			
		||||
        [context deleteObject:site];
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        [[NSNotificationCenter defaultCenter] postNotificationName:MPElementUpdatedNotification object:element.objectID];
 | 
			
		||||
        element = newElement;
 | 
			
		||||
        [[NSNotificationCenter defaultCenter] postNotificationName:MPSiteUpdatedNotification object:site.objectID];
 | 
			
		||||
        site = newSite;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [[NSNotificationCenter defaultCenter] postNotificationName:MPElementUpdatedNotification object:element.objectID];
 | 
			
		||||
    return element;
 | 
			
		||||
    [[NSNotificationCenter defaultCenter] postNotificationName:MPSiteUpdatedNotification object:site.objectID];
 | 
			
		||||
    return site;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPImportResult)importSites:(NSString *)importedSitesString
 | 
			
		||||
@@ -467,9 +467,9 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
    NSData *importKeyID = nil;
 | 
			
		||||
    BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
 | 
			
		||||
    NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
 | 
			
		||||
    NSMutableSet *elementsToDelete = [NSMutableSet set];
 | 
			
		||||
    NSMutableArray *importedSiteElements = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
 | 
			
		||||
    NSFetchRequest *elementFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
 | 
			
		||||
    NSMutableSet *sitesToDelete = [NSMutableSet set];
 | 
			
		||||
    NSMutableArray *importedSiteSites = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
 | 
			
		||||
    NSFetchRequest *siteFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
 | 
			
		||||
    for (NSString *importedSiteLine in importedSiteLines) {
 | 
			
		||||
        if ([importedSiteLine hasPrefix:@"#"]) {
 | 
			
		||||
            // Comment or header
 | 
			
		||||
@@ -491,10 +491,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
                err( @"Invalid header format in line: %@", importedSiteLine );
 | 
			
		||||
                return MPImportResultMalformedInput;
 | 
			
		||||
            }
 | 
			
		||||
            NSTextCheckingResult *headerElements = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
 | 
			
		||||
            NSTextCheckingResult *headerSites = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
 | 
			
		||||
                                                                             range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
 | 
			
		||||
            NSString *headerName = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:1]];
 | 
			
		||||
            NSString *headerValue = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:2]];
 | 
			
		||||
            NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
 | 
			
		||||
            NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
 | 
			
		||||
            if ([headerName isEqualToString:@"User Name"]) {
 | 
			
		||||
                importUserName = headerValue;
 | 
			
		||||
 | 
			
		||||
@@ -586,27 +586,27 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
        // Find existing site.
 | 
			
		||||
        if (user) {
 | 
			
		||||
            elementFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", siteName, user];
 | 
			
		||||
            NSArray *existingSites = [context executeFetchRequest:elementFetchRequest error:&error];
 | 
			
		||||
            siteFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", siteName, user];
 | 
			
		||||
            NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error];
 | 
			
		||||
            if (!existingSites) {
 | 
			
		||||
                err( @"Lookup of existing sites failed for site: %@, user: %@, error: %@", siteName, user.userID, error );
 | 
			
		||||
                return MPImportResultInternalError;
 | 
			
		||||
            }
 | 
			
		||||
            if ([existingSites count]) {
 | 
			
		||||
                dbg( @"Existing sites: %@", existingSites );
 | 
			
		||||
                [elementsToDelete addObjectsFromArray:existingSites];
 | 
			
		||||
                [sitesToDelete addObjectsFromArray:existingSites];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        [importedSiteElements addObject:@[ lastUsed, uses, type, version, counter, loginName, siteName, exportContent ]];
 | 
			
		||||
        [importedSiteSites addObject:@[ lastUsed, uses, type, version, counter, loginName, siteName, exportContent ]];
 | 
			
		||||
        dbg( @"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, counter=%@, loginName=%@, siteName=%@, exportContent=%@",
 | 
			
		||||
                lastUsed, uses, type, version, counter, loginName, siteName, exportContent );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ask for confirmation to import these sites and the master password of the user.
 | 
			
		||||
    inf( @"Importing %lu sites, deleting %lu sites, for user: %@", (unsigned long)[importedSiteElements count],
 | 
			
		||||
            (unsigned long)[elementsToDelete count], [MPUserEntity idFor:importUserName] );
 | 
			
		||||
    NSString *userMasterPassword = askUserPassword( user? user.name: importUserName, [importedSiteElements count],
 | 
			
		||||
            [elementsToDelete count] );
 | 
			
		||||
    inf( @"Importing %lu sites, deleting %lu sites, for user: %@", (unsigned long)[importedSiteSites count],
 | 
			
		||||
            (unsigned long)[sitesToDelete count], [MPUserEntity idFor:importUserName] );
 | 
			
		||||
    NSString *userMasterPassword = askUserPassword( user? user.name: importUserName, [importedSiteSites count],
 | 
			
		||||
            [sitesToDelete count] );
 | 
			
		||||
    if (!userMasterPassword) {
 | 
			
		||||
        inf( @"Import cancelled." );
 | 
			
		||||
        return MPImportResultCancelled;
 | 
			
		||||
@@ -622,8 +622,8 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Delete existing sites.
 | 
			
		||||
    if (elementsToDelete.count)
 | 
			
		||||
        [elementsToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
 | 
			
		||||
    if (sitesToDelete.count)
 | 
			
		||||
        [sitesToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
 | 
			
		||||
            inf( @"Deleting site: %@, it will be replaced by an imported site.", [obj name] );
 | 
			
		||||
            [context deleteObject:obj];
 | 
			
		||||
        }];
 | 
			
		||||
@@ -644,10 +644,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Import new sites.
 | 
			
		||||
    for (NSArray *siteElements in importedSiteElements) {
 | 
			
		||||
    for (NSArray *siteElements in importedSiteSites) {
 | 
			
		||||
        NSDate *lastUsed = [[NSDateFormatter rfc3339DateFormatter] dateFromString:siteElements[0]];
 | 
			
		||||
        NSUInteger uses = (unsigned)[siteElements[1] integerValue];
 | 
			
		||||
        MPElementType type = (MPElementType)[siteElements[2] integerValue];
 | 
			
		||||
        MPSiteType type = (MPSiteType)[siteElements[2] integerValue];
 | 
			
		||||
        NSUInteger version = (unsigned)[siteElements[3] integerValue];
 | 
			
		||||
        NSUInteger counter = [siteElements[4] length]? (unsigned)[siteElements[4] integerValue]: NSNotFound;
 | 
			
		||||
        NSString *loginName = [siteElements[5] length]? siteElements[5]: nil;
 | 
			
		||||
@@ -656,7 +656,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
        // Create new site.
 | 
			
		||||
        NSString *typeEntityName = [MPAlgorithmForVersion( version ) classNameOfType:type];
 | 
			
		||||
        MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        MPSiteEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
 | 
			
		||||
        element.name = siteName;
 | 
			
		||||
        element.loginName = loginName;
 | 
			
		||||
        element.user = user;
 | 
			
		||||
@@ -666,9 +666,9 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
        element.version = version;
 | 
			
		||||
        if ([exportContent length]) {
 | 
			
		||||
            if (clearText)
 | 
			
		||||
                [element.algorithm importClearTextPassword:exportContent intoElement:element usingKey:userKey];
 | 
			
		||||
                [element.algorithm importClearTextPassword:exportContent intoSite:element usingKey:userKey];
 | 
			
		||||
            else
 | 
			
		||||
                [element.algorithm importProtectedPassword:exportContent protectedByKey:importKey intoElement:element usingKey:userKey];
 | 
			
		||||
                [element.algorithm importProtectedPassword:exportContent protectedByKey:importKey intoSite:element usingKey:userKey];
 | 
			
		||||
        }
 | 
			
		||||
        if ([element isKindOfClass:[MPElementGeneratedEntity class]] && counter != NSNotFound)
 | 
			
		||||
            ((MPElementGeneratedEntity *)element).counter = counter;
 | 
			
		||||
@@ -719,10 +719,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
    [export appendFormat:@"#               used      used      type                       name\t                     name\tpassword\n"];
 | 
			
		||||
 | 
			
		||||
    // Sites.
 | 
			
		||||
    for (MPElementEntity *element in activeUser.elements) {
 | 
			
		||||
    for (MPSiteEntity *element in activeUser.elements) {
 | 
			
		||||
        NSDate *lastUsed = element.lastUsed;
 | 
			
		||||
        NSUInteger uses = element.uses;
 | 
			
		||||
        MPElementType type = element.type;
 | 
			
		||||
        MPSiteType type = element.type;
 | 
			
		||||
        NSUInteger version = element.version;
 | 
			
		||||
        NSUInteger counter = 0;
 | 
			
		||||
        NSString *loginName = element.loginName;
 | 
			
		||||
@@ -735,11 +735,11 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Determine the content to export.
 | 
			
		||||
        if (!(type & MPElementFeatureDevicePrivate)) {
 | 
			
		||||
        if (!(type & MPSiteFeatureDevicePrivate)) {
 | 
			
		||||
            if (revealPasswords)
 | 
			
		||||
                content = [element.algorithm resolvePasswordForElement:element usingKey:self.key];
 | 
			
		||||
            else if (type & MPElementFeatureExportContent)
 | 
			
		||||
                content = [element.algorithm exportPasswordForElement:element usingKey:self.key];
 | 
			
		||||
                content = [element.algorithm resolvePasswordForSite:element usingKey:self.key];
 | 
			
		||||
            else if (type & MPSiteFeatureExportContent)
 | 
			
		||||
                content = [element.algorithm exportPasswordForSite:element usingKey:self.key];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [export appendFormat:@"%@  %8ld  %8s  %25s\t%25s\t%@\n",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementEntity.h
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import <CoreData/CoreData.h>
 | 
			
		||||
 | 
			
		||||
@class MPUserEntity;
 | 
			
		||||
 | 
			
		||||
@interface MPElementEntity : NSManagedObject
 | 
			
		||||
 | 
			
		||||
//@property (nonatomic, retain) id content; // Hide here, reveal in MPElementStoredEntity
 | 
			
		||||
@property (nonatomic, retain) NSDate * lastUsed;
 | 
			
		||||
@property (nonatomic, retain) NSString * loginName;
 | 
			
		||||
@property (nonatomic, retain) NSString * name;
 | 
			
		||||
@property (nonatomic, retain) NSNumber * requiresExplicitMigration_;
 | 
			
		||||
@property (nonatomic, retain) NSNumber * type_;
 | 
			
		||||
@property (nonatomic, retain) NSNumber * uses_;
 | 
			
		||||
@property (nonatomic, retain) NSNumber * version_;
 | 
			
		||||
@property (nonatomic, retain) NSNumber * loginGenerated_;
 | 
			
		||||
@property (nonatomic, retain) MPUserEntity *user;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementEntity.m
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
#import "MPUserEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@implementation MPElementEntity
 | 
			
		||||
 | 
			
		||||
//@dynamic content;
 | 
			
		||||
@dynamic lastUsed;
 | 
			
		||||
@dynamic loginName;
 | 
			
		||||
@dynamic name;
 | 
			
		||||
@dynamic requiresExplicitMigration_;
 | 
			
		||||
@dynamic type_;
 | 
			
		||||
@dynamic uses_;
 | 
			
		||||
@dynamic version_;
 | 
			
		||||
@dynamic loginGenerated_;
 | 
			
		||||
@dynamic user;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementGeneratedEntity.h
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import <CoreData/CoreData.h>
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@interface MPElementGeneratedEntity : MPElementEntity
 | 
			
		||||
 | 
			
		||||
@property (nonatomic, retain) NSNumber * counter_;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementGeneratedEntity.m
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPElementGeneratedEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@implementation MPElementGeneratedEntity
 | 
			
		||||
 | 
			
		||||
@dynamic counter_;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementStoredEntity.h
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import <CoreData/CoreData.h>
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@interface MPElementStoredEntity : MPElementEntity
 | 
			
		||||
 | 
			
		||||
@property (nonatomic, retain) NSData * contentObject;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementStoredEntity.m
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPElementStoredEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@implementation MPElementStoredEntity
 | 
			
		||||
 | 
			
		||||
@dynamic contentObject;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementEntities.h
 | 
			
		||||
//  MPEntities.h
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 31/05/12.
 | 
			
		||||
@@ -7,9 +7,9 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
#import "MPElementStoredEntity.h"
 | 
			
		||||
#import "MPElementGeneratedEntity.h"
 | 
			
		||||
#import "MPSiteEntity.h"
 | 
			
		||||
#import "MPSiteStoredEntity.h"
 | 
			
		||||
#import "MPSiteGeneratedEntity.h"
 | 
			
		||||
#import "MPUserEntity.h"
 | 
			
		||||
#import "MPAlgorithm.h"
 | 
			
		||||
#import "MPFixable.h"
 | 
			
		||||
@@ -22,10 +22,10 @@
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@interface MPElementEntity(MP)<MPFixable>
 | 
			
		||||
@interface MPSiteEntity(MP)<MPFixable>
 | 
			
		||||
 | 
			
		||||
@property(assign) BOOL loginGenerated;
 | 
			
		||||
@property(assign) MPElementType type;
 | 
			
		||||
@property(assign) MPSiteType type;
 | 
			
		||||
@property(readonly) NSString *typeName;
 | 
			
		||||
@property(readonly) NSString *typeShortName;
 | 
			
		||||
@property(readonly) NSString *typeClassName;
 | 
			
		||||
@@ -44,7 +44,7 @@
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@interface MPElementGeneratedEntity(MP)
 | 
			
		||||
@interface MPSiteGeneratedEntity(MP)
 | 
			
		||||
 | 
			
		||||
@property(assign) NSUInteger counter;
 | 
			
		||||
 | 
			
		||||
@@ -54,7 +54,7 @@
 | 
			
		||||
 | 
			
		||||
@property(assign) NSUInteger avatar;
 | 
			
		||||
@property(assign) BOOL saveKey;
 | 
			
		||||
@property(assign) MPElementType defaultType;
 | 
			
		||||
@property(assign) MPSiteType defaultType;
 | 
			
		||||
@property(readonly) NSString *userID;
 | 
			
		||||
 | 
			
		||||
+ (NSString *)idFor:(NSString *)userName;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
//
 | 
			
		||||
//  MPElementEntities.m
 | 
			
		||||
//  MPEntities.m
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 31/05/12.
 | 
			
		||||
@@ -34,16 +34,16 @@
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPElementEntity(MP)
 | 
			
		||||
@implementation MPSiteEntity(MP)
 | 
			
		||||
 | 
			
		||||
- (MPFixableResult)findAndFixInconsistenciesInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return MPFixableResultNoProblems;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)type {
 | 
			
		||||
- (MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    return (MPElementType)[self.type_ unsignedIntegerValue];
 | 
			
		||||
    return (MPSiteType)[self.type_ unsignedIntegerValue];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setLoginGenerated:(BOOL)aLoginGenerated {
 | 
			
		||||
@@ -56,7 +56,7 @@
 | 
			
		||||
    return [self.loginGenerated_ boolValue];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setType:(MPElementType)aType {
 | 
			
		||||
- (void)setType:(MPSiteType)aType {
 | 
			
		||||
 | 
			
		||||
    self.type_ = @(aType);
 | 
			
		||||
}
 | 
			
		||||
@@ -138,11 +138,11 @@
 | 
			
		||||
- (BOOL)migrateExplicitly:(BOOL)explicit {
 | 
			
		||||
 | 
			
		||||
    while (self.version < MPAlgorithmDefaultVersion)
 | 
			
		||||
        if ([MPAlgorithmForVersion( self.version + 1 ) migrateElement:self explicit:explicit])
 | 
			
		||||
            inf( @"%@ migration to version: %ld succeeded for element: %@",
 | 
			
		||||
        if ([MPAlgorithmForVersion( self.version + 1 ) migrateSite:self explicit:explicit])
 | 
			
		||||
            inf( @"%@ migration to version: %ld succeeded for site: %@",
 | 
			
		||||
                    explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
 | 
			
		||||
        else {
 | 
			
		||||
            wrn( @"%@ migration to version: %ld failed for element: %@",
 | 
			
		||||
            wrn( @"%@ migration to version: %ld failed for site: %@",
 | 
			
		||||
                    explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
 | 
			
		||||
            return NO;
 | 
			
		||||
        }
 | 
			
		||||
@@ -152,33 +152,33 @@
 | 
			
		||||
 | 
			
		||||
- (NSString *)resolveLoginUsingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return [self.algorithm resolveLoginForElement:self usingKey:key];
 | 
			
		||||
    return [self.algorithm resolveLoginForSite:self usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString *)resolvePasswordUsingKey:(MPKey *)key {
 | 
			
		||||
 | 
			
		||||
    return [self.algorithm resolvePasswordForElement:self usingKey:key];
 | 
			
		||||
    return [self.algorithm resolvePasswordForSite:self usingKey:key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolveLoginUsingKey:(MPKey *)key result:(void ( ^ )(NSString *))result {
 | 
			
		||||
 | 
			
		||||
    [self.algorithm resolveLoginForElement:self usingKey:key result:result];
 | 
			
		||||
    [self.algorithm resolveLoginForSite:self usingKey:key result:result];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)resolvePasswordUsingKey:(MPKey *)key result:(void ( ^ )(NSString *))result {
 | 
			
		||||
 | 
			
		||||
    [self.algorithm resolvePasswordForElement:self usingKey:key result:result];
 | 
			
		||||
    [self.algorithm resolvePasswordForSite:self usingKey:key result:result];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPElementGeneratedEntity(MP)
 | 
			
		||||
@implementation MPSiteGeneratedEntity(MP)
 | 
			
		||||
 | 
			
		||||
- (MPFixableResult)findAndFixInconsistenciesInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    MPFixableResult result = [super findAndFixInconsistenciesInContext:context];
 | 
			
		||||
 | 
			
		||||
    if (!self.type || self.type == (MPElementType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
 | 
			
		||||
    if (!self.type || self.type == (MPSiteType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
 | 
			
		||||
        // Invalid self.type
 | 
			
		||||
        result = MPApplyFix( result, ^MPFixableResult {
 | 
			
		||||
            wrn( @"Invalid type for: %@ of %@, type: %ld.  Will use %ld instead.",
 | 
			
		||||
@@ -186,18 +186,18 @@
 | 
			
		||||
            self.type = self.user.defaultType;
 | 
			
		||||
            return MPFixableResultProblemsFixed;
 | 
			
		||||
        } );
 | 
			
		||||
    if (!self.type || self.type == (MPElementType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
 | 
			
		||||
    if (!self.type || self.type == (MPSiteType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
 | 
			
		||||
        // Invalid self.user.defaultType
 | 
			
		||||
        result = MPApplyFix( result, ^MPFixableResult {
 | 
			
		||||
            wrn( @"Invalid type for: %@ of %@, type: %ld.  Will use %ld instead.",
 | 
			
		||||
                    self.name, self.user.name, (long)self.type, (long)MPElementTypeGeneratedLong );
 | 
			
		||||
            self.type = MPElementTypeGeneratedLong;
 | 
			
		||||
                    self.name, self.user.name, (long)self.type, (long)MPSiteTypeGeneratedLong );
 | 
			
		||||
            self.type = MPSiteTypeGeneratedLong;
 | 
			
		||||
            return MPFixableResultProblemsFixed;
 | 
			
		||||
        } );
 | 
			
		||||
    if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
 | 
			
		||||
        // Mismatch between self.type and self.class
 | 
			
		||||
        result = MPApplyFix( result, ^MPFixableResult {
 | 
			
		||||
            for (MPElementType newType = self.type; self.type != (newType = [self.algorithm nextType:newType]);)
 | 
			
		||||
            for (MPSiteType newType = self.type; self.type != (newType = [self.algorithm nextType:newType]);)
 | 
			
		||||
                if ([self isKindOfClass:[self.algorithm classOfType:newType]]) {
 | 
			
		||||
                    wrn( @"Mismatching type for: %@ of %@, type: %lu, class: %@.  Will use %ld instead.",
 | 
			
		||||
                            self.name, self.user.name, (long)self.type, self.class, (long)newType );
 | 
			
		||||
@@ -225,7 +225,7 @@
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@implementation MPElementStoredEntity(MP)
 | 
			
		||||
@implementation MPSiteStoredEntity(MP)
 | 
			
		||||
 | 
			
		||||
- (MPFixableResult)findAndFixInconsistenciesInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +236,7 @@
 | 
			
		||||
            MPKey *key = [MPAppDelegate_Shared get].key;
 | 
			
		||||
            if (key && [[MPAppDelegate_Shared get] activeUserInContext:context] == self.user) {
 | 
			
		||||
                wrn( @"Content object not encrypted for: %@ of %@.  Will re-encrypt.", self.name, self.user.name );
 | 
			
		||||
                [self.algorithm savePassword:[self.contentObject description] toElement:self usingKey:key];
 | 
			
		||||
                [self.algorithm savePassword:[self.contentObject description] toSite:self usingKey:key];
 | 
			
		||||
                return MPFixableResultProblemsFixed;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -271,12 +271,12 @@
 | 
			
		||||
    self.saveKey_ = @(aSaveKey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)defaultType {
 | 
			
		||||
- (MPSiteType)defaultType {
 | 
			
		||||
 | 
			
		||||
    return (MPElementType)[self.defaultType_ unsignedIntegerValue]?: MPElementTypeGeneratedLong;
 | 
			
		||||
    return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setDefaultType:(MPElementType)aDefaultType {
 | 
			
		||||
- (void)setDefaultType:(MPSiteType)aDefaultType {
 | 
			
		||||
 | 
			
		||||
    self.defaultType_ = @(aDefaultType);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,38 +8,39 @@
 | 
			
		||||
 | 
			
		||||
#import "MPKey.h"
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM(NSUInteger, MPElementTypeClass) {
 | 
			
		||||
typedef NS_ENUM( NSUInteger, MPSiteTypeClass ) {
 | 
			
		||||
    /** Generate the password. */
 | 
			
		||||
            MPElementTypeClassGenerated = 1 << 4,
 | 
			
		||||
            MPSiteTypeClassGenerated = 1 << 4,
 | 
			
		||||
    /** Store the password. */
 | 
			
		||||
            MPElementTypeClassStored = 1 << 5,
 | 
			
		||||
            MPSiteTypeClassStored = 1 << 5,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM(NSUInteger, MPElementVariant) {
 | 
			
		||||
typedef NS_ENUM( NSUInteger, MPSiteVariant ) {
 | 
			
		||||
    /** Generate the password. */
 | 
			
		||||
            MPElementVariantPassword,
 | 
			
		||||
            MPSiteVariantPassword,
 | 
			
		||||
    /** Generate the login name. */
 | 
			
		||||
            MPElementVariantLogin,
 | 
			
		||||
            MPSiteVariantLogin,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM(NSUInteger, MPElementFeature) {
 | 
			
		||||
typedef NS_ENUM( NSUInteger, MPSiteFeature ) {
 | 
			
		||||
    /** Export the key-protected content data. */
 | 
			
		||||
            MPElementFeatureExportContent = 1 << 10,
 | 
			
		||||
            MPSiteFeatureExportContent = 1 << 10,
 | 
			
		||||
    /** Never export content. */
 | 
			
		||||
            MPElementFeatureDevicePrivate = 1 << 11,
 | 
			
		||||
            MPSiteFeatureDevicePrivate = 1 << 11,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM(NSUInteger, MPElementType) {
 | 
			
		||||
    MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
    MPElementTypeGeneratedName = 0xF | MPElementTypeClassGenerated | 0x0,
 | 
			
		||||
typedef NS_ENUM(NSUInteger, MPSiteType) {
 | 
			
		||||
    MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedBasic = 0x4 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedShort = 0x3 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedPIN = 0x5 | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedName = 0xE | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
    MPSiteTypeGeneratedPhrase = 0xF | MPSiteTypeClassGenerated | 0x0,
 | 
			
		||||
 | 
			
		||||
    MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
 | 
			
		||||
    MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
 | 
			
		||||
    MPSiteTypeStoredPersonal = 0x0 | MPSiteTypeClassStored | MPSiteFeatureExportContent,
 | 
			
		||||
    MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MPErrorDomain                         @"MPErrorDomain"
 | 
			
		||||
@@ -52,7 +53,7 @@ typedef NS_ENUM(NSUInteger, MPElementType) {
 | 
			
		||||
#define MPCheckpointEditPassword              @"MPCheckpointEditPassword"
 | 
			
		||||
#define MPCheckpointEditLoginName             @"MPCheckpointEditLoginName"
 | 
			
		||||
#define MPCheckpointUseType                   @"MPCheckpointUseType"
 | 
			
		||||
#define MPCheckpointDeleteElement             @"MPCheckpointDeleteElement"
 | 
			
		||||
#define MPCheckpointDeleteSite                @"MPCheckpointDeleteSite"
 | 
			
		||||
#define MPCheckpointShowGuide                 @"MPCheckpointShowGuide"
 | 
			
		||||
#define MPCheckpointShowSetup                 @"MPCheckpointShowSetup"
 | 
			
		||||
#define MPCheckpointChangeMP                  @"MPCheckpointChangeMP"
 | 
			
		||||
@@ -76,7 +77,7 @@ typedef NS_ENUM(NSUInteger, MPElementType) {
 | 
			
		||||
#define MPSignedInNotification                @"MPSignedInNotification"
 | 
			
		||||
#define MPSignedOutNotification               @"MPSignedOutNotification"
 | 
			
		||||
#define MPKeyForgottenNotification            @"MPKeyForgottenNotification"
 | 
			
		||||
#define MPElementUpdatedNotification          @"MPElementUpdatedNotification"
 | 
			
		||||
#define MPSiteUpdatedNotification             @"MPSiteUpdatedNotification"
 | 
			
		||||
#define MPCheckConfigNotification             @"MPCheckConfigNotification"
 | 
			
		||||
#define MPSitesImportedNotification           @"MPSitesImportedNotification"
 | 
			
		||||
#define MPFoundInconsistenciesNotification    @"MPFoundInconsistenciesNotification"
 | 
			
		||||
@@ -85,6 +86,7 @@ typedef NS_ENUM(NSUInteger, MPElementType) {
 | 
			
		||||
#define MPInconsistenciesFixResultUserKey     @"MPInconsistenciesFixResultUserKey"
 | 
			
		||||
 | 
			
		||||
#define MPProductGenerateLogins               @"com.lyndir.masterpassword.products.generatelogins"
 | 
			
		||||
#define MPProductAdvancedExport               @"com.lyndir.masterpassword.products.advancedexport"
 | 
			
		||||
 | 
			
		||||
static void MPCheckpoint(NSString *checkpoint, NSDictionary *attributes) {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,14 @@
 | 
			
		||||
//  MPUserEntity.h
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-21.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
#import <CoreData/CoreData.h>
 | 
			
		||||
 | 
			
		||||
@class MPElementEntity;
 | 
			
		||||
@class MPSiteEntity;
 | 
			
		||||
 | 
			
		||||
@interface MPUserEntity : NSManagedObject
 | 
			
		||||
 | 
			
		||||
@@ -24,8 +24,8 @@
 | 
			
		||||
 | 
			
		||||
@interface MPUserEntity (CoreDataGeneratedAccessors)
 | 
			
		||||
 | 
			
		||||
- (void)addElementsObject:(MPElementEntity *)value;
 | 
			
		||||
- (void)removeElementsObject:(MPElementEntity *)value;
 | 
			
		||||
- (void)addElementsObject:(MPSiteEntity *)value;
 | 
			
		||||
- (void)removeElementsObject:(MPSiteEntity *)value;
 | 
			
		||||
- (void)addElements:(NSSet *)values;
 | 
			
		||||
- (void)removeElements:(NSSet *)values;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,12 @@
 | 
			
		||||
//  MPUserEntity.m
 | 
			
		||||
//  MasterPassword-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-14.
 | 
			
		||||
//  Created by Maarten Billemont on 2014-09-21.
 | 
			
		||||
//  Copyright (c) 2014 Lyndir. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPUserEntity.h"
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
#import "MPSiteEntity.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@implementation MPUserEntity
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,12 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import <Foundation/Foundation.h>
 | 
			
		||||
@class MPElementEntity;
 | 
			
		||||
@class MPSiteEntity;
 | 
			
		||||
 | 
			
		||||
@interface MPElementModel : NSObject
 | 
			
		||||
 | 
			
		||||
@property (nonatomic) NSString *siteName;
 | 
			
		||||
@property (nonatomic) MPElementType type;
 | 
			
		||||
@property (nonatomic) MPSiteType type;
 | 
			
		||||
@property (nonatomic) NSString *typeName;
 | 
			
		||||
@property (nonatomic) NSString *content;
 | 
			
		||||
@property (nonatomic) NSString *contentDisplay;
 | 
			
		||||
@@ -34,8 +34,8 @@
 | 
			
		||||
@property (nonatomic) BOOL generated;
 | 
			
		||||
@property (nonatomic) BOOL stored;
 | 
			
		||||
 | 
			
		||||
- (id)initWithEntity:(MPElementEntity *)entity;
 | 
			
		||||
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc;
 | 
			
		||||
- (id)initWithEntity:(MPSiteEntity *)entity;
 | 
			
		||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
 | 
			
		||||
 | 
			
		||||
- (void)updateContent;
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "MPElementModel.h"
 | 
			
		||||
#import "MPElementEntity.h"
 | 
			
		||||
#import "MPSiteEntity.h"
 | 
			
		||||
#import "MPEntities.h"
 | 
			
		||||
#import "MPAppDelegate_Shared.h"
 | 
			
		||||
#import "MPAppDelegate_Store.h"
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
    BOOL _initialized;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (id)initWithEntity:(MPElementEntity *)entity {
 | 
			
		||||
- (id)initWithEntity:(MPSiteEntity *)entity {
 | 
			
		||||
 | 
			
		||||
    if (!(self = [super init]))
 | 
			
		||||
        return nil;
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setEntity:(MPElementEntity *)entity {
 | 
			
		||||
- (void)setEntity:(MPSiteEntity *)entity {
 | 
			
		||||
 | 
			
		||||
    if ([_entityOID isEqual:entity.objectID])
 | 
			
		||||
        return;
 | 
			
		||||
@@ -58,13 +58,13 @@
 | 
			
		||||
    [self updateContent:entity];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc {
 | 
			
		||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc {
 | 
			
		||||
 | 
			
		||||
    if (!_entityOID)
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    NSError *error;
 | 
			
		||||
    MPElementEntity *entity = (MPElementEntity *)[moc existingObjectWithID:_entityOID error:&error];
 | 
			
		||||
    MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:_entityOID error:&error];
 | 
			
		||||
    if (!entity)
 | 
			
		||||
        err( @"Couldn't retrieve active element: %@", error );
 | 
			
		||||
 | 
			
		||||
@@ -82,7 +82,7 @@
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *entity = [self entityInContext:context];
 | 
			
		||||
        MPSiteEntity *entity = [self entityInContext:context];
 | 
			
		||||
        if ([entity isKindOfClass:[MPElementGeneratedEntity class]]) {
 | 
			
		||||
            ((MPElementGeneratedEntity *)entity).counter = counter;
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
@@ -94,22 +94,22 @@
 | 
			
		||||
 | 
			
		||||
- (BOOL)generated {
 | 
			
		||||
 | 
			
		||||
    return self.type & MPElementTypeClassGenerated;
 | 
			
		||||
    return self.type & MPSiteTypeClassGenerated;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)stored {
 | 
			
		||||
 | 
			
		||||
    return self.type & MPElementTypeClassStored;
 | 
			
		||||
    return self.type & MPSiteTypeClassStored;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)updateContent {
 | 
			
		||||
 | 
			
		||||
    [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        [self updateContent:[MPElementEntity existingObjectWithID:_entityOID inContext:context]];
 | 
			
		||||
        [self updateContent:[MPSiteEntity existingObjectWithID:_entityOID inContext:context]];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)updateContent:(MPElementEntity *)entity {
 | 
			
		||||
- (void)updateContent:(MPSiteEntity *)entity {
 | 
			
		||||
 | 
			
		||||
    static NSRegularExpression *re_anyChar;
 | 
			
		||||
    static dispatch_once_t once = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -229,7 +229,8 @@
 | 
			
		||||
        switch (returnCode) {
 | 
			
		||||
            case NSAlertFirstButtonReturn: {
 | 
			
		||||
                // "Create" button.
 | 
			
		||||
                [[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                [[MPMacAppDelegate get]
 | 
			
		||||
                        addSiteNamed:[self.siteField stringValue] completion:^(MPSiteEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                    if (element)
 | 
			
		||||
                        PearlMainQueue( ^{ [self updateElements]; } );
 | 
			
		||||
                }];
 | 
			
		||||
@@ -243,10 +244,10 @@
 | 
			
		||||
        switch (returnCode) {
 | 
			
		||||
            case NSAlertFirstButtonReturn: {
 | 
			
		||||
                // "Save" button.
 | 
			
		||||
                MPElementType type = (MPElementType)[self.passwordTypesMatrix.selectedCell tag];
 | 
			
		||||
                MPSiteType type = (MPSiteType)[self.passwordTypesMatrix.selectedCell tag];
 | 
			
		||||
                [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                    MPElementEntity *entity = [[MPMacAppDelegate get] changeElement:[self.selectedElement entityInContext:context]
 | 
			
		||||
                                                                      saveInContext:context toType:type];
 | 
			
		||||
                    MPSiteEntity *entity = [[MPMacAppDelegate get] changeSite:[self.selectedElement entityInContext:context]
 | 
			
		||||
                                                                saveInContext:context toType:type];
 | 
			
		||||
                    if ([entity isKindOfClass:[MPElementStoredEntity class]] && ![(MPElementStoredEntity *)entity contentObject].length)
 | 
			
		||||
                        PearlMainQueue( ^{
 | 
			
		||||
                            [self changePassword:nil];
 | 
			
		||||
@@ -264,7 +265,7 @@
 | 
			
		||||
                // "Save" button.
 | 
			
		||||
                NSString *loginName = [(NSSecureTextField *)alert.accessoryView stringValue];
 | 
			
		||||
                [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                    MPElementEntity *entity = [self.selectedElement entityInContext:context];
 | 
			
		||||
                    MPSiteEntity *entity = [self.selectedElement entityInContext:context];
 | 
			
		||||
                    entity.loginName = loginName;
 | 
			
		||||
                    [context saveToStore];
 | 
			
		||||
                }];
 | 
			
		||||
@@ -280,8 +281,8 @@
 | 
			
		||||
                // "Save" button.
 | 
			
		||||
                NSString *password = [(NSSecureTextField *)alert.accessoryView stringValue];
 | 
			
		||||
                [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                    MPElementEntity *entity = [self.selectedElement entityInContext:context];
 | 
			
		||||
                    [entity.algorithm savePassword:password toElement:entity usingKey:[MPMacAppDelegate get].key];
 | 
			
		||||
                    MPSiteEntity *entity = [self.selectedElement entityInContext:context];
 | 
			
		||||
                    [entity.algorithm savePassword:password toSite:entity usingKey:[MPMacAppDelegate get].key];
 | 
			
		||||
                    [context saveToStore];
 | 
			
		||||
                }];
 | 
			
		||||
                break;
 | 
			
		||||
@@ -397,12 +398,12 @@
 | 
			
		||||
- (IBAction)changeType:(id)sender {
 | 
			
		||||
 | 
			
		||||
    MPElementModel *element = self.selectedElement;
 | 
			
		||||
    NSArray *types = [element.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN];
 | 
			
		||||
    NSArray *types = [element.algorithm allTypesStartingWith:MPSiteTypeGeneratedPIN];
 | 
			
		||||
    [self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
 | 
			
		||||
    for (NSUInteger t = 0; t < [types count]; ++t) {
 | 
			
		||||
        MPElementType type = [types[t] unsignedIntegerValue];
 | 
			
		||||
        MPSiteType type = [types[t] unsignedIntegerValue];
 | 
			
		||||
        NSString *title = [element.algorithm nameOfType:type];
 | 
			
		||||
        if (type & MPElementTypeClassGenerated)
 | 
			
		||||
        if (type & MPSiteTypeClassGenerated)
 | 
			
		||||
            title = [element.algorithm generatePasswordForSiteNamed:element.siteName ofType:type
 | 
			
		||||
                                                        withCounter:element.counter usingKey:[MPMacAppDelegate get].key];
 | 
			
		||||
 | 
			
		||||
@@ -514,7 +515,7 @@
 | 
			
		||||
    NSString *query = [self query];
 | 
			
		||||
    [profiler finishJob:@"query"];
 | 
			
		||||
    [MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
 | 
			
		||||
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
 | 
			
		||||
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
 | 
			
		||||
        fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO]];
 | 
			
		||||
        fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
 | 
			
		||||
                                                                  query, query, [[MPMacAppDelegate get] activeUserInContext:context]];
 | 
			
		||||
@@ -529,7 +530,7 @@
 | 
			
		||||
        [profiler finishJob:@"do fetch"];
 | 
			
		||||
 | 
			
		||||
        NSMutableArray *newElements = [NSMutableArray arrayWithCapacity:[siteResults count]];
 | 
			
		||||
        for (MPElementEntity *element in siteResults)
 | 
			
		||||
        for (MPSiteEntity *element in siteResults)
 | 
			
		||||
            [newElements addObject:[[MPElementModel alloc] initWithEntity:element]];
 | 
			
		||||
        [profiler finishJob:@"make models"];
 | 
			
		||||
        self.elements = newElements;
 | 
			
		||||
 
 | 
			
		||||
@@ -60,9 +60,6 @@
 | 
			
		||||
		DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA01724A667003798D8 /* MPAppDelegate_Shared.m */; };
 | 
			
		||||
		DA5E5CFB1724A667003798D8 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */; };
 | 
			
		||||
		DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA41724A667003798D8 /* MPConfig.m */; };
 | 
			
		||||
		DA5E5CFD1724A667003798D8 /* MPElementEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA61724A667003798D8 /* MPElementEntity.m */; };
 | 
			
		||||
		DA5E5CFE1724A667003798D8 /* MPElementGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA81724A667003798D8 /* MPElementGeneratedEntity.m */; };
 | 
			
		||||
		DA5E5CFF1724A667003798D8 /* MPElementStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CAA1724A667003798D8 /* MPElementStoredEntity.m */; };
 | 
			
		||||
		DA5E5D001724A667003798D8 /* MPEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CAC1724A667003798D8 /* MPEntities.m */; };
 | 
			
		||||
		DA5E5D011724A667003798D8 /* MPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CAE1724A667003798D8 /* MPKey.m */; };
 | 
			
		||||
		DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB11724A667003798D8 /* MPUserEntity.m */; };
 | 
			
		||||
@@ -78,6 +75,10 @@
 | 
			
		||||
		DA8ED895192906920099B726 /* PearlTween.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8ED891192906920099B726 /* PearlTween.m */; };
 | 
			
		||||
		DA8ED896192906920099B726 /* PearlTween.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED892192906920099B726 /* PearlTween.h */; };
 | 
			
		||||
		DA8ED897192906920099B726 /* map-macro.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED894192906920099B726 /* map-macro.h */; };
 | 
			
		||||
		DA9521BD19CEA3FD002E3AD5 /* MPSiteStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521B519CEA3FD002E3AD5 /* MPSiteStoredEntity.m */; };
 | 
			
		||||
		DA9521BE19CEA3FD002E3AD5 /* MPSiteQuestion.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521B719CEA3FD002E3AD5 /* MPSiteQuestion.m */; };
 | 
			
		||||
		DA9521BF19CEA3FD002E3AD5 /* MPSiteGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521B919CEA3FD002E3AD5 /* MPSiteGeneratedEntity.m */; };
 | 
			
		||||
		DA9521C019CEA3FD002E3AD5 /* MPSiteEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521BB19CEA3FD002E3AD5 /* MPSiteEntity.m */; };
 | 
			
		||||
		DAAA81B0195A8D1300FA30D9 /* gradient.png in Resources */ = {isa = PBXBuildFile; fileRef = DAAA81AF195A8D1300FA30D9 /* gradient.png */; };
 | 
			
		||||
		DABC6C02175D8C85000C15D4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
 | 
			
		||||
		DABC6C15175D8CE1000C15D4 /* RHStatusItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = DABC6C14175D8CE1000C15D4 /* RHStatusItemView.m */; };
 | 
			
		||||
@@ -302,12 +303,6 @@
 | 
			
		||||
		DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA31724A667003798D8 /* MPConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPConfig.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA41724A667003798D8 /* MPConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPConfig.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA51724A667003798D8 /* MPElementEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA61724A667003798D8 /* MPElementEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA71724A667003798D8 /* MPElementGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementGeneratedEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA81724A667003798D8 /* MPElementGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementGeneratedEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CA91724A667003798D8 /* MPElementStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementStoredEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CAA1724A667003798D8 /* MPElementStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementStoredEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CAB1724A667003798D8 /* MPEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntities.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CAC1724A667003798D8 /* MPEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEntities.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA5E5CAD1724A667003798D8 /* MPKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPKey.h; sourceTree = "<group>"; };
 | 
			
		||||
@@ -734,6 +729,14 @@
 | 
			
		||||
		DA8ED891192906920099B726 /* PearlTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlTween.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA8ED892192906920099B726 /* PearlTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlTween.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA8ED894192906920099B726 /* map-macro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "map-macro.h"; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B519CEA3FD002E3AD5 /* MPSiteStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteStoredEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B619CEA3FD002E3AD5 /* MPSiteStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteStoredEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B719CEA3FD002E3AD5 /* MPSiteQuestion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteQuestion.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B819CEA3FD002E3AD5 /* MPSiteQuestion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteQuestion.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B919CEA3FD002E3AD5 /* MPSiteGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteGeneratedEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521BA19CEA3FD002E3AD5 /* MPSiteGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteGeneratedEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521BB19CEA3FD002E3AD5 /* MPSiteEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521BC19CEA3FD002E3AD5 /* MPSiteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DAAA81AF195A8D1300FA30D9 /* gradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gradient.png; sourceTree = "<group>"; };
 | 
			
		||||
		DABB981515100B4000B05417 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
 | 
			
		||||
		DABC6C01175D8C85000C15D4 /* libRHStatusItemView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRHStatusItemView.a; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
			
		||||
@@ -995,6 +998,14 @@
 | 
			
		||||
		DA5E5C961724A667003798D8 /* ObjC */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				DA9521B519CEA3FD002E3AD5 /* MPSiteStoredEntity.m */,
 | 
			
		||||
				DA9521B619CEA3FD002E3AD5 /* MPSiteStoredEntity.h */,
 | 
			
		||||
				DA9521B719CEA3FD002E3AD5 /* MPSiteQuestion.m */,
 | 
			
		||||
				DA9521B819CEA3FD002E3AD5 /* MPSiteQuestion.h */,
 | 
			
		||||
				DA9521B919CEA3FD002E3AD5 /* MPSiteGeneratedEntity.m */,
 | 
			
		||||
				DA9521BA19CEA3FD002E3AD5 /* MPSiteGeneratedEntity.h */,
 | 
			
		||||
				DA9521BB19CEA3FD002E3AD5 /* MPSiteEntity.m */,
 | 
			
		||||
				DA9521BC19CEA3FD002E3AD5 /* MPSiteEntity.h */,
 | 
			
		||||
				DA3B8454190FC89700246EEA /* MPFixable.m */,
 | 
			
		||||
				DA3B8455190FC89700246EEA /* MPFixable.h */,
 | 
			
		||||
				DA5E5CB21724A667003798D8 /* Mac */,
 | 
			
		||||
@@ -1012,12 +1023,6 @@
 | 
			
		||||
				DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */,
 | 
			
		||||
				DA5E5CA31724A667003798D8 /* MPConfig.h */,
 | 
			
		||||
				DA5E5CA41724A667003798D8 /* MPConfig.m */,
 | 
			
		||||
				DA5E5CA51724A667003798D8 /* MPElementEntity.h */,
 | 
			
		||||
				DA5E5CA61724A667003798D8 /* MPElementEntity.m */,
 | 
			
		||||
				DA5E5CA71724A667003798D8 /* MPElementGeneratedEntity.h */,
 | 
			
		||||
				DA5E5CA81724A667003798D8 /* MPElementGeneratedEntity.m */,
 | 
			
		||||
				DA5E5CA91724A667003798D8 /* MPElementStoredEntity.h */,
 | 
			
		||||
				DA5E5CAA1724A667003798D8 /* MPElementStoredEntity.m */,
 | 
			
		||||
				DA5E5CAB1724A667003798D8 /* MPEntities.h */,
 | 
			
		||||
				DA5E5CAC1724A667003798D8 /* MPEntities.m */,
 | 
			
		||||
				DA5E5CAD1724A667003798D8 /* MPKey.h */,
 | 
			
		||||
@@ -2137,22 +2142,23 @@
 | 
			
		||||
			isa = PBXSourcesBuildPhase;
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
			files = (
 | 
			
		||||
				DA9521BF19CEA3FD002E3AD5 /* MPSiteGeneratedEntity.m in Sources */,
 | 
			
		||||
				DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */,
 | 
			
		||||
				DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */,
 | 
			
		||||
				DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */,
 | 
			
		||||
				DA9521BE19CEA3FD002E3AD5 /* MPSiteQuestion.m in Sources */,
 | 
			
		||||
				DA5E5CF91724A667003798D8 /* MPAppDelegate_Key.m in Sources */,
 | 
			
		||||
				DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */,
 | 
			
		||||
				DA5E5CFB1724A667003798D8 /* MPAppDelegate_Store.m in Sources */,
 | 
			
		||||
				DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */,
 | 
			
		||||
				DA5E5CFD1724A667003798D8 /* MPElementEntity.m in Sources */,
 | 
			
		||||
				DA5E5CFE1724A667003798D8 /* MPElementGeneratedEntity.m in Sources */,
 | 
			
		||||
				DA5E5CFF1724A667003798D8 /* MPElementStoredEntity.m in Sources */,
 | 
			
		||||
				DA29992C19C6A89900AF7DF1 /* MasterPassword.xcdatamodeld in Sources */,
 | 
			
		||||
				DA3B8456190FC89700246EEA /* MPFixable.m in Sources */,
 | 
			
		||||
				DA5E5D001724A667003798D8 /* MPEntities.m in Sources */,
 | 
			
		||||
				DA5E5D011724A667003798D8 /* MPKey.m in Sources */,
 | 
			
		||||
				DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */,
 | 
			
		||||
				DA9521BD19CEA3FD002E3AD5 /* MPSiteStoredEntity.m in Sources */,
 | 
			
		||||
				DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */,
 | 
			
		||||
				DA9521C019CEA3FD002E3AD5 /* MPSiteEntity.m in Sources */,
 | 
			
		||||
				DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */,
 | 
			
		||||
				DA5E5D0C1724A667003798D8 /* main.m in Sources */,
 | 
			
		||||
				93D39C5789EFA607CF788082 /* MPElementModel.m in Sources */,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,17 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
 | 
			
		||||
       lastSavedToolsVersion="1171" systemVersion="11E53" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
 | 
			
		||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6244" systemVersion="13E28" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPSiteEntity" isAbstract="YES" elementID="58EE245C-6827-4C11-BB7E-5722F2426EC2" syncable="YES">
 | 
			
		||||
        <attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" attributeType="Date" syncable="YES"/>
 | 
			
		||||
        <attribute name="name" attributeType="String" minValueString="1" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
 | 
			
		||||
        <attribute name="uses_" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
 | 
			
		||||
                      inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPSiteGeneratedEntity" parentEntity="MPElementEntity" elementID="789304EA-070D-4982-8C20-54EECFC20CB6" syncable="YES">
 | 
			
		||||
        <attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPElementStoredEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPSiteStoredEntity" parentEntity="MPElementEntity" elementID="BEEF1688-0CCD-4699-A86A-4D860FE2CEB8" syncable="YES">
 | 
			
		||||
        <attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
 | 
			
		||||
@@ -22,9 +20,10 @@
 | 
			
		||||
        <attribute name="keyID" optional="YES" attributeType="Binary" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" optional="YES" attributeType="Date" syncable="YES"/>
 | 
			
		||||
        <attribute name="name" attributeType="String" syncable="YES"/>
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO"/>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
 | 
			
		||||
                      inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
 | 
			
		||||
            <userInfo/>
 | 
			
		||||
        </attribute>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <elements>
 | 
			
		||||
        <element name="MPElementEntity" positionX="160" positionY="192" width="128" height="135"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
 | 
			
		||||
       lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
 | 
			
		||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6244" systemVersion="13E28" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPSiteEntity" isAbstract="YES" elementID="58EE245C-6827-4C11-BB7E-5722F2426EC2" syncable="YES">
 | 
			
		||||
        <attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="name" attributeType="String" minValueString="1" indexed="YES" syncable="YES"/>
 | 
			
		||||
@@ -12,13 +11,12 @@
 | 
			
		||||
        <attribute name="userName" optional="YES" attributeType="String" syncable="YES"/>
 | 
			
		||||
        <attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
 | 
			
		||||
                      inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPSiteGeneratedEntity" parentEntity="MPElementEntity" elementID="789304EA-070D-4982-8C20-54EECFC20CB6" syncable="YES">
 | 
			
		||||
        <attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPElementStoredEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPSiteStoredEntity" parentEntity="MPElementEntity" elementID="BEEF1688-0CCD-4699-A86A-4D860FE2CEB8" syncable="YES">
 | 
			
		||||
        <attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
 | 
			
		||||
@@ -31,8 +29,7 @@
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
 | 
			
		||||
            <userInfo/>
 | 
			
		||||
        </attribute>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
 | 
			
		||||
                      inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <elements>
 | 
			
		||||
        <element name="MPElementEntity" positionX="0" positionY="0" width="128" height="180"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
 | 
			
		||||
       lastSavedToolsVersion="1810" systemVersion="12B19" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
 | 
			
		||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6244" systemVersion="13E28" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPSiteEntity" isAbstract="YES" elementID="58EE245C-6827-4C11-BB7E-5722F2426EC2" syncable="YES">
 | 
			
		||||
        <attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="loginName" optional="YES" attributeType="String" elementID="A1B9F981-D33C-4BFE-9F94-C9D3E1F78E51" syncable="YES"/>
 | 
			
		||||
@@ -12,13 +11,12 @@
 | 
			
		||||
        <attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
 | 
			
		||||
        <attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
 | 
			
		||||
                      inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPSiteGeneratedEntity" parentEntity="MPElementEntity" elementID="789304EA-070D-4982-8C20-54EECFC20CB6" syncable="YES">
 | 
			
		||||
        <attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPElementStoredEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPSiteStoredEntity" parentEntity="MPElementEntity" elementID="BEEF1688-0CCD-4699-A86A-4D860FE2CEB8" syncable="YES">
 | 
			
		||||
        <attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
 | 
			
		||||
@@ -31,8 +29,7 @@
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
 | 
			
		||||
            <userInfo/>
 | 
			
		||||
        </attribute>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
 | 
			
		||||
                      inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <elements>
 | 
			
		||||
        <element name="MPElementEntity" positionX="-0" positionY="-286" width="128" height="178"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"
 | 
			
		||||
       lastSavedToolsVersion="2057" systemVersion="12C60" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
 | 
			
		||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6244" systemVersion="13E28" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPSiteEntity" isAbstract="YES" elementID="58EE245C-6827-4C11-BB7E-5722F2426EC2" syncable="YES">
 | 
			
		||||
        <attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="loginName" optional="YES" attributeType="String" elementID="A1B9F981-D33C-4BFE-9F94-C9D3E1F78E51" syncable="YES"/>
 | 
			
		||||
@@ -12,13 +11,12 @@
 | 
			
		||||
        <attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
 | 
			
		||||
        <attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements"
 | 
			
		||||
                      inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPSiteGeneratedEntity" parentEntity="MPElementEntity" elementID="789304EA-070D-4982-8C20-54EECFC20CB6" syncable="YES">
 | 
			
		||||
        <attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPElementStoredEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPSiteStoredEntity" parentEntity="MPElementEntity" elementID="BEEF1688-0CCD-4699-A86A-4D860FE2CEB8" syncable="YES">
 | 
			
		||||
        <attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
 | 
			
		||||
@@ -30,8 +28,7 @@
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
 | 
			
		||||
            <userInfo/>
 | 
			
		||||
        </attribute>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity"
 | 
			
		||||
                      inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <elements>
 | 
			
		||||
        <element name="MPElementEntity" positionX="-0" positionY="-286" width="128" height="178"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6244" systemVersion="13E28" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
 | 
			
		||||
    <entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
 | 
			
		||||
    <entity name="MPSiteEntity" representedClassName="MPSiteEntity" isAbstract="YES" elementID="58EE245C-6827-4C11-BB7E-5722F2426EC2" syncable="YES">
 | 
			
		||||
        <attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
 | 
			
		||||
        <attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="loginGenerated_" attributeType="Boolean" defaultValueString="NO" syncable="YES"/>
 | 
			
		||||
@@ -12,12 +12,17 @@
 | 
			
		||||
        <attribute name="type_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
 | 
			
		||||
        <attribute name="uses_" attributeType="Integer 16" defaultValueString="0" indexed="YES" syncable="YES"/>
 | 
			
		||||
        <attribute name="version_" attributeType="Integer 16" minValueString="0" defaultValueString="0" syncable="YES"/>
 | 
			
		||||
        <relationship name="questions" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="MPSiteQuestion" inverseName="site" inverseEntity="MPSiteQuestion" syncable="YES"/>
 | 
			
		||||
        <relationship name="user" minCount="1" maxCount="1" deletionRule="Nullify" destinationEntity="MPUserEntity" inverseName="elements" inverseEntity="MPUserEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementGeneratedEntity" representedClassName="MPElementGeneratedEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPSiteGeneratedEntity" representedClassName="MPSiteGeneratedEntity" parentEntity="MPSiteEntity" elementID="789304EA-070D-4982-8C20-54EECFC20CB6" syncable="YES">
 | 
			
		||||
        <attribute name="counter_" optional="YES" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPElementStoredEntity" representedClassName="MPElementStoredEntity" parentEntity="MPElementEntity" syncable="YES">
 | 
			
		||||
    <entity name="MPSiteQuestion" representedClassName="MPSiteQuestion" syncable="YES">
 | 
			
		||||
        <attribute name="keyword" attributeType="String" syncable="YES"/>
 | 
			
		||||
        <relationship name="site" maxCount="1" deletionRule="Nullify" destinationEntity="MPSiteEntity" inverseName="questions" inverseEntity="MPSiteEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPSiteStoredEntity" representedClassName="MPSiteStoredEntity" parentEntity="MPSiteEntity" elementID="BEEF1688-0CCD-4699-A86A-4D860FE2CEB8" syncable="YES">
 | 
			
		||||
        <attribute name="contentObject" optional="YES" attributeType="Transformable" storedInTruthFile="YES" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
 | 
			
		||||
@@ -29,12 +34,13 @@
 | 
			
		||||
        <attribute name="saveKey_" attributeType="Boolean" defaultValueString="NO">
 | 
			
		||||
            <userInfo/>
 | 
			
		||||
        </attribute>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
 | 
			
		||||
        <relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPSiteEntity" inverseName="user" inverseEntity="MPSiteEntity" syncable="YES"/>
 | 
			
		||||
    </entity>
 | 
			
		||||
    <elements>
 | 
			
		||||
        <element name="MPElementEntity" positionX="-0" positionY="-286" width="128" height="193"/>
 | 
			
		||||
        <element name="MPElementGeneratedEntity" positionX="216" positionY="-288" width="128" height="58"/>
 | 
			
		||||
        <element name="MPElementStoredEntity" positionX="214" positionY="-171" width="128" height="58"/>
 | 
			
		||||
        <element name="MPSiteEntity" positionX="-0" positionY="-286" width="128" height="208"/>
 | 
			
		||||
        <element name="MPSiteGeneratedEntity" positionX="216" positionY="-288" width="128" height="58"/>
 | 
			
		||||
        <element name="MPSiteQuestion" positionX="-2" positionY="-9" width="128" height="73"/>
 | 
			
		||||
        <element name="MPSiteStoredEntity" positionX="214" positionY="-171" width="128" height="58"/>
 | 
			
		||||
        <element name="MPUserEntity" positionX="-218" positionY="-288" width="128" height="148"/>
 | 
			
		||||
    </elements>
 | 
			
		||||
</model>
 | 
			
		||||
</model>
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@
 | 
			
		||||
- (void)updatePassword {
 | 
			
		||||
 | 
			
		||||
    NSString *siteName = self.siteField.text;
 | 
			
		||||
    MPElementType siteType = [self siteType];
 | 
			
		||||
    MPSiteType siteType = [self siteType];
 | 
			
		||||
    NSUInteger siteCounter = (NSUInteger)self.counterStepper.value;
 | 
			
		||||
    self.counterLabel.text = strf( @"%lu", (unsigned long)siteCounter );
 | 
			
		||||
 | 
			
		||||
@@ -145,21 +145,21 @@
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (enum MPElementType)siteType {
 | 
			
		||||
- (enum MPSiteType)siteType {
 | 
			
		||||
 | 
			
		||||
    switch (self.typeControl.selectedSegmentIndex) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            return MPElementTypeGeneratedMaximum;
 | 
			
		||||
            return MPSiteTypeGeneratedMaximum;
 | 
			
		||||
        case 1:
 | 
			
		||||
            return MPElementTypeGeneratedLong;
 | 
			
		||||
            return MPSiteTypeGeneratedLong;
 | 
			
		||||
        case 2:
 | 
			
		||||
            return MPElementTypeGeneratedMedium;
 | 
			
		||||
            return MPSiteTypeGeneratedMedium;
 | 
			
		||||
        case 3:
 | 
			
		||||
            return MPElementTypeGeneratedBasic;
 | 
			
		||||
            return MPSiteTypeGeneratedBasic;
 | 
			
		||||
        case 4:
 | 
			
		||||
            return MPElementTypeGeneratedShort;
 | 
			
		||||
            return MPSiteTypeGeneratedShort;
 | 
			
		||||
        case 5:
 | 
			
		||||
            return MPElementTypeGeneratedPIN;
 | 
			
		||||
            return MPSiteTypeGeneratedPIN;
 | 
			
		||||
        default:
 | 
			
		||||
            Throw(@"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ typedef NS_ENUM ( NSUInteger, MPPasswordCellMode ) {
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordCell : MPCell <UIScrollViewDelegate, UITextFieldDelegate>
 | 
			
		||||
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated;
 | 
			
		||||
- (void)setElement:(MPSiteEntity *)element animated:(BOOL)animated;
 | 
			
		||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
 | 
			
		||||
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,7 @@
 | 
			
		||||
    [self updateAnimated:animated];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated {
 | 
			
		||||
- (void)setElement:(MPSiteEntity *)element animated:(BOOL)animated {
 | 
			
		||||
 | 
			
		||||
    _elementOID = [element objectID];
 | 
			
		||||
    [self updateAnimated:animated];
 | 
			
		||||
@@ -195,7 +195,7 @@
 | 
			
		||||
        NSString *password = self.passwordField.text;
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            TimeToCrack timeToCrack;
 | 
			
		||||
            MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
            MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
            id<MPAlgorithm> algorithm = element.algorithm?: MPAlgorithmDefault;
 | 
			
		||||
            MPAttacker attackHardware = [[MPConfig get].siteAttacker unsignedIntegerValue];
 | 
			
		||||
            if ([algorithm timeToCrack:&timeToCrack passwordOfType:[self elementInContext:context].type byAttacker:attackHardware] ||
 | 
			
		||||
@@ -214,12 +214,12 @@
 | 
			
		||||
        NSString *text = textField.text;
 | 
			
		||||
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
            MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
            if (!element)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (textField == self.passwordField) {
 | 
			
		||||
                if ([element.algorithm savePassword:text toElement:element usingKey:[MPiOSAppDelegate get].key])
 | 
			
		||||
                if ([element.algorithm savePassword:text toSite:element usingKey:[MPiOSAppDelegate get].key])
 | 
			
		||||
                    [PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
 | 
			
		||||
            }
 | 
			
		||||
            else if (textField == self.loginNameField &&
 | 
			
		||||
@@ -243,7 +243,7 @@
 | 
			
		||||
 | 
			
		||||
- (IBAction)doDelete:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    MPElementEntity *element = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
    MPSiteEntity *element = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
    if (!element)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@@ -265,10 +265,10 @@
 | 
			
		||||
 | 
			
		||||
    [PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
 | 
			
		||||
                         initSheet:^(UIActionSheet *sheet) {
 | 
			
		||||
                             MPElementEntity
 | 
			
		||||
                             MPSiteEntity
 | 
			
		||||
                                     *mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
                             for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
 | 
			
		||||
                                 MPElementType type = [typeNumber unsignedIntegerValue];
 | 
			
		||||
                                 MPSiteType type = [typeNumber unsignedIntegerValue];
 | 
			
		||||
                                 NSString *typeName = [MPAlgorithmDefault nameOfType:type];
 | 
			
		||||
                                 if (type == mainElement.type)
 | 
			
		||||
                                     [sheet addButtonWithTitle:strf( @"● %@", typeName )];
 | 
			
		||||
@@ -279,11 +279,11 @@
 | 
			
		||||
                if (buttonIndex == [sheet cancelButtonIndex])
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                MPElementType type = [[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPElementTypeGeneratedLong;
 | 
			
		||||
                MPSiteType type = [[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
 | 
			
		||||
 | 
			
		||||
                [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                    MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
                    element = [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:type];
 | 
			
		||||
                    MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
                    element = [[MPiOSAppDelegate get] changeSite:element saveInContext:context toType:type];
 | 
			
		||||
                    [self setElement:element animated:YES];
 | 
			
		||||
                }];
 | 
			
		||||
            }          cancelTitle:@"Cancel" destructiveTitle:nil otherTitles:nil];
 | 
			
		||||
@@ -294,7 +294,7 @@
 | 
			
		||||
    self.loginNameField.enabled = YES;
 | 
			
		||||
    self.passwordField.enabled = YES;
 | 
			
		||||
 | 
			
		||||
    if ([self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].type & MPElementTypeClassStored)
 | 
			
		||||
    if ([self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].type & MPSiteTypeClassStored)
 | 
			
		||||
        [self.passwordField becomeFirstResponder];
 | 
			
		||||
    else
 | 
			
		||||
        [self.loginNameField becomeFirstResponder];
 | 
			
		||||
@@ -331,7 +331,7 @@
 | 
			
		||||
- (IBAction)doIncrementCounter:(UIButton *)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -363,7 +363,7 @@
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -393,7 +393,7 @@
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    [[MPiOSAppDelegate get]
 | 
			
		||||
                            addElementNamed:self.transientSite completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                            addSiteNamed:self.transientSite completion:^(MPSiteEntity *element, NSManagedObjectContext *context) {
 | 
			
		||||
                        [self copyContentOfElement:element saveInContext:context];
 | 
			
		||||
 | 
			
		||||
                        PearlMainQueueAfter( .3f, ^{
 | 
			
		||||
@@ -424,7 +424,7 @@
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
        MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
        if (![self copyLoginOfElement:element saveInContext:context]) {
 | 
			
		||||
            element.loginGenerated = YES;
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
@@ -462,7 +462,7 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [UIView animateWithDuration:animated? .3f: 0 animations:^{
 | 
			
		||||
        MPElementEntity *mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
        MPSiteEntity *mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
 | 
			
		||||
 | 
			
		||||
        // UI
 | 
			
		||||
        self.upgradeButton.alpha = mainElement.requiresExplicitMigration? 1: 0;
 | 
			
		||||
@@ -470,7 +470,7 @@
 | 
			
		||||
        self.loginNameContainer.alpha = settingsMode || mainElement.loginGenerated || [mainElement.loginName length]? 0.7f: 0;
 | 
			
		||||
        self.loginNameField.textColor = [UIColor colorWithHexString:mainElement.loginGenerated? @"5E636D": @"6D5E63"];
 | 
			
		||||
        self.modeButton.alpha = self.transientSite? 0: settingsMode? 0.5f: 0.1f;
 | 
			
		||||
        self.counterLabel.alpha = self.counterButton.alpha = mainElement.type & MPElementTypeClassGenerated? 0.5f: 0;
 | 
			
		||||
        self.counterLabel.alpha = self.counterButton.alpha = mainElement.type & MPSiteTypeClassGenerated? 0.5f: 0;
 | 
			
		||||
        self.modeButton.selected = settingsMode;
 | 
			
		||||
        self.strengthLabel.gone = !settingsMode;
 | 
			
		||||
        self.modeScrollView.scrollEnabled = !self.transientSite;
 | 
			
		||||
@@ -491,17 +491,17 @@
 | 
			
		||||
        // Site Password
 | 
			
		||||
        self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
 | 
			
		||||
        self.passwordField.attributedPlaceholder = stra(
 | 
			
		||||
                mainElement.type & MPElementTypeClassStored? strl( @"No password" ):
 | 
			
		||||
                mainElement.type & MPElementTypeClassGenerated? strl( @"..." ): @"", @{
 | 
			
		||||
                mainElement.type & MPSiteTypeClassStored? strl( @"No password" ):
 | 
			
		||||
                mainElement.type & MPSiteTypeClassGenerated? strl( @"..." ): @"", @{
 | 
			
		||||
                NSForegroundColorAttributeName : [UIColor whiteColor]
 | 
			
		||||
        } );
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPElementEntity *element = [self elementInContext:context];
 | 
			
		||||
            MPSiteEntity *element = [self elementInContext:context];
 | 
			
		||||
            MPKey *key = [MPiOSAppDelegate get].key;
 | 
			
		||||
            NSString *password, *loginName = [element resolveLoginUsingKey:key];
 | 
			
		||||
            if (self.transientSite)
 | 
			
		||||
                password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:
 | 
			
		||||
                                [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPElementTypeGeneratedLong
 | 
			
		||||
                                [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPSiteTypeGeneratedLong
 | 
			
		||||
                                                                withCounter:1 usingKey:key];
 | 
			
		||||
            else if (element)
 | 
			
		||||
                password = [element resolvePasswordUsingKey:key];
 | 
			
		||||
@@ -549,7 +549,7 @@
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)copyContentOfElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
- (BOOL)copyContentOfElement:(MPSiteEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    inf( @"Copying password for: %@", element.name );
 | 
			
		||||
    NSString *password = [element resolvePasswordUsingKey:[MPAppDelegate_Shared get].key];
 | 
			
		||||
@@ -566,10 +566,10 @@
 | 
			
		||||
    return YES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)copyLoginOfElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
- (BOOL)copyLoginOfElement:(MPSiteEntity *)element saveInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    inf( @"Copying login for: %@", element.name );
 | 
			
		||||
    NSString *loginName = [element.algorithm resolveLoginForElement:element usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
    NSString *loginName = [element.algorithm resolveLoginForSite:element usingKey:[MPiOSAppDelegate get].key];
 | 
			
		||||
    if (![loginName length])
 | 
			
		||||
        return NO;
 | 
			
		||||
 | 
			
		||||
@@ -583,9 +583,9 @@
 | 
			
		||||
    return YES;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementEntity *)elementInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
- (MPSiteEntity *)elementInContext:(NSManagedObjectContext *)context {
 | 
			
		||||
 | 
			
		||||
    return [MPElementEntity existingObjectWithID:_elementOID inContext:context];
 | 
			
		||||
    return [MPSiteEntity existingObjectWithID:_elementOID inContext:context];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
//  Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
@class MPElementEntity;
 | 
			
		||||
@class MPSiteEntity;
 | 
			
		||||
@class MPCoachmark;
 | 
			
		||||
 | 
			
		||||
@interface MPPasswordsViewController : UIViewController<UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
 | 
			
		||||
 
 | 
			
		||||
@@ -423,7 +423,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
 | 
			
		||||
    if (!_fetchedResultsController) {
 | 
			
		||||
        _showTransientItem = NO;
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
 | 
			
		||||
            NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
 | 
			
		||||
            NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
 | 
			
		||||
            fetchRequest.sortDescriptors = @[
 | 
			
		||||
                    [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
            self.generatedTypeControl.selectedSegmentIndex = -1;
 | 
			
		||||
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPElementType defaultType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType = [self typeForSelectedSegment];
 | 
			
		||||
            MPSiteType defaultType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType = [self typeForSelectedSegment];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
@@ -179,31 +179,31 @@
 | 
			
		||||
    return nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (enum MPElementType)typeForSelectedSegment {
 | 
			
		||||
- (enum MPSiteType)typeForSelectedSegment {
 | 
			
		||||
 | 
			
		||||
    NSInteger selectedGeneratedIndex = self.generatedTypeControl.selectedSegmentIndex;
 | 
			
		||||
    NSInteger selectedStoredIndex = self.storedTypeControl.selectedSegmentIndex;
 | 
			
		||||
 | 
			
		||||
    switch (selectedGeneratedIndex) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            return MPElementTypeGeneratedMaximum;
 | 
			
		||||
            return MPSiteTypeGeneratedMaximum;
 | 
			
		||||
        case 1:
 | 
			
		||||
            return MPElementTypeGeneratedLong;
 | 
			
		||||
            return MPSiteTypeGeneratedLong;
 | 
			
		||||
        case 2:
 | 
			
		||||
            return MPElementTypeGeneratedMedium;
 | 
			
		||||
            return MPSiteTypeGeneratedMedium;
 | 
			
		||||
        case 3:
 | 
			
		||||
            return MPElementTypeGeneratedBasic;
 | 
			
		||||
            return MPSiteTypeGeneratedBasic;
 | 
			
		||||
        case 4:
 | 
			
		||||
            return MPElementTypeGeneratedShort;
 | 
			
		||||
            return MPSiteTypeGeneratedShort;
 | 
			
		||||
        case 5:
 | 
			
		||||
            return MPElementTypeGeneratedPIN;
 | 
			
		||||
            return MPSiteTypeGeneratedPIN;
 | 
			
		||||
        default:
 | 
			
		||||
 | 
			
		||||
            switch (selectedStoredIndex) {
 | 
			
		||||
                case 0:
 | 
			
		||||
                    return MPElementTypeStoredPersonal;
 | 
			
		||||
                    return MPSiteTypeStoredPersonal;
 | 
			
		||||
                case 1:
 | 
			
		||||
                    return MPElementTypeStoredDevicePrivate;
 | 
			
		||||
                    return MPSiteTypeStoredDevicePrivate;
 | 
			
		||||
                default:
 | 
			
		||||
                    Throw( @"unsupported selected type index: generated=%ld, stored=%ld", (long)selectedGeneratedIndex,
 | 
			
		||||
                                    (long)selectedStoredIndex );
 | 
			
		||||
@@ -211,32 +211,32 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSInteger)generatedSegmentIndexForType:(MPElementType)type {
 | 
			
		||||
- (NSInteger)generatedSegmentIndexForType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeGeneratedMaximum:
 | 
			
		||||
        case MPSiteTypeGeneratedMaximum:
 | 
			
		||||
            return 0;
 | 
			
		||||
        case MPElementTypeGeneratedLong:
 | 
			
		||||
        case MPSiteTypeGeneratedLong:
 | 
			
		||||
            return 1;
 | 
			
		||||
        case MPElementTypeGeneratedMedium:
 | 
			
		||||
        case MPSiteTypeGeneratedMedium:
 | 
			
		||||
            return 2;
 | 
			
		||||
        case MPElementTypeGeneratedBasic:
 | 
			
		||||
        case MPSiteTypeGeneratedBasic:
 | 
			
		||||
            return 3;
 | 
			
		||||
        case MPElementTypeGeneratedShort:
 | 
			
		||||
        case MPSiteTypeGeneratedShort:
 | 
			
		||||
            return 4;
 | 
			
		||||
        case MPElementTypeGeneratedPIN:
 | 
			
		||||
        case MPSiteTypeGeneratedPIN:
 | 
			
		||||
            return 5;
 | 
			
		||||
        default:
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSInteger)storedSegmentIndexForType:(MPElementType)type {
 | 
			
		||||
- (NSInteger)storedSegmentIndexForType:(MPSiteType)type {
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case MPElementTypeStoredPersonal:
 | 
			
		||||
        case MPSiteTypeStoredPersonal:
 | 
			
		||||
            return 0;
 | 
			
		||||
        case MPElementTypeStoredDevicePrivate:
 | 
			
		||||
        case MPSiteTypeStoredDevicePrivate:
 | 
			
		||||
            return 1;
 | 
			
		||||
        default:
 | 
			
		||||
            return -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -134,6 +134,8 @@
 | 
			
		||||
 | 
			
		||||
    if ([productIdentifier isEqualToString:MPProductGenerateLogins])
 | 
			
		||||
        return self.generateLoginCell;
 | 
			
		||||
    if ([productIdentifier isEqualToString:MPProductAdvancedExport])
 | 
			
		||||
        return self.advancedExportCell;
 | 
			
		||||
 | 
			
		||||
    return nil;
 | 
			
		||||
}
 | 
			
		||||
@@ -145,19 +147,24 @@
 | 
			
		||||
    [hideCells addObjectsFromArray:self.allCellsBySection[0]];
 | 
			
		||||
 | 
			
		||||
    for (SKProduct *product in products) {
 | 
			
		||||
        [self showCell:self.generateLoginCell ifProduct:product hasProductIdentifier:MPProductGenerateLogins showingCells:showCells];
 | 
			
		||||
        [self showCellForProductWithIdentifier:MPProductGenerateLogins ifProduct:product showingCells:showCells];
 | 
			
		||||
        [self showCellForProductWithIdentifier:MPProductAdvancedExport ifProduct:product showingCells:showCells];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [hideCells removeObjectsInArray:showCells];
 | 
			
		||||
    [self updateCellsHiding:hideCells showing:showCells animation:UITableViewRowAnimationAutomatic];
 | 
			
		||||
    if ([self.tableView numberOfRowsInSection:0])
 | 
			
		||||
        [self updateCellsHiding:hideCells showing:showCells animation:UITableViewRowAnimationAutomatic];
 | 
			
		||||
    else
 | 
			
		||||
        [self updateCellsHiding:hideCells showing:showCells animation:UITableViewRowAnimationNone];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)showCell:(MPStoreProductCell *)cell ifProduct:(SKProduct *)product hasProductIdentifier:(NSString *)productIdentifier
 | 
			
		||||
    showingCells:(NSMutableArray *)showCells {
 | 
			
		||||
- (void)showCellForProductWithIdentifier:(NSString *)productIdentifier ifProduct:(SKProduct *)product
 | 
			
		||||
                            showingCells:(NSMutableArray *)showCells {
 | 
			
		||||
 | 
			
		||||
    if (![product.productIdentifier isEqualToString:productIdentifier])
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    MPStoreProductCell *cell = [self cellForProductIdentifier:productIdentifier];
 | 
			
		||||
    [showCells addObject:cell];
 | 
			
		||||
 | 
			
		||||
    self.currencyFormatter.locale = product.priceLocale;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,11 @@
 | 
			
		||||
@protocol MPTypeDelegate<NSObject>
 | 
			
		||||
 | 
			
		||||
@required
 | 
			
		||||
- (void)didSelectType:(MPElementType)type;
 | 
			
		||||
- (MPElementType)selectedType;
 | 
			
		||||
- (void)didSelectType:(MPSiteType)type;
 | 
			
		||||
- (MPSiteType)selectedType;
 | 
			
		||||
 | 
			
		||||
@optional
 | 
			
		||||
- (MPElementEntity *)selectedElement;
 | 
			
		||||
- (MPSiteEntity *)selectedElement;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
 | 
			
		||||
@interface MPTypeViewController()
 | 
			
		||||
 | 
			
		||||
- (MPElementType)typeAtIndexPath:(NSIndexPath *)indexPath;
 | 
			
		||||
- (MPSiteType)typeAtIndexPath:(NSIndexPath *)indexPath;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
@@ -63,15 +63,15 @@
 | 
			
		||||
 | 
			
		||||
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
 | 
			
		||||
 | 
			
		||||
    MPElementEntity *selectedElement = nil;
 | 
			
		||||
    MPSiteEntity *selectedElement = nil;
 | 
			
		||||
    if ([self.delegate respondsToSelector:@selector(selectedElement)])
 | 
			
		||||
        selectedElement = [self.delegate selectedElement];
 | 
			
		||||
 | 
			
		||||
    MPElementType cellType = [self typeAtIndexPath:indexPath];
 | 
			
		||||
    MPElementType selectedType = selectedElement? selectedElement.type: [self.delegate selectedType];
 | 
			
		||||
    MPSiteType cellType = [self typeAtIndexPath:indexPath];
 | 
			
		||||
    MPSiteType selectedType = selectedElement? selectedElement.type: [self.delegate selectedType];
 | 
			
		||||
    cell.selected = (selectedType == cellType);
 | 
			
		||||
 | 
			
		||||
    if (cellType != (MPElementType)NSNotFound && cellType & MPElementTypeClassGenerated) {
 | 
			
		||||
    if (cellType != (MPSiteType)NSNotFound && cellType & MPSiteTypeClassGenerated) {
 | 
			
		||||
        [(UITextField *)[cell viewWithTag:2] setText:@"..."];
 | 
			
		||||
 | 
			
		||||
        NSString *name = selectedElement.name;
 | 
			
		||||
@@ -96,8 +96,8 @@
 | 
			
		||||
 | 
			
		||||
    NSAssert(self.navigationController.topViewController == self, @"Not the currently active navigation item.");
 | 
			
		||||
 | 
			
		||||
    MPElementType type = [self typeAtIndexPath:indexPath];
 | 
			
		||||
    if (type == (MPElementType)NSNotFound)
 | 
			
		||||
    MPSiteType type = [self typeAtIndexPath:indexPath];
 | 
			
		||||
    if (type == (MPSiteType)NSNotFound)
 | 
			
		||||
            // Selected a non-type row.
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@@ -105,28 +105,28 @@
 | 
			
		||||
    [self.navigationController popViewControllerAnimated:YES];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPElementType)typeAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
- (MPSiteType)typeAtIndexPath:(NSIndexPath *)indexPath {
 | 
			
		||||
 | 
			
		||||
    switch (indexPath.section) {
 | 
			
		||||
        case 0: {
 | 
			
		||||
            // Generated
 | 
			
		||||
            switch (indexPath.row) {
 | 
			
		||||
                case 0:
 | 
			
		||||
                    return (MPElementType)NSNotFound;
 | 
			
		||||
                    return (MPSiteType)NSNotFound;
 | 
			
		||||
                case 1:
 | 
			
		||||
                    return MPElementTypeGeneratedMaximum;
 | 
			
		||||
                    return MPSiteTypeGeneratedMaximum;
 | 
			
		||||
                case 2:
 | 
			
		||||
                    return MPElementTypeGeneratedLong;
 | 
			
		||||
                    return MPSiteTypeGeneratedLong;
 | 
			
		||||
                case 3:
 | 
			
		||||
                    return MPElementTypeGeneratedMedium;
 | 
			
		||||
                    return MPSiteTypeGeneratedMedium;
 | 
			
		||||
                case 4:
 | 
			
		||||
                    return MPElementTypeGeneratedBasic;
 | 
			
		||||
                    return MPSiteTypeGeneratedBasic;
 | 
			
		||||
                case 5:
 | 
			
		||||
                    return MPElementTypeGeneratedShort;
 | 
			
		||||
                    return MPSiteTypeGeneratedShort;
 | 
			
		||||
                case 6:
 | 
			
		||||
                    return MPElementTypeGeneratedPIN;
 | 
			
		||||
                    return MPSiteTypeGeneratedPIN;
 | 
			
		||||
                case 7:
 | 
			
		||||
                    return (MPElementType)NSNotFound;
 | 
			
		||||
                    return (MPSiteType)NSNotFound;
 | 
			
		||||
 | 
			
		||||
                default: {
 | 
			
		||||
                    Throw(@"Unsupported row: %ld, when selecting generated element type.", (long)indexPath.row);
 | 
			
		||||
@@ -138,13 +138,13 @@
 | 
			
		||||
            // Stored
 | 
			
		||||
            switch (indexPath.row) {
 | 
			
		||||
                case 0:
 | 
			
		||||
                    return (MPElementType)NSNotFound;
 | 
			
		||||
                    return (MPSiteType)NSNotFound;
 | 
			
		||||
                case 1:
 | 
			
		||||
                    return MPElementTypeStoredPersonal;
 | 
			
		||||
                    return MPSiteTypeStoredPersonal;
 | 
			
		||||
                case 2:
 | 
			
		||||
                    return MPElementTypeStoredDevicePrivate;
 | 
			
		||||
                    return MPSiteTypeStoredDevicePrivate;
 | 
			
		||||
                case 3:
 | 
			
		||||
                    return (MPElementType)NSNotFound;
 | 
			
		||||
                    return (MPSiteType)NSNotFound;
 | 
			
		||||
 | 
			
		||||
                default: {
 | 
			
		||||
                    Throw(@"Unsupported row: %ld, when selecting stored element type.", (long)indexPath.row);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
	objects = {
 | 
			
		||||
 | 
			
		||||
/* Begin PBXBuildFile section */
 | 
			
		||||
		93D390C1B93F9D3AE37DD0A5 /* MPAnswersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39C426E03358384018E85 /* MPAnswersViewController.m */; };
 | 
			
		||||
		93D391ECBD9BD2C64115B5DD /* PearlSizedTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */; };
 | 
			
		||||
		93D391ED37C9F687FA51EAA1 /* MPEmergencySegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3937712BF1B67623E5764 /* MPEmergencySegue.m */; };
 | 
			
		||||
		93D3922A53E41A54832E90D9 /* PearlOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FADEB325D8D54A957D /* PearlOverlay.m */; };
 | 
			
		||||
@@ -157,6 +158,11 @@
 | 
			
		||||
		DA854C8318D4CFBF00106317 /* avatar-add@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA854C8118D4CFBF00106317 /* avatar-add@2x.png */; };
 | 
			
		||||
		DA854C8418D4CFBF00106317 /* avatar-add.png in Resources */ = {isa = PBXBuildFile; fileRef = DA854C8218D4CFBF00106317 /* avatar-add.png */; };
 | 
			
		||||
		DA945C8717E3F3FD0053236B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA945C8617E3F3FD0053236B /* Images.xcassets */; };
 | 
			
		||||
		DA9521A819CEA3DE002E3AD5 /* MPSiteEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521A719CEA3DE002E3AD5 /* MPSiteEntity.m */; };
 | 
			
		||||
		DA9521AB19CEA3DE002E3AD5 /* MPSiteQuestion.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521AA19CEA3DE002E3AD5 /* MPSiteQuestion.m */; };
 | 
			
		||||
		DA9521AE19CEA3DE002E3AD5 /* MPSiteStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521AD19CEA3DE002E3AD5 /* MPSiteStoredEntity.m */; };
 | 
			
		||||
		DA9521B119CEA3DE002E3AD5 /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521B019CEA3DE002E3AD5 /* MPUserEntity.m */; };
 | 
			
		||||
		DA9521B419CEA3DE002E3AD5 /* MPSiteGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9521B319CEA3DE002E3AD5 /* MPSiteGeneratedEntity.m */; };
 | 
			
		||||
		DA95D5F214DF0B2C008D1B94 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */; };
 | 
			
		||||
		DAA141201922FF020032B392 /* PearlTween.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA1411C1922FF020032B392 /* PearlTween.m */; };
 | 
			
		||||
		DAA141211922FF020032B392 /* PearlTween.h in Headers */ = {isa = PBXBuildFile; fileRef = DAA1411D1922FF020032B392 /* PearlTween.h */; };
 | 
			
		||||
@@ -275,13 +281,14 @@
 | 
			
		||||
		DACE2F6D19BA6A2A0010F92E /* PearlMutableStaticTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DACE2F6919BA6A2A0010F92E /* PearlMutableStaticTableViewController.h */; };
 | 
			
		||||
		DACE2F6E19BA6A2A0010F92E /* UIView+FontScale.h in Headers */ = {isa = PBXBuildFile; fileRef = DACE2F6A19BA6A2A0010F92E /* UIView+FontScale.h */; };
 | 
			
		||||
		DAD312C21552A22700A3F9ED /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD312C01552A20800A3F9ED /* libsqlite3.dylib */; };
 | 
			
		||||
		DADB4EC719C66FB60065A78D /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DADB4EC619C66FB60065A78D /* MPUserEntity.m */; };
 | 
			
		||||
		DADB4ECA19C66FB60065A78D /* MPElementEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DADB4EC919C66FB60065A78D /* MPElementEntity.m */; };
 | 
			
		||||
		DADB4ECD19C66FB60065A78D /* MPElementGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DADB4ECC19C66FB60065A78D /* MPElementGeneratedEntity.m */; };
 | 
			
		||||
		DADB4ED019C66FB70065A78D /* MPElementStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DADB4ECF19C66FB70065A78D /* MPElementStoredEntity.m */; };
 | 
			
		||||
		DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAE1EF2417E942DE00BC0086 /* Localizable.strings */; };
 | 
			
		||||
		DAE2725919C93B80007C5262 /* libInAppSettingsKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAFC5655172C573B00CB5CC5 /* libInAppSettingsKit.a */; };
 | 
			
		||||
		DAE2725A19C93B8E007C5262 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA70EC7F1811B13C00F65DB2 /* StoreKit.framework */; };
 | 
			
		||||
		DAE2725E19CA98A5007C5262 /* thumb_advanced_export.png in Resources */ = {isa = PBXBuildFile; fileRef = DAE2725B19CA98A5007C5262 /* thumb_advanced_export.png */; };
 | 
			
		||||
		DAE2725F19CA98A5007C5262 /* thumb_advanced_export@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAE2725C19CA98A5007C5262 /* thumb_advanced_export@2x.png */; };
 | 
			
		||||
		DAE2726019CA98A5007C5262 /* thumb_advanced_export@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAE2725D19CA98A5007C5262 /* thumb_advanced_export@3x.png */; };
 | 
			
		||||
		DAE2726319CE9CB3007C5262 /* UITableViewCell+PearlDeque.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE2726119CE9CB3007C5262 /* UITableViewCell+PearlDeque.m */; };
 | 
			
		||||
		DAE2726419CE9CB3007C5262 /* UITableViewCell+PearlDeque.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE2726219CE9CB3007C5262 /* UITableViewCell+PearlDeque.h */; };
 | 
			
		||||
		DAEBC45314F6364500987BF6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
 | 
			
		||||
		DAEC85B518E3DD9A007FC0DF /* UIView+Touches.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */; };
 | 
			
		||||
		DAEC85B618E3DD9A007FC0DF /* PearlUINavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEC85B218E3DD9A007FC0DF /* PearlUINavigationBar.m */; };
 | 
			
		||||
@@ -438,12 +445,14 @@
 | 
			
		||||
		93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39BAA71DE51B4D8A1286C /* MPCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCell.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39C426E03358384018E85 /* MPAnswersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnswersViewController.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsSegue.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCombinedViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39D6604447D7708039155 /* MPAnswersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnswersViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
 | 
			
		||||
		93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; };
 | 
			
		||||
		93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlAdjustInsets.h"; sourceTree = "<group>"; };
 | 
			
		||||
@@ -529,6 +538,16 @@
 | 
			
		||||
		DA854C8118D4CFBF00106317 /* avatar-add@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add@2x.png"; sourceTree = "<group>"; };
 | 
			
		||||
		DA854C8218D4CFBF00106317 /* avatar-add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add.png"; sourceTree = "<group>"; };
 | 
			
		||||
		DA945C8617E3F3FD0053236B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521A619CEA3DE002E3AD5 /* MPSiteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521A719CEA3DE002E3AD5 /* MPSiteEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521A919CEA3DE002E3AD5 /* MPSiteQuestion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteQuestion.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521AA19CEA3DE002E3AD5 /* MPSiteQuestion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteQuestion.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521AC19CEA3DE002E3AD5 /* MPSiteStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteStoredEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521AD19CEA3DE002E3AD5 /* MPSiteStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteStoredEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521AF19CEA3DE002E3AD5 /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B019CEA3DE002E3AD5 /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B219CEA3DE002E3AD5 /* MPSiteGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteGeneratedEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DA9521B319CEA3DE002E3AD5 /* MPSiteGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteGeneratedEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
 | 
			
		||||
		DAA141191922FED80032B392 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = "<group>"; };
 | 
			
		||||
		DAA1411C1922FF020032B392 /* PearlTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlTween.m; sourceTree = "<group>"; };
 | 
			
		||||
@@ -1174,19 +1193,11 @@
 | 
			
		||||
		DABD3BAB1711E2DC00CF925C /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BAC1711E2DC00CF925C /* MPConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPConfig.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BAD1711E2DC00CF925C /* MPConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPConfig.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BAE1711E2DC00CF925C /* MPElementEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BAF1711E2DC00CF925C /* MPElementEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB01711E2DC00CF925C /* MPElementGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementGeneratedEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB11711E2DC00CF925C /* MPElementGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementGeneratedEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB21711E2DC00CF925C /* MPElementStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementStoredEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB31711E2DC00CF925C /* MPElementStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementStoredEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB41711E2DC00CF925C /* MPEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntities.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB51711E2DC00CF925C /* MPEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEntities.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB61711E2DC00CF925C /* MPKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPKey.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB71711E2DC00CF925C /* MPKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPKey.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB81711E2DC00CF925C /* MPTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTypes.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BB91711E2DC00CF925C /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BBA1711E2DC00CF925C /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BD11711E2DC00CF925C /* MasterPassword 1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MasterPassword 1.xcdatamodel"; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BD21711E2DC00CF925C /* MasterPassword 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MasterPassword 2.xcdatamodel"; sourceTree = "<group>"; };
 | 
			
		||||
		DABD3BD31711E2DC00CF925C /* MasterPassword 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MasterPassword 3.xcdatamodel"; sourceTree = "<group>"; };
 | 
			
		||||
@@ -1232,16 +1243,13 @@
 | 
			
		||||
		DACE2F6919BA6A2A0010F92E /* PearlMutableStaticTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlMutableStaticTableViewController.h; sourceTree = "<group>"; };
 | 
			
		||||
		DACE2F6A19BA6A2A0010F92E /* UIView+FontScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+FontScale.h"; sourceTree = "<group>"; };
 | 
			
		||||
		DAD312C01552A20800A3F9ED /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
 | 
			
		||||
		DADB4EC519C66FB50065A78D /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4EC619C66FB60065A78D /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4EC819C66FB60065A78D /* MPElementEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4EC919C66FB60065A78D /* MPElementEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4ECB19C66FB60065A78D /* MPElementGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementGeneratedEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4ECC19C66FB60065A78D /* MPElementGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementGeneratedEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4ECE19C66FB60065A78D /* MPElementStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementStoredEntity.h; sourceTree = "<group>"; };
 | 
			
		||||
		DADB4ECF19C66FB70065A78D /* MPElementStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementStoredEntity.m; sourceTree = "<group>"; };
 | 
			
		||||
		DADBB55918DB0CFC00D099FE /* keyboard-dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-dark@2x.png"; sourceTree = "<group>"; };
 | 
			
		||||
		DAE1EF2317E942DE00BC0086 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 | 
			
		||||
		DAE2725B19CA98A5007C5262 /* thumb_advanced_export.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_advanced_export.png; sourceTree = "<group>"; };
 | 
			
		||||
		DAE2725C19CA98A5007C5262 /* thumb_advanced_export@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_advanced_export@2x.png"; sourceTree = "<group>"; };
 | 
			
		||||
		DAE2725D19CA98A5007C5262 /* thumb_advanced_export@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_advanced_export@3x.png"; sourceTree = "<group>"; };
 | 
			
		||||
		DAE2726119CE9CB3007C5262 /* UITableViewCell+PearlDeque.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableViewCell+PearlDeque.m"; sourceTree = "<group>"; };
 | 
			
		||||
		DAE2726219CE9CB3007C5262 /* UITableViewCell+PearlDeque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableViewCell+PearlDeque.h"; sourceTree = "<group>"; };
 | 
			
		||||
		DAE8E65119867AB500416A0F /* libopensslcrypto-ios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-ios.a"; sourceTree = "<group>"; };
 | 
			
		||||
		DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 | 
			
		||||
		DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Touches.m"; sourceTree = "<group>"; };
 | 
			
		||||
@@ -1473,6 +1481,8 @@
 | 
			
		||||
				DA5BFA45147E415C00F98B1E /* Products */,
 | 
			
		||||
				93D39149A5F1F9B174D6D061 /* MPStoreViewController.h */,
 | 
			
		||||
				93D3957D76F71A652716EECC /* MPStoreViewController.m */,
 | 
			
		||||
				93D39C426E03358384018E85 /* MPAnswersViewController.m */,
 | 
			
		||||
				93D39D6604447D7708039155 /* MPAnswersViewController.h */,
 | 
			
		||||
			);
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
@@ -1553,6 +1563,9 @@
 | 
			
		||||
		DABD360D1711E29400CF925C /* Media */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				DAE2725B19CA98A5007C5262 /* thumb_advanced_export.png */,
 | 
			
		||||
				DAE2725C19CA98A5007C5262 /* thumb_advanced_export@2x.png */,
 | 
			
		||||
				DAE2725D19CA98A5007C5262 /* thumb_advanced_export@3x.png */,
 | 
			
		||||
				DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */,
 | 
			
		||||
				DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */,
 | 
			
		||||
				DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */,
 | 
			
		||||
@@ -2257,14 +2270,6 @@
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				DABD3BD71711E2DC00CF925C /* iOS */,
 | 
			
		||||
				DADB4ECE19C66FB60065A78D /* MPElementStoredEntity.h */,
 | 
			
		||||
				DADB4ECF19C66FB70065A78D /* MPElementStoredEntity.m */,
 | 
			
		||||
				DADB4ECB19C66FB60065A78D /* MPElementGeneratedEntity.h */,
 | 
			
		||||
				DADB4ECC19C66FB60065A78D /* MPElementGeneratedEntity.m */,
 | 
			
		||||
				DADB4EC819C66FB60065A78D /* MPElementEntity.h */,
 | 
			
		||||
				DADB4EC919C66FB60065A78D /* MPElementEntity.m */,
 | 
			
		||||
				DADB4EC519C66FB50065A78D /* MPUserEntity.h */,
 | 
			
		||||
				DADB4EC619C66FB60065A78D /* MPUserEntity.m */,
 | 
			
		||||
				DABD3BA01711E2DC00CF925C /* MPAlgorithm.h */,
 | 
			
		||||
				DABD3BA11711E2DC00CF925C /* MPAlgorithm.m */,
 | 
			
		||||
				DABD3BA21711E2DC00CF925C /* MPAlgorithmV0.h */,
 | 
			
		||||
@@ -2279,20 +2284,22 @@
 | 
			
		||||
				DABD3BAB1711E2DC00CF925C /* MPAppDelegate_Store.m */,
 | 
			
		||||
				DABD3BAC1711E2DC00CF925C /* MPConfig.h */,
 | 
			
		||||
				DABD3BAD1711E2DC00CF925C /* MPConfig.m */,
 | 
			
		||||
				DABD3BAE1711E2DC00CF925C /* MPElementEntity.h */,
 | 
			
		||||
				DABD3BAF1711E2DC00CF925C /* MPElementEntity.m */,
 | 
			
		||||
				DABD3BB01711E2DC00CF925C /* MPElementGeneratedEntity.h */,
 | 
			
		||||
				DABD3BB11711E2DC00CF925C /* MPElementGeneratedEntity.m */,
 | 
			
		||||
				DABD3BB21711E2DC00CF925C /* MPElementStoredEntity.h */,
 | 
			
		||||
				DABD3BB31711E2DC00CF925C /* MPElementStoredEntity.m */,
 | 
			
		||||
				DABD3BB41711E2DC00CF925C /* MPEntities.h */,
 | 
			
		||||
				DABD3BB51711E2DC00CF925C /* MPEntities.m */,
 | 
			
		||||
				DABD3BB61711E2DC00CF925C /* MPKey.h */,
 | 
			
		||||
				DABD3BB71711E2DC00CF925C /* MPKey.m */,
 | 
			
		||||
				DABD3BB81711E2DC00CF925C /* MPTypes.h */,
 | 
			
		||||
				DABD3BB91711E2DC00CF925C /* MPUserEntity.h */,
 | 
			
		||||
				DABD3BBA1711E2DC00CF925C /* MPUserEntity.m */,
 | 
			
		||||
				DABD3BD01711E2DC00CF925C /* MasterPassword.xcdatamodeld */,
 | 
			
		||||
				DA9521AC19CEA3DE002E3AD5 /* MPSiteStoredEntity.h */,
 | 
			
		||||
				DA9521AF19CEA3DE002E3AD5 /* MPUserEntity.h */,
 | 
			
		||||
				DA9521B019CEA3DE002E3AD5 /* MPUserEntity.m */,
 | 
			
		||||
				DA9521AD19CEA3DE002E3AD5 /* MPSiteStoredEntity.m */,
 | 
			
		||||
				DA9521B219CEA3DE002E3AD5 /* MPSiteGeneratedEntity.h */,
 | 
			
		||||
				DA9521B319CEA3DE002E3AD5 /* MPSiteGeneratedEntity.m */,
 | 
			
		||||
				DA9521A919CEA3DE002E3AD5 /* MPSiteQuestion.h */,
 | 
			
		||||
				DA9521AA19CEA3DE002E3AD5 /* MPSiteQuestion.m */,
 | 
			
		||||
				DA9521A619CEA3DE002E3AD5 /* MPSiteEntity.h */,
 | 
			
		||||
				DA9521A719CEA3DE002E3AD5 /* MPSiteEntity.m */,
 | 
			
		||||
				93D399F244BB522A317811BB /* MPFixable.h */,
 | 
			
		||||
				93D39A813CA9D7E192261ED2 /* MPFixable.m */,
 | 
			
		||||
				93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */,
 | 
			
		||||
@@ -2589,6 +2596,8 @@
 | 
			
		||||
		DAFE460715039823003ABA7C /* Pearl-UIKit */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				DAE2726119CE9CB3007C5262 /* UITableViewCell+PearlDeque.m */,
 | 
			
		||||
				DAE2726219CE9CB3007C5262 /* UITableViewCell+PearlDeque.h */,
 | 
			
		||||
				DAEFB01C19BCBD9E00525079 /* UIView+LayoutGone.m */,
 | 
			
		||||
				DAEFB01D19BCBD9E00525079 /* UIView+LayoutGone.h */,
 | 
			
		||||
				DACE2F6719BA6A2A0010F92E /* UIView+FontScale.m */,
 | 
			
		||||
@@ -2725,6 +2734,7 @@
 | 
			
		||||
				DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */,
 | 
			
		||||
				DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
 | 
			
		||||
				DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
 | 
			
		||||
				DAE2726419CE9CB3007C5262 /* UITableViewCell+PearlDeque.h in Headers */,
 | 
			
		||||
				DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */,
 | 
			
		||||
				DACE2F6E19BA6A2A0010F92E /* UIView+FontScale.h in Headers */,
 | 
			
		||||
				DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */,
 | 
			
		||||
@@ -3071,6 +3081,7 @@
 | 
			
		||||
				DA250A031956484D00AC23F1 /* image-7@2x.png in Resources */,
 | 
			
		||||
				DA25C5FA197CCAE00046CDCF /* icon_delete.png in Resources */,
 | 
			
		||||
				DA25C601197DBF260046CDCF /* icon_trash@2x.png in Resources */,
 | 
			
		||||
				DAE2725E19CA98A5007C5262 /* thumb_advanced_export.png in Resources */,
 | 
			
		||||
				DABD39551711E29700CF925C /* avatar-6.png in Resources */,
 | 
			
		||||
				DABD39561711E29700CF925C /* avatar-6@2x.png in Resources */,
 | 
			
		||||
				DABD39571711E29700CF925C /* avatar-7.png in Resources */,
 | 
			
		||||
@@ -3092,6 +3103,7 @@
 | 
			
		||||
				DABD39881711E29700CF925C /* SourceCodePro-ExtraLight.otf in Resources */,
 | 
			
		||||
				DABD39A01711E29700CF925C /* icon_action.png in Resources */,
 | 
			
		||||
				DABD39A11711E29700CF925C /* icon_action@2x.png in Resources */,
 | 
			
		||||
				DAE2726019CA98A5007C5262 /* thumb_advanced_export@3x.png in Resources */,
 | 
			
		||||
				DABD39F21711E29700CF925C /* icon_cancel.png in Resources */,
 | 
			
		||||
				DA25C5FB197CCAE00046CDCF /* icon_delete@2x.png in Resources */,
 | 
			
		||||
				DA29993219C9132F00AF7DF1 /* thumb_generated_login@3x.png in Resources */,
 | 
			
		||||
@@ -3106,6 +3118,7 @@
 | 
			
		||||
				DABD3AA01711E29800CF925C /* icon_pause.png in Resources */,
 | 
			
		||||
				DABD3AA11711E29800CF925C /* icon_pause@2x.png in Resources */,
 | 
			
		||||
				DABD3AAA1711E29800CF925C /* icon_person.png in Resources */,
 | 
			
		||||
				DAE2725F19CA98A5007C5262 /* thumb_advanced_export@2x.png in Resources */,
 | 
			
		||||
				DABD3AAB1711E29800CF925C /* icon_person@2x.png in Resources */,
 | 
			
		||||
				DABD3ABC1711E29800CF925C /* icon_play.png in Resources */,
 | 
			
		||||
				DABD3ABD1711E29800CF925C /* icon_play@2x.png in Resources */,
 | 
			
		||||
@@ -3209,19 +3222,19 @@
 | 
			
		||||
				DABD3C081711E2DC00CF925C /* MPKey.m in Sources */,
 | 
			
		||||
				DABD3C141711E2DC00CF925C /* MasterPassword.xcdatamodeld in Sources */,
 | 
			
		||||
				DABD3C151711E2DC00CF925C /* MPiOSAppDelegate.m in Sources */,
 | 
			
		||||
				DA9521A819CEA3DE002E3AD5 /* MPSiteEntity.m in Sources */,
 | 
			
		||||
				DABD3C1C1711E2DC00CF925C /* MPGuideViewController.m in Sources */,
 | 
			
		||||
				DABD3C1E1711E2DC00CF925C /* MPPreferencesViewController.m in Sources */,
 | 
			
		||||
				DABD3C1F1711E2DC00CF925C /* MPTypeViewController.m in Sources */,
 | 
			
		||||
				DABD3C211711E2DC00CF925C /* MPiOSConfig.m in Sources */,
 | 
			
		||||
				DABD3C271711E2DC00CF925C /* main.m in Sources */,
 | 
			
		||||
				DADB4EC719C66FB60065A78D /* MPUserEntity.m in Sources */,
 | 
			
		||||
				93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */,
 | 
			
		||||
				DA9521AE19CEA3DE002E3AD5 /* MPSiteStoredEntity.m in Sources */,
 | 
			
		||||
				DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */,
 | 
			
		||||
				93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */,
 | 
			
		||||
				DADB4ECD19C66FB60065A78D /* MPElementGeneratedEntity.m in Sources */,
 | 
			
		||||
				93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */,
 | 
			
		||||
				93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */,
 | 
			
		||||
				DADB4ED019C66FB70065A78D /* MPElementStoredEntity.m in Sources */,
 | 
			
		||||
				DA9521B419CEA3DE002E3AD5 /* MPSiteGeneratedEntity.m in Sources */,
 | 
			
		||||
				93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */,
 | 
			
		||||
				93D39392DEDA376F93C6C718 /* MPCell.m in Sources */,
 | 
			
		||||
				93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */,
 | 
			
		||||
@@ -3231,9 +3244,9 @@
 | 
			
		||||
				93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */,
 | 
			
		||||
				93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */,
 | 
			
		||||
				93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */,
 | 
			
		||||
				DADB4ECA19C66FB60065A78D /* MPElementEntity.m in Sources */,
 | 
			
		||||
				93D39EAA4D064193074D3021 /* MPFixable.m in Sources */,
 | 
			
		||||
				93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */,
 | 
			
		||||
				DA9521B119CEA3DE002E3AD5 /* MPUserEntity.m in Sources */,
 | 
			
		||||
				93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */,
 | 
			
		||||
				93D3939661CE37180AF7CD6A /* MPStoreViewController.m in Sources */,
 | 
			
		||||
				DA9521AB19CEA3DE002E3AD5 /* MPSiteQuestion.m in Sources */,
 | 
			
		||||
@@ -3290,6 +3303,7 @@
 | 
			
		||||
				DAFE4A4715039824003ABA7C /* PearlLayout.m in Sources */,
 | 
			
		||||
				DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */,
 | 
			
		||||
				DAFE4A4915039824003ABA7C /* PearlLayoutView.m in Sources */,
 | 
			
		||||
				DAE2726319CE9CB3007C5262 /* UITableViewCell+PearlDeque.m in Sources */,
 | 
			
		||||
				DAFE4A4B15039824003ABA7C /* PearlMessageView.m in Sources */,
 | 
			
		||||
				DACE2F6519BA6A0A0010F92E /* PearlProfiler.m in Sources */,
 | 
			
		||||
				DAFE4A4D15039824003ABA7C /* PearlRootViewController.m in Sources */,
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,9 @@
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
            <string>Exo2.0-Bold</string>
 | 
			
		||||
        </mutableArray>
 | 
			
		||||
        <mutableArray key="Exo2.0-ExtraBold.otf">
 | 
			
		||||
            <string>Exo2.0-ExtraBold</string>
 | 
			
		||||
@@ -64,6 +67,7 @@
 | 
			
		||||
            <string>Exo2.0-Regular</string>
 | 
			
		||||
            <string>Exo2.0-Regular</string>
 | 
			
		||||
            <string>Exo2.0-Regular</string>
 | 
			
		||||
            <string>Exo2.0-Regular</string>
 | 
			
		||||
        </mutableArray>
 | 
			
		||||
        <mutableArray key="Exo2.0-Thin.otf">
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
@@ -82,11 +86,15 @@
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
            <string>Exo2.0-Thin</string>
 | 
			
		||||
        </mutableArray>
 | 
			
		||||
        <mutableArray key="SourceCodePro-Black.otf">
 | 
			
		||||
            <string>SourceCodePro-Black</string>
 | 
			
		||||
            <string>SourceCodePro-Black</string>
 | 
			
		||||
            <string>SourceCodePro-Black</string>
 | 
			
		||||
            <string>SourceCodePro-Black</string>
 | 
			
		||||
            <string>SourceCodePro-Black</string>
 | 
			
		||||
        </mutableArray>
 | 
			
		||||
        <mutableArray key="SourceCodePro-ExtraLight.otf">
 | 
			
		||||
            <string>SourceCodePro-ExtraLight</string>
 | 
			
		||||
@@ -581,7 +589,7 @@
 | 
			
		||||
                </tabBarController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="4Z1-Y7-eUn" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="1408.5" y="1319.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="2016.5" y="1319.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Preferences-->
 | 
			
		||||
        <scene sceneID="w0h-au-0xw">
 | 
			
		||||
@@ -1035,7 +1043,7 @@
 | 
			
		||||
                </tableViewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="fk3-aq-W8p" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="2016.5" y="2175.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="2624.5" y="2175.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Passwords View Controller-->
 | 
			
		||||
        <scene sceneID="I40-Es-1gK">
 | 
			
		||||
@@ -1575,6 +1583,7 @@
 | 
			
		||||
                        <outlet property="popdownToTopConstraint" destination="BdD-Kc-eHl" id="59Y-ap-Yn4"/>
 | 
			
		||||
                        <outlet property="popdownView" destination="XNM-XQ-rMe" id="FaW-4m-Fff"/>
 | 
			
		||||
                        <segue destination="z9O-w0-6oR" kind="modal" identifier="guide" id="Ql4-wf-T8u"/>
 | 
			
		||||
                        <segue destination="koB-V2-GYf" kind="modal" identifier="answers" id="PbR-2r-Ebm"/>
 | 
			
		||||
                    </connections>
 | 
			
		||||
                </viewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="APh-u5-vFI" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
@@ -1864,7 +1873,7 @@
 | 
			
		||||
                </navigationController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="PQz-c8-3Ww" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="2016.5" y="1319.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="2624.5" y="1319.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Settings-->
 | 
			
		||||
        <scene sceneID="fmc-CS-nuo">
 | 
			
		||||
@@ -1899,7 +1908,7 @@
 | 
			
		||||
                </tableViewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="sDE-fE-FNc" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="2656.5" y="1319.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="3264.5" y="1319.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Usage-->
 | 
			
		||||
        <scene sceneID="9SY-7D-CE9">
 | 
			
		||||
@@ -2099,7 +2108,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
 | 
			
		||||
                </viewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="SoG-sw-ghb" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="1408.5" y="2175.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="2016.5" y="2175.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Pearl Navigation Controller-->
 | 
			
		||||
        <scene sceneID="rfj-6W-TSu">
 | 
			
		||||
@@ -2550,7 +2559,7 @@ See </string>
 | 
			
		||||
                                                    <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                                    <nil key="highlightedColor"/>
 | 
			
		||||
                                                </label>
 | 
			
		||||
                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_generated_login.png" translatesAutoresizingMaskIntoConstraints="NO" id="dPE-KG-tzV">
 | 
			
		||||
                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_advanced_export.png" translatesAutoresizingMaskIntoConstraints="NO" id="dPE-KG-tzV">
 | 
			
		||||
                                                    <rect key="frame" x="88" y="20" width="198" height="198"/>
 | 
			
		||||
                                                </imageView>
 | 
			
		||||
                                                <activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="27T-E7-pLh">
 | 
			
		||||
@@ -2787,7 +2796,182 @@ See </string>
 | 
			
		||||
                </tableViewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="WvF-bk-cgx" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="2016.5" y="442.5"/>
 | 
			
		||||
            <point key="canvasLocation" x="2624.5" y="463.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
        <!--Preferences-->
 | 
			
		||||
        <scene sceneID="u8w-6D-Zhe">
 | 
			
		||||
            <objects>
 | 
			
		||||
                <tableViewController automaticallyAdjustsScrollViewInsets="NO" id="koB-V2-GYf" customClass="MPAnswersViewController" sceneMemberID="viewController">
 | 
			
		||||
                    <tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="vKY-AK-ugj" customClass="MPTableView">
 | 
			
		||||
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
 | 
			
		||||
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
 | 
			
		||||
                        <color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                        <inset key="scrollIndicatorInsets" minX="0.0" minY="64" maxX="0.0" maxY="49"/>
 | 
			
		||||
                        <color key="separatorColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                        <prototypes>
 | 
			
		||||
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPGlobalAnswersCell" rowHeight="133" id="DT2-Vb-uXj" userLabel="Global Answer" customClass="MPGlobalAnswersCell">
 | 
			
		||||
                                <rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
 | 
			
		||||
                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="DT2-Vb-uXj" id="URA-cl-MJP">
 | 
			
		||||
                                    <rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
 | 
			
		||||
                                    <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                    <subviews>
 | 
			
		||||
                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Answer for lyndir.com:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tal-1I-HQw" userLabel="Title Label">
 | 
			
		||||
                                            <rect key="frame" x="8" y="8" width="180" height="20.5"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="hok petwuvaqu xixo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="GfC-j4-Qx7" userLabel="Answer Field">
 | 
			
		||||
                                            <rect key="frame" x="8" y="48" width="359" height="43"/>
 | 
			
		||||
                                            <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                            <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
 | 
			
		||||
                                            <connections>
 | 
			
		||||
                                                <action selector="textFieldDidChange:" destination="W2g-yv-V3V" eventType="editingChanged" id="fY9-xg-DPG"/>
 | 
			
		||||
                                                <outlet property="delegate" destination="W2g-yv-V3V" id="TeI-f1-KlA"/>
 | 
			
		||||
                                            </connections>
 | 
			
		||||
                                        </textField>
 | 
			
		||||
                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Use this as the answer for each of the security questions on this site." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EUe-A5-H8h">
 | 
			
		||||
                                            <rect key="frame" x="8" y="99" width="359" height="13.5"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="11"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </subviews>
 | 
			
		||||
                                    <constraints>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="EUe-A5-H8h" secondAttribute="trailing" constant="8" id="076-4e-NlP"/>
 | 
			
		||||
                                        <constraint firstItem="GfC-j4-Qx7" firstAttribute="top" secondItem="Tal-1I-HQw" secondAttribute="bottom" constant="20" id="A4A-ds-Uc4"/>
 | 
			
		||||
                                        <constraint firstAttribute="bottom" secondItem="EUe-A5-H8h" secondAttribute="bottom" constant="20" symbolic="YES" id="AKM-6g-fhT"/>
 | 
			
		||||
                                        <constraint firstItem="GfC-j4-Qx7" firstAttribute="leading" secondItem="URA-cl-MJP" secondAttribute="leading" constant="8" id="JHy-eG-ckd"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="GfC-j4-Qx7" secondAttribute="trailing" constant="8" id="NAP-0S-Vda"/>
 | 
			
		||||
                                        <constraint firstItem="Tal-1I-HQw" firstAttribute="leading" secondItem="URA-cl-MJP" secondAttribute="leading" constant="8" id="Udh-0D-wR7"/>
 | 
			
		||||
                                        <constraint firstItem="EUe-A5-H8h" firstAttribute="leading" secondItem="URA-cl-MJP" secondAttribute="leading" constant="8" id="pEG-lI-KQN"/>
 | 
			
		||||
                                        <constraint firstItem="Tal-1I-HQw" firstAttribute="top" secondItem="URA-cl-MJP" secondAttribute="top" constant="8" id="x6h-mG-HZ4"/>
 | 
			
		||||
                                        <constraint firstItem="EUe-A5-H8h" firstAttribute="top" secondItem="GfC-j4-Qx7" secondAttribute="bottom" constant="8" symbolic="YES" id="xLP-uA-9z2"/>
 | 
			
		||||
                                    </constraints>
 | 
			
		||||
                                </tableViewCellContentView>
 | 
			
		||||
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                <connections>
 | 
			
		||||
                                    <outlet property="answerField" destination="GfC-j4-Qx7" id="egp-cZ-E1x"/>
 | 
			
		||||
                                    <outlet property="titleLabel" destination="Tal-1I-HQw" id="9s2-2n-cB4"/>
 | 
			
		||||
                                </connections>
 | 
			
		||||
                            </tableViewCell>
 | 
			
		||||
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPSendAnswersCell" rowHeight="44" id="tvm-WZ-MDZ" userLabel="Send Answers" customClass="MPSendAnswersCell">
 | 
			
		||||
                                <rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
 | 
			
		||||
                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tvm-WZ-MDZ" id="BTm-Lm-V9p">
 | 
			
		||||
                                    <rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
 | 
			
		||||
                                    <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                    <subviews>
 | 
			
		||||
                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Send the answer(s) to my email" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AAV-yg-dfK">
 | 
			
		||||
                                            <rect key="frame" x="8" y="8" width="326" height="27.5"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="12"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </subviews>
 | 
			
		||||
                                    <constraints>
 | 
			
		||||
                                        <constraint firstAttribute="bottom" secondItem="AAV-yg-dfK" secondAttribute="bottom" constant="8" id="LJV-LG-n0h"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="AAV-yg-dfK" secondAttribute="trailing" constant="8" id="NBf-3q-dHH"/>
 | 
			
		||||
                                        <constraint firstItem="AAV-yg-dfK" firstAttribute="leading" secondItem="BTm-Lm-V9p" secondAttribute="leading" constant="8" id="WpS-gx-b0s"/>
 | 
			
		||||
                                        <constraint firstItem="AAV-yg-dfK" firstAttribute="top" secondItem="BTm-Lm-V9p" secondAttribute="top" constant="8" id="t5X-Jg-8Ai"/>
 | 
			
		||||
                                    </constraints>
 | 
			
		||||
                                </tableViewCellContentView>
 | 
			
		||||
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                            </tableViewCell>
 | 
			
		||||
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="checkmark" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPMultipleAnswersCell" rowHeight="44" id="5MB-qb-oPk" userLabel="Multiple Answers" customClass="MPMultipleAnswersCell">
 | 
			
		||||
                                <rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
 | 
			
		||||
                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5MB-qb-oPk" id="4wX-xO-9QU">
 | 
			
		||||
                                    <rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
 | 
			
		||||
                                    <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                    <subviews>
 | 
			
		||||
                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="This site needs different answers for each question" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="een-0g-CMy">
 | 
			
		||||
                                            <rect key="frame" x="8" y="8" width="320" height="27.5"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="12"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </subviews>
 | 
			
		||||
                                    <constraints>
 | 
			
		||||
                                        <constraint firstItem="een-0g-CMy" firstAttribute="top" secondItem="4wX-xO-9QU" secondAttribute="top" constant="8" id="9ZQ-yN-0jZ"/>
 | 
			
		||||
                                        <constraint firstAttribute="bottom" secondItem="een-0g-CMy" secondAttribute="bottom" constant="8" id="JTE-x8-fAk"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="een-0g-CMy" secondAttribute="trailing" constant="8" id="LMQ-CT-XDx"/>
 | 
			
		||||
                                        <constraint firstItem="een-0g-CMy" firstAttribute="leading" secondItem="4wX-xO-9QU" secondAttribute="leading" constant="8" id="w3c-zJ-Mbm"/>
 | 
			
		||||
                                    </constraints>
 | 
			
		||||
                                </tableViewCellContentView>
 | 
			
		||||
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                            </tableViewCell>
 | 
			
		||||
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPAnswersQuestionCell" rowHeight="130" id="iFm-3w-hOv" userLabel="Question" customClass="MPAnswersQuestionCell">
 | 
			
		||||
                                <rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
 | 
			
		||||
                                <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="iFm-3w-hOv" id="X5d-5g-uJa">
 | 
			
		||||
                                    <rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
 | 
			
		||||
                                    <autoresizingMask key="autoresizingMask"/>
 | 
			
		||||
                                    <subviews>
 | 
			
		||||
                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="mother" textAlignment="center" minimumFontSize="14" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="T2F-PD-Nw8" userLabel="Question Field">
 | 
			
		||||
                                            <rect key="frame" x="8" y="19" width="359" height="30"/>
 | 
			
		||||
                                            <color key="backgroundColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="0.5" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="28"/>
 | 
			
		||||
                                            <textInputTraits key="textInputTraits" keyboardType="namePhonePad" keyboardAppearance="alert" returnKeyType="done"/>
 | 
			
		||||
                                            <connections>
 | 
			
		||||
                                                <outlet property="delegate" destination="S8q-YF-Kt9" id="TtZ-rC-HTB"/>
 | 
			
		||||
                                            </connections>
 | 
			
		||||
                                        </textField>
 | 
			
		||||
                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="pifm gup balvabi yiz" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="3xA-ez-efa" userLabel="Answer Field">
 | 
			
		||||
                                            <rect key="frame" x="20" y="90.5" width="335" height="31"/>
 | 
			
		||||
                                            <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
 | 
			
		||||
                                            <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
 | 
			
		||||
                                            <connections>
 | 
			
		||||
                                                <action selector="textFieldDidChange:" destination="W2g-yv-V3V" eventType="editingChanged" id="nFl-TF-gF7"/>
 | 
			
		||||
                                                <outlet property="delegate" destination="W2g-yv-V3V" id="U4z-82-k15"/>
 | 
			
		||||
                                            </connections>
 | 
			
		||||
                                        </textField>
 | 
			
		||||
                                        <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Enter the single most significant word in the question above." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qqg-Ny-7Po">
 | 
			
		||||
                                            <rect key="frame" x="8" y="57" width="359" height="13.5"/>
 | 
			
		||||
                                            <fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="11"/>
 | 
			
		||||
                                            <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                            <nil key="highlightedColor"/>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </subviews>
 | 
			
		||||
                                    <constraints>
 | 
			
		||||
                                        <constraint firstItem="3xA-ez-efa" firstAttribute="leading" secondItem="X5d-5g-uJa" secondAttribute="leading" constant="20" symbolic="YES" id="01X-Q1-hbE"/>
 | 
			
		||||
                                        <constraint firstAttribute="bottom" secondItem="3xA-ez-efa" secondAttribute="bottom" constant="8" id="7lO-8k-3xJ"/>
 | 
			
		||||
                                        <constraint firstItem="3xA-ez-efa" firstAttribute="top" secondItem="Qqg-Ny-7Po" secondAttribute="bottom" constant="20" id="MnT-on-L2d"/>
 | 
			
		||||
                                        <constraint firstItem="Qqg-Ny-7Po" firstAttribute="top" secondItem="T2F-PD-Nw8" secondAttribute="bottom" constant="8" id="Xla-SS-lW7"/>
 | 
			
		||||
                                        <constraint firstItem="T2F-PD-Nw8" firstAttribute="leading" secondItem="X5d-5g-uJa" secondAttribute="leading" constant="8" id="YAl-Zz-fp3"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="3xA-ez-efa" secondAttribute="trailing" constant="20" symbolic="YES" id="YSK-xt-QtB"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="Qqg-Ny-7Po" secondAttribute="trailing" constant="8" id="ZKi-Kb-iF2"/>
 | 
			
		||||
                                        <constraint firstItem="Qqg-Ny-7Po" firstAttribute="leading" secondItem="X5d-5g-uJa" secondAttribute="leading" constant="8" id="o3h-oy-hyw"/>
 | 
			
		||||
                                        <constraint firstAttribute="trailing" secondItem="T2F-PD-Nw8" secondAttribute="trailing" constant="8" id="tCL-PD-pms"/>
 | 
			
		||||
                                    </constraints>
 | 
			
		||||
                                </tableViewCellContentView>
 | 
			
		||||
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
 | 
			
		||||
                                <connections>
 | 
			
		||||
                                    <outlet property="answerField" destination="3xA-ez-efa" id="xob-uu-1u7"/>
 | 
			
		||||
                                    <outlet property="questionField" destination="T2F-PD-Nw8" id="Ekp-t8-Hli"/>
 | 
			
		||||
                                </connections>
 | 
			
		||||
                            </tableViewCell>
 | 
			
		||||
                        </prototypes>
 | 
			
		||||
                        <sections/>
 | 
			
		||||
                        <connections>
 | 
			
		||||
                            <outlet property="dataSource" destination="koB-V2-GYf" id="fwt-DL-nza"/>
 | 
			
		||||
                            <outlet property="delegate" destination="koB-V2-GYf" id="dJF-bd-2ux"/>
 | 
			
		||||
                        </connections>
 | 
			
		||||
                    </tableView>
 | 
			
		||||
                    <tabBarItem key="tabBarItem" title="Preferences" image="icon_person.png" id="GwN-2X-LQ6"/>
 | 
			
		||||
                    <nil key="simulatedStatusBarMetrics"/>
 | 
			
		||||
                    <nil key="simulatedBottomBarMetrics"/>
 | 
			
		||||
                    <connections>
 | 
			
		||||
                        <outlet property="showHelpCell" destination="5MB-qb-oPk" id="7Db-6P-bBY"/>
 | 
			
		||||
                    </connections>
 | 
			
		||||
                </tableViewController>
 | 
			
		||||
                <placeholder placeholderIdentifier="IBFirstResponder" id="kXh-18-fq5" userLabel="First Responder" sceneMemberID="firstResponder"/>
 | 
			
		||||
            </objects>
 | 
			
		||||
            <point key="canvasLocation" x="1408.5" y="2175.5"/>
 | 
			
		||||
        </scene>
 | 
			
		||||
    </scenes>
 | 
			
		||||
    <resources>
 | 
			
		||||
@@ -2807,6 +2991,7 @@ See </string>
 | 
			
		||||
        <image name="icon_up.png" width="32" height="32"/>
 | 
			
		||||
        <image name="identity.png" width="82" height="80"/>
 | 
			
		||||
        <image name="image-0.png" width="320" height="568"/>
 | 
			
		||||
        <image name="thumb_advanced_export.png" width="198" height="198"/>
 | 
			
		||||
        <image name="thumb_generated_login.png" width="198" height="198"/>
 | 
			
		||||
        <image name="tip_basic_black.png" width="210" height="60"/>
 | 
			
		||||
        <image name="ui_spinner.png" width="75" height="75"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
			
		||||
<plist version="1.0">
 | 
			
		||||
<dict>
 | 
			
		||||
	<key>MPElementGeneratedEntity</key>
 | 
			
		||||
	<key>MPSiteGeneratedEntity</key>
 | 
			
		||||
	<dict>
 | 
			
		||||
		<key>Login Name</key>
 | 
			
		||||
		<array>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user