Make new site creation on Mac same as iOS.
[FIXED] Unable to create a site that is a substring of an existing site.
This commit is contained in:
parent
ca8f14fd3e
commit
a383d0eee7
@ -80,7 +80,7 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
|
|||||||
|
|
||||||
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
|
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
|
||||||
|
|
||||||
uint8_t *const buffer = malloc(32);
|
uint8_t *const buffer = malloc( 32 );
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -96,24 +96,29 @@ const char *mpw_idForBuf(const void *buf, size_t length) {
|
|||||||
return mpw_hex( hash, 32 );
|
return mpw_hex( hash, 32 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **mpw_hex_buf = NULL;
|
//static char **mpw_hex_buf = NULL;
|
||||||
static unsigned int mpw_hex_buf_i = 0;
|
//static unsigned int mpw_hex_buf_i = 0;
|
||||||
|
|
||||||
const char *mpw_hex(const void *buf, size_t length) {
|
const char *mpw_hex(const void *buf, size_t length) {
|
||||||
|
|
||||||
if (!mpw_hex_buf) {
|
// FIXME
|
||||||
mpw_hex_buf = malloc( 10 * sizeof( char* ) );
|
// if (!mpw_hex_buf) {
|
||||||
for (uint8_t i = 0; i < 10; ++i)
|
// mpw_hex_buf = malloc( 10 * sizeof( char * ) );
|
||||||
mpw_hex_buf[i] = NULL;
|
// for (uint8_t i = 0; i < 10; ++i)
|
||||||
}
|
// mpw_hex_buf[i] = NULL;
|
||||||
mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
// }
|
||||||
|
// mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
||||||
|
//
|
||||||
|
// mpw_hex_buf[mpw_hex_buf_i] = realloc( mpw_hex_buf[mpw_hex_buf_i], length * 2 + 1 );
|
||||||
|
// for (size_t kH = 0; kH < length; kH++)
|
||||||
|
// sprintf( &(mpw_hex_buf[mpw_hex_buf_i][kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
||||||
|
|
||||||
mpw_hex_buf[mpw_hex_buf_i] = realloc( mpw_hex_buf[mpw_hex_buf_i], length * 2 + 1 );
|
// return mpw_hex_buf[mpw_hex_buf_i];
|
||||||
for (size_t kH = 0; kH < length; kH++)
|
return NULL;
|
||||||
sprintf( &(mpw_hex_buf[mpw_hex_buf_i][kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
|
||||||
|
|
||||||
return mpw_hex_buf[mpw_hex_buf_i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *mpw_hex_l(uint32_t number) {
|
const char *mpw_hex_l(uint32_t number) {
|
||||||
|
|
||||||
return mpw_hex( &number, sizeof( number ) );
|
return mpw_hex( &number, sizeof( number ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +149,8 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
|||||||
const char *accessory[] = {
|
const char *accessory[] = {
|
||||||
"◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣",
|
"◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣",
|
||||||
"☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟",
|
"☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟",
|
||||||
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" };
|
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌"
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t identiconSeed[32];
|
uint8_t identiconSeed[32];
|
||||||
HMAC_SHA256_Buf( masterPassword, strlen( masterPassword ), fullName, strlen( fullName ), identiconSeed );
|
HMAC_SHA256_Buf( masterPassword, strlen( masterPassword ), fullName, strlen( fullName ), identiconSeed );
|
||||||
@ -206,8 +212,8 @@ const size_t mpw_charlen(const char *utf8String) {
|
|||||||
|
|
||||||
size_t charlen = 0;
|
size_t charlen = 0;
|
||||||
char *remainingString = (char *)utf8String;
|
char *remainingString = (char *)utf8String;
|
||||||
for (int charByteSize; (charByteSize = mpw_charByteSize( *remainingString )); remainingString += charByteSize)
|
for (int charByteSize; (charByteSize = mpw_charByteSize( (unsigned char)*remainingString )); remainingString += charByteSize)
|
||||||
++charlen;
|
++charlen;
|
||||||
|
|
||||||
return charlen;
|
return charlen;
|
||||||
}
|
}
|
||||||
|
@ -463,26 +463,26 @@
|
|||||||
- (void)useSite {
|
- (void)useSite {
|
||||||
|
|
||||||
MPSiteModel *selectedSite = [self selectedSite];
|
MPSiteModel *selectedSite = [self selectedSite];
|
||||||
if (selectedSite) {
|
if (!selectedSite)
|
||||||
// Performing action while content is available. Copy it.
|
return;
|
||||||
[self copyContent:selectedSite.content];
|
|
||||||
|
|
||||||
[self fadeOut];
|
if (selectedSite.transient) {
|
||||||
|
[self createNewSite:selectedSite.name];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NSUserNotification *notification = [NSUserNotification new];
|
// Performing action while content is available. Copy it.
|
||||||
notification.title = @"Password Copied";
|
[self copyContent:selectedSite.content];
|
||||||
if (selectedSite.loginName.length)
|
|
||||||
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
[self fadeOut];
|
||||||
else
|
|
||||||
notification.subtitle = selectedSite.name;
|
NSUserNotification *notification = [NSUserNotification new];
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
notification.title = @"Password Copied";
|
||||||
}
|
if (selectedSite.loginName.length)
|
||||||
else {
|
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
||||||
NSString *siteName = [self.siteField stringValue];
|
else
|
||||||
if ([siteName length])
|
notification.subtitle = selectedSite.name;
|
||||||
// Performing action without content but a site name is written.
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||||
[self createNewSite:siteName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateUser {
|
- (void)updateUser {
|
||||||
@ -549,9 +549,15 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL exact = NO;
|
||||||
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||||
for (MPSiteEntity *site in siteResults)
|
for (MPSiteEntity *site in siteResults) {
|
||||||
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]];
|
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]];
|
||||||
|
exact |= [site.name isEqualToString:queryString];
|
||||||
|
}
|
||||||
|
if (!exact && [queryString length])
|
||||||
|
[newSites addObject:[[MPSiteModel alloc] initWithName:queryString]];
|
||||||
|
dbg( @"newSites: %@", newSites );
|
||||||
self.sites = newSites;
|
self.sites = newSites;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,12 @@
|
|||||||
@property (nonatomic) NSUInteger counter;
|
@property (nonatomic) NSUInteger counter;
|
||||||
@property (nonatomic) NSDate *lastUsed;
|
@property (nonatomic) NSDate *lastUsed;
|
||||||
@property (nonatomic) id<MPAlgorithm> algorithm;
|
@property (nonatomic) id<MPAlgorithm> algorithm;
|
||||||
@property (nonatomic) BOOL generated;
|
@property (nonatomic, readonly) BOOL generated;
|
||||||
@property (nonatomic) BOOL stored;
|
@property (nonatomic, readonly) BOOL stored;
|
||||||
|
@property (nonatomic, readonly) BOOL transient;
|
||||||
|
|
||||||
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups;
|
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups;
|
||||||
|
- (instancetype)initWithName:(NSString *)siteName;
|
||||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
||||||
|
|
||||||
- (void)updateContent;
|
- (void)updateContent;
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
BOOL _initialized;
|
BOOL _initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||||
|
|
||||||
if (!(self = [super init]))
|
if (!(self = [super init]))
|
||||||
return nil;
|
return nil;
|
||||||
@ -39,6 +39,17 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithName:(NSString *)siteName {
|
||||||
|
|
||||||
|
if (!(self = [super init]))
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
[self setTransientSiteName:siteName];
|
||||||
|
_initialized = YES;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||||
|
|
||||||
if ([_entityOID isEqual:entity.objectID])
|
if ([_entityOID isEqual:entity.objectID])
|
||||||
@ -73,6 +84,28 @@
|
|||||||
[self updateContent:entity];
|
[self updateContent:entity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setTransientSiteName:(NSString *)siteName {
|
||||||
|
|
||||||
|
_entityOID = nil;
|
||||||
|
|
||||||
|
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
||||||
|
paragraphStyle.alignment = NSCenterTextAlignment;
|
||||||
|
self.displayedName = stra( siteName, @{
|
||||||
|
NSBackgroundColorAttributeName : [NSColor alternateSelectedControlColor],
|
||||||
|
NSParagraphStyleAttributeName : paragraphStyle,
|
||||||
|
} );
|
||||||
|
self.name = siteName;
|
||||||
|
self.algorithm = MPAlgorithmDefault;
|
||||||
|
self.lastUsed = nil;
|
||||||
|
self.type = [MPAppDelegate_Shared get].activeUserForMainThread.defaultType;
|
||||||
|
self.typeName = [self.algorithm nameOfType:self.type];
|
||||||
|
self.uses = @0;
|
||||||
|
self.counter = 1;
|
||||||
|
|
||||||
|
// Find all password types and the index of the current type amongst them.
|
||||||
|
[self updateContent];
|
||||||
|
}
|
||||||
|
|
||||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc {
|
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc {
|
||||||
|
|
||||||
if (!_entityOID)
|
if (!_entityOID)
|
||||||
@ -96,15 +129,18 @@
|
|||||||
// This wasn't a change to the entity.
|
// This wasn't a change to the entity.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
if (_entityOID)
|
||||||
MPSiteEntity *entity = [self entityInContext:context];
|
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) {
|
MPSiteEntity *entity = [self entityInContext:context];
|
||||||
((MPGeneratedSiteEntity *)entity).counter = counter;
|
if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) {
|
||||||
[context saveToStore];
|
((MPGeneratedSiteEntity *)entity).counter = counter;
|
||||||
|
[context saveToStore];
|
||||||
|
|
||||||
[self updateContent:entity];
|
[self updateContent:entity];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
else
|
||||||
|
[self updateContent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)generated {
|
- (BOOL)generated {
|
||||||
@ -117,36 +153,60 @@
|
|||||||
return self.type & MPSiteTypeClassStored;
|
return self.type & MPSiteTypeClassStored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)transient {
|
||||||
|
|
||||||
|
return _entityOID == nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateContent {
|
- (void)updateContent {
|
||||||
|
|
||||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
if (_entityOID)
|
||||||
[self updateContent:[MPSiteEntity existingObjectWithID:_entityOID inContext:context]];
|
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
}];
|
[self updateContent:[MPSiteEntity existingObjectWithID:_entityOID inContext:context]];
|
||||||
|
}];
|
||||||
|
else
|
||||||
|
PearlNotMainQueue( ^{
|
||||||
|
NSString *password = [self.algorithm generatePasswordForSiteNamed:self.name ofType:self.type withCounter:self.counter
|
||||||
|
usingKey:[MPAppDelegate_Shared get].key];
|
||||||
|
NSString *loginName = [self.algorithm generateLoginForSiteNamed:self.name usingKey:[MPAppDelegate_Shared get].key];
|
||||||
|
[self updatePasswordWithResult:password];
|
||||||
|
[self updateLoginNameWithResult:loginName];
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateContent:(MPSiteEntity *)entity {
|
- (void)updateContent:(MPSiteEntity *)entity {
|
||||||
|
|
||||||
|
[entity resolvePasswordUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||||
|
[self updatePasswordWithResult:result];
|
||||||
|
}];
|
||||||
|
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||||
|
[self updateLoginNameWithResult:result];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updatePasswordWithResult:(NSString *)result {
|
||||||
|
|
||||||
static NSRegularExpression *re_anyChar;
|
static NSRegularExpression *re_anyChar;
|
||||||
static dispatch_once_t once = 0;
|
static dispatch_once_t once = 0;
|
||||||
dispatch_once( &once, ^{
|
dispatch_once( &once, ^{
|
||||||
re_anyChar = [NSRegularExpression regularExpressionWithPattern:@"." options:0 error:nil];
|
re_anyChar = [NSRegularExpression regularExpressionWithPattern:@"." options:0 error:nil];
|
||||||
} );
|
} );
|
||||||
|
|
||||||
[entity resolvePasswordUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
NSString *displayResult = result;
|
||||||
NSString *displayResult = result;
|
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
||||||
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
displayResult = [displayResult stringByReplacingMatchesOfExpression:re_anyChar withTemplate:@"●"];
|
||||||
displayResult = [displayResult stringByReplacingMatchesOfExpression:re_anyChar withTemplate:@"●"];
|
|
||||||
|
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
self.content = result;
|
self.content = result;
|
||||||
self.displayedContent = displayResult;
|
self.displayedContent = displayResult;
|
||||||
} );
|
} );
|
||||||
}];
|
}
|
||||||
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
|
||||||
PearlMainQueue( ^{
|
- (void)updateLoginNameWithResult:(NSString *)loginName {
|
||||||
self.loginName = result;
|
|
||||||
} );
|
PearlMainQueue( ^{
|
||||||
}];
|
self.loginName = loginName;
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
Reference in New Issue
Block a user