On Sep 8, 2010, at 10:40, Christiaan Hofman wrote:
> On Sep 8, 2010, at 19:27, Christiaan Hofman wrote:
>>
>> 1. Apparently Apple has problems with the fragment separator in the URL (#).
>> Looking at our code, this used to work in the past because we explicitly
>> don't escape those, but somehow Apple has decided that it doesn't like them,
>> though it's a valid URI character. I don't know how that should be handled,
>> as escaping them would also be wrong.
>
> Correction, it does not seem to be related to the "#" character. It is really
> a problem in the way we try to escape special characters. Though I don't see
> why that actually should give a problem, because in the end we do escape
> them. Anyway, this should be fixed in tomorrow's nightly.
Unfortunately, this URL has multiple encoded # characters and one that's not
supposed to be encoded, which is gross. The real problem that the escaping
code is trying to solve is in dealing with partially-escaped URL strings, so
the call to CFURLCreateStringByReplacingPercentEscapes needs to be restored.
I'm pretty sure I filed a bug on this with Apple years ago, and the
documentation now includes an example doing exactly this with a DOI.
Here's a version that works with Themis' URL, although I haven't tested it
extensively:
+ (NSURL *)URLWithStringByNormalizingPercentEscapes:(NSString *)string
baseURL:(NSURL *)baseURL;
{
CFStringRef urlString = (CFStringRef)string;
if(BDIsEmptyString(urlString))
return nil;
CFAllocatorRef allocator = baseURL ? CFGetAllocator((CFURLRef)baseURL) :
CFAllocatorGetDefault();
/*
Some badly formed URLs come in with multiple # characters, but a URL can
only contain a single fragment.
Use the leftmost # to denote the fragment as CFURL does, and escape it
separately.
*/
NSRange fragmentRange = [string rangeOfString:@"#"];
CFStringRef fragmentString = NULL;
if (fragmentRange.location != NSNotFound &&
(NSUInteger)CFStringGetLength(urlString) > (fragmentRange.location + 1)) {
// skip the assumed fragment position
fragmentString = (CFStringRef)[string
substringFromIndex:(fragmentRange.location + 1)];
urlString = (CFStringRef)[string
substringToIndex:fragmentRange.location];
fragmentString = CFURLCreateStringByAddingPercentEscapes(allocator,
(CFStringRef)fragmentString, CFSTR(""), NULL, kCFStringEncodingUTF8);
// autorelease to deal with multiple exit points
fragmentString = (CFStringRef)[(id)fragmentString autorelease];
}
/*
Normalize the URL string to deal with partially escaped URLs.
CFURLCreateStringByAddingPercentEscapes
will replace % in existing percent escapes with a %25, which is the
percent character escape.
*/
CFStringRef unescapedString =
CFURLCreateStringByReplacingPercentEscapes(allocator, urlString, CFSTR(""));
if(unescapedString == NULL) return nil;
// we need to validate URL strings, as some DOI URL's contain characters
that need to be escaped
urlString = CFURLCreateStringByAddingPercentEscapes(allocator,
unescapedString, CFSTR(""), NULL, kCFStringEncodingUTF8);
CFRelease(unescapedString);
if (fragmentString) {
CFMutableStringRef finalString = CFStringCreateMutableCopy(allocator,
CFStringGetLength(urlString), urlString);
CFStringAppend(finalString, CFSTR("#"));
CFStringAppend(finalString, (CFStringRef)fragmentString);
CFRelease(urlString);
urlString = finalString;
}
CFURLRef theURL = CFURLCreateWithString(allocator, urlString,
(CFURLRef)baseURL);
CFRelease(urlString);
return [(NSURL *)theURL autorelease];
}
------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:
Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
_______________________________________________
Bibdesk-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-users