diff --git a/ChangeLog b/ChangeLog index 0d78f9082..2e730e7e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-08-26 Richard Frith-Macdonald + + * Headers/Foundation/NSURL.h: + * Headers/Additions/GNUstepBase/GSCategories.h: + * Source/NSURL.m: + * Source/Additions/GSCategories.m: + Add new -fulPath method to do what -path used to do, because for OSX + compatibility the -path method now returns a path without any + trailing slash, making it impossible to reconsitute a URL string + from its individual parts :-( + * Source/GSHTTPURLHandle.m: + * Source/NSURLProtocol.m: + Use the new -fullPath method to build the request line sent to the + remote web server. + 2009-08-25 Richard Frith-Macdonald * Version: bump to 1.19.2 diff --git a/Headers/Additions/GNUstepBase/GSCategories.h b/Headers/Additions/GNUstepBase/GSCategories.h index d376de27d..51a47ac9e 100644 --- a/Headers/Additions/GNUstepBase/GSCategories.h +++ b/Headers/Additions/GNUstepBase/GSCategories.h @@ -331,6 +331,10 @@ typedef enum _NSGNUstepStringEncoding + (id)newLockAt:(id *)location; @end +@interface NSURL (GSCategories) +- (NSString*) fullPath; +@end + /* ------------------------------------------------------------------------ * Functions */ diff --git a/Headers/Foundation/NSURL.h b/Headers/Foundation/NSURL.h index eb753194f..22193861f 100644 --- a/Headers/Foundation/NSURL.h +++ b/Headers/Foundation/NSURL.h @@ -119,6 +119,12 @@ GS_EXPORT NSString* const NSURLFileScheme; #endif /* GS_API_MACOSX */ +@interface NSURL (GSCategories) +/** Returns the full path for this URL including any trailing slash. + */ +- (NSString*) fullPath; +@end + #if defined(__cplusplus) } #endif diff --git a/Source/Additions/GSCategories.m b/Source/Additions/GSCategories.m index 1ac7d9f18..38a0ecc2f 100644 --- a/Source/Additions/GSCategories.m +++ b/Source/Additions/GSCategories.m @@ -1606,3 +1606,25 @@ executablePath(NSFileManager *mgr, NSString *path) } @end +@implementation NSURL (GSCategories) +- (NSString*) fullPath +{ + NSRange r; + NSString *s; + + s = [self absoluteString]; + if ((r = [s rangeOfString: @";"]).length > 0) + { + s = [s substringFromIndex: r.location]; + } + else if ((r = [s rangeOfString: @"?"]).length > 0) + { + s = [s substringFromIndex: r.location]; + } + r = [s rangeOfString: @"//"]; + s = [s substringFromIndex: NSMaxRange(r)]; + r = [s rangeOfString: @"/"]; + s = [s substringFromIndex: r.location]; + return s; +} +@end diff --git a/Source/GSHTTPURLHandle.m b/Source/GSHTTPURLHandle.m index d5529a42b..aa00b951c 100644 --- a/Source/GSHTTPURLHandle.m +++ b/Source/GSHTTPURLHandle.m @@ -511,7 +511,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data) auth = [authentication authorizationForAuthentication: nil method: method - path: [u path]]; + path: [u fullPath]]; /* If authentication is nil then auth will also be nil */ if (auth != nil) @@ -728,7 +728,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data) auth = [authentication authorizationForAuthentication: ac method: method - path: [url path]]; + path: [url fullPath]]; if (auth != nil) { [self writeProperty: auth forKey: @"Authorization"]; @@ -900,7 +900,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data) if (debug) NSLog(@"%@ %p %s", NSStringFromSelector(_cmd), self, keepalive?"K":""); - path = [[u path] stringByTrimmingSpaces]; + path = [[u fullPath] stringByTrimmingSpaces]; if ([path length] == 0) { path = @"/"; @@ -1487,7 +1487,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data) method = @"GET"; } } - path = [[u path] stringByTrimmingSpaces]; + path = [[u fullPath] stringByTrimmingSpaces]; if ([path length] == 0) { path = @"/"; diff --git a/Source/NSURL.m b/Source/NSURL.m index 3a1ebad69..d27c773b3 100644 --- a/Source/NSURL.m +++ b/Source/NSURL.m @@ -1242,6 +1242,92 @@ static unsigned urlAlign; return fragment; } +- (char*) _path: (char*)buf +{ + char *ptr = buf; + char *tmp = buf; + + if (myData->pathIsAbsolute == YES) + { + if (myData->hasNoPath == NO) + { + *tmp++ = '/'; + } + strcpy(tmp, myData->path); + } + else if (_baseURL == nil) + { + strcpy(tmp, myData->path); + } + else if (*myData->path == 0) + { + if (baseData->hasNoPath == NO) + { + *tmp++ = '/'; + } + strcpy(tmp, baseData->path); + } + else + { + char *start = baseData->path; + char *end = strrchr(start, '/'); + + if (end != 0) + { + *tmp++ = '/'; + strncpy(tmp, start, end - start); + tmp += end - start; + } + *tmp++ = '/'; + strcpy(tmp, myData->path); + } + + unescape(buf, buf); + +#if defined(__MINGW32__) + /* On windows a file URL path may be of the form C:\xxx (ie we should + * not insert the leading slash). + * Also the vertical bar symbol may have been used instead of the + * colon, so we need to convert that. + */ + if (myData->isFile == YES) + { + if (ptr[1] && isalpha(ptr[1])) + { + if (ptr[2] == ':' || ptr[2] == '|') + { + if (ptr[3] == '\0' || ptr[3] == '/' || ptr[3] == '\\') + { + ptr[2] = ':'; + ptr++; + } + } + } + } +#endif + return ptr; +} + +- (NSString*) fullPath +{ + NSString *path = nil; + + /* + * If this scheme is from a URL without generic format, there is no path. + */ + if (myData->isGeneric == YES) + { + unsigned int len = (_baseURL ? strlen(baseData->path) : 0) + + strlen(myData->path) + 3; + char buf[len]; + char *ptr; + + ptr = [self _path: buf]; + path = [NSString stringWithUTF8String: ptr]; + } + return path; +} + /** * Returns the host portion of the receiver or nil if there is no * host supplied in the URL.
@@ -1412,74 +1498,19 @@ static unsigned urlAlign; unsigned int len = (_baseURL ? strlen(baseData->path) : 0) + strlen(myData->path) + 3; char buf[len]; - char *ptr = buf; - char *tmp = buf; + char *ptr; + char *tmp; - if (myData->pathIsAbsolute == YES) - { - if (myData->hasNoPath == NO) - { - *tmp++ = '/'; - } - strcpy(tmp, myData->path); - } - else if (_baseURL == nil) - { - strcpy(tmp, myData->path); - } - else if (*myData->path == 0) - { - if (baseData->hasNoPath == NO) - { - *tmp++ = '/'; - } - strcpy(tmp, baseData->path); - } - else - { - char *start = baseData->path; - char *end = strrchr(start, '/'); + ptr = [self _path: buf]; - if (end != 0) - { - *tmp++ = '/'; - strncpy(tmp, start, end - start); - tmp += end - start; - } - *tmp++ = '/'; - strcpy(tmp, myData->path); - } - - unescape(buf, buf); /* Remove any trailing '/' from the path for MacOS-X compatibility. */ - tmp = buf + strlen(buf) - 1; - if (tmp > buf && *tmp == '/') + tmp = ptr + strlen(ptr) - 1; + if (tmp > ptr && *tmp == '/') { *tmp = '\0'; } -#if defined(__MINGW32__) - /* On windows a file URL path may be of the form C:\xxx (ie we should - * not insert the leading slash). - * Also the vertical bar symbol may have been used instead of the - * colon, so we need to convert that. - */ - if (myData->isFile == YES) - { - if (ptr[1] && isalpha(ptr[1])) - { - if (ptr[2] == ':' || ptr[2] == '|') - { - if (ptr[3] == '\0' || ptr[3] == '/' || ptr[3] == '\\') - { - ptr[2] = ':'; - ptr++; - } - } - } - } -#endif path = [NSString stringWithUTF8String: ptr]; } return path; diff --git a/Source/NSURLProtocol.m b/Source/NSURLProtocol.m index 490bb0d40..b0ad2d33c 100644 --- a/Source/NSURLProtocol.m +++ b/Source/NSURLProtocol.m @@ -614,7 +614,7 @@ static NSURLProtocol *placeholder = nil; /* Perform a redirect if the path is empty. * As per MacOs-X documentation. */ - if ([[[this->request URL] path] length] == 0) + if ([[[this->request URL] fullPath] length] == 0) { NSString *s = [[this->request URL] absoluteString]; NSURL *url; @@ -1058,7 +1058,7 @@ static NSURLProtocol *placeholder = nil; auth = [authentication authorizationForAuthentication: hdr method: [this->request HTTPMethod] - path: [url path]]; + path: [url fullPath]]; } if (auth == nil) @@ -1274,7 +1274,7 @@ static NSURLProtocol *placeholder = nil; [m appendString: [this->request HTTPMethod]]; [m appendString: @" "]; u = [this->request URL]; - s = [u path]; + s = [u fullPath]; if ([s hasPrefix: @"/"] == NO) { [m appendString: @"/"]; @@ -1692,7 +1692,7 @@ static NSURLProtocol *placeholder = nil; NSURLResponse *r; NSData *data = [NSData data]; // no data - // we could pass different content depending on the [url path] + // we could pass different content depending on the url path r = [[NSURLResponse alloc] initWithURL: [this->request URL] MIMEType: @"text/html" expectedContentLength: 0