diff --git a/platform-darwin/Source/MPAlgorithm.h b/platform-darwin/Source/MPAlgorithm.h index b58ccce0..93372566 100644 --- a/platform-darwin/Source/MPAlgorithm.h +++ b/platform-darwin/Source/MPAlgorithm.h @@ -58,6 +58,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack); - (Class)classOfType:(MPSiteType)type; - (NSArray *)allTypes; - (NSArray *)allTypesStartingWith:(MPSiteType)startingType; +- (MPSiteType)defaultType; - (MPSiteType)nextType:(MPSiteType)type; - (MPSiteType)previousType:(MPSiteType)type; diff --git a/platform-darwin/Source/MPAlgorithmV0.m b/platform-darwin/Source/MPAlgorithmV0.m index 423a9760..bca243c8 100644 --- a/platform-darwin/Source/MPAlgorithmV0.m +++ b/platform-darwin/Source/MPAlgorithmV0.m @@ -286,6 +286,11 @@ NSOperationQueue *_mpwQueue = nil; return allTypes; } +- (MPSiteType)defaultType { + + return MPSiteTypeGeneratedLong; +} + - (MPSiteType)nextType:(MPSiteType)type { switch (type) { @@ -309,9 +314,9 @@ NSOperationQueue *_mpwQueue = nil; return MPSiteTypeStoredDevicePrivate; case MPSiteTypeStoredDevicePrivate: return MPSiteTypeGeneratedPhrase; - default: - return MPSiteTypeGeneratedLong; } + + return [self defaultType]; } - (MPSiteType)previousType:(MPSiteType)type { diff --git a/platform-darwin/Source/MPAppDelegate_Store.m b/platform-darwin/Source/MPAppDelegate_Store.m index f8672726..66242070 100644 --- a/platform-darwin/Source/MPAppDelegate_Store.m +++ b/platform-darwin/Source/MPAppDelegate_Store.m @@ -537,12 +537,13 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); // Parse import data. inf( @"Importing sites." ); - __block MPUserEntity *user = nil; - id importAlgorithm = nil; NSUInteger importFormat = 0; + __block MPUserEntity *user = nil; NSUInteger importAvatar = NSNotFound; - NSString *importBundleVersion = nil, *importUserName = nil; NSData *importKeyID = nil; + NSString *importBundleVersion = nil, *importUserName = nil; + id importAlgorithm = nil; + MPSiteType importDefaultType = (MPSiteType)0; BOOL headerStarted = NO, headerEnded = NO, clearText = NO; NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]; NSMutableSet *sitesToDelete = [NSMutableSet set]; @@ -573,7 +574,15 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); range:NSMakeRange( 0, [importedSiteLine length] )] lastObject]; NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]]; 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; NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; @@ -591,21 +600,18 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); user = [users lastObject]; dbg( @"Existing user? %@", [user debugDescription] ); } + if ([headerName isEqualToString:@"Avatar"]) + importAvatar = (NSUInteger)[headerValue integerValue]; if ([headerName isEqualToString:@"Key ID"]) importKeyID = [headerValue decodeHex]; if ([headerName isEqualToString:@"Version"]) { importBundleVersion = headerValue; importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion ); } - 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:@"Avatar"]) - importAvatar = (NSUInteger)[headerValue integerValue]; + if ([headerName isEqualToString:@"Algorithm"]) + importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] ); + if ([headerName isEqualToString:@"Default Type"]) + importDefaultType = (MPSiteType)[headerValue integerValue]; if ([headerName isEqualToString:@"Passwords"]) { if ([headerValue isEqualToString:@"VISIBLE"]) clearText = YES; @@ -709,6 +715,8 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); if (user) { if (importAvatar != NSNotFound) user.avatar = importAvatar; + if (importDefaultType) + user.defaultType = importDefaultType; dbg( @"Updating User: %@", [user debugDescription] ); } else { @@ -716,6 +724,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); user.name = importUserName; user.algorithm = MPAlgorithmDefault; user.keyID = [userKey keyIDForAlgorithm:user.algorithm]; + user.defaultType = importDefaultType?: user.algorithm.defaultType; if (importAvatar != NSNotFound) user.avatar = importAvatar; 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:@"# \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:@"# Full Name: %@\n", activeUser.name]; [export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar]; [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:@"# Format: 1\n"]; - if (revealPasswords) - [export appendFormat:@"# Passwords: VISIBLE\n"]; - else - [export appendFormat:@"# Passwords: PROTECTED\n"]; + [export appendFormat:@"# Algorithm: %d\n", activeUser.algorithm.version]; + [export appendFormat:@"# Default Type: %d\n", activeUser.defaultType]; + [export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"]; [export appendFormat:@"##\n"]; [export appendFormat:@"#\n"]; [export appendFormat:@"# Last Times Password Login\t Site\tSite\n"]; diff --git a/platform-darwin/Source/MPEntities.m b/platform-darwin/Source/MPEntities.m index f78651d6..74c3355b 100644 --- a/platform-darwin/Source/MPEntities.m +++ b/platform-darwin/Source/MPEntities.m @@ -237,8 +237,8 @@ // Invalid self.user.defaultType result = MPApplyFix( result, ^MPFixableResult { wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.", - self.name, self.user.name, (long)self.type, (long)MPSiteTypeGeneratedLong ); - self.type = MPSiteTypeGeneratedLong; + self.name, self.user.name, (long)self.type, (long)[self.algorithm defaultType] ); + self.type = [self.algorithm defaultType]; return MPFixableResultProblemsFixed; } ); if (![self isKindOfClass:[self.algorithm classOfType:self.type]]) @@ -330,7 +330,7 @@ - (MPSiteType)defaultType { - return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: MPSiteTypeGeneratedLong; + return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType; } - (void)setDefaultType:(MPSiteType)aDefaultType { diff --git a/platform-darwin/Source/iOS/MPPasswordCell.m b/platform-darwin/Source/iOS/MPPasswordCell.m index 5bc30595..d4f7a5ee 100644 --- a/platform-darwin/Source/iOS/MPPasswordCell.m +++ b/platform-darwin/Source/iOS/MPPasswordCell.m @@ -281,12 +281,12 @@ [self setMode:MPPasswordCellModePassword animated:YES]; + MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; [PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic initSheet:^(UIActionSheet *sheet) { - MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; - for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) { + for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) { MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue]; - NSString *typeName = [MPAlgorithmDefault nameOfType:type]; + NSString *typeName = [mainSite.algorithm nameOfType:type]; if (type == mainSite.type) [sheet addButtonWithTitle:strf( @"● %@", typeName )]; else @@ -296,7 +296,8 @@ if (buttonIndex == [sheet cancelButtonIndex]) 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) { MPSiteEntity *site = [self siteInContext:context]; @@ -550,7 +551,7 @@ BOOL loginGenerated = site.loginGenerated; 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) password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType withCounter:1 usingKey:key]; diff --git a/platform-darwin/Source/iOS/MPUsersViewController.m b/platform-darwin/Source/iOS/MPUsersViewController.m index 1bfa4813..aa7d9ae8 100644 --- a/platform-darwin/Source/iOS/MPUsersViewController.m +++ b/platform-darwin/Source/iOS/MPUsersViewController.m @@ -220,6 +220,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) { if (isNew) { user = [MPUserEntity insertNewObjectInContext:context]; user.algorithm = MPAlgorithmDefault; + user.defaultType = user.algorithm.defaultType; user.avatar = newUserAvatar; user.name = newUserName; }