Adapt macOS for new APIs.
This commit is contained in:
parent
f5c7d11f0e
commit
d7193f7753
@ -23,11 +23,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
//#ifdef NS_ENUM
|
#ifdef NS_ENUM
|
||||||
//#define enum(_type, _name) NS_ENUM(_type, _name)
|
#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||||
//#else
|
#else
|
||||||
#define enum(_type, _name) _type _name; enum
|
#define enum(_type, _name) _type _name; enum
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
//// Types.
|
//// Types.
|
||||||
|
|
||||||
|
@ -64,10 +64,10 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
|||||||
|
|
||||||
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
|
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
|
||||||
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
||||||
withCounter:(NSUInteger)counter usingKey:(MPKey *)key;
|
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key;
|
||||||
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key;
|
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key;
|
||||||
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
||||||
withCounter:(NSUInteger)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key;
|
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key;
|
||||||
|
|
||||||
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||||
|
|
||||||
|
@ -180,6 +180,9 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
case MPResultTypeStatefulDevice:
|
case MPResultTypeStatefulDevice:
|
||||||
return @"Device Private Password";
|
return @"Device Private Password";
|
||||||
|
|
||||||
|
case MPResultTypeDeriveKey:
|
||||||
|
return @"Crypto Key";
|
||||||
}
|
}
|
||||||
|
|
||||||
Throw( @"Type not supported: %lu", (long)type );
|
Throw( @"Type not supported: %lu", (long)type );
|
||||||
@ -220,6 +223,9 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
case MPResultTypeStatefulDevice:
|
case MPResultTypeStatefulDevice:
|
||||||
return @"Device";
|
return @"Device";
|
||||||
|
|
||||||
|
case MPResultTypeDeriveKey:
|
||||||
|
return @"Key";
|
||||||
}
|
}
|
||||||
|
|
||||||
Throw( @"Type not supported: %lu", (long)type );
|
Throw( @"Type not supported: %lu", (long)type );
|
||||||
@ -265,6 +271,9 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
case MPResultTypeStatefulDevice:
|
case MPResultTypeStatefulDevice:
|
||||||
return [MPStoredSiteEntity class];
|
return [MPStoredSiteEntity class];
|
||||||
|
|
||||||
|
case MPResultTypeDeriveKey:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Throw( @"Type not supported: %lu", (long)type );
|
Throw( @"Type not supported: %lu", (long)type );
|
||||||
@ -314,6 +323,8 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
return MPResultTypeStatefulDevice;
|
return MPResultTypeStatefulDevice;
|
||||||
case MPResultTypeStatefulDevice:
|
case MPResultTypeStatefulDevice:
|
||||||
return MPResultTypeTemplatePhrase;
|
return MPResultTypeTemplatePhrase;
|
||||||
|
case MPResultTypeDeriveKey:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self defaultType];
|
return [self defaultType];
|
||||||
@ -330,12 +341,12 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
|
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
|
||||||
|
|
||||||
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplateName parameter:nil withCounter:1
|
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplateName parameter:nil withCounter:MPCounterValueInitial
|
||||||
variant:MPKeyPurposeIdentification context:nil usingKey:key];
|
variant:MPKeyPurposeIdentification context:nil usingKey:key];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
||||||
withCounter:(NSUInteger)counter usingKey:(MPKey *)key {
|
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key {
|
||||||
|
|
||||||
return [self mpwResultForSiteNamed:name ofType:type parameter:nil withCounter:counter
|
return [self mpwResultForSiteNamed:name ofType:type parameter:nil withCounter:counter
|
||||||
variant:MPKeyPurposeAuthentication context:nil usingKey:key];
|
variant:MPKeyPurposeAuthentication context:nil usingKey:key];
|
||||||
@ -343,17 +354,18 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
|
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
|
||||||
|
|
||||||
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplatePhrase parameter:nil withCounter:1
|
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplatePhrase parameter:nil withCounter:MPCounterValueInitial
|
||||||
variant:MPKeyPurposeRecovery context:question usingKey:key];
|
variant:MPKeyPurposeRecovery context:question usingKey:key];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
||||||
withCounter:(NSUInteger)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key {
|
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context
|
||||||
|
usingKey:(MPKey *)key {
|
||||||
|
|
||||||
__block NSString *result = nil;
|
__block NSString *result = nil;
|
||||||
[self mpw_perform:^{
|
[self mpw_perform:^{
|
||||||
char const *resultBytes = mpw_siteResult( [key keyForAlgorithm:self],
|
char const *resultBytes = mpw_siteResult( [key keyForAlgorithm:self],
|
||||||
name.UTF8String, (uint32_t)counter, purpose, context.UTF8String, type, parameter.UTF8String, [self version] );
|
name.UTF8String, counter, purpose, context.UTF8String, type, parameter.UTF8String, [self version] );
|
||||||
if (resultBytes) {
|
if (resultBytes) {
|
||||||
result = [NSString stringWithCString:resultBytes encoding:NSUTF8StringEncoding];
|
result = [NSString stringWithCString:resultBytes encoding:NSUTF8StringEncoding];
|
||||||
mpw_free_string( resultBytes );
|
mpw_free_string( resultBytes );
|
||||||
@ -393,11 +405,11 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
[PearlKeyChain deleteItemForQuery:siteQuery];
|
[PearlKeyChain deleteItemForQuery:siteQuery];
|
||||||
else
|
else
|
||||||
[PearlKeyChain addOrUpdateItemForQuery:siteQuery withAttributes:@{
|
[PearlKeyChain addOrUpdateItemForQuery:siteQuery withAttributes:@{
|
||||||
(__bridge id)kSecValueData : state,
|
(__bridge id)kSecValueData: state,
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
(__bridge id)kSecAttrAccessible:
|
(__bridge id)kSecAttrAccessible:
|
||||||
site.type & MPSiteFeatureDevicePrivate? (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
site.type & MPSiteFeatureDevicePrivate? (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
||||||
: (__bridge id)kSecAttrAccessibleWhenUnlocked,
|
: (__bridge id)kSecAttrAccessibleWhenUnlocked,
|
||||||
#endif
|
#endif
|
||||||
}];
|
}];
|
||||||
((MPStoredSiteEntity *)site).contentObject = nil;
|
((MPStoredSiteEntity *)site).contentObject = nil;
|
||||||
@ -490,7 +502,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSUInteger counter = ((MPGeneratedSiteEntity *)site).counter;
|
MPCounterValue counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||||
|
|
||||||
PearlNotMainQueue( ^{
|
PearlNotMainQueue( ^{
|
||||||
resultBlock( [algorithm mpwTemplateForSiteNamed:name ofType:type withCounter:counter usingKey:key] );
|
resultBlock( [algorithm mpwTemplateForSiteNamed:name ofType:type withCounter:counter usingKey:key] );
|
||||||
@ -517,7 +529,12 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
} );
|
} );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MPResultTypeDeriveKey:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Throw( @"Type not supported: %lu", (long)type );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
|
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
|
||||||
@ -563,8 +580,8 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||||
if (cipherText && cipherText.length && site.type & MPResultTypeClassStateful) {
|
if (cipherText && cipherText.length && site.type & MPResultTypeClassStateful) {
|
||||||
NSString *plainText = [self mpwResultForSiteNamed:site.name ofType:site.type parameter:cipherText
|
NSString *plainText = [self mpwResultForSiteNamed:site.name ofType:site.type parameter:cipherText
|
||||||
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
|
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
|
||||||
usingKey:importKey];
|
usingKey:importKey];
|
||||||
if (plainText)
|
if (plainText)
|
||||||
[self savePassword:plainText toSite:site usingKey:key];
|
[self savePassword:plainText toSite:site usingKey:key];
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,16 @@ __END_DECLS
|
|||||||
} \
|
} \
|
||||||
error; \
|
error; \
|
||||||
})
|
})
|
||||||
|
#else
|
||||||
|
#define MPError(error_, message, ...) ({ \
|
||||||
|
NSError *error = error_; \
|
||||||
|
err( message @"%@%@", ##__VA_ARGS__, error? @"\n": @"", [error fullDescription]?: @"" ); \
|
||||||
|
error; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MPMakeError(message, ...) ({ \
|
#define MPMakeError(message, ...) ({ \
|
||||||
MPError( [NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{ \
|
MPError( [NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{ \
|
||||||
NSLocalizedDescriptionKey: strf( message, ##__VA_ARGS__ ) \
|
NSLocalizedDescriptionKey: strf( message, ##__VA_ARGS__ ) \
|
||||||
}], @"" ); \
|
}], @"" ); \
|
||||||
})
|
})
|
||||||
#else
|
|
||||||
#define MPError(error_, message, ...) ({ \
|
|
||||||
err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \
|
|
||||||
})
|
|
||||||
#endif
|
|
||||||
|
@ -269,23 +269,22 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
[openPanel close];
|
[openPanel close];
|
||||||
|
|
||||||
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
|
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
|
||||||
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
|
^(NSData *importedSitesData, NSURLResponse *response, NSError *urlError) {
|
||||||
if (error)
|
if (urlError)
|
||||||
MPError( error, @"While reading imported sites from %@.", url );
|
[[NSAlert alertWithError:MPError( urlError, @"While reading imported sites from %@.", url )] runModal];
|
||||||
if (!importedSitesData)
|
if (!importedSitesData)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
||||||
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
[self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||||
__block NSString *masterPassword = nil;
|
__block NSString *masterPassword = nil;
|
||||||
|
|
||||||
PearlMainQueueWait( ^{
|
PearlMainQueueWait( ^{
|
||||||
NSAlert *alert = [NSAlert new];
|
NSAlert *alert = [NSAlert new];
|
||||||
[alert addButtonWithTitle:@"Unlock"];
|
[alert addButtonWithTitle:@"Unlock"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
alert.messageText = @"Import File's Master Password";
|
alert.messageText = strf( @"Importing Sites For\n%@", userName );
|
||||||
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
|
alert.informativeText = @"Enter the master password used to create this export file.";
|
||||||
@"Enter that master password to unlock the exported data.", userName );
|
|
||||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||||
[alert layout];
|
[alert layout];
|
||||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||||
@ -293,16 +292,15 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
return masterPassword;
|
return masterPassword;
|
||||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
} askUserPassword:^NSString *(NSString *userName) {
|
||||||
__block NSString *masterPassword = nil;
|
__block NSString *masterPassword = nil;
|
||||||
|
|
||||||
PearlMainQueueWait( ^{
|
PearlMainQueueWait( ^{
|
||||||
NSAlert *alert = [NSAlert new];
|
NSAlert *alert = [NSAlert new];
|
||||||
[alert addButtonWithTitle:@"Import"];
|
[alert addButtonWithTitle:@"Import"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
alert.messageText = strf( @"Master Password for\n%@", userName );
|
alert.messageText = strf( @"Master Password For\n%@", userName );
|
||||||
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
|
alert.informativeText = @"Enter the current master password for this user.";
|
||||||
(unsigned long)importCount, (unsigned long)deleteCount );
|
|
||||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||||
[alert layout];
|
[alert layout];
|
||||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||||
@ -310,37 +308,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
return masterPassword;
|
return masterPassword;
|
||||||
|
} result:^(NSError *error) {
|
||||||
|
[self updateUsers];
|
||||||
|
|
||||||
|
if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError))
|
||||||
|
[[NSAlert alertWithError:error] runModal];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
PearlMainQueue( ^{
|
|
||||||
switch (result) {
|
|
||||||
case MPImportResultSuccess: {
|
|
||||||
[self updateUsers];
|
|
||||||
|
|
||||||
NSAlert *alert = [NSAlert new];
|
|
||||||
alert.messageText = @"Successfully imported sites.";
|
|
||||||
[alert runModal];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MPImportResultCancelled:
|
|
||||||
break;
|
|
||||||
case MPImportResultInternalError:
|
|
||||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
|
||||||
NSLocalizedDescriptionKey: @"Import failed because of an internal error."
|
|
||||||
}]] runModal];
|
|
||||||
break;
|
|
||||||
case MPImportResultMalformedInput:
|
|
||||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
|
||||||
NSLocalizedDescriptionKey: @"The import doesn't look like a Master Password export."
|
|
||||||
}]] runModal];
|
|
||||||
break;
|
|
||||||
case MPImportResultInvalidPassword:
|
|
||||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
|
||||||
NSLocalizedDescriptionKey: @"Incorrect master password for the import sites."
|
|
||||||
}]] runModal];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}] resume];
|
}] resume];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,25 +482,43 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NSError *coordinateError = nil;
|
[self exportSitesRevealPasswords:revealPasswords
|
||||||
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
|
askExportPassword:^NSString *(NSString *userName) {
|
||||||
[[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:savePanel.URL options:0
|
return PearlMainQueueAwait( ^id {
|
||||||
error:&coordinateError byAccessor:
|
NSAlert *alert = [NSAlert new];
|
||||||
^(NSURL *newURL) {
|
[alert addButtonWithTitle:@"Import"];
|
||||||
NSError *writeError = nil;
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
if (![exportedSites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
alert.messageText = strf( @"Master Password For\n%@", userName );
|
||||||
MPError( writeError, @"Could not write to the export file." );
|
alert.informativeText = @"Enter the current master password for this user.";
|
||||||
|
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||||
|
[alert layout];
|
||||||
|
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||||
|
return ((NSTextField *)alert.accessoryView).stringValue;
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
|
} );
|
||||||
|
} result:^(NSString *mpsites, NSError *error) {
|
||||||
|
if (!mpsites || error) {
|
||||||
|
PearlMainQueue( ^{
|
||||||
|
[[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal];
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSError *coordinateError = nil;
|
||||||
|
[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
|
||||||
|
coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) {
|
||||||
|
NSError *writeError = nil;
|
||||||
|
if (![mpsites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
[[NSAlert alertWithError:writeError] runModal];
|
[[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal];
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
if (coordinateError) {
|
if (coordinateError)
|
||||||
MPError( coordinateError, @"Write access to the export file could not be obtained." );
|
PearlMainQueue( ^{
|
||||||
PearlMainQueue( ^{
|
[[NSAlert alertWithError:MPError( coordinateError, @"Could not gain access to the export file." )] runModal];
|
||||||
[[NSAlert alertWithError:coordinateError] runModal];
|
} );
|
||||||
} );
|
}];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateUsers {
|
- (void)updateUsers {
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
@property(nonatomic) NSString *name;
|
@property(nonatomic) NSString *name;
|
||||||
@property(nonatomic) NSAttributedString *displayedName;
|
@property(nonatomic) NSAttributedString *displayedName;
|
||||||
@property(nonatomic) MPSiteType type;
|
@property(nonatomic) MPResultType type;
|
||||||
@property(nonatomic) NSString *typeName;
|
@property(nonatomic) NSString *typeName;
|
||||||
@property(nonatomic) NSString *content;
|
@property(nonatomic) NSString *content;
|
||||||
@property(nonatomic) NSString *displayedContent;
|
@property(nonatomic) NSString *displayedContent;
|
||||||
@ -36,7 +36,7 @@
|
|||||||
@property(nonatomic) NSString *loginName;
|
@property(nonatomic) NSString *loginName;
|
||||||
@property(nonatomic) BOOL loginGenerated;
|
@property(nonatomic) BOOL loginGenerated;
|
||||||
@property(nonatomic) NSNumber *uses;
|
@property(nonatomic) NSNumber *uses;
|
||||||
@property(nonatomic) NSUInteger counter;
|
@property(nonatomic) MPCounterValue counter;
|
||||||
@property(nonatomic) NSDate *lastUsed;
|
@property(nonatomic) NSDate *lastUsed;
|
||||||
@property(nonatomic) id<MPAlgorithm> algorithm;
|
@property(nonatomic) id<MPAlgorithm> algorithm;
|
||||||
@property(nonatomic) MPAlgorithmVersion algorithmVersion;
|
@property(nonatomic) MPAlgorithmVersion algorithmVersion;
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
self.type = entity.type;
|
self.type = entity.type;
|
||||||
self.typeName = entity.typeName;
|
self.typeName = entity.typeName;
|
||||||
self.uses = entity.uses_;
|
self.uses = entity.uses_;
|
||||||
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: 0;
|
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: MPCounterValueInitial;
|
||||||
self.loginGenerated = entity.loginGenerated;
|
self.loginGenerated = entity.loginGenerated;
|
||||||
|
|
||||||
// Find all password types and the index of the current type amongst them.
|
// Find all password types and the index of the current type amongst them.
|
||||||
@ -104,7 +104,7 @@
|
|||||||
self.type = user.defaultType;
|
self.type = user.defaultType;
|
||||||
self.typeName = [self.algorithm nameOfType:self.type];
|
self.typeName = [self.algorithm nameOfType:self.type];
|
||||||
self.uses = @0;
|
self.uses = @0;
|
||||||
self.counter = 1;
|
self.counter = MPCounterValueDefault;
|
||||||
|
|
||||||
// Find all password types and the index of the current type amongst them.
|
// Find all password types and the index of the current type amongst them.
|
||||||
[self updateContent];
|
[self updateContent];
|
||||||
@ -116,14 +116,14 @@
|
|||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:self.entityOID error:&error];
|
MPSiteEntity *entity = [moc existingObjectWithID:self.entityOID error:&error];
|
||||||
if (!entity)
|
if (!entity)
|
||||||
MPError( error, @"Couldn't retrieve active site." );
|
MPError( error, @"Couldn't retrieve active site." );
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCounter:(NSUInteger)counter {
|
- (void)setCounter:(MPCounterValue)counter {
|
||||||
|
|
||||||
if (self.counter == counter)
|
if (self.counter == counter)
|
||||||
return;
|
return;
|
||||||
@ -210,12 +210,12 @@
|
|||||||
|
|
||||||
- (BOOL)generated {
|
- (BOOL)generated {
|
||||||
|
|
||||||
return self.type & MPSiteTypeClassGenerated;
|
return self.type & MPResultTypeClassTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)stored {
|
- (BOOL)stored {
|
||||||
|
|
||||||
return self.type & MPSiteTypeClassStored;
|
return self.type & MPResultTypeClassStateful;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)transient {
|
- (BOOL)transient {
|
||||||
|
@ -373,9 +373,9 @@
|
|||||||
NSArray *types = [site.algorithm allTypes];
|
NSArray *types = [site.algorithm allTypes];
|
||||||
[self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
|
[self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
|
||||||
for (NSUInteger t = 0; t < [types count]; ++t) {
|
for (NSUInteger t = 0; t < [types count]; ++t) {
|
||||||
MPSiteType type = (MPSiteType)[types[t] unsignedIntegerValue];
|
MPResultType type = (MPResultType)[types[t] unsignedIntegerValue];
|
||||||
NSString *title = [site.algorithm nameOfType:type];
|
NSString *title = [site.algorithm nameOfType:type];
|
||||||
if (type & MPSiteTypeClassGenerated)
|
if (type & MPResultTypeClassTemplate)
|
||||||
title = strf( @"%@ – %@", [site.algorithm mpwTemplateForSiteNamed:site.name ofType:type withCounter:site.counter
|
title = strf( @"%@ – %@", [site.algorithm mpwTemplateForSiteNamed:site.name ofType:type withCounter:site.counter
|
||||||
usingKey:[MPMacAppDelegate get].key], title );
|
usingKey:[MPMacAppDelegate get].key], title );
|
||||||
|
|
||||||
@ -397,7 +397,7 @@
|
|||||||
switch (returnCode) {
|
switch (returnCode) {
|
||||||
case NSAlertFirstButtonReturn: {
|
case NSAlertFirstButtonReturn: {
|
||||||
// "Save" button.
|
// "Save" button.
|
||||||
MPSiteType type = (MPSiteType)[self.passwordTypesMatrix.selectedCell tag];
|
MPResultType type = (MPResultType)[self.passwordTypesMatrix.selectedCell tag];
|
||||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
MPSiteEntity *entity = [[MPMacAppDelegate get] changeSite:[self.selectedSite entityInContext:context]
|
MPSiteEntity *entity = [[MPMacAppDelegate get] changeSite:[self.selectedSite entityInContext:context]
|
||||||
saveInContext:context toType:type];
|
saveInContext:context toType:type];
|
||||||
|
@ -436,17 +436,15 @@
|
|||||||
|
|
||||||
[self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
|
[self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
|
||||||
return PearlAwait( ^(void (^setResult)(id)) {
|
return PearlAwait( ^(void (^setResult)(id)) {
|
||||||
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
|
[PearlAlert showAlertWithTitle:strf( @"Master Password For:\n%@", userName )
|
||||||
message:strf( @"%@'s export was done using a different master password.\n"
|
message:@"Enter the user's master password to create an export file."
|
||||||
@"Enter that master password to unlock the exported data.", userName )
|
|
||||||
viewStyle:UIAlertViewStyleSecureTextInput
|
viewStyle:UIAlertViewStyleSecureTextInput
|
||||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||||
setResult( nil );
|
setResult( nil );
|
||||||
else
|
else
|
||||||
setResult( [alert_ textFieldAtIndex:0].text );
|
setResult( [alert_ textFieldAtIndex:0].text );
|
||||||
}
|
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Export", nil];
|
||||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
|
|
||||||
} );
|
} );
|
||||||
} result:^(NSString *mpsites, NSError *error) {
|
} result:^(NSString *mpsites, NSError *error) {
|
||||||
if (!mpsites || error) {
|
if (!mpsites || error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user