@@ -322,16 +322,20 @@ @selector(characterIsMember:), character)); } @end void -OFURIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet) +OFURIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet, + bool allowPercent) { void *pool = objc_autoreleasePoolPush(); - characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc] - initWithCharacterSet: characterSet] autorelease]; + if (allowPercent) + characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc] + initWithCharacterSet: characterSet] autorelease]; + else + characterSet = characterSet.invertedSet; if ([string indexOfCharacterFromSet: characterSet] != OFNotFound) @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); @@ -444,18 +448,18 @@ self->_percentEncodedPassword = [[OFString alloc] initWithUTF8String: colon + 1 length: length - (colon - UTF8String) - 1]; OFURIVerifyIsEscaped(self->_percentEncodedPassword, - [OFCharacterSet URIPasswordAllowedCharacterSet]); + [OFCharacterSet URIPasswordAllowedCharacterSet], true); } else self->_percentEncodedUser = [[OFString alloc] initWithUTF8String: UTF8String length: length]; OFURIVerifyIsEscaped(self->_percentEncodedUser, - [OFCharacterSet URIUserAllowedCharacterSet]); + [OFCharacterSet URIUserAllowedCharacterSet], true); } static void parseHostPort(OFURI *self, const char *UTF8String, size_t length) { @@ -497,11 +501,11 @@ UTF8String += length; length = 0; } OFURIVerifyIsEscaped(self->_percentEncodedHost, - [OFCharacterSet URIHostAllowedCharacterSet]); + [OFCharacterSet URIHostAllowedCharacterSet], true); } if (length == 0) return; @@ -557,11 +561,11 @@ *fragmentString = [OFString stringWithUTF8String: fragment + 1 length: length - (fragment - UTF8String) - 1]; OFURIVerifyIsEscaped(*fragmentString, - [OFCharacterSet URIQueryAllowedCharacterSet]); + [OFCharacterSet URIQueryAllowedCharacterSet], true); length = fragment - UTF8String; } if ((query = memchr(UTF8String, '?', length)) != NULL) { @@ -568,20 +572,20 @@ *queryString = [OFString stringWithUTF8String: query + 1 length: length - (query - UTF8String) - 1]; OFURIVerifyIsEscaped(*queryString, - [OFCharacterSet URIFragmentAllowedCharacterSet]); + [OFCharacterSet URIFragmentAllowedCharacterSet], true); length = query - UTF8String; } *pathString = [OFString stringWithUTF8String: UTF8String length: length]; OFURIVerifyIsEscaped(*pathString, - [OFCharacterSet URIQueryAllowedCharacterSet]); + [OFCharacterSet URIQueryAllowedCharacterSet], true); } - (instancetype)initWithString: (OFString *)string { self = [super init]; @@ -595,17 +599,16 @@ if ((colon = strchr(UTF8String, ':')) == NULL || colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0])) @throw [OFInvalidFormatException exception]; - _percentEncodedScheme = [[[OFString - stringWithUTF8String: UTF8String - length: colon - UTF8String] lowercaseString] - copy]; + _scheme = [[[OFString stringWithUTF8String: UTF8String + length: colon - UTF8String] + lowercaseString] copy]; - OFURIVerifyIsEscaped(_percentEncodedScheme, - [OFCharacterSet URISchemeAllowedCharacterSet]); + OFURIVerifyIsEscaped(_scheme, + [OFCharacterSet URISchemeAllowedCharacterSet], false); length -= colon - UTF8String + 1; UTF8String = colon + 1; if (length >= 2 && UTF8String[0] == '/' && @@ -712,11 +715,11 @@ const char *UTF8String = string.UTF8String; size_t length = string.UTF8StringLength; bool hasAuthority = false; OFString *path, *query = nil, *fragment = nil; - _percentEncodedScheme = [URI->_percentEncodedScheme copy]; + _scheme = [URI->_scheme copy]; if (length >= 2 && UTF8String[0] == '/' && UTF8String[1] == '/') { size_t authorityLength; @@ -818,11 +821,11 @@ _percentEncodedHost = [percentEncodedHost copy]; if (isDirectory && ![path hasSuffix: @"/"]) path = [path stringByAppendingString: @"/"]; - _percentEncodedScheme = @"file"; + _scheme = @"file"; _percentEncodedPath = [[path stringByAddingPercentEncodingWithAllowedCharacters: [OFCharacterSet URIPathAllowedCharacterSet]] copy]; objc_autoreleasePoolPop(pool); @@ -858,11 +861,11 @@ return self; } - (void)dealloc { - [_percentEncodedScheme release]; + [_scheme release]; [_percentEncodedHost release]; [_port release]; [_percentEncodedUser release]; [_percentEncodedPassword release]; [_percentEncodedPath release]; @@ -882,12 +885,11 @@ if (![object isKindOfClass: [OFURI class]]) return false; URI = object; - if (URI->_percentEncodedScheme != _percentEncodedScheme && - ![URI->_percentEncodedScheme isEqual: _percentEncodedScheme]) + if (URI->_scheme != _scheme && ![URI->_scheme isEqual: _scheme]) return false; if (URI->_percentEncodedHost != _percentEncodedHost && ![URI->_percentEncodedHost isEqual: _percentEncodedHost]) return false; if (URI->_port != _port && ![URI->_port isEqual: _port]) @@ -915,11 +917,11 @@ { unsigned long hash; OFHashInit(&hash); - OFHashAddHash(&hash, _percentEncodedScheme.hash); + OFHashAddHash(&hash, _scheme.hash); OFHashAddHash(&hash, _percentEncodedHost.hash); OFHashAddHash(&hash, _port.hash); OFHashAddHash(&hash, _percentEncodedUser.hash); OFHashAddHash(&hash, _percentEncodedPassword.hash); OFHashAddHash(&hash, _percentEncodedPath.hash); @@ -931,16 +933,11 @@ return hash; } - (OFString *)scheme { - return _percentEncodedScheme.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedScheme -{ - return _percentEncodedScheme; + return _scheme; } - (OFString *)host { if ([_percentEncodedHost hasPrefix: @"["] && @@ -999,11 +996,11 @@ - (OFArray *)pathComponents { void *pool = objc_autoreleasePoolPush(); #ifdef OF_HAVE_FILES - bool isFile = [_percentEncodedScheme isEqual: @"file"]; + bool isFile = [_scheme isEqual: @"file"]; #endif OFMutableArray *ret; size_t count; #ifdef OF_HAVE_FILES @@ -1152,11 +1149,11 @@ - (id)mutableCopy { OFURI *copy = [[OFMutableURI alloc] init]; @try { - copy->_percentEncodedScheme = [_percentEncodedScheme copy]; + copy->_scheme = [_scheme copy]; copy->_percentEncodedHost = [_percentEncodedHost copy]; copy->_port = [_port copy]; copy->_percentEncodedUser = [_percentEncodedUser copy]; copy->_percentEncodedPassword = [_percentEncodedPassword copy]; copy->_percentEncodedPath = [_percentEncodedPath copy]; @@ -1172,11 +1169,11 @@ - (OFString *)string { OFMutableString *ret = [OFMutableString string]; - [ret appendFormat: @"%@:", _percentEncodedScheme]; + [ret appendFormat: @"%@:", _scheme]; if (_percentEncodedHost != nil || _port != nil || _percentEncodedUser != nil || _percentEncodedPassword != nil) [ret appendString: @"//"]; @@ -1210,11 +1207,11 @@ - (OFString *)fileSystemRepresentation { void *pool = objc_autoreleasePoolPush(); OFString *path; - if (![_percentEncodedScheme isEqual: @"file"]) + if (![_scheme isEqual: @"file"]) @throw [OFInvalidArgumentException exception]; if (![_percentEncodedPath hasPrefix: @"/"]) @throw [OFInvalidFormatException exception];