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

Reply via email to