2
0

Default password type + new user confirmation.

[ADDED]     User preference for default password type.
[RENAMED]   Secure type to Maximum Security.
[FIXED]     Logging bug in password generation.
[ADDED]     Confirmation popup after new user creation.
This commit is contained in:
Maarten Billemont 2012-06-11 16:15:49 +02:00
parent afafa473a7
commit 9c875d4311
23 changed files with 371 additions and 157 deletions

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit e93f7c406b157df3a4538becd2bff8b9ee7b0be8
Subproject commit 0a5a01b8862a3e8d986b23513c5d40ebc152b6fc

View File

@ -8,10 +8,6 @@
/* Begin PBXBuildFile section */
DA04E33E14B1E70400ECA4F3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */; };
DA076C75157D58E5008968D7 /* MPElementGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA076C74157D58E5008968D7 /* MPElementGeneratedEntity.m */; };
DA076C78157D58E5008968D7 /* MPElementEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA076C77157D58E5008968D7 /* MPElementEntity.m */; };
DA076C7B157D58E5008968D7 /* MPElementStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA076C7A157D58E5008968D7 /* MPElementStoredEntity.m */; };
DA076C7E157D58E6008968D7 /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA076C7D157D58E6008968D7 /* MPUserEntity.m */; };
DA0A1D0515690A9A0092735D /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0315690A9A0092735D /* Default.png */; };
DA0A1D0615690A9A0092735D /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0415690A9A0092735D /* Default@2x.png */; };
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; };
@ -24,6 +20,10 @@
DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */; };
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; };
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; };
DA40C2611586099D0079CE6E /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA40C2601586099D0079CE6E /* MPUserEntity.m */; };
DA40C2641586099E0079CE6E /* MPElementEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA40C2631586099E0079CE6E /* MPElementEntity.m */; };
DA40C2671586099E0079CE6E /* MPElementGeneratedEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA40C2661586099E0079CE6E /* MPElementGeneratedEntity.m */; };
DA40C26A1586099E0079CE6E /* MPElementStoredEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA40C2691586099E0079CE6E /* MPElementStoredEntity.m */; };
DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; };
DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; };
@ -908,14 +908,6 @@
/* Begin PBXFileReference section */
DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
DA076C73157D58E5008968D7 /* MPElementGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementGeneratedEntity.h; sourceTree = "<group>"; };
DA076C74157D58E5008968D7 /* MPElementGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementGeneratedEntity.m; sourceTree = "<group>"; };
DA076C76157D58E5008968D7 /* MPElementEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementEntity.h; sourceTree = "<group>"; };
DA076C77157D58E5008968D7 /* MPElementEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementEntity.m; sourceTree = "<group>"; };
DA076C79157D58E5008968D7 /* MPElementStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementStoredEntity.h; sourceTree = "<group>"; };
DA076C7A157D58E5008968D7 /* MPElementStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementStoredEntity.m; sourceTree = "<group>"; };
DA076C7C157D58E6008968D7 /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
DA076C7D157D58E6008968D7 /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
DA0A1D0315690A9A0092735D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/Default.png; sourceTree = SOURCE_ROOT; };
DA0A1D0415690A9A0092735D /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/Default@2x.png"; sourceTree = SOURCE_ROOT; };
DA0A1D0715690AD40092735D /* tip_arrow_banana.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_banana.png; path = Resources/Tooltips/tip_arrow_banana.png; sourceTree = SOURCE_ROOT; };
@ -935,6 +927,14 @@
DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-UIKit.m"; sourceTree = "<group>"; };
DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = "<group>"; };
DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; };
DA40C25F1586099D0079CE6E /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
DA40C2601586099D0079CE6E /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
DA40C2621586099E0079CE6E /* MPElementEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementEntity.h; sourceTree = "<group>"; };
DA40C2631586099E0079CE6E /* MPElementEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementEntity.m; sourceTree = "<group>"; };
DA40C2651586099E0079CE6E /* MPElementGeneratedEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementGeneratedEntity.h; sourceTree = "<group>"; };
DA40C2661586099E0079CE6E /* MPElementGeneratedEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementGeneratedEntity.m; sourceTree = "<group>"; };
DA40C2681586099E0079CE6E /* MPElementStoredEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementStoredEntity.h; sourceTree = "<group>"; };
DA40C2691586099E0079CE6E /* MPElementStoredEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementStoredEntity.m; sourceTree = "<group>"; };
DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; };
DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; };
DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = "<group>"; };
@ -1968,17 +1968,17 @@
DA5BFA50147E415C00F98B1E /* MasterPassword */ = {
isa = PBXGroup;
children = (
DAB8D43C15036BCF00CED3BC /* MasterPassword.xcdatamodeld */,
DA076C7C157D58E6008968D7 /* MPUserEntity.h */,
DA076C7D157D58E6008968D7 /* MPUserEntity.m */,
DA076C79157D58E5008968D7 /* MPElementStoredEntity.h */,
DA076C7A157D58E5008968D7 /* MPElementStoredEntity.m */,
DA076C76157D58E5008968D7 /* MPElementEntity.h */,
DA076C77157D58E5008968D7 /* MPElementEntity.m */,
DA076C73157D58E5008968D7 /* MPElementGeneratedEntity.h */,
DA076C74157D58E5008968D7 /* MPElementGeneratedEntity.m */,
DA40C2681586099E0079CE6E /* MPElementStoredEntity.h */,
DA40C2691586099E0079CE6E /* MPElementStoredEntity.m */,
DA40C2651586099E0079CE6E /* MPElementGeneratedEntity.h */,
DA40C2661586099E0079CE6E /* MPElementGeneratedEntity.m */,
DA40C2621586099E0079CE6E /* MPElementEntity.h */,
DA40C2631586099E0079CE6E /* MPElementEntity.m */,
DA40C25F1586099D0079CE6E /* MPUserEntity.h */,
DA40C2601586099D0079CE6E /* MPUserEntity.m */,
DA0E07941577FE490008A67E /* MPEntities.h */,
DA0E07951577FE490008A67E /* MPEntities.m */,
DAB8D43C15036BCF00CED3BC /* MasterPassword.xcdatamodeld */,
DA600C2415054F3A008E9AB6 /* MPAppDelegate_Key.h */,
DA600C2315054F3A008E9AB6 /* MPAppDelegate_Key.m */,
DA4426041557C1990052177D /* MPAppDelegate_Shared.h */,
@ -4171,10 +4171,10 @@
DA4426091557C1990052177D /* MPAppDelegate_Store.m in Sources */,
DA0E07961577FE490008A67E /* MPEntities.m in Sources */,
DAC728CA157C247B00889EF2 /* MPPreferencesViewController.m in Sources */,
DA076C75157D58E5008968D7 /* MPElementGeneratedEntity.m in Sources */,
DA076C78157D58E5008968D7 /* MPElementEntity.m in Sources */,
DA076C7B157D58E5008968D7 /* MPElementStoredEntity.m in Sources */,
DA076C7E157D58E6008968D7 /* MPUserEntity.m in Sources */,
DA40C2611586099D0079CE6E /* MPUserEntity.m in Sources */,
DA40C2641586099E0079CE6E /* MPElementEntity.m in Sources */,
DA40C2671586099E0079CE6E /* MPElementGeneratedEntity.m in Sources */,
DA40C26A1586099E0079CE6E /* MPElementStoredEntity.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -2,7 +2,7 @@
// MPElementEntity.h
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
@ -14,10 +14,10 @@
@interface MPElementEntity : NSManagedObject
@property (nonatomic, retain) id content;
@property (nonatomic, retain) NSDate *lastUsed;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSNumber *type_;
@property (nonatomic, retain) NSNumber *uses_;
@property (nonatomic, retain) NSDate * lastUsed;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * type_;
@property (nonatomic, retain) NSNumber * uses_;
@property (nonatomic, retain) MPUserEntity *user;
@end

View File

@ -2,11 +2,12 @@
// MPElementEntity.m
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
#import "MPElementEntity.h"
#import "MPUserEntity.h"
@implementation MPElementEntity

View File

@ -2,7 +2,7 @@
// MPElementGeneratedEntity.h
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
@ -13,6 +13,6 @@
@interface MPElementGeneratedEntity : MPElementEntity
@property (nonatomic, retain) NSNumber *counter_;
@property (nonatomic, retain) NSNumber * counter_;
@end

View File

@ -2,7 +2,7 @@
// MPElementGeneratedEntity.m
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//

View File

@ -2,7 +2,7 @@
// MPElementStoredEntity.h
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//

View File

@ -2,7 +2,7 @@
// MPElementStoredEntity.m
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//

View File

@ -35,5 +35,6 @@
@property (assign) NSUInteger avatar;
@property (assign) BOOL saveKey;
@property (assign) MPElementType defaultType;
@end

View File

@ -9,6 +9,7 @@
#import "MPEntities.h"
#import "MPAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPUserEntity.h"
@implementation MPElementEntity (MP)
@ -17,9 +18,9 @@
return (MPElementType)[self.type_ unsignedIntegerValue];
}
- (void)setType:(MPElementType)type {
- (void)setType:(MPElementType)aType {
self.type_ = PearlUnsignedInteger(type);
self.type_ = PearlUnsignedInteger(aType);
}
- (NSUInteger)uses {
@ -172,4 +173,14 @@
self.saveKey_ = [NSNumber numberWithBool:aSaveKey];
}
- (MPElementType)defaultType {
return (MPElementType)[self.defaultType_ unsignedIntegerValue];
}
- (void)setDefaultType:(MPElementType)aDefaultType {
self.defaultType_ = PearlUnsignedInteger(aDefaultType);
}
@end

View File

@ -31,17 +31,18 @@ typedef enum {
} MPElementFeature;
typedef enum {
MPElementTypeGeneratedSecure = 0x0 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
} MPElementType;
// TODO: Review checkpoints
#define MPTestFlightCheckpointAction @"MPTestFlightCheckpointAction"
#define MPTestFlightCheckpointHelpChapter @"MPTestFlightCheckpointHelpChapter_%@"
#define MPTestFlightCheckpointCopyToPasteboard @"MPTestFlightCheckpointCopyToPasteboard"
@ -81,6 +82,7 @@ NSData *keyForPassword(NSString *password, NSString *username);
NSData *keyIDForPassword(NSString *password, NSString *username);
NSData *keyIDForKey(NSData *key);
NSString *NSStringFromMPElementType(MPElementType type);
NSString *NSStringShortFromMPElementType(MPElementType type);
NSString *ClassNameFromMPElementType(MPElementType type);
Class ClassFromMPElementType(MPElementType type);
NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, uint32_t counter);

View File

@ -46,8 +46,8 @@ NSString *NSStringFromMPElementType(MPElementType type) {
return nil;
switch (type) {
case MPElementTypeGeneratedSecure:
return @"Secure Password";
case MPElementTypeGeneratedMaximum:
return @"Maximum Security Password";
case MPElementTypeGeneratedLong:
return @"Long Password";
@ -75,13 +75,48 @@ NSString *NSStringFromMPElementType(MPElementType type) {
}
}
NSString *NSStringShortFromMPElementType(MPElementType type) {
if (!type)
return nil;
switch (type) {
case MPElementTypeGeneratedMaximum:
return @"Maximum";
case MPElementTypeGeneratedLong:
return @"Long";
case MPElementTypeGeneratedMedium:
return @"Medium";
case MPElementTypeGeneratedShort:
return @"Short";
case MPElementTypeGeneratedBasic:
return @"Basic";
case MPElementTypeGeneratedPIN:
return @"PIN";
case MPElementTypeStoredPersonal:
return @"Personal";
case MPElementTypeStoredDevicePrivate:
return @"Device";
default:
Throw(@"Type not supported: %d", type);
}
}
Class ClassFromMPElementType(MPElementType type) {
if (!type)
return nil;
switch (type) {
case MPElementTypeGeneratedSecure:
case MPElementTypeGeneratedMaximum:
return [MPElementGeneratedEntity class];
case MPElementTypeGeneratedLong:
@ -141,7 +176,7 @@ NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, ui
withExtension:@"plist"]];
// Determine the seed whose bytes will be used for calculating a password
trc(@"seed from: hmac-sha256(key, 'com.lyndir.masterpassword' | %u | %@ | %u)", key, name.length, name, counter);
trc(@"seed from: hmac-sha256(%@, 'com.lyndir.masterpassword' | %u | %@ | %u)", key, name.length, name, counter);
uint32_t ncounter = htonl(counter), nnameLength = htonl(name.length);
NSData *seed = [[NSData dataByConcatenatingDatas:
[@"com.lyndir.masterpassword" dataUsingEncoding:NSUTF8StringEncoding],

View File

@ -2,7 +2,7 @@
// MPUserEntity.h
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
@ -13,12 +13,13 @@
@interface MPUserEntity : NSManagedObject
@property (nonatomic, retain) NSNumber *avatar_;
@property (nonatomic, retain) NSData *keyID;
@property (nonatomic, retain) NSDate *lastUsed;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSNumber *saveKey_;
@property (nonatomic, retain) NSSet *elements;
@property (nonatomic, retain) NSNumber * avatar_;
@property (nonatomic, retain) NSData * keyID;
@property (nonatomic, retain) NSDate * lastUsed;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * saveKey_;
@property (nonatomic, retain) NSNumber * defaultType_;
@property (nonatomic, retain) NSSet *elements;
@end
@interface MPUserEntity (CoreDataGeneratedAccessors)

View File

@ -2,11 +2,12 @@
// MPUserEntity.m
// MasterPassword-iOS
//
// Created by Maarten Billemont on 04/06/12.
// Created by Maarten Billemont on 11/06/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
#import "MPUserEntity.h"
#import "MPElementEntity.h"
@implementation MPUserEntity
@ -16,6 +17,7 @@
@dynamic lastUsed;
@dynamic name;
@dynamic saveKey_;
@dynamic defaultType_;
@dynamic elements;
@end

View File

@ -16,6 +16,7 @@
</entity>
<entity name="MPUserEntity" representedClassName="MPUserEntity" syncable="YES">
<attribute name="avatar_" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
<attribute name="defaultType_" attributeType="Integer 16" defaultValueString="17" syncable="YES"/>
<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"/>
@ -26,6 +27,6 @@
<element name="MPElementEntity" positionX="160" positionY="192" width="128" height="135"/>
<element name="MPElementGeneratedEntity" positionX="160" positionY="192" width="128" height="60"/>
<element name="MPElementStoredEntity" positionX="160" positionY="192" width="128" height="60"/>
<element name="MPUserEntity" positionX="160" positionY="192" width="128" height="135"/>
<element name="MPUserEntity" positionX="160" positionY="192" width="128" height="150"/>
</elements>
</model>

View File

@ -61,7 +61,7 @@
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"MP_Main_ChooseType"])
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
}

View File

@ -8,14 +8,16 @@
#import <UIKit/UIKit.h>
#import "IASKAppSettingsViewController.h"
#import "MPTypeViewController.h"
@interface MPPreferencesViewController : UITableViewController<IASKSettingsDelegate>
@interface MPPreferencesViewController : UITableViewController<IASKSettingsDelegate, MPTypeDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *avatarsView;
@property (weak, nonatomic) IBOutlet UIButton *avatarTemplate;
@property (weak, nonatomic) IBOutlet UISwitch *savePasswordSwitch;
@property (weak, nonatomic) IBOutlet UITableViewCell *exportCell;
@property (weak, nonatomic) IBOutlet UITableViewCell *changeMPCell;
@property (weak, nonatomic) IBOutlet UILabel *defaultTypeLabel;
- (IBAction)didToggleSwitch:(UISwitch *)sender;
- (IBAction)settings:(id)sender;

View File

@ -10,6 +10,7 @@
#import "MPPreferencesViewController.h"
#import "MPAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
@interface MPPreferencesViewController ()
@ -21,6 +22,7 @@
@synthesize savePasswordSwitch;
@synthesize exportCell;
@synthesize changeMPCell;
@synthesize defaultTypeLabel;
- (void)viewDidLoad {
@ -51,8 +53,10 @@
avatar.backgroundColor = [UIColor clearColor];
} options:0];
[avatar onSelect:^(BOOL selected) {
if (selected)
if (selected) {
[MPAppDelegate get].activeUser.avatar = (unsigned)avatar.tag;
[[MPAppDelegate get] saveContext];
}
} options:0];
avatar.selected = (a == [MPAppDelegate get].activeUser.avatar);
}
@ -70,6 +74,7 @@
} recurse:NO];
self.savePasswordSwitch.on = [MPAppDelegate get].activeUser.saveKey;
self.defaultTypeLabel.text = NSStringShortFromMPElementType([MPAppDelegate get].activeUser.defaultType);
[super viewWillAppear:animated];
}
@ -87,9 +92,16 @@
[self setSavePasswordSwitch:nil];
[self setExportCell:nil];
[self setChangeMPCell:nil];
[self setDefaultTypeLabel:nil];
[super viewDidUnload];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"MP_ChooseType"])
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
@ -113,6 +125,21 @@
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - MPTypeDelegate
- (void)didSelectType:(MPElementType)type {
[MPAppDelegate get].activeUser.defaultType = type;
[[MPAppDelegate get] saveContext];
self.defaultTypeLabel.text = NSStringShortFromMPElementType([MPAppDelegate get].activeUser.defaultType);
}
- (MPElementType)selectedType {
return [MPAppDelegate get].activeUser.defaultType;
}
#pragma mark - IBActions
- (IBAction)didToggleSwitch:(UISwitch *)sender {
@ -121,6 +148,7 @@
[[MPAppDelegate get] storeSavedKeyFor:[MPAppDelegate get].activeUser];
else
[[MPAppDelegate get] forgetSavedKeyFor:[MPAppDelegate get].activeUser];
[[MPAppDelegate get] saveContext];
}
- (IBAction)settings:(UIBarButtonItem *)sender {

View File

@ -302,14 +302,14 @@
return;
[self.fetchedResultsController.managedObjectContext performBlock:^{
MPElementGeneratedEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(
[MPElementGeneratedEntity class])
MPElementType type = [MPAppDelegate get].activeUser.defaultType;
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:ClassNameFromMPElementType(type)
inManagedObjectContext:self.fetchedResultsController.managedObjectContext];
assert([element isKindOfClass:ClassFromMPElementType(element.type)]);
assert([MPAppDelegate get].activeUser.keyID);
assert([MPAppDelegate get].activeUser);
element.name = siteName;
element.user = [MPAppDelegate get].activeUser;
element.type = type;
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didSelectElement:element];

View File

@ -92,7 +92,7 @@
case 0:
return NSNotFound;
case 1:
return MPElementTypeGeneratedSecure;
return MPElementTypeGeneratedMaximum;
case 2:
return MPElementTypeGeneratedLong;
case 3:

View File

@ -35,10 +35,6 @@
@synthesize avatarShadowColor = _avatarShadowColor;
// [UIView animateWithDuration:1.0f delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
// self.lock.alpha = 0.5f;
// } completion:nil];
- (void)initAvatarAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user {
UIScrollView *alertAvatarScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(12, 30, 260, 150)];
@ -50,9 +46,9 @@
for (int a = 0; a < MPAvatarCount; ++a) {
UIButton *avatar = [self.avatarTemplate cloneAddedTo:alertAvatarScrollView];
avatar.tag = a;
avatar.hidden = NO;
avatar.center = CGPointMake(
avatar.tag = a;
avatar.hidden = NO;
avatar.center = CGPointMake(
(20 + self.avatarTemplate.bounds.size.width / 2) * (a + 1) + self.avatarTemplate.bounds.size.width / 2 * a,
20 + self.avatarTemplate.bounds.size.height / 2);
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", a)] forState:UIControlStateNormal];
@ -83,6 +79,32 @@
[alertAvatarScrollView setContentOffset:selectedOffset animated:YES];
}
- (void)initConfirmationAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user {
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(12, 70, 260, 110)];
[alert addSubview:container];
UIButton *alertAvatar = [self.avatarTemplate cloneAddedTo:container];
alertAvatar.center = CGPointMake(130, 55);
alertAvatar.hidden = NO;
alertAvatar.layer.shadowColor = [UIColor blackColor].CGColor;
alertAvatar.layer.shadowOpacity = 1;
alertAvatar.layer.shadowRadius = 5;
alertAvatar.backgroundColor = [UIColor clearColor];
[alertAvatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%d", user.avatar)] forState:UIControlStateNormal];
UILabel *alertNameLabel = [self.nameLabel cloneAddedTo:container];
alertNameLabel.center = alertAvatar.center;
alertNameLabel.text = user.name;
alertNameLabel.bounds = CGRectSetHeight(alertNameLabel.bounds,
[alertNameLabel.text sizeWithFont:self.nameLabel.font
constrainedToSize:CGSizeMake(alertNameLabel.bounds.size.width - 10,
100)
lineBreakMode:self.nameLabel.lineBreakMode].height);
alertNameLabel.layer.cornerRadius = 5;
alertNameLabel.backgroundColor = [UIColor blackColor];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
@ -167,15 +189,15 @@
- (UIButton *)setupAvatar:(UIButton *)avatar forUser:(MPUserEntity *)user {
avatar.center = CGPointMake(avatar.center.x + [self.avatarToUser count] * 160, avatar.center.y);
avatar.hidden = NO;
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
avatar.layer.shadowOpacity = 1;
avatar.layer.shadowRadius = 20;
avatar.layer.masksToBounds = NO;
avatar.backgroundColor = [UIColor clearColor];
avatar.tag = user.avatar;
avatar.center = CGPointMake(avatar.center.x + [self.avatarToUser count] * 160, avatar.center.y);
avatar.hidden = NO;
avatar.layer.cornerRadius = avatar.bounds.size.height / 2;
avatar.layer.shadowColor = [UIColor blackColor].CGColor;
avatar.layer.shadowOpacity = 1;
avatar.layer.shadowRadius = 20;
avatar.layer.masksToBounds = NO;
avatar.backgroundColor = [UIColor clearColor];
avatar.tag = user.avatar;
[avatar setBackgroundImage:[UIImage imageNamed:PearlString(@"avatar-%u", user.avatar)]
forState:UIControlStateNormal];
@ -225,36 +247,78 @@
- (void)didSelectNewUserAvatar:(UIButton *)newUserAvatar {
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class])
inManagedObjectContext:[MPAppDelegate managedObjectContext]];
[self showNewUserNameAlertFor:newUser completion:^(BOOL finished){
newUserAvatar.selected = NO;
if (!finished)
[[MPAppDelegate managedObjectContext] deleteObject:newUser];
}];
}
- (void)showNewUserNameAlertFor:(MPUserEntity *)newUser completion:(void (^)(BOOL finished))completion {
[PearlAlert showAlertWithTitle:@"Enter Your Name"
message:nil viewStyle:UIAlertViewStylePlainTextInput
initAlert:^(UIAlertView *alert, UITextField *firstField) {
firstField.autocapitalizationType = UITextAutocapitalizationTypeWords;
firstField.keyboardType = UIKeyboardTypeAlphabet;
firstField.text = newUser.name;
firstField.placeholder = @"eg. Robert Lee Mitchell";
}
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex])
if (buttonIndex == [alert cancelButtonIndex]) {
completion(NO);
return;
}
MPUserEntity *newUser = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPUserEntity class])
inManagedObjectContext:[MPAppDelegate managedObjectContext]];
newUser.name = [alert textFieldAtIndex:0].text;
[PearlAlert showAlertWithTitle:@"Choose Your Avatar"
message:@"\n\n\n\n\n\n" viewStyle:UIAlertViewStyleDefault
initAlert:^(UIAlertView *_alert, UITextField *firstField) {
[self initAvatarAlert:_alert forUser:newUser];
}
tappedButtonBlock:^(UIAlertView *_alert, NSInteger _buttonIndex) {
newUserAvatar.selected = NO;
self.selectedUser = newUser;
[self updateUsers];
} cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
// Save
newUser.name = [alert textFieldAtIndex:0].text;
[self showNewUserAvatarAlertFor:newUser completion:completion];
}
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonSave, nil];
}
- (void)showNewUserAvatarAlertFor:(MPUserEntity *)newUser completion:(void (^)(BOOL finished))completion {
[PearlAlert showAlertWithTitle:@"Choose Your Avatar"
message:@"\n\n\n\n\n\n" viewStyle:UIAlertViewStyleDefault
initAlert:^(UIAlertView *_alert, UITextField *_firstField) {
[self initAvatarAlert:_alert forUser:newUser];
}
tappedButtonBlock:^(UIAlertView *_alert, NSInteger _buttonIndex) {
// Okay
[self showNewUserConfirmationAlertFor:newUser completion:completion];
} cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
}
- (void)showNewUserConfirmationAlertFor:(MPUserEntity *)newUser completion:(void (^)(BOOL finished))completion {
[PearlAlert showAlertWithTitle:@"Is this correct?"
message:
@"Please double-check your name.\n"
@"\n\n\n\n\n\n"
viewStyle:UIAlertViewStyleDefault
initAlert:^void(UIAlertView *__alert, UITextField *__firstField) {
[self initConfirmationAlert:__alert forUser:newUser];
}
tappedButtonBlock:^void(UIAlertView *__alert, NSInteger __buttonIndex) {
if (__buttonIndex == [__alert cancelButtonIndex]) {
[self showNewUserNameAlertFor:newUser completion:completion];
return;
}
// Confirm
completion(YES);
self.selectedUser = newUser;
[self updateUsers];
}
cancelTitle:@"Change" otherTitles:@"Confirm", nil];
}
- (void)updateLayoutAnimated:(BOOL)animated allowScroll:(BOOL)allowScroll completion:(void (^)(BOOL finished))completion {
if (animated) {
@ -276,7 +340,7 @@
if (self.selectedUser && !self.passwordView.alpha) {
self.passwordView.alpha = 1;
self.avatarsView.center = CGPointMake(160, 100);
self.avatarsView.center = CGPointMake(160, 170);
self.avatarsView.scrollEnabled = NO;
self.nameLabel.center = CGPointMake(160, 84);
self.nameLabel.backgroundColor = [UIColor blackColor];
@ -286,7 +350,7 @@
} else
if (!self.selectedUser && self.passwordView.alpha == 1) {
self.passwordView.alpha = 0;
self.avatarsView.center = CGPointMake(160, 240);
self.avatarsView.center = CGPointMake(160, 310);
self.avatarsView.scrollEnabled = YES;
self.nameLabel.center = CGPointMake(160, 296);
self.nameLabel.backgroundColor = [UIColor clearColor];

View File

@ -16,21 +16,21 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
<view key="tableFooterView" contentMode="scaleToFill" id="aNa-wb-cYK">
<rect key="frame" x="0.0" y="627" width="320" height="20"/>
<rect key="frame" x="0.0" y="737" width="320" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<sections>
<tableViewSection id="gUv-FU-O36">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="162" id="NCB-rX-weq">
<rect key="frame" x="0.0" y="0.0" width="320" height="162"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="210" id="NCB-rX-weq">
<rect key="frame" x="0.0" y="0.0" width="320" height="210"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="161"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="209"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Generated" lineBreakMode="tailTruncation" minimumFontSize="10" id="azh-GA-KA1">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="1. Generated" lineBreakMode="tailTruncation" minimumFontSize="10" id="azh-GA-KA1">
<rect key="frame" x="20" y="20" width="280" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="GillSans-Bold" family="Gill Sans" pointSize="17"/>
@ -40,10 +40,12 @@
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="E4a-XS-Qlz">
<rect key="frame" x="20" y="49" width="280" height="112"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<string key="text">These types create a safe password for your site.
The passwords aren't saved anywhere. This is a major advantage: if you lose your device, your passwords cannot be stolen. You can use any other device to get all your passwords back, no need for restoring backups or any other pains.</string>
<rect key="frame" x="20" y="49" width="280" height="164"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<string key="text">These types create a password for you.
"Copy-friendly" passwords are easier to read and make copying the password to another computer or physical item less troublesome.
"Long Password"s are great for general use. If the site will accept it and you don't mind giving up copy-friendlyness, you can opt for a maximum security password instead.</string>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@ -56,7 +58,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="PBE-wW-HXv">
<rect key="frame" x="0.0" y="162" width="320" height="44"/>
<rect key="frame" x="0.0" y="210" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -67,7 +69,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Secure Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="Twq-Pz-E1B">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Maximum Security Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="Twq-Pz-E1B">
<rect key="frame" x="20" y="0.0" width="280" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
@ -89,7 +91,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="Fho-bQ-ENV">
<rect key="frame" x="0.0" y="206" width="320" height="44"/>
<rect key="frame" x="0.0" y="254" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -109,7 +111,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 14 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="J9t-dg-gQm">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Copy-friendly, 14 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="J9t-dg-gQm">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -122,7 +124,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="re0-ZT-bnP">
<rect key="frame" x="0.0" y="250" width="320" height="44"/>
<rect key="frame" x="0.0" y="298" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -142,7 +144,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 8 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="MI2-JM-j4b">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Copy-friendly, 8 characters, contains symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="MI2-JM-j4b">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -155,7 +157,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="4pb-c9-i2D">
<rect key="frame" x="0.0" y="294" width="320" height="44"/>
<rect key="frame" x="0.0" y="342" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -175,7 +177,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Word-like, 4 characters, no symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="Zi3-26-3iq">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Copy-friendly, 4 characters, no symbols." lineBreakMode="tailTruncation" minimumFontSize="10" id="Zi3-26-3iq">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
@ -188,7 +190,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ywW-4w-Wej">
<rect key="frame" x="0.0" y="338" width="320" height="44"/>
<rect key="frame" x="0.0" y="386" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -221,7 +223,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="5p5-OD-zpn">
<rect key="frame" x="0.0" y="382" width="320" height="44"/>
<rect key="frame" x="0.0" y="430" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -257,14 +259,14 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
</tableViewSection>
<tableViewSection id="Jqk-Jl-vVm">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="113" id="OK2-fa-fDw">
<rect key="frame" x="0.0" y="426" width="320" height="113"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="175" id="OK2-fa-fDw">
<rect key="frame" x="0.0" y="474" width="320" height="175"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="112"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="174"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="User-specified" lineBreakMode="tailTruncation" minimumFontSize="10" id="146-3h-mdD">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="2. User-specified" lineBreakMode="tailTruncation" minimumFontSize="10" id="146-3h-mdD">
<rect key="frame" x="20" y="20" width="280" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="GillSans-Bold" family="Gill Sans" pointSize="17"/>
@ -274,9 +276,12 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="Bbk-lL-BeB">
<rect key="frame" x="20" y="49" width="280" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<string key="text">If you need to specify a custom password for your site, use one of these types. The site's password will be encrypted using your master password.</string>
<rect key="frame" x="20" y="49" width="280" height="125"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<string key="text">These types save a custom password for you.
Your passwords will be AES-encrypted with your master password.
"Device Private" means the password will never leave your device. It will not be included in iCloud and iTunes backups or site exports.</string>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@ -289,7 +294,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="Q2e-yF-SSN">
<rect key="frame" x="0.0" y="539" width="320" height="44"/>
<rect key="frame" x="0.0" y="649" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -322,7 +327,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="ePk-a9-aNi">
<rect key="frame" x="0.0" y="583" width="320" height="44"/>
<rect key="frame" x="0.0" y="693" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -501,7 +506,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="NKe-nv-566" kind="push" identifier="MP_Main_ChooseType" id="vw4-Vd-O6q"/>
<segue destination="NKe-nv-566" kind="push" identifier="MP_ChooseType" id="vw4-Vd-O6q"/>
</connections>
</button>
</subviews>
@ -781,14 +786,6 @@ L4m3P4sSw0rD</string>
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="Tap and hold to delete." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="DBJ-Qi-ZcF">
<rect key="frame" x="32" y="460" width="256" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</label>
<view contentMode="scaleToFill" id="7cc-yu-i0m">
<rect key="frame" x="20" y="168" width="280" height="88"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
@ -842,7 +839,7 @@ L4m3P4sSw0rD</string>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" indicatorStyle="white" delaysContentTouches="NO" id="Blg-F1-9NA">
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="340"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="Ten-ig-gog">
@ -881,6 +878,14 @@ L4m3P4sSw0rD</string>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="Tap and hold to delete." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="DBJ-Qi-ZcF">
<rect key="frame" x="32" y="460" width="256" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</label>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="keypad.png" id="4tz-l4-4Kj">
<rect key="frame" x="0.0" y="264" width="320" height="216"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -941,7 +946,7 @@ L4m3P4sSw0rD</string>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="calibratedRGB"/>
<view key="tableFooterView" contentMode="scaleToFill" id="63M-7L-M7o">
<rect key="frame" x="0.0" y="492" width="320" height="20"/>
<rect key="frame" x="0.0" y="536" width="320" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
@ -1038,14 +1043,9 @@ L4m3P4sSw0rD</string>
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="top" image="ui_list_first.png" id="8dk-FW-Tse">
<rect key="frame" x="10" y="0.0" width="300" height="50"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="bottom" image="ui_list_last.png" id="5oz-I2-Nos">
<rect key="frame" x="10" y="34" width="300" height="10"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_first.png" id="8dk-FW-Tse">
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Save Password" lineBreakMode="tailTruncation" minimumFontSize="10" id="0Mf-7e-quo">
@ -1077,12 +1077,55 @@ L4m3P4sSw0rD</string>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="gray" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="ruw-YM-LQK">
<rect key="frame" x="0.0" y="336" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_list_last.png" id="YjI-sp-m0W">
<rect key="frame" x="10" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<rect key="contentStretch" x="0.10000000000000001" y="0.20000000000000001" width="0.79999999999999982" height="0.59999999999999964"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Default password type" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" id="Cna-C5-ovR">
<rect key="frame" x="20" y="0.0" width="285" height="23"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
<size key="shadowOffset" width="0.0" height="1"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Password type used for new sites." lineBreakMode="tailTruncation" minimumFontSize="10" id="uh9-NL-39c">
<rect key="frame" x="20" y="23" width="280" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" name="GillSans-LightItalic" family="Gill Sans" pointSize="14"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Long" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="vKJ-1b-NeO">
<rect key="frame" x="200" y="11" width="100" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="GillSans" family="Gill Sans" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="NKe-nv-566" kind="push" identifier="MP_ChooseType" id="KIl-ZW-M7G"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="dN3-cJ-9WA">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="68" id="xBt-OT-BYA">
<rect key="frame" x="0.0" y="336" width="320" height="68"/>
<rect key="frame" x="0.0" y="380" width="320" height="68"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="67"/>
@ -1111,8 +1154,8 @@ L4m3P4sSw0rD</string>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="X2m-92-Qzh">
<rect key="frame" x="0.0" y="404" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="gray" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="44" id="X2m-92-Qzh">
<rect key="frame" x="0.0" y="448" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -1144,8 +1187,8 @@ L4m3P4sSw0rD</string>
</view>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="glr-eJ-qKq">
<rect key="frame" x="0.0" y="448" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="gray" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="glr-eJ-qKq">
<rect key="frame" x="0.0" y="492" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
@ -1196,6 +1239,7 @@ L4m3P4sSw0rD</string>
<outlet property="avatarTemplate" destination="6ap-Xw-Ubd" id="WW7-3k-5QJ"/>
<outlet property="avatarsView" destination="TMH-Xt-EnD" id="zdf-xt-piZ"/>
<outlet property="changeMPCell" destination="glr-eJ-qKq" id="EpZ-xu-JGh"/>
<outlet property="defaultTypeLabel" destination="vKJ-1b-NeO" id="4vz-2l-xXk"/>
<outlet property="exportCell" destination="X2m-92-Qzh" id="zjs-9C-uKX"/>
<outlet property="savePasswordSwitch" destination="ilG-0h-SOb" id="iZD-gQ-pve"/>
</connections>
@ -1280,6 +1324,7 @@ L4m3P4sSw0rD</string>
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
<relationship kind="outlet" name="changeMPCell" candidateClass="UITableViewCell"/>
<relationship kind="outlet" name="defaultTypeLabel" candidateClass="UILabel"/>
<relationship kind="outlet" name="exportCell" candidateClass="UITableViewCell"/>
<relationship kind="outlet" name="savePasswordSwitch" candidateClass="UISwitch"/>
</relationships>
@ -1320,4 +1365,7 @@ L4m3P4sSw0rD</string>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination"/>
</simulatedMetricsContainer>
<inferredMetricsTieBreakers>
<segue reference="KIl-ZW-M7G"/>
</inferredMetricsTieBreakers>
</document>

View File

@ -4,16 +4,34 @@
<dict>
<key>MPElementGeneratedEntity</key>
<dict>
<key>Secure Password</key>
<key>Maximum Security Password</key>
<array>
<string>aonxxxxxxxxxxxxxxxxx</string>
<string>axxxxxxxxxxxxxxxxxon</string>
<string>anoxxxxxxxxxxxxxxxxx</string>
<string>axxxxxxxxxxxxxxxxxno</string>
</array>
<key>Long Password</key>
<array>
<string>CvcvnoCvcvCvcv</string>
<string>CvcvCvcvnoCvcv</string>
<string>CvcvCvcvCvcvno</string>
<string>CvccnoCvcvCvcv</string>
<string>CvccCvcvnoCvcv</string>
<string>CvccCvcvCvcvno</string>
<string>CvcvnoCvccCvcv</string>
<string>CvcvCvccnoCvcv</string>
<string>CvcvCvccCvcvno</string>
<string>CvcvnoCvcvCvcc</string>
<string>CvcvCvcvnoCvcc</string>
<string>CvcvCvcvCvccno</string>
<string>CvccnoCvccCvcv</string>
<string>CvccCvccnoCvcv</string>
<string>CvccCvccCvcvno</string>
<string>CvcvnoCvccCvcc</string>
<string>CvcvCvccnoCvcc</string>
<string>CvcvCvccCvccno</string>
<string>CvccnoCvcvCvcc</string>
<string>CvccCvcvnoCvcc</string>
<string>CvccCvcvCvccno</string>
</array>
<key>Medium Password</key>
<array>
@ -52,7 +70,7 @@
<key>n</key>
<string>0123456789</string>
<key>o</key>
<string>!@#$%^&amp;*()</string>
<string>@&amp;%?,=[]_:-+*$#!'^~;()/.</string>
<key>x</key>
<string>AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&amp;*()</string>
</dict>