Improve support for import/export headers on iOS/Mac.
[ADDED] iOS/macOS support for Full Name, Algorithm and Default Type mpsites headers.
This commit is contained in:
parent
c99252809d
commit
d9bd604436
@ -58,6 +58,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
|||||||
- (Class)classOfType:(MPSiteType)type;
|
- (Class)classOfType:(MPSiteType)type;
|
||||||
- (NSArray *)allTypes;
|
- (NSArray *)allTypes;
|
||||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
|
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
|
||||||
|
- (MPSiteType)defaultType;
|
||||||
- (MPSiteType)nextType:(MPSiteType)type;
|
- (MPSiteType)nextType:(MPSiteType)type;
|
||||||
- (MPSiteType)previousType:(MPSiteType)type;
|
- (MPSiteType)previousType:(MPSiteType)type;
|
||||||
|
|
||||||
|
@ -286,6 +286,11 @@ NSOperationQueue *_mpwQueue = nil;
|
|||||||
return allTypes;
|
return allTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (MPSiteType)defaultType {
|
||||||
|
|
||||||
|
return MPSiteTypeGeneratedLong;
|
||||||
|
}
|
||||||
|
|
||||||
- (MPSiteType)nextType:(MPSiteType)type {
|
- (MPSiteType)nextType:(MPSiteType)type {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -309,9 +314,9 @@ NSOperationQueue *_mpwQueue = nil;
|
|||||||
return MPSiteTypeStoredDevicePrivate;
|
return MPSiteTypeStoredDevicePrivate;
|
||||||
case MPSiteTypeStoredDevicePrivate:
|
case MPSiteTypeStoredDevicePrivate:
|
||||||
return MPSiteTypeGeneratedPhrase;
|
return MPSiteTypeGeneratedPhrase;
|
||||||
default:
|
|
||||||
return MPSiteTypeGeneratedLong;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [self defaultType];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MPSiteType)previousType:(MPSiteType)type {
|
- (MPSiteType)previousType:(MPSiteType)type {
|
||||||
|
@ -537,12 +537,13 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
|
|
||||||
// Parse import data.
|
// Parse import data.
|
||||||
inf( @"Importing sites." );
|
inf( @"Importing sites." );
|
||||||
__block MPUserEntity *user = nil;
|
|
||||||
id<MPAlgorithm> importAlgorithm = nil;
|
|
||||||
NSUInteger importFormat = 0;
|
NSUInteger importFormat = 0;
|
||||||
|
__block MPUserEntity *user = nil;
|
||||||
NSUInteger importAvatar = NSNotFound;
|
NSUInteger importAvatar = NSNotFound;
|
||||||
NSString *importBundleVersion = nil, *importUserName = nil;
|
|
||||||
NSData *importKeyID = nil;
|
NSData *importKeyID = nil;
|
||||||
|
NSString *importBundleVersion = nil, *importUserName = nil;
|
||||||
|
id<MPAlgorithm> importAlgorithm = nil;
|
||||||
|
MPSiteType importDefaultType = (MPSiteType)0;
|
||||||
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
||||||
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||||
NSMutableSet *sitesToDelete = [NSMutableSet set];
|
NSMutableSet *sitesToDelete = [NSMutableSet set];
|
||||||
@ -573,7 +574,15 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||||
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
|
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
|
||||||
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
|
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
|
||||||
if ([headerName isEqualToString:@"User Name"]) {
|
|
||||||
|
if ([headerName isEqualToString:@"Format"]) {
|
||||||
|
importFormat = (NSUInteger)[headerValue integerValue];
|
||||||
|
if (importFormat >= [sitePatterns count]) {
|
||||||
|
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
||||||
|
return MPImportResultInternalError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (([headerName isEqualToString:@"User Name"] || [headerName isEqualToString:@"Full Name"]) && !importUserName) {
|
||||||
importUserName = headerValue;
|
importUserName = headerValue;
|
||||||
|
|
||||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||||
@ -591,21 +600,18 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
user = [users lastObject];
|
user = [users lastObject];
|
||||||
dbg( @"Existing user? %@", [user debugDescription] );
|
dbg( @"Existing user? %@", [user debugDescription] );
|
||||||
}
|
}
|
||||||
|
if ([headerName isEqualToString:@"Avatar"])
|
||||||
|
importAvatar = (NSUInteger)[headerValue integerValue];
|
||||||
if ([headerName isEqualToString:@"Key ID"])
|
if ([headerName isEqualToString:@"Key ID"])
|
||||||
importKeyID = [headerValue decodeHex];
|
importKeyID = [headerValue decodeHex];
|
||||||
if ([headerName isEqualToString:@"Version"]) {
|
if ([headerName isEqualToString:@"Version"]) {
|
||||||
importBundleVersion = headerValue;
|
importBundleVersion = headerValue;
|
||||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||||
}
|
}
|
||||||
if ([headerName isEqualToString:@"Format"]) {
|
if ([headerName isEqualToString:@"Algorithm"])
|
||||||
importFormat = (NSUInteger)[headerValue integerValue];
|
importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] );
|
||||||
if (importFormat >= [sitePatterns count]) {
|
if ([headerName isEqualToString:@"Default Type"])
|
||||||
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
importDefaultType = (MPSiteType)[headerValue integerValue];
|
||||||
return MPImportResultInternalError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ([headerName isEqualToString:@"Avatar"])
|
|
||||||
importAvatar = (NSUInteger)[headerValue integerValue];
|
|
||||||
if ([headerName isEqualToString:@"Passwords"]) {
|
if ([headerName isEqualToString:@"Passwords"]) {
|
||||||
if ([headerValue isEqualToString:@"VISIBLE"])
|
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||||
clearText = YES;
|
clearText = YES;
|
||||||
@ -709,6 +715,8 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
if (user) {
|
if (user) {
|
||||||
if (importAvatar != NSNotFound)
|
if (importAvatar != NSNotFound)
|
||||||
user.avatar = importAvatar;
|
user.avatar = importAvatar;
|
||||||
|
if (importDefaultType)
|
||||||
|
user.defaultType = importDefaultType;
|
||||||
dbg( @"Updating User: %@", [user debugDescription] );
|
dbg( @"Updating User: %@", [user debugDescription] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -716,6 +724,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
user.name = importUserName;
|
user.name = importUserName;
|
||||||
user.algorithm = MPAlgorithmDefault;
|
user.algorithm = MPAlgorithmDefault;
|
||||||
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
||||||
|
user.defaultType = importDefaultType?: user.algorithm.defaultType;
|
||||||
if (importAvatar != NSNotFound)
|
if (importAvatar != NSNotFound)
|
||||||
user.avatar = importAvatar;
|
user.avatar = importAvatar;
|
||||||
dbg( @"Created User: %@", [user debugDescription] );
|
dbg( @"Created User: %@", [user debugDescription] );
|
||||||
@ -785,16 +794,16 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
|
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
|
||||||
[export appendFormat:@"# \n"];
|
[export appendFormat:@"# \n"];
|
||||||
[export appendFormat:@"##\n"];
|
[export appendFormat:@"##\n"];
|
||||||
|
[export appendFormat:@"# Format: 1\n"];
|
||||||
|
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||||
[export appendFormat:@"# User Name: %@\n", activeUser.name];
|
[export appendFormat:@"# User Name: %@\n", activeUser.name];
|
||||||
|
[export appendFormat:@"# Full Name: %@\n", activeUser.name];
|
||||||
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
|
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
|
||||||
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
|
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
|
||||||
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
|
||||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||||
[export appendFormat:@"# Format: 1\n"];
|
[export appendFormat:@"# Algorithm: %d\n", activeUser.algorithm.version];
|
||||||
if (revealPasswords)
|
[export appendFormat:@"# Default Type: %d\n", activeUser.defaultType];
|
||||||
[export appendFormat:@"# Passwords: VISIBLE\n"];
|
[export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"];
|
||||||
else
|
|
||||||
[export appendFormat:@"# Passwords: PROTECTED\n"];
|
|
||||||
[export appendFormat:@"##\n"];
|
[export appendFormat:@"##\n"];
|
||||||
[export appendFormat:@"#\n"];
|
[export appendFormat:@"#\n"];
|
||||||
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
|
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
|
||||||
|
@ -237,8 +237,8 @@
|
|||||||
// Invalid self.user.defaultType
|
// Invalid self.user.defaultType
|
||||||
result = MPApplyFix( result, ^MPFixableResult {
|
result = MPApplyFix( result, ^MPFixableResult {
|
||||||
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
|
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
|
||||||
self.name, self.user.name, (long)self.type, (long)MPSiteTypeGeneratedLong );
|
self.name, self.user.name, (long)self.type, (long)[self.algorithm defaultType] );
|
||||||
self.type = MPSiteTypeGeneratedLong;
|
self.type = [self.algorithm defaultType];
|
||||||
return MPFixableResultProblemsFixed;
|
return MPFixableResultProblemsFixed;
|
||||||
} );
|
} );
|
||||||
if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
|
if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
|
||||||
@ -330,7 +330,7 @@
|
|||||||
|
|
||||||
- (MPSiteType)defaultType {
|
- (MPSiteType)defaultType {
|
||||||
|
|
||||||
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDefaultType:(MPSiteType)aDefaultType {
|
- (void)setDefaultType:(MPSiteType)aDefaultType {
|
||||||
|
@ -281,12 +281,12 @@
|
|||||||
|
|
||||||
[self setMode:MPPasswordCellModePassword animated:YES];
|
[self setMode:MPPasswordCellModePassword animated:YES];
|
||||||
|
|
||||||
|
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||||
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
|
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
|
||||||
initSheet:^(UIActionSheet *sheet) {
|
initSheet:^(UIActionSheet *sheet) {
|
||||||
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
|
||||||
for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
|
|
||||||
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
|
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
|
||||||
NSString *typeName = [MPAlgorithmDefault nameOfType:type];
|
NSString *typeName = [mainSite.algorithm nameOfType:type];
|
||||||
if (type == mainSite.type)
|
if (type == mainSite.type)
|
||||||
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
||||||
else
|
else
|
||||||
@ -296,7 +296,8 @@
|
|||||||
if (buttonIndex == [sheet cancelButtonIndex])
|
if (buttonIndex == [sheet cancelButtonIndex])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MPSiteType type = (MPSiteType)[[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
MPSiteType type = (MPSiteType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?:
|
||||||
|
mainSite.user.defaultType?: mainSite.algorithm.defaultType;
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
MPSiteEntity *site = [self siteInContext:context];
|
MPSiteEntity *site = [self siteInContext:context];
|
||||||
@ -550,7 +551,7 @@
|
|||||||
|
|
||||||
BOOL loginGenerated = site.loginGenerated;
|
BOOL loginGenerated = site.loginGenerated;
|
||||||
NSString *password = nil, *loginName = [site resolveLoginUsingKey:key];
|
NSString *password = nil, *loginName = [site resolveLoginUsingKey:key];
|
||||||
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPSiteTypeGeneratedLong;
|
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPAlgorithmDefault.defaultType;
|
||||||
if (self.transientSite && transientType & MPSiteTypeClassGenerated)
|
if (self.transientSite && transientType & MPSiteTypeClassGenerated)
|
||||||
password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType
|
password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType
|
||||||
withCounter:1 usingKey:key];
|
withCounter:1 usingKey:key];
|
||||||
|
@ -220,6 +220,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
|
|||||||
if (isNew) {
|
if (isNew) {
|
||||||
user = [MPUserEntity insertNewObjectInContext:context];
|
user = [MPUserEntity insertNewObjectInContext:context];
|
||||||
user.algorithm = MPAlgorithmDefault;
|
user.algorithm = MPAlgorithmDefault;
|
||||||
|
user.defaultType = user.algorithm.defaultType;
|
||||||
user.avatar = newUserAvatar;
|
user.avatar = newUserAvatar;
|
||||||
user.name = newUserName;
|
user.name = newUserName;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user