Revision: 27942
http://sourceforge.net/p/bibdesk/svn/27942
Author: hofman
Date: 2022-09-27 09:40:56 +0000 (Tue, 27 Sep 2022)
Log Message:
-----------
Keep track in serverinfo whether password is in the keychain. Save password in
keychain when not after editing, or when using a dictionary value or URL
representation. Implement URL method in serverinfo class.
Modified Paths:
--------------
trunk/bibdesk/BDSKGroup+Scripting.m
trunk/bibdesk/BDSKSearchGroup.h
trunk/bibdesk/BDSKSearchGroup.m
trunk/bibdesk/BDSKSearchGroupServerManager.m
trunk/bibdesk/BDSKSearchGroupSheetController.m
trunk/bibdesk/BDSKServerInfo.h
trunk/bibdesk/BDSKServerInfo.m
trunk/bibdesk/BibDocument_Groups.m
Modified: trunk/bibdesk/BDSKGroup+Scripting.m
===================================================================
--- trunk/bibdesk/BDSKGroup+Scripting.m 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BDSKGroup+Scripting.m 2022-09-27 09:40:56 UTC (rev 27942)
@@ -576,7 +576,7 @@
}
- (NSString *)scriptingURL {
- return [[self bdsksearchURL] absoluteString];
+ return [[[self serverInfo] URLValue] absoluteString];
}
@end
Modified: trunk/bibdesk/BDSKSearchGroup.h
===================================================================
--- trunk/bibdesk/BDSKSearchGroup.h 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BDSKSearchGroup.h 2022-09-27 09:40:56 UTC (rev 27942)
@@ -91,8 +91,6 @@
@property (nonatomic, readonly) NSFormatter *searchStringFormatter;
-@property (nonatomic, readonly) NSURL *bdsksearchURL;
-
+ (NSDictionary *)dictionaryWithBdsksearchURL:(NSURL *)bdsksearchURL;
+ (id<BDSKSearchGroupServer>)copyServerWithGroup:(id<BDSKSearchGroup>)group
serverInfo:(BDSKServerInfo *)info;
Modified: trunk/bibdesk/BDSKSearchGroup.m
===================================================================
--- trunk/bibdesk/BDSKSearchGroup.m 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BDSKSearchGroup.m 2022-09-27 09:40:56 UTC (rev 27942)
@@ -63,7 +63,7 @@
@implementation BDSKSearchGroup
-@dynamic type, serverInfo, searchTerm, history, numberOfAvailableResults,
errorMessage, hasMoreResults, searchStringFormatter, bdsksearchURL;
+@dynamic type, serverInfo, searchTerm, history, numberOfAvailableResults,
errorMessage, hasMoreResults, searchStringFormatter;
+ (void)initialize {
BDSKINITIALIZE;
@@ -108,8 +108,7 @@
- (id)initWithDictionary:(NSDictionary *)groupDict {
NSString *aSearchTerm = [groupDict objectForKey:@"search term"];
NSArray *aHistory = [groupDict objectForKey:@"history"];
- // use BDSKMutableServerInfo, so the password will be save in the keychain
- BDSKServerInfo *serverInfo = [[BDSKMutableServerInfo alloc]
initWithDictionary:groupDict];
+ BDSKServerInfo *serverInfo = [[BDSKServerInfo alloc]
initWithDictionary:groupDict];
self = [self initWithServerInfo:serverInfo searchTerm:aSearchTerm];
if (self) {
@@ -316,62 +315,6 @@
return [server numberOfAvailableResults] > [server numberOfFetchedResults];
}
-static inline NSString *escapeUser(NSString *string) {
- return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLUserAllowedCharacterSet]];
-}
-
-static inline NSString *escapePassword(NSString *string) {
- return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLPasswordAllowedCharacterSet]];
-}
-
-static inline NSString *escapeHost(NSString *string) {
- return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLHostAllowedCharacterSet]];
-}
-
-static NSString *escapeDatabaseOrName(NSString *string) {
- static NSCharacterSet *URLDatabaseOrNameAllowedCharacterSet = nil;
- if (URLDatabaseOrNameAllowedCharacterSet == nil) {
- NSMutableCharacterSet *tmpSet = [[NSCharacterSet
URLPathAllowedCharacterSet] mutableCopy];
- [tmpSet removeCharactersInString:@"/"];
- URLDatabaseOrNameAllowedCharacterSet = [tmpSet copy];
- [tmpSet release];
- }
- return [string
stringByAddingPercentEncodingWithAllowedCharacters:URLDatabaseOrNameAllowedCharacterSet];
-}
-
-- (NSURL *)bdsksearchURL {
- NSURLComponents *components = [[NSURLComponents alloc] init];
- [components setScheme:BDSKSearchGroupURLScheme];
- BDSKServerInfo *serverInfo = [self serverInfo];
- NSString *username = [serverInfo username];
- if (username)
- [components setPercentEncodedUser:escapeUser(username)];
- if ([serverInfo isZoom]) {
- [components setPercentEncodedHost:escapeHost([serverInfo host])];
- [components setPort:[NSNumber numberWithInteger:[[serverInfo port]
integerValue]]];
- } else {
- [components setPercentEncodedHost:[serverInfo type]];
- }
- [components setPercentEncodedPath:[NSString stringWithFormat:@"/%@;%@",
escapeDatabaseOrName([serverInfo database]), escapeDatabaseOrName([serverInfo
name])]];
- if ([serverInfo isZoom]) {
- NSMutableArray *query = [NSMutableArray array];
- [[serverInfo options] enumerateKeysAndObjectsUsingBlock:^(NSString
*key, NSString *value, BOOL *stop){
- if ([key isEqualToString:@"removeDiacritics"])
- value = [serverInfo removeDiacritics] ? @"1" : @"0";
- else if ([key isEqualToString:@"username"] || [key
isEqualToString:@"password"])
- return;
- [query addObject:[NSString stringWithFormat:@"%@=%@", key, [value
stringByAddingPercentEscapesForQueryTerm]]];
- }];
- if ([query count])
- [components setPercentEncodedQuery:[query
componentsJoinedByString:@"&"]];
- } else if ([serverInfo isISI] && [serverInfo isLite]) {
- [components setPercentEncodedQuery:@"lite=1"];
- }
- NSURL *url = [components URL];
- [components release];
- return url;
-}
-
#pragma mark NSPasteboardItemDataProvider
- (void)pasteboard:(NSPasteboard *)pboard item:(NSPasteboardItem *)item
provideDataForType:(NSString *)type {
Modified: trunk/bibdesk/BDSKSearchGroupServerManager.m
===================================================================
--- trunk/bibdesk/BDSKSearchGroupServerManager.m 2022-09-27 06:30:20 UTC
(rev 27941)
+++ trunk/bibdesk/BDSKSearchGroupServerManager.m 2022-09-27 09:40:56 UTC
(rev 27942)
@@ -166,18 +166,18 @@
- (void)addServer:(BDSKServerInfo *)serverInfo
{
- serverInfo = [[serverInfo copy] autorelease];
- [searchGroupServers addObject:serverInfo];
+ // this also makes sure any password is saved in the keychain
+ [self saveServerFile:serverInfo];
+ [searchGroupServers addObject:[[serverInfo copy] autorelease]];
[searchGroupServers sortUsingDescriptors:sortDescriptors];
- [self saveServerFile:serverInfo];
}
- (void)setServer:(BDSKServerInfo *)serverInfo atIndex:(NSUInteger)idx {
- serverInfo = [[serverInfo copy] autorelease];
+ // this also makes sure any password is saved in the keychain
+ [self saveServerFile:serverInfo];
[self deleteServerFile:[searchGroupServers objectAtIndex:idx]];
- [searchGroupServers replaceObjectAtIndex:idx withObject:serverInfo];
+ [searchGroupServers replaceObjectAtIndex:idx withObject:[[serverInfo copy]
autorelease]];
[searchGroupServers sortUsingDescriptors:sortDescriptors];
- [self saveServerFile:serverInfo];
}
- (void)removeServerAtIndex:(NSUInteger)idx {
Modified: trunk/bibdesk/BDSKSearchGroupSheetController.m
===================================================================
--- trunk/bibdesk/BDSKSearchGroupSheetController.m 2022-09-27 06:30:20 UTC
(rev 27941)
+++ trunk/bibdesk/BDSKSearchGroupSheetController.m 2022-09-27 09:40:56 UTC
(rev 27942)
@@ -166,9 +166,12 @@
#pragma mark Actions
- (IBAction)dismiss:(id)sender {
- if ([sender tag] == NSOKButton && [self commitEditing] == NO) {
- NSBeep();
- return;
+ if ([sender tag] == NSOKButton) {
+ if ([self commitEditing] == NO) {
+ NSBeep();
+ return;
+ }
+ [serverInfo savePasswordInKeychain];
}
[super dismiss:sender];
Modified: trunk/bibdesk/BDSKServerInfo.h
===================================================================
--- trunk/bibdesk/BDSKServerInfo.h 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BDSKServerInfo.h 2022-09-27 09:40:56 UTC (rev 27942)
@@ -52,6 +52,7 @@
NSString *host;
NSString *port;
NSMutableDictionary *options;
+ BOOL passwordInKeychain;
}
+ (id)defaultServerInfoWithType:(NSString *)aType;
@@ -83,9 +84,13 @@
@property (nonatomic, readonly) BDSKServerType serverType;
+@property (nonatomic, readonly) NSURL *URLValue;
+
// use this to get the password, as the accessor returns nil to deny access to
templating
- (BOOL)getUsername:(NSString **)username password:(NSString **)password;
+- (void)savePasswordInKeychain;
+
@end
@interface BDSKMutableServerInfo : BDSKServerInfo
Modified: trunk/bibdesk/BDSKServerInfo.m
===================================================================
--- trunk/bibdesk/BDSKServerInfo.m 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BDSKServerInfo.m 2022-09-27 09:40:56 UTC (rev 27942)
@@ -69,14 +69,10 @@
// Currently, anything other than zoom is expected to have just a type, name,
and database.
// Also when other validations are necessary, changing the type must make sure
that the data validates properly for the new type, if necessary adding missing
values.
-@interface BDSKMutableServerInfo ()
-- (void)savePasswordInKeychain;
-@end
-
@implementation BDSKServerInfo
@synthesize type, name, database;
-@dynamic dictionaryValue, host, port, password, username, recordSyntax,
resultEncoding, queryConfig, removeDiacritics, lite, options, entrez, zoom,
ISI, DBLP, serverType;
+@dynamic dictionaryValue, host, port, password, username, recordSyntax,
resultEncoding, queryConfig, removeDiacritics, lite, options, entrez, zoom,
ISI, DBLP, serverType, URLValue;
+ (BOOL)accessInstanceVariablesDirectly { return NO; }
@@ -92,7 +88,7 @@
options:isZoom ? [NSDictionary
dictionary] : nil] autorelease];
}
-- (id)initWithType:(NSString *)aType name:(NSString *)aName database:(NSString
*)aDbase host:(NSString *)aHost port:(NSString *)aPort options:(NSDictionary
*)opts;
+- (id)initWithType:(NSString *)aType name:(NSString *)aName database:(NSString
*)aDbase host:(NSString *)aHost port:(NSString *)aPort options:(NSDictionary
*)opts passwordInKeychain:(BOOL)flag;
{
self = [super init];
if (self) {
@@ -99,6 +95,7 @@
type = [aType copy];
name = [aName copy];
database = [aDbase copy];
+ passwordInKeychain = flag;
if ([self isEntrez] || [self isISI] || [self isDBLP]) {
host = nil;
port = nil;
@@ -115,6 +112,18 @@
return self;
}
+- (id)initWithType:(NSString *)aType name:(NSString *)aName database:(NSString
*)aDbase host:(NSString *)aHost port:(NSString *)aPort options:(NSDictionary
*)opts;
+{
+ self = [self initWithType:aType
+ name:aName
+ database:aDbase
+ host:aHost
+ port:aPort
+ options:opts
+ passwordInKeychain:NO];
+ return self;
+}
+
- (id)initWithDictionary:(NSDictionary *)info;
{
self = [self initWithType:[info objectForKey:TYPE_KEY]
@@ -122,20 +131,19 @@
database:[info objectForKey:DATABASE_KEY]
host:[info objectForKey:HOST_KEY]
port:[info objectForKey:PORT_KEY]
- options:[info objectForKey:OPTIONS_KEY]];
+ options:[info objectForKey:OPTIONS_KEY]
+ passwordInKeychain:NO];
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
- self = [super init];
- if (self) {
- type = [[decoder decodeObjectForKey:TYPE_KEY] retain];
- name = [[decoder decodeObjectForKey:NAME_KEY] retain];
- database = [[decoder decodeObjectForKey:DATABASE_KEY] retain];
- host = [[decoder decodeObjectForKey:HOST_KEY] retain];
- port = [[decoder decodeObjectForKey:PORT_KEY] retain];
- options = [[decoder decodeObjectForKey:OPTIONS_KEY] mutableCopy];
- }
+ self = [self initWithType:[decoder decodeObjectForKey:TYPE_KEY]
+ name:[decoder decodeObjectForKey:NAME_KEY]
+ database:[decoder decodeObjectForKey:DATABASE_KEY]
+ host:[decoder decodeObjectForKey:HOST_KEY]
+ port:[decoder decodeObjectForKey:PORT_KEY]
+ options:[decoder decodeObjectForKey:OPTIONS_KEY]
+ passwordInKeychain:NO];
return self;
}
@@ -149,12 +157,12 @@
}
- (id)copyWithZone:(NSZone *)aZone {
- id copy = [[BDSKServerInfo allocWithZone:aZone] initWithType:[self type]
name:[self name] database:[self database] host:[self host] port:[self port]
options:options];
+ id copy = [[BDSKServerInfo allocWithZone:aZone] initWithType:[self type]
name:[self name] database:[self database] host:[self host] port:[self port]
options:options passwordInKeychain:passwordInKeychain];
return copy;
}
- (id)mutableCopyWithZone:(NSZone *)aZone {
- id copy = [[BDSKMutableServerInfo allocWithZone:aZone] initWithType:[self
type] name:[self name] database:[self database] host:[self host] port:[self
port] options:options];
+ id copy = [[BDSKMutableServerInfo allocWithZone:aZone] initWithType:[self
type] name:[self name] database:[self database] host:[self host] port:[self
port] options:options passwordInKeychain:passwordInKeychain];
return copy;
}
@@ -208,6 +216,7 @@
}
- (NSDictionary *)dictionaryValue {
+ [self savePasswordInKeychain];
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithCapacity:7];
[info setValue:[self type] forKey:TYPE_KEY];
[info setValue:[self name] forKey:NAME_KEY];
@@ -285,7 +294,8 @@
return NO;
*password = [BDSKPasswordController
passwordForKeychainServer:server port:[[self port] integerValue] account:user];
if (*password == nil)
- return YES;
+ return NO;
+ passwordInKeychain = YES;
[options setObject:*password forKey:PASSWORD_KEY];
}
}
@@ -292,6 +302,77 @@
return YES;
}
+- (void)savePasswordInKeychain {
+ if (passwordInKeychain || [self isZoom] == NO && [self isISI] == NO)
+ return;
+ // don't get the password from the keychain
+ NSString *password = [options objectForKey:PASSWORD_KEY];
+ if (password == nil)
+ return;
+ NSString *account = [self username];
+ NSString *server = [self isISI] ? ISI_SERVER : [self host];
+ if (account == nil || server == nil)
+ return;
+ if ([BDSKPasswordController addOrModifyPassword:password
forKeychainServer:server port:[[self port] integerValue] account:account])
+ passwordInKeychain = YES;
+}
+
+static inline NSString *escapeUser(NSString *string) {
+ return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLUserAllowedCharacterSet]];
+}
+
+static inline NSString *escapePassword(NSString *string) {
+ return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLPasswordAllowedCharacterSet]];
+}
+
+static inline NSString *escapeHost(NSString *string) {
+ return [string
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet
URLHostAllowedCharacterSet]];
+}
+
+static NSString *escapeDatabaseOrName(NSString *string) {
+ static NSCharacterSet *URLDatabaseOrNameAllowedCharacterSet = nil;
+ if (URLDatabaseOrNameAllowedCharacterSet == nil) {
+ NSMutableCharacterSet *tmpSet = [[NSCharacterSet
URLPathAllowedCharacterSet] mutableCopy];
+ [tmpSet removeCharactersInString:@"/"];
+ URLDatabaseOrNameAllowedCharacterSet = [tmpSet copy];
+ [tmpSet release];
+ }
+ return [string
stringByAddingPercentEncodingWithAllowedCharacters:URLDatabaseOrNameAllowedCharacterSet];
+}
+
+- (NSURL *)URLValue {
+ [self savePasswordInKeychain];
+ NSURLComponents *components = [[NSURLComponents alloc] init];
+ [components setScheme:BDSKSearchGroupURLScheme];
+ NSString *username = [self username];
+ if (username)
+ [components setPercentEncodedUser:escapeUser(username)];
+ if ([self isZoom]) {
+ [components setPercentEncodedHost:escapeHost([self host])];
+ [components setPort:[NSNumber numberWithInteger:[[self port]
integerValue]]];
+ } else {
+ [components setPercentEncodedHost:[self type]];
+ }
+ [components setPercentEncodedPath:[NSString stringWithFormat:@"/%@;%@",
escapeDatabaseOrName([self database]), escapeDatabaseOrName([self name])]];
+ if ([self isZoom]) {
+ NSMutableArray *query = [NSMutableArray array];
+ [[self options] enumerateKeysAndObjectsUsingBlock:^(NSString *key,
NSString *value, BOOL *stop){
+ if ([key isEqualToString:@"removeDiacritics"])
+ value = [self removeDiacritics] ? @"1" : @"0";
+ else if ([key isEqualToString:@"username"] || [key
isEqualToString:@"password"])
+ return;
+ [query addObject:[NSString stringWithFormat:@"%@=%@", key, [value
stringByAddingPercentEscapesForQueryTerm]]];
+ }];
+ if ([query count])
+ [components setPercentEncodedQuery:[query
componentsJoinedByString:@"&"]];
+ } else if ([self isISI] && [self isLite]) {
+ [components setPercentEncodedQuery:@"lite=1"];
+ }
+ NSURL *url = [components URL];
+ [components release];
+ return url;
+}
+
@end
@@ -321,16 +402,6 @@
return set;
}
-- (id)copyWithZone:(NSZone *)zone {
- [self savePasswordInKeychain];
- return [super copyWithZone:zone];
-}
-
-- (NSDictionary *)dictionaryValue {
- [self savePasswordInKeychain];
- return [super dictionaryValue];
-}
-
// When changing the type, all data must be properly updated to be valid,
taking into account the condition implict in the validation methods
- (void)setType:(NSString *)newType {
if ([type isEqualToString:newType] == NO) {
@@ -346,6 +417,7 @@
} else {
BDSKDESTROY(options);
}
+ passwordInKeychain = NO;
}
}
@@ -363,6 +435,8 @@
- (void)setHost:(NSString *)newHost;
{
+ if (passwordInKeychain && isEqualOrBothNil(host, newHost) == NO)
+ passwordInKeychain = NO;
[host autorelease];
host = [newHost copy];
}
@@ -369,6 +443,8 @@
- (void)setPort:(NSString *)newPort;
{
+ if (passwordInKeychain && isEqualOrBothNil(port, newPort) == NO)
+ passwordInKeychain = NO;
[port autorelease];
port = [newPort copy];
}
@@ -394,6 +470,8 @@
- (void)setUsername:(NSString *)newUser;
{
+ if (passwordInKeychain && isEqualOrBothNil([self username], newUser) == NO)
+ passwordInKeychain = NO;
[self setOptionValue:newUser forKey:USERNAME_KEY];
}
@@ -469,18 +547,4 @@
return isValid;
}
-- (void)savePasswordInKeychain {
- if ([self isZoom] == NO && [self isISI] == NO)
- return;
- // don't get the password from the keychain
- NSString *password = [options objectForKey:PASSWORD_KEY];
- if (password == nil)
- return;
- NSString *account = [self username];
- NSString *server = [self isISI] ? ISI_SERVER : [self host];
- if (account == nil || server == nil)
- return;
- [BDSKPasswordController addOrModifyPassword:password
forKeychainServer:server port:[[self port] integerValue] account:account];
-}
-
@end
Modified: trunk/bibdesk/BibDocument_Groups.m
===================================================================
--- trunk/bibdesk/BibDocument_Groups.m 2022-09-27 06:30:20 UTC (rev 27941)
+++ trunk/bibdesk/BibDocument_Groups.m 2022-09-27 09:40:56 UTC (rev 27942)
@@ -1161,7 +1161,7 @@
return;
}
if ([group groupType] == BDSKSearchGroupType) {
- url = [(BDSKSearchGroup *)group bdsksearchURL];
+ url = [[(BDSKSearchGroup *)group serverInfo] URLValue];
title = [[(BDSKSearchGroup *)group serverInfo] name];
} else if ([group groupType] == BDSKURLGroupType) {
url = [(BDSKURLGroup *)group URL];
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit