Revision: 29245 http://sourceforge.net/p/bibdesk/svn/29245 Author: hofman Date: 2025-04-30 14:56:23 +0000 (Wed, 30 Apr 2025) Log Message: ----------- Use POST for SRU server, so we don't have a limit on the search term
Modified Paths: -------------- trunk/bibdesk/BDSKSRUGroupServer.m Modified: trunk/bibdesk/BDSKSRUGroupServer.m =================================================================== --- trunk/bibdesk/BDSKSRUGroupServer.m 2025-04-29 14:17:40 UTC (rev 29244) +++ trunk/bibdesk/BDSKSRUGroupServer.m 2025-04-30 14:56:23 UTC (rev 29245) @@ -65,8 +65,6 @@ - (void)resetSearch; - (void)fetch; -- (void)startDownloadFromURL:(NSURL *)theURL; - @end #pragma mark - @@ -106,29 +104,40 @@ return nil; } -#pragma mark URLs +#pragma mark URL requests -- (NSURLComponents *)baseURLComponents { +static inline NSString *escapeHost(NSString *string) { + return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; +} + +- (NSURL *)serverURL { NSString *host = [[[self serverInfo] host] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; NSInteger port = [[[self serverInfo] port] integerValue]; NSString *database = [[[self serverInfo] database] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]; NSURLComponents *components = [[NSURLComponents alloc] init]; [components setScheme:[[self serverInfo] isSecure] ? @"https" : @"http"]; - [components setPercentEncodedHost:host]; + [components setPercentEncodedHost:escapeHost(host)]; if (port > 0) [components setPort:[NSNumber numberWithInteger:port]]; [components setPercentEncodedPath:[@"/" stringByAppendingString:database]]; - return components; + return [components URL]; } -- (NSURL *)searchURLWithRange:(NSRange)range { - NSURLComponents *components = [self baseURLComponents]; +// because wwe use POST, we only need to escape &, as that can be confused with the separator +static NSString *escapeQueryTerm(NSString *string) { + static NSCharacterSet *URLQueryAllowedCharacterSet = nil; + if (URLQueryAllowedCharacterSet == nil) + URLQueryAllowedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"&"] invertedSet]; + return [string stringByAddingPercentEncodingWithAllowedCharacters:URLQueryAllowedCharacterSet]; +} + +- (NSString *)searchQueryWithRange:(NSRange)range { NSMutableArray *query = [NSMutableArray array]; NSString *version = [[[self serverInfo] options] objectForKey:@"version"] ?: @"1.1"; NSString *syntax = [[self class] normalizedRecordSyntax:[[[self serverInfo] options] objectForKey:@"recordSyntax"]]; [query addObject:[@"version=" stringByAppendingString:version]]; [query addObject:@"operation=searchRetrieve"]; - [query addObject:[@"query=" stringByAppendingString:[[self searchTerm] stringByAddingPercentEscapesForQueryTerm]]]; + [query addObject:[@"query=" stringByAppendingString:escapeQueryTerm([self searchTerm])]]; if (syntax) [query addObject:[@"recordSchema=" stringByAppendingString:syntax]]; if (range.length > 0) { @@ -135,10 +144,19 @@ [query addObject:[NSString stringWithFormat:@"startRecord=%lu", 1 + range.location]]; [query addObject:[NSString stringWithFormat:@"maximumRecords=%lu", range.length]]; } - [components setPercentEncodedQuery:[query componentsJoinedByString:@"&"]]; - return [components URL]; + return [query componentsJoinedByString:@"&"]; } +- (void)startDownloadForRange:(NSRange)range { + NSString *query = [self searchQueryWithRange:range]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self serverURL]]; + [request setHTTPMethod:@"POST"]; + [request setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-type"]; + [request setHTTPBody:[query dataUsingEncoding:NSUTF8StringEncoding]]; + [download cancel]; + download = [[BDSKDownloader sharedDownloader] startDataDownloadWithRequest:request delegate:self]; +} + #pragma mark BDSKSearchGroupServer protocol - (NSString *)type { return BDSKSearchGroupSRU; } @@ -157,7 +175,7 @@ } - (void)retrieveWithSearchTerm:(NSString *)aSearchTerm { - if ([[[self baseURLComponents] URL] canConnect]) { + if ([[self serverURL] canConnect]) { if ([[self searchTerm] isEqualToString:aSearchTerm] == NO || needsReset) { [self setSearchTerm:aSearchTerm]; [self resetSearch]; @@ -195,12 +213,8 @@ [self reset]; if (NO == [NSString isEmptyString:[self searchTerm]]) { - // get the initial XML document with our search parameters in it - NSURL *initialURL = [self searchURLWithRange:NSMakeRange(0, 0)]; - BDSKPRECONDITION(initialURL); - downloadState = BDSKSRUStateSearch; - [self startDownloadFromURL:initialURL]; + [self startDownloadForRange:NSMakeRange(0, 0)]; needsReset = NO; } } @@ -231,15 +245,12 @@ return; } - NSRange returnRange = NSMakeRange([self numberOfFetchedResults], MIN([self numberOfAvailableResults] - [self numberOfFetchedResults], MAX_RESULTS)); + requestedResults = MIN([self numberOfAvailableResults] - [self numberOfFetchedResults], MAX_RESULTS); - NSURL *theURL = [self searchURLWithRange:returnRange]; - BDSKPOSTCONDITION(theURL); + NSRange returnRange = NSMakeRange([self numberOfFetchedResults], requestedResults); - requestedResults = returnRange.length; - downloadState = BDSKSRUStateRetrieve; - [self startDownloadFromURL:theURL]; + [self startDownloadForRange:returnRange]; } #pragma mark Downloading @@ -350,10 +361,4 @@ return [group windowForSheetForObject:self]; } -- (void)startDownloadFromURL:(NSURL *)theURL { - NSURLRequest *request = [NSURLRequest requestWithURL:theURL]; - [download cancel]; - download = [[BDSKDownloader sharedDownloader] startDataDownloadWithRequest:request delegate:self]; -} - @end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Bibdesk-commit mailing list Bibdesk-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bibdesk-commit