/* NSUrl.m - Class NSURL Copyright (C) 1999 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 This file is part of the GNUstep Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Note from Manuel Guesdon: * I've made some test to compare apple NSURL results and GNUstep NSURL results but as there this class is not very documented, some function may be incorrect * I've put 2 functions to make tests. You can add your own tests * Some functions are not implemented */ #include #include #include #include #include #include #include #include #include #include #include NSString* NSURLFileScheme=@"file"; NSString* NSURLPartKey_host=@"host"; NSString* NSURLPartKey_port=@"port"; NSString* NSURLPartKey_user=@"user"; NSString* NSURLPartKey_password=@"password"; NSString* NSURLPartKey_path=@"path"; NSString* NSURLPartKey_fragment=@"fragment"; NSString* NSURLPartKey_parameterString=@"parameterString"; NSString* NSURLPartKey_query=@"query"; //=================================================================================== @implementation NSURL //----------------------------------------------------------------------------------- +(id)fileURLWithPath:(NSString*)_path { return [[[NSURL alloc] initFileURLWithPath:_path] autorelease]; }; //----------------------------------------------------------------------------------- +(id)URLWithString:(NSString*)_urlString { return [[[NSURL alloc] initWithString:_urlString] autorelease]; }; //----------------------------------------------------------------------------------- +(id)URLWithString:(NSString*)_urlString relativeToURL:(NSURL*)_baseURL { return [[[NSURL alloc] initWithString:_urlString relativeToURL:_baseURL] autorelease]; }; //----------------------------------------------------------------------------------- -(id)initWithScheme:(NSString*)_scheme host:(NSString*)_host path:(NSString*)_path { NSString* _urlString=nil; if (_host) _urlString=[NSString stringWithFormat:@"%@://%@",_scheme,_host]; else _urlString=[NSString stringWithFormat:@"%@:",_scheme]; if (_path) _urlString=[_urlString stringByAppendingString:_path]; self=[self initWithString:_urlString]; return self; }; //----------------------------------------------------------------------------------- //Non Standard Function -(id)initWithScheme:(NSString*)_scheme host:(NSString*)_host port:(NSNumber*)_port path:(NSString*)_path { NSString* tmpHost=nil; if (_port) tmpHost=[NSString stringWithFormat:@"%@:%@",_host,_port]; else tmpHost=_host; self=[self initWithScheme:_scheme host:tmpHost path:_path]; return self; }; //----------------------------------------------------------------------------------- //Do a initWithScheme:NSFileScheme host:nil path:_path -(id)initFileURLWithPath:(NSString*)_path { self=[self initWithScheme:NSURLFileScheme host:nil path:_path]; return self; }; //----------------------------------------------------------------------------------- // urlString is escaped -(id)initWithString:(NSString*)_urlString { self=[self init]; ASSIGNCOPY(urlString,_urlString); return self; }; //----------------------------------------------------------------------------------- //urlString!=nil // urlString is escaped -(id)initWithString:(NSString*)_urlString relativeToURL:(NSURL*)_baseURL { self=[self init]; ASSIGNCOPY(urlString,_urlString); ASSIGNCOPY(baseURL,_baseURL); return self; }; //----------------------------------------------------------------------------------- -(void)dealloc { DESTROY(urlString); DESTROY(baseURL); [super dealloc]; } //----------------------------------------------------------------------------------- -(id)copyWithZone: (NSZone*)zone { if (NSShouldRetainWithZone(self, zone) == NO) return [[isa allocWithZone: zone] initWithString:urlString relativeToURL:baseURL]; else return [self retain]; }; //----------------------------------------------------------------------------------- -(void)encodeWithCoder:(NSCoder*)aCoder { [super encodeWithCoder: aCoder]; [aCoder encodeObject:urlString]; [aCoder encodeObject:baseURL]; //FIXME? clients ? }; //----------------------------------------------------------------------------------- -(id)initWithCoder: (NSCoder*)aCoder { self = [super initWithCoder: aCoder]; [aCoder decodeValueOfObjCType: @encode(id) at:&urlString]; [aCoder decodeValueOfObjCType: @encode(id) at:&baseURL]; //FIXME? clients ? return self; }; //----------------------------------------------------------------------------------- -(NSString*)description { NSString* dscr=urlString; if (baseURL) dscr=[dscr stringByAppendingFormat:@" -- %@",baseURL]; return dscr; }; //----------------------------------------------------------------------------------- // Non Standard Function -(NSString*)baseURLAbsolutePart { if (baseURL) { NSString* suffix=[baseURL path]; NSString* tmp=nil; if ([baseURL query]) suffix=[suffix stringByAppendingFormat:@"?%@",[baseURL query]]; // /test?aa=bb&cc=dd -- http://user:passwd@www.gnustep.org:80/apache // ==> http://user:passwd@www.gnustep.org:80/ tmp=[[baseURL absoluteString]stringWithoutSuffix:suffix]; // ==> http://user:passwd@www.gnustep.org:80 if ([tmp hasSuffix:@"/"]) tmp=[tmp stringWithoutSuffix:@"/"]; return tmp; } else return @""; }; //----------------------------------------------------------------------------------- -(NSString*)absoluteString { NSString* absString=nil; if (baseURL) { // /test?aa=bb&cc=dd -- http://user:passwd@www.gnustep.org:80/apache // ==> http://user:passwd@www.gnustep.org:80 absString=[self baseURLAbsolutePart]; if ([urlString hasPrefix:@"/"]) absString=[absString stringByAppendingString:urlString]; else absString=[absString stringByAppendingFormat:@"/%@",urlString]; } else absString=urlString; return absString; }; //----------------------------------------------------------------------------------- -(NSString*)relativeString { return urlString; }; //----------------------------------------------------------------------------------- -(NSURL*)baseURL { return baseURL; }; //----------------------------------------------------------------------------------- -(NSURL*)absoluteURL { if (!baseURL) return self; else return [NSURL URLWithString:[self absoluteString]]; }; //----------------------------------------------------------------------------------- -(NSString*)scheme { NSString* scheme=nil; NSString* absoluteString=[self absoluteString]; NSRange range=[absoluteString rangeOfString:@"://"]; if (range.length>0) scheme=[absoluteString substringToIndex:range.location]; return scheme; }; //----------------------------------------------------------------------------------- -(NSString*)resourceSpecifier { NSString* absoluteString=[self absoluteString]; NSRange range=[absoluteString rangeOfString:@"://"]; if (range.length>0) return [absoluteString substringFromIndex:range.location+1]; else return absoluteString; }; //----------------------------------------------------------------------------------- //Non Standard Function -(NSDictionary*)explode { NSMutableDictionary* elements=nil; NSString* resourceSpecifier=[self resourceSpecifier]; if ([resourceSpecifier hasPrefix:@"//"]) { int index=2; NSRange range; elements=[[NSMutableDictionary new] autorelease]; if (![[self scheme] isEqualToString:NSURLFileScheme]) { range=[resourceSpecifier rangeOfString:@"/" options:0 range:NSMakeRange(index,[resourceSpecifier length]-index)]; if (range.length>0) { NSString* userPasswordHostPort=[resourceSpecifier substringWithRange:NSMakeRange(index,range.location-index)]; NSString* userPassword=nil; NSString* hostPort=nil; index=range.location; range=[userPasswordHostPort rangeOfString:@"@"]; if (range.length>0) { if (range.location>0) userPassword=[userPasswordHostPort substringToIndex:range.location]; if (range.location+1<[userPasswordHostPort length]) hostPort=[userPasswordHostPort substringFromIndex:range.location+1]; } else hostPort=userPasswordHostPort; if (userPassword) { range=[userPassword rangeOfString:@":"]; if (range.length>0) { if (range.location>0) [elements setObject:[userPassword substringToIndex:range.location] forKey:NSURLPartKey_user]; if (range.location+1<[userPassword length]) [elements setObject:[userPassword substringFromIndex:range.location+1] forKey:NSURLPartKey_password]; } else [elements setObject:userPassword forKey:NSURLPartKey_user]; }; if (hostPort) { range=[hostPort rangeOfString:@":"]; if (range.length>0) { if (range.location>0) [elements setObject:[hostPort substringToIndex:range.location] forKey:NSURLPartKey_host]; if (range.location+1<[hostPort length]) [elements setObject:[NSNumber valueFromString: [hostPort substringFromIndex:range.location+1]] forKey:NSURLPartKey_port]; } else [elements setObject:hostPort forKey:NSURLPartKey_host]; }; }; } else index--; //To Take a / range=[resourceSpecifier rangeOfString:@"?" options:0 range:NSMakeRange(index,[resourceSpecifier length]-index)]; if (range.length>0) { if (range.location>0) [elements setObject:[resourceSpecifier substringWithRange:NSMakeRange(index,range.location-index)] forKey:NSURLPartKey_path]; if (range.location+1<[resourceSpecifier length]) [elements setObject:[resourceSpecifier substringFromIndex:range.location+1] forKey:NSURLPartKey_query]; } else [elements setObject:[resourceSpecifier substringFromIndex:index] forKey:NSURLPartKey_path]; } else { [NSException raise:NSGenericException format:@"'%@' is a bad URL",self]; }; return elements; }; //----------------------------------------------------------------------------------- -(NSString*)host { return [[self explode] objectForKey:NSURLPartKey_host]; }; //----------------------------------------------------------------------------------- -(NSNumber*)port; { return [[self explode] objectForKey:NSURLPartKey_port]; }; //----------------------------------------------------------------------------------- -(NSString*)user; { return [[self explode] objectForKey:NSURLPartKey_user]; }; //----------------------------------------------------------------------------------- -(NSString*)password; { return [[self explode] objectForKey:NSURLPartKey_password]; }; //----------------------------------------------------------------------------------- -(NSString*)path; { return [[self explode] objectForKey:NSURLPartKey_path]; }; //----------------------------------------------------------------------------------- -(NSString*)fragment; { return [[self explode] objectForKey:NSURLPartKey_fragment]; }; //----------------------------------------------------------------------------------- -(NSString*)parameterString; { return [[self explode] objectForKey:NSURLPartKey_parameterString]; }; //----------------------------------------------------------------------------------- -(NSString*)query; { return [[self explode] objectForKey:NSURLPartKey_query]; }; //----------------------------------------------------------------------------------- -(NSString*)relativePath { //FIXME? return [self path]; }; //----------------------------------------------------------------------------------- -(BOOL)isFileURL { return [[self scheme] isEqualToString:NSURLFileScheme]; }; //----------------------------------------------------------------------------------- -(NSURL*)standardizedURL { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void) URLHandle:(NSURLHandle*)sender resourceDataDidBecomeAvailable:(NSData*)newData { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)URLHandleResourceDidBeginLoading:(NSURLHandle*)sender { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)URLHandleResourceDidFinishLoading:(NSURLHandle*)sender { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)URLHandleResourceDidCancelLoading:(NSURLHandle*)sender { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void) URLHandle:(NSURLHandle*)sender resourceDidFailLoadingWithReason:(NSString*)reason { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- //FIXME: delete these fn when NSURL will be validated +(void)test { NSURL* url2; NSURL* url3; NSURL* url=[NSURL URLWithString:@"http://user:passwd@www.gnustep.org:80/apache"]; url2=[NSURL URLWithString:@"/test?aa=bb&cc=dd" relativeToURL:url]; url3=[NSURL URLWithString:@"test?aa=bb&cc=dd" relativeToURL:url]; NSLog(@"===url==="); [NSURL testPrint:url]; NSLog(@"===url2==="); [NSURL testPrint:url2]; NSLog(@"===url3==="); [NSURL testPrint:url3]; }; +(void)testPrint:(NSURL*)url { id _baseURL=nil; id _urlString=nil; void* _clients=0; GSGetInstanceVariable(url,@"baseURL",&_baseURL); GSGetInstanceVariable(url,@"urlString",&_urlString); GSGetInstanceVariable(url,@"clients",&_clients); NSLog(@"*BaseURL: %ld",(long)_baseURL); NSLog(@"*BaseURL: %@",[_baseURL description]); NSLog(@"*urlString: %@",_urlString); NSLog(@"*clients: %ld",(long)_clients); NSLog(@"*host: %@",[url host]); NSLog(@"*port: %@",[url port]); NSLog(@"*user: %@",[url user]); NSLog(@"*password: %@",[url password]); NSLog(@"*path: %@",[url path]); NSLog(@"*fragment: %@",[url fragment]); NSLog(@"*parameterString: %@",[url parameterString]); NSLog(@"*query: %@",[url query]); NSLog(@"*relativePath: %@",[url relativePath]); NSLog(@"*absoluteString: %@",[url absoluteString]); NSLog(@"*relativeString: %@",[url relativeString]); NSLog(@"*baseURL: %@",[[url baseURL] description]); NSLog(@"*absoluteURL: %@",[[url absoluteURL] description]); NSLog(@"*scheme: %@",[url scheme]); NSLog(@"*resourceSpecifier: %@",[url resourceSpecifier]); NSLog(@"*description: %@",[url description]); }; @end //=================================================================================== @implementation NSURL (NSURLLoading) //----------------------------------------------------------------------------------- -(NSData*)resourceDataUsingCache:(BOOL)shouldUseCache { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)loadResourceDataNotifyingClient:(id)client usingCache:(BOOL)shouldUseCache { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(NSURLHandle*)URLHandleUsingCache:(BOOL)shouldUseCache { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(BOOL)setResourceData:(NSData*)data { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(id)propertyForKey:(NSString*)propertyKey { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(BOOL)setProperty:(id)property forKey:(NSString*)propertyKey; { //FIXME [self notImplemented: _cmd]; }; @end //=================================================================================== @implementation NSObject (NSURLClient) //----------------------------------------------------------------------------------- -(void) URL:(NSURL*)sender resourceDataDidBecomeAvailable:(NSData*)newBytes { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)URLResourceDidFinishLoading:(NSURL*)sender { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void)URLResourceDidCancelLoading:(NSURL*)sender { //FIXME [self notImplemented: _cmd]; }; //----------------------------------------------------------------------------------- -(void) URL:(NSURL*)sender resourceDidFailLoadingWithReason:(NSString*)reason { //FIXME [self notImplemented: _cmd]; }; @end