From 9fe535a1acb19bef31362719247d5c3243083b47 Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 25 Aug 2004 22:32:04 +0000 Subject: [PATCH] fixed to URL processing git-svn-id: http://svn.opengroupware.org/SOPE/trunk@58 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-core/NGExtensions/ChangeLog | 5 + .../NGExtensions/FdExt.subproj/NSURL+misc.m | 193 +++++++++++++----- .../NGExtensions/NGExtensions/NSURL+misc.h | 16 ++ sope-core/NGExtensions/Version | 2 +- 4 files changed, 166 insertions(+), 50 deletions(-) diff --git a/sope-core/NGExtensions/ChangeLog b/sope-core/NGExtensions/ChangeLog index 310abf01..5d6d971c 100644 --- a/sope-core/NGExtensions/ChangeLog +++ b/sope-core/NGExtensions/ChangeLog @@ -1,3 +1,8 @@ +2004-08-26 Helge Hess + + * FdExt.subproj/NSURL+misc.m: fixed some URL processing methods + (v4.3.108) + 2004-08-25 Marcus Mueller * NGCalendarDateRange.m: properly fixed intersectionDateRange: to not diff --git a/sope-core/NGExtensions/FdExt.subproj/NSURL+misc.m b/sope-core/NGExtensions/FdExt.subproj/NSURL+misc.m index fca96e8d..7870f2de 100644 --- a/sope-core/NGExtensions/FdExt.subproj/NSURL+misc.m +++ b/sope-core/NGExtensions/FdExt.subproj/NSURL+misc.m @@ -18,7 +18,6 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id$ #include "NSURL+misc.h" #include "common.h" @@ -86,8 +85,8 @@ static BOOL debugURLProcessing = NO; - (NSString *)stringValueRelativeToURL:(NSURL *)_base { /* Sample: - base: http://localhost:20000/dbd.woa/so/localhost/ self: http://localhost:20000/dbd.woa/so/localhost/Databases/A + base: http://localhost:20000/dbd.woa/so/localhost/ => Databases/A Note: on Panther Foundation the -path misses the trailing slash! @@ -145,7 +144,8 @@ static BOOL debugURLProcessing = NO; if (debugURLProcessing) { NSLog(@"%s: same namespace, but no direct relative (%@, base %@) => '%@'", - __PRETTY_FUNCTION__, self, _base, relPath); + __PRETTY_FUNCTION__, + [self absoluteString], [_base absoluteString], relPath); } return relPath; } @@ -217,32 +217,12 @@ static BOOL isEqual(id o1, id o2) { return @"/"; } - /* this is the same like the absoltute path, only without a leading "/" .. */ - return [p substringFromIndex:1]; + /* this is the same like the absolute path, only without a leading "/" .. */ + return [p characterAtIndex:0] == '/' ? [p substringFromIndex:1] : p; } -- (NSString *)urlPathRelativeToPath:(NSString *)_base { +static NSString *calcRelativePathOfChildURL(NSString *self, NSString *_base) { /* - This can be used for URLs in the same namespace. It should - never return an absolute path (it only does in error conditions). - */ - - if (_base == nil || [_base length] == 0) { - NSLog(@"%s: invalid base (nil or length 0), using absolute path '%@' ...", - __PRETTY_FUNCTION__, self); - return self; - } - - if ([_base isEqualToString:@"/"]) - return [self urlPathRelativeToRoot]; - if ([_base isEqualToString:self]) - return [self urlPathRelativeToSelf]; - - if (debugURLProcessing) - NSLog(@"%s: %@ relative to %@ ...", __PRETTY_FUNCTION__, self, _base); - - if ([self hasPrefix:_base]) { - /* the whole base URI is prefix of our URI: case a) b: "/a/b/c" @@ -259,19 +239,19 @@ static BOOL isEqual(id o1, id o2) { b=s is already catched above and s is guaranteed to be longer than b. - */ - unsigned blen; - NSString *result; + */ + unsigned blen; + NSString *result; - if (debugURLProcessing) + if (debugURLProcessing) NSLog(@"%s: has base as prefix ...", __PRETTY_FUNCTION__); - blen = [_base length]; + blen = [_base length]; - if ([_base characterAtIndex:(blen - 1)] == '/') { + if ([_base characterAtIndex:(blen - 1)] == '/') { /* last char of 'b' is '/' => case b) */ result = [self substringFromIndex:blen]; - } - else { + } + else { /* last char of 'b' is not a slash (either case a) or case c)), both are handled in the same way (search last / ...) @@ -288,23 +268,62 @@ static BOOL isEqual(id o1, id o2) { /* no we have case b) ... */ result = [self substringFromIndex:(r.location + 1)]; } - } - return result; } - else { - NSString *prefix; - unsigned plen; + return result; +} + +- (NSString *)commonDirPathPrefixWithString:(NSString *)_other { + // TODO: the implementation can probably be optimized a _LOT_ + /* eg "/home/images/" vs "/home/index.html" => "/home/", _not_ "/home/i" ! */ + NSString *s; + unsigned len; + NSRange r; + + if (_other == self) + return self; + + s = [self commonPrefixWithString:_other options:0]; + len = [s length]; + if (len == 0) + return s; + if ([s characterAtIndex:(len - 1)] == '/') + return s; + + r = [s rangeOfString:@"/" options:NSBackwardsSearch]; + if (r.length == 0) /* hm, can't happen? */ + return nil; + + return [s substringToIndex:(r.location + r.length)];; +} + +static +NSString *calcRelativePathOfNonChildURL(NSString *self, NSString *_base) { + unsigned numSlashes; + NSString *result; + NSString *prefix; + NSString *suffix; + unsigned plen; + + prefix = [self commonDirPathPrefixWithString:_base]; + plen = [prefix length]; + suffix = [self substringFromIndex:plen]; + numSlashes = 0; - prefix = [self commonPrefixWithString:_base options:0]; - plen = [prefix length]; + if (debugURLProcessing) { + NSLog(@"%s: does not have base as prefix, common '%@'\n" + @" self='%@'\n" + @" base='%@'\n" + @" suffix='%@'", + __PRETTY_FUNCTION__, prefix, self, _base, suffix); + } - if (plen == 0) { + if (plen == 0) { NSLog(@"%s: invalid strings, no common prefix ...: '%@' and '%@' !", __PRETTY_FUNCTION__, self, _base); return self; - } + } - if (plen == 1) { + if (plen == 1) { /* common prefix is root. That is, nothing in common: b: "/a/b" @@ -314,7 +333,11 @@ static BOOL isEqual(id o1, id o2) { b: "/a/b/" s: "/l" >: "../../l" + (number of slashes without root * "..", then the trailer?) */ + unsigned i, len; + + len = [_base length]; if ([prefix characterAtIndex:0] != '/') { NSLog(@"%s: invalid strings, common prefix '%@' is not '/': " @@ -322,14 +345,86 @@ static BOOL isEqual(id o1, id o2) { __PRETTY_FUNCTION__, self, _base, prefix); } - /* TODO: to be completed ... */ - return self; - } + for (i = 1 /* skip root */; i < len; i++) { + if ([_base characterAtIndex:i] == '/') + numSlashes++; + } + } + else { + /* + base: /dev/en/projects/bsd/index.html + self: /dev/en/macosx/ + => ../../macosx/ + */ + NSString *basesuffix; + unsigned i, len; + + basesuffix = [_base substringFromIndex:plen]; + len = [basesuffix length]; + + for (i = 0; i < len; i++) { + if ([basesuffix characterAtIndex:i] == '/') + numSlashes++; + } + } + + if (debugURLProcessing) + NSLog(@"%s: slashes: %d", __PRETTY_FUNCTION__, numSlashes); - /* TODO: to be completed ... */ + /* optimization for some depths */ + switch (numSlashes) { + case 0: /* no slashes in base: b:/a, s:/images/a => images/a */ + result = suffix; + break; + case 1: /* one slash in base: b:/a/, s:/images/a => ../images/a, etc */ + result = [@"../" stringByAppendingString:suffix]; + break; + case 2: result = [@"../../" stringByAppendingString:suffix]; break; + case 3: result = [@"../../../" stringByAppendingString:suffix]; break; + case 4: result = [@"../../../../" stringByAppendingString:suffix]; break; + case 5: result = [@"../../../../../" stringByAppendingString:suffix];break; + default: { + NSMutableString *ms; + unsigned i; + + ms = [NSMutableString stringWithCapacity:(numSlashes * 3)]; + for (i = 0; i < numSlashes; i++) + [ms appendString:@"../"]; + [ms appendString:suffix]; + result = ms; + break; + } } + if (debugURLProcessing) + NSLog(@"%s: => '%@'", __PRETTY_FUNCTION__, result); + return result; +} + +- (NSString *)urlPathRelativeToPath:(NSString *)_base { + /* + This can be used for URLs in the same namespace. It should + never return an absolute path (it only does in error conditions). + */ + // TODO: the implementation can probably be optimized a _LOT_ + + if (_base == nil || [_base length] == 0) { + NSLog(@"%s: invalid base (nil or length 0), using absolute path '%@' ...", + __PRETTY_FUNCTION__, self); + return self; + } + + if ([_base isEqualToString:@"/"]) + return [self urlPathRelativeToRoot]; + if ([_base isEqualToString:self]) + return [self urlPathRelativeToSelf]; + + if (debugURLProcessing) + NSLog(@"%s: %@ relative to %@ ...", __PRETTY_FUNCTION__, self, _base); + + if ([self hasPrefix:_base]) + return calcRelativePathOfChildURL(self, _base); - return self; + return calcRelativePathOfNonChildURL(self, _base); } @end /* NSString(URLPathProcessing) */ diff --git a/sope-core/NGExtensions/NGExtensions/NSURL+misc.h b/sope-core/NGExtensions/NGExtensions/NSURL+misc.h index 7e3a0415..8ad20a7f 100644 --- a/sope-core/NGExtensions/NGExtensions/NSURL+misc.h +++ b/sope-core/NGExtensions/NGExtensions/NSURL+misc.h @@ -51,8 +51,24 @@ /* relative path processing (should never return an absolute path) */ +/* + eg: "/a/b/c.html" + should resolve to: "c.html" + + Directories are a bit more difficult, eg: + "/a/b/c/" + is resolved to + "../c/" +*/ - (NSString *)urlPathRelativeToSelf; + +/* this is the same like the absolute path, only without a leading "/" .. */ - (NSString *)urlPathRelativeToRoot; + +/* + This can be used for URLs in the same namespace. It should + never return an absolute path (it only does in error conditions). +*/ - (NSString *)urlPathRelativeToPath:(NSString *)_base; @end diff --git a/sope-core/NGExtensions/Version b/sope-core/NGExtensions/Version index 33b1f960..78cd4928 100644 --- a/sope-core/NGExtensions/Version +++ b/sope-core/NGExtensions/Version @@ -1,5 +1,5 @@ # $Id$ -SUBMINOR_VERSION:=107 +SUBMINOR_VERSION:=108 # v4.2.72 requires libEOControl v4.2.39 -- 2.39.5