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 buffer = malloc(32);
|
||||
uint8_t *const buffer = malloc( 32 );
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
@ -96,24 +96,29 @@ const char *mpw_idForBuf(const void *buf, size_t length) {
|
||||
return mpw_hex( hash, 32 );
|
||||
}
|
||||
|
||||
static char **mpw_hex_buf = NULL;
|
||||
static unsigned int mpw_hex_buf_i = 0;
|
||||
//static char **mpw_hex_buf = NULL;
|
||||
//static unsigned int mpw_hex_buf_i = 0;
|
||||
|
||||
const char *mpw_hex(const void *buf, size_t length) {
|
||||
|
||||
if (!mpw_hex_buf) {
|
||||
mpw_hex_buf = malloc( 10 * sizeof( char* ) );
|
||||
for (uint8_t i = 0; i < 10; ++i)
|
||||
mpw_hex_buf[i] = NULL;
|
||||
}
|
||||
mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
||||
// FIXME
|
||||
// if (!mpw_hex_buf) {
|
||||
// mpw_hex_buf = malloc( 10 * sizeof( char * ) );
|
||||
// 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[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 );
|
||||
for (size_t kH = 0; kH < length; kH++)
|
||||
sprintf( &(mpw_hex_buf[mpw_hex_buf_i][kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
||||
|
||||
return mpw_hex_buf[mpw_hex_buf_i];
|
||||
// return mpw_hex_buf[mpw_hex_buf_i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *mpw_hex_l(uint32_t number) {
|
||||
|
||||
return mpw_hex( &number, sizeof( number ) );
|
||||
}
|
||||
|
||||
@ -144,7 +149,8 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
const char *accessory[] = {
|
||||
"◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣",
|
||||
"☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟",
|
||||
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" };
|
||||
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌"
|
||||
};
|
||||
|
||||
uint8_t identiconSeed[32];
|
||||
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;
|
||||
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;
|
||||
|
||||
return charlen;
|
||||
return charlen;
|
||||
}
|
||||
|
@ -463,26 +463,26 @@
|
||||
- (void)useSite {
|
||||
|
||||
MPSiteModel *selectedSite = [self selectedSite];
|
||||
if (selectedSite) {
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:selectedSite.content];
|
||||
if (!selectedSite)
|
||||
return;
|
||||
|
||||
[self fadeOut];
|
||||
if (selectedSite.transient) {
|
||||
[self createNewSite:selectedSite.name];
|
||||
return;
|
||||
}
|
||||
|
||||
NSUserNotification *notification = [NSUserNotification new];
|
||||
notification.title = @"Password Copied";
|
||||
if (selectedSite.loginName.length)
|
||||
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
||||
else
|
||||
notification.subtitle = selectedSite.name;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
else {
|
||||
NSString *siteName = [self.siteField stringValue];
|
||||
if ([siteName length])
|
||||
// Performing action without content but a site name is written.
|
||||
[self createNewSite:siteName];
|
||||
}
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:selectedSite.content];
|
||||
|
||||
[self fadeOut];
|
||||
|
||||
NSUserNotification *notification = [NSUserNotification new];
|
||||
notification.title = @"Password Copied";
|
||||
if (selectedSite.loginName.length)
|
||||
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
||||
else
|
||||
notification.subtitle = selectedSite.name;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
|
||||
- (void)updateUser {
|
||||
@ -549,9 +549,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL exact = NO;
|
||||
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||
for (MPSiteEntity *site in siteResults)
|
||||
for (MPSiteEntity *site in siteResults) {
|
||||
[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;
|
||||
}];
|
||||
}
|
||||
|
@ -35,10 +35,12 @@
|
||||
@property (nonatomic) NSUInteger counter;
|
||||
@property (nonatomic) NSDate *lastUsed;
|
||||
@property (nonatomic) id<MPAlgorithm> algorithm;
|
||||
@property (nonatomic) BOOL generated;
|
||||
@property (nonatomic) BOOL stored;
|
||||
@property (nonatomic, readonly) BOOL generated;
|
||||
@property (nonatomic, readonly) BOOL stored;
|
||||
@property (nonatomic, readonly) BOOL transient;
|
||||
|
||||
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups;
|
||||
- (instancetype)initWithName:(NSString *)siteName;
|
||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
||||
|
||||
- (void)updateContent;
|
||||
|
@ -28,7 +28,7 @@
|
||||
BOOL _initialized;
|
||||
}
|
||||
|
||||
- (id)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
||||
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
@ -39,6 +39,17 @@
|
||||
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 {
|
||||
|
||||
if ([_entityOID isEqual:entity.objectID])
|
||||
@ -73,6 +84,28 @@
|
||||
[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 {
|
||||
|
||||
if (!_entityOID)
|
||||
@ -96,15 +129,18 @@
|
||||
// This wasn't a change to the entity.
|
||||
return;
|
||||
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *entity = [self entityInContext:context];
|
||||
if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) {
|
||||
((MPGeneratedSiteEntity *)entity).counter = counter;
|
||||
[context saveToStore];
|
||||
if (_entityOID)
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *entity = [self entityInContext:context];
|
||||
if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) {
|
||||
((MPGeneratedSiteEntity *)entity).counter = counter;
|
||||
[context saveToStore];
|
||||
|
||||
[self updateContent:entity];
|
||||
}
|
||||
}];
|
||||
[self updateContent:entity];
|
||||
}
|
||||
}];
|
||||
else
|
||||
[self updateContent];
|
||||
}
|
||||
|
||||
- (BOOL)generated {
|
||||
@ -117,36 +153,60 @@
|
||||
return self.type & MPSiteTypeClassStored;
|
||||
}
|
||||
|
||||
- (BOOL)transient {
|
||||
|
||||
return _entityOID == nil;
|
||||
}
|
||||
|
||||
- (void)updateContent {
|
||||
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
[self updateContent:[MPSiteEntity existingObjectWithID:_entityOID inContext:context]];
|
||||
}];
|
||||
if (_entityOID)
|
||||
[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 {
|
||||
|
||||
[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 dispatch_once_t once = 0;
|
||||
dispatch_once( &once, ^{
|
||||
re_anyChar = [NSRegularExpression regularExpressionWithPattern:@"." options:0 error:nil];
|
||||
} );
|
||||
|
||||
[entity resolvePasswordUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
NSString *displayResult = result;
|
||||
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
||||
displayResult = [displayResult stringByReplacingMatchesOfExpression:re_anyChar withTemplate:@"●"];
|
||||
NSString *displayResult = result;
|
||||
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
||||
displayResult = [displayResult stringByReplacingMatchesOfExpression:re_anyChar withTemplate:@"●"];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
self.content = result;
|
||||
self.displayedContent = displayResult;
|
||||
} );
|
||||
}];
|
||||
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
PearlMainQueue( ^{
|
||||
self.loginName = result;
|
||||
} );
|
||||
}];
|
||||
PearlMainQueue( ^{
|
||||
self.content = result;
|
||||
self.displayedContent = displayResult;
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)updateLoginNameWithResult:(NSString *)loginName {
|
||||
|
||||
PearlMainQueue( ^{
|
||||
self.loginName = loginName;
|
||||
} );
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user