Improvements to password import.
[FIXED] Importing of mpsites with passwords showing for stored password types. [FIXED] Don't try to show mail composition dialog when the user has no mail account configured. This will crash. Instead, show a friendly popup explaining things. [IMPROVED] Message of password export emails. [FIXED] Hierarchy of MPUnlockVC so password field becomes touchable.
This commit is contained in:
parent
b7e91358be
commit
4d4ba3425e
@ -16,6 +16,4 @@
|
|||||||
- (void)storeSavedKeyFor:(MPUserEntity *)user;
|
- (void)storeSavedKeyFor:(MPUserEntity *)user;
|
||||||
- (void)forgetSavedKeyFor:(MPUserEntity *)user;
|
- (void)forgetSavedKeyFor:(MPUserEntity *)user;
|
||||||
|
|
||||||
- (NSData *)keyWithLength:(NSUInteger)keyLength;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -169,9 +169,4 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)keyWithLength:(NSUInteger)keyLength {
|
|
||||||
|
|
||||||
return [self.key subdataWithRange:NSMakeRange(0, MIN(keyLength, self.key.length))];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -217,9 +217,10 @@
|
|||||||
if (!headerPattern || !sitePattern)
|
if (!headerPattern || !sitePattern)
|
||||||
return MPImportResultInternalError;
|
return MPImportResultInternalError;
|
||||||
|
|
||||||
|
NSData *key = nil;
|
||||||
NSString *keyIDHex = nil, *userName = nil;
|
NSString *keyIDHex = nil, *userName = nil;
|
||||||
MPUserEntity *user = nil;
|
MPUserEntity *user = nil;
|
||||||
BOOL headerStarted = NO, headerEnded = NO;
|
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
||||||
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||||
NSMutableSet *elementsToDelete = [NSMutableSet set];
|
NSMutableSet *elementsToDelete = [NSMutableSet set];
|
||||||
NSMutableArray *importedSiteElements = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
|
NSMutableArray *importedSiteElements = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
|
||||||
@ -246,19 +247,24 @@
|
|||||||
}
|
}
|
||||||
NSTextCheckingResult *headerElements = [[headerPattern matchesInString:importedSiteLine options:0
|
NSTextCheckingResult *headerElements = [[headerPattern matchesInString:importedSiteLine options:0
|
||||||
range:NSMakeRange(0, [importedSiteLine length])] lastObject];
|
range:NSMakeRange(0, [importedSiteLine length])] lastObject];
|
||||||
NSString *key = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:1]];
|
NSString *headerName = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:1]];
|
||||||
NSString *value = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:2]];
|
NSString *headerValue = [importedSiteLine substringWithRange:[headerElements rangeAtIndex:2]];
|
||||||
if ([key isEqualToString:@"User Name"]) {
|
if ([headerName isEqualToString:@"User Name"]) {
|
||||||
userName = value;
|
userName = headerValue;
|
||||||
|
key = keyForPassword(password, userName);
|
||||||
|
|
||||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||||
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", userName];
|
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", userName];
|
||||||
user = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
|
user = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
|
||||||
}
|
}
|
||||||
if ([key isEqualToString:@"Key ID"]) {
|
if ([headerName isEqualToString:@"Key ID"]) {
|
||||||
if (![(keyIDHex = value) isEqualToString:[keyIDForPassword(password, userName) encodeHex]])
|
if (![(keyIDHex = headerValue) isEqualToString:[keyIDForKey(key) encodeHex]])
|
||||||
return MPImportResultInvalidPassword;
|
return MPImportResultInvalidPassword;
|
||||||
}
|
}
|
||||||
|
if ([headerName isEqualToString:@"Passwords"]) {
|
||||||
|
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||||
|
clearText = YES;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -337,7 +343,10 @@
|
|||||||
element.uses = uses;
|
element.uses = uses;
|
||||||
element.lastUsed = lastUsed;
|
element.lastUsed = lastUsed;
|
||||||
if ([exportContent length])
|
if ([exportContent length])
|
||||||
[element importContent:exportContent];
|
if (clearText)
|
||||||
|
[element importClearTextContent:exportContent usingKey:key];
|
||||||
|
else
|
||||||
|
[element importProtectedContent:exportContent];
|
||||||
}
|
}
|
||||||
[self saveContext];
|
[self saveContext];
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
- (NSUInteger)use;
|
- (NSUInteger)use;
|
||||||
- (NSString *)exportContent;
|
- (NSString *)exportContent;
|
||||||
- (void)importContent:(NSString *)content;
|
- (void)importProtectedContent:(NSString *)protectedContent;
|
||||||
|
- (void)importClearTextContent:(NSString *)clearContent usingKey:(NSData *)key;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -50,10 +50,14 @@
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)importContent:(NSString *)content {
|
- (void)importProtectedContent:(NSString *)content {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)importClearTextContent:(NSString *)content usingKey:(NSData *)key {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *)description {
|
- (NSString *)description {
|
||||||
|
|
||||||
return PearlString(@"%@:%@", [self class], [self name]);
|
return PearlString(@"%@:%@", [self class], [self name]);
|
||||||
@ -107,8 +111,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (id)content {
|
- (id)content {
|
||||||
|
|
||||||
|
return [self contentUsingKey:[MPAppDelegate get].key];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setContent:(id)content {
|
||||||
|
|
||||||
|
[self setContent:content usingKey:[MPAppDelegate get].key];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)contentUsingKey:(NSData *)key {
|
||||||
|
|
||||||
assert(self.type & MPElementTypeClassStored);
|
assert(self.type & MPElementTypeClassStored);
|
||||||
|
assert([keyIDForKey(key) isEqualToData:self.user.keyID]);
|
||||||
|
|
||||||
NSData *encryptedContent;
|
NSData *encryptedContent;
|
||||||
if (self.type & MPElementFeatureDevicePrivate)
|
if (self.type & MPElementFeatureDevicePrivate)
|
||||||
@ -116,15 +131,16 @@
|
|||||||
else
|
else
|
||||||
encryptedContent = self.contentObject;
|
encryptedContent = self.contentObject;
|
||||||
|
|
||||||
NSData *decryptedContent = [encryptedContent decryptWithSymmetricKey:[[MPAppDelegate get] keyWithLength:PearlCryptKeySize]
|
NSData *decryptedContent = [encryptedContent decryptWithSymmetricKey:subkeyForKey(key, PearlCryptKeySize) padding:YES];
|
||||||
padding:YES];
|
|
||||||
return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding];
|
return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setContent:(id)content {
|
- (void)setContent:(id)content usingKey:(NSData *)key {
|
||||||
|
|
||||||
NSData *encryptedContent = [[content description] encryptWithSymmetricKey:[[MPAppDelegate get] keyWithLength:PearlCryptKeySize]
|
assert(self.type & MPElementTypeClassStored);
|
||||||
padding:YES];
|
assert([keyIDForKey(key) isEqualToData:self.user.keyID]);
|
||||||
|
|
||||||
|
NSData *encryptedContent = [[content description] encryptWithSymmetricKey:subkeyForKey(key, PearlCryptKeySize) padding:YES];
|
||||||
|
|
||||||
if (self.type & MPElementFeatureDevicePrivate) {
|
if (self.type & MPElementFeatureDevicePrivate) {
|
||||||
[PearlKeyChain addOrUpdateItemForQuery:[MPElementStoredEntity queryForDevicePrivateElementNamed:self.name]
|
[PearlKeyChain addOrUpdateItemForQuery:[MPElementStoredEntity queryForDevicePrivateElementNamed:self.name]
|
||||||
@ -144,9 +160,14 @@
|
|||||||
return [self.contentObject encodeBase64];
|
return [self.contentObject encodeBase64];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)importContent:(NSString *)content {
|
- (void)importProtectedContent:(NSString *)protectedContent {
|
||||||
|
|
||||||
self.contentObject = [content decodeBase64];
|
self.contentObject = [protectedContent decodeBase64];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)importClearTextContent:(NSString *)clearContent usingKey:(NSData *)key {
|
||||||
|
|
||||||
|
[self setContent:clearContent usingKey:key];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -78,6 +78,7 @@ typedef enum {
|
|||||||
#define MPNotificationElementUsed @"MPNotificationElementUsed"
|
#define MPNotificationElementUsed @"MPNotificationElementUsed"
|
||||||
|
|
||||||
NSData *keyForPassword(NSString *password, NSString *username);
|
NSData *keyForPassword(NSString *password, NSString *username);
|
||||||
|
NSData *subkeyForKey(NSData *key, NSUInteger subkeyLength);
|
||||||
NSData *keyIDForPassword(NSString *password, NSString *username);
|
NSData *keyIDForPassword(NSString *password, NSString *username);
|
||||||
NSData *keyIDForKey(NSData *key);
|
NSData *keyIDForKey(NSData *key);
|
||||||
NSString *NSStringFromMPElementType(MPElementType type);
|
NSString *NSStringFromMPElementType(MPElementType type);
|
||||||
|
@ -30,6 +30,13 @@ NSData *keyForPassword(NSString *password, NSString *username) {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NSData *subkeyForKey(NSData *key, NSUInteger subkeyLength) {
|
||||||
|
|
||||||
|
return [key subdataWithRange:NSMakeRange(0, MIN(subkeyLength, key.length))];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NSData *keyIDForPassword(NSString *password, NSString *username) {
|
NSData *keyIDForPassword(NSString *password, NSString *username) {
|
||||||
|
|
||||||
return keyIDForKey(keyForPassword(password, username));
|
return keyIDForKey(keyForPassword(password, username));
|
||||||
|
@ -202,8 +202,6 @@
|
|||||||
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
|
|
||||||
|
|
||||||
[super application:application didFinishLaunchingWithOptions:launchOptions];
|
[super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||||
|
|
||||||
inf(@"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier]);
|
inf(@"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier]);
|
||||||
@ -419,26 +417,47 @@
|
|||||||
// Safe Export
|
// Safe Export
|
||||||
[self exportShowPasswords:NO];
|
[self exportShowPasswords:NO];
|
||||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
||||||
// Safe Export
|
// Show Passwords
|
||||||
[self exportShowPasswords:YES];
|
[self exportShowPasswords:YES];
|
||||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
||||||
} otherTitles:nil];
|
} otherTitles:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)exportShowPasswords:(BOOL)showPasswords {
|
- (void)exportShowPasswords:(BOOL)showPasswords {
|
||||||
|
|
||||||
|
if (![MFMailComposeViewController canSendMail]) {
|
||||||
|
[PearlAlert showAlertWithTitle:@"Cannot Send Mail"
|
||||||
|
message:
|
||||||
|
@"Your device is not yet set up for sending mail.\n"
|
||||||
|
@"Close Master Password, go into Settings and add a Mail account."
|
||||||
|
viewStyle:UIAlertViewStyleDefault
|
||||||
|
initAlert:nil tappedButtonBlock:nil
|
||||||
|
cancelTitle:[PearlStrings get].commonButtonOkay
|
||||||
|
otherTitles:nil];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NSString *exportedSites = [self exportSitesShowingPasswords:showPasswords];
|
NSString *exportedSites = [self exportSitesShowingPasswords:showPasswords];
|
||||||
NSString *message;
|
NSString *message;
|
||||||
if (showPasswords)
|
|
||||||
message = PearlString(
|
|
||||||
@"Export of %@'s Master Password sites with passwords visible.\n"
|
|
||||||
@"REMINDER: Make sure nobody else sees this file! All passwords are visible!\n",
|
|
||||||
self.activeUser.name);
|
|
||||||
else
|
|
||||||
message = PearlString(
|
|
||||||
@"Backup of %@'s Master Password sites.\n",
|
|
||||||
self.activeUser.name);
|
|
||||||
|
|
||||||
|
if (showPasswords)
|
||||||
|
message = PearlString(@"Export of Master Password sites with passwords included.\n"
|
||||||
|
@"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n"
|
||||||
|
@"--\n"
|
||||||
|
@"%@\n"
|
||||||
|
@"Master Password %@, build %@",
|
||||||
|
self.activeUser.name,
|
||||||
|
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||||
|
[PearlInfoPlist get].CFBundleVersion);
|
||||||
|
else
|
||||||
|
message = PearlString(@"Backup of Master Password sites.\n\n\n"
|
||||||
|
@"--\n"
|
||||||
|
@"%@\n"
|
||||||
|
@"Master Password %@, build %@",
|
||||||
|
self.activeUser.name,
|
||||||
|
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||||
|
[PearlInfoPlist get].CFBundleVersion);
|
||||||
|
|
||||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'DD"];
|
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'DD"];
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="1.1" toolsVersion="2182" systemVersion="11E53" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="KZF-fe-y9n">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="1.1" toolsVersion="2182" systemVersion="11E53" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="KZF-fe-y9n">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment defaultVersion="1296" identifier="iOS"/>
|
|
||||||
<development defaultVersion="4200" identifier="xcode"/>
|
<development defaultVersion="4200" identifier="xcode"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="1181"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="1181"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@ -828,54 +827,6 @@ L4m3P4sSw0rD</string>
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<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"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Enter your master password:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RhX-bA-EhC">
|
|
||||||
<rect key="frame" x="12" y="0.0" width="256" height="20"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
|
||||||
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="17"/>
|
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_textfield.png" id="ivR-Xl-NrT">
|
|
||||||
<rect key="frame" x="0.0" y="28" width="280" height="60"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
|
||||||
<rect key="contentStretch" x="0.25" y="0.25" width="0.49999999999999961" height="0.49999999999999961"/>
|
|
||||||
</imageView>
|
|
||||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="center" clearsOnBeginEditing="YES" minimumFontSize="17" id="rTR-7Q-X8o">
|
|
||||||
<rect key="frame" x="0.0" y="28" width="280" height="60"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="36"/>
|
|
||||||
<textInputTraits key="textInputTraits" enablesReturnKeyAutomatically="YES" secureTextEntry="YES"/>
|
|
||||||
<connections>
|
|
||||||
<outlet property="delegate" destination="Nbn-Rv-sP1" id="Y0T-cI-gF1"/>
|
|
||||||
</connections>
|
|
||||||
</textField>
|
|
||||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="NvG-0R-eTZ">
|
|
||||||
<rect key="frame" x="35" y="0.0" width="210" height="60"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="3se-By-a9W">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="210" height="60"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
</imageView>
|
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Incorrect password." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="gQ2-mB-BP4">
|
|
||||||
<rect key="frame" x="15" y="0.5" width="180" height="40"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
|
||||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" id="27q-lX-0vy">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" id="27q-lX-0vy">
|
||||||
<rect key="frame" x="105" y="30" width="110" height="110"/>
|
<rect key="frame" x="105" y="30" width="110" height="110"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
@ -904,6 +855,54 @@ L4m3P4sSw0rD</string>
|
|||||||
<outletCollection property="gestureRecognizers" destination="9WS-yS-aqQ" appends="YES" id="B9k-bg-gqA"/>
|
<outletCollection property="gestureRecognizers" destination="9WS-yS-aqQ" appends="YES" id="B9k-bg-gqA"/>
|
||||||
</connections>
|
</connections>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
|
<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"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Enter your master password:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RhX-bA-EhC">
|
||||||
|
<rect key="frame" x="12" y="0.0" width="256" height="20"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" name="Copperplate" family="Copperplate" pointSize="17"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_textfield.png" id="ivR-Xl-NrT">
|
||||||
|
<rect key="frame" x="0.0" y="28" width="280" height="60"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
<rect key="contentStretch" x="0.25" y="0.25" width="0.49999999999999961" height="0.49999999999999961"/>
|
||||||
|
</imageView>
|
||||||
|
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="center" clearsOnBeginEditing="YES" minimumFontSize="17" id="rTR-7Q-X8o">
|
||||||
|
<rect key="frame" x="10" y="28" width="260" height="60"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="36"/>
|
||||||
|
<textInputTraits key="textInputTraits" enablesReturnKeyAutomatically="YES" secureTextEntry="YES"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="Nbn-Rv-sP1" id="Y0T-cI-gF1"/>
|
||||||
|
</connections>
|
||||||
|
</textField>
|
||||||
|
<view userInteractionEnabled="NO" contentMode="scaleToFill" id="NvG-0R-eTZ">
|
||||||
|
<rect key="frame" x="35" y="0.0" width="210" height="60"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" id="3se-By-a9W">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="210" height="60"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Incorrect password." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="gQ2-mB-BP4">
|
||||||
|
<rect key="frame" x="15" y="0.5" width="180" height="40"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.0" contentMode="left" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" id="8s0-nT-Aoq">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.0" contentMode="left" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" id="8s0-nT-Aoq">
|
||||||
<rect key="frame" x="90" y="289" width="140" height="15"/>
|
<rect key="frame" x="90" y="289" width="140" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
@ -942,7 +941,7 @@ L4m3P4sSw0rD</string>
|
|||||||
<outlet property="deleteTip" destination="DBJ-Qi-ZcF" id="VXD-Zc-UYi"/>
|
<outlet property="deleteTip" destination="DBJ-Qi-ZcF" id="VXD-Zc-UYi"/>
|
||||||
<outlet property="nameLabel" destination="0NM-NI-7UR" id="GBg-Ry-sqj"/>
|
<outlet property="nameLabel" destination="0NM-NI-7UR" id="GBg-Ry-sqj"/>
|
||||||
<outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/>
|
<outlet property="oldNameLabel" destination="8s0-nT-Aoq" id="plu-1H-MVc"/>
|
||||||
<outlet property="passwordField" destination="rTR-7Q-X8o" id="CDA-iP-kCm"/>
|
<outlet property="passwordField" destination="rTR-7Q-X8o" id="Vsn-uO-4lO"/>
|
||||||
<outlet property="passwordTipLabel" destination="gQ2-mB-BP4" id="aHU-tn-duI"/>
|
<outlet property="passwordTipLabel" destination="gQ2-mB-BP4" id="aHU-tn-duI"/>
|
||||||
<outlet property="passwordTipView" destination="NvG-0R-eTZ" id="4Mx-TL-yfu"/>
|
<outlet property="passwordTipView" destination="NvG-0R-eTZ" id="4Mx-TL-yfu"/>
|
||||||
<outlet property="passwordView" destination="7cc-yu-i0m" id="WoF-Ab-PPC"/>
|
<outlet property="passwordView" destination="7cc-yu-i0m" id="WoF-Ab-PPC"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user