From 4b86f1463c665f1d3510be07344993d12aecf149 Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 20 Jul 2005 14:51:39 +0000 Subject: [PATCH] moved etag support code to SOGoObject base class git-svn-id: http://svn.opengroupware.org/SOGo/trunk@851 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/SoObjects/SOGo/ChangeLog | 5 + SOGo/SoObjects/SOGo/SOGoContentObject.h | 1 - SOGo/SoObjects/SOGo/SOGoContentObject.m | 122 +---------------------- SOGo/SoObjects/SOGo/SOGoObject.h | 4 + SOGo/SoObjects/SOGo/SOGoObject.m | 124 ++++++++++++++++++++++++ SOGo/SoObjects/SOGo/Version | 2 +- 6 files changed, 135 insertions(+), 123 deletions(-) diff --git a/SOGo/SoObjects/SOGo/ChangeLog b/SOGo/SoObjects/SOGo/ChangeLog index abb58241..8658cf46 100644 --- a/SOGo/SoObjects/SOGo/ChangeLog +++ b/SOGo/SoObjects/SOGo/ChangeLog @@ -1,3 +1,8 @@ +2005-07-20 Helge Hess + + * SOGoContentObject.m: moved generic etag checking to SOGoObject (to + share implementation with Mailer) (v0.9.65) + 2005-07-19 Marcus Mueller * AgenorUserManager.m: properly implemented internet/intranet vacation diff --git a/SOGo/SoObjects/SOGo/SOGoContentObject.h b/SOGo/SoObjects/SOGo/SOGoContentObject.h index 1567063b..f4c2efe0 100644 --- a/SOGo/SoObjects/SOGo/SOGoContentObject.h +++ b/SOGo/SoObjects/SOGo/SOGoContentObject.h @@ -54,7 +54,6 @@ /* etag support */ - (id)davEntityTag; -- (NSException *)matchesRequestConditionInContext:(id)_ctx; /* message type */ diff --git a/SOGo/SoObjects/SOGo/SOGoContentObject.m b/SOGo/SoObjects/SOGo/SOGoContentObject.m index 10ae9f0c..193bb9d6 100644 --- a/SOGo/SoObjects/SOGo/SOGoContentObject.m +++ b/SOGo/SoObjects/SOGo/SOGoContentObject.m @@ -21,7 +21,6 @@ #include "SOGoContentObject.h" #include "SOGoFolder.h" -#include #include "common.h" #include @@ -31,14 +30,7 @@ @implementation SOGoContentObject -static BOOL kontactGroupDAV = YES; - -+ (void)initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - kontactGroupDAV = - [ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"] ? NO : YES; -} +// TODO: check superclass version - (void)dealloc { [self->content release]; @@ -258,118 +250,6 @@ static BOOL kontactGroupDAV = YES; return [folder versionOfContentWithName:[self nameInContainer]]; } -- (NSArray *)parseETagList:(NSString *)_c { - NSMutableArray *ma; - NSArray *etags; - unsigned i, count; - - if ([_c length] == 0) - return nil; - if ([_c isEqualToString:@"*"]) - return nil; - - etags = [_c componentsSeparatedByString:@","]; - count = [etags count]; - ma = [NSMutableArray arrayWithCapacity:count]; - for (i = 0; i < count; i++) { - NSString *etag; - - etag = [[etags objectAtIndex:i] stringByTrimmingSpaces]; - if ([etag hasPrefix:@"\""] && [etag hasSuffix:@"\""]) - etag = [etag substringWithRange:NSMakeRange(1, [etag length] - 2)]; - - if (etag != nil) [ma addObject:etag]; - } - return ma; -} - -- (NSException *)checkIfMatchCondition:(NSString *)_c inContext:(id)_ctx { - /* only run the request if one of the etags matches the resource etag */ - NSArray *etags; - NSString *etag; - - if ([_c isEqualToString:@"*"]) - /* to ensure that the resource exists! */ - return nil; - - if ((etags = [self parseETagList:_c]) == nil) - return nil; - if ([etags count] == 0) /* no etags to check for? */ - return nil; - - etag = [self davEntityTag]; - if ([etag length] == 0) /* has no etag, ignore */ - return nil; - - if ([etags containsObject:etag]) { - [self debugWithFormat:@"etag '%@' matches: %@", etag, - [etags componentsJoinedByString:@","]]; - return nil; /* one etag matches, so continue with request */ - } - - /* hack for Kontact 3.4 */ - - if (kontactGroupDAV) { - WEClientCapabilities *cc; - - cc = [[(WOContext *)_ctx request] clientCapabilities]; - if ([[cc userAgentType] isEqualToString:@"Konqueror"]) { - if ([cc majorVersion] == 3 && [cc minorVersion] == 4) { - [self logWithFormat: - @"WARNING: applying Kontact 3.4 GroupDAV hack" - @" - etag check is disabled!" - @" (can be enabled using 'ZSDisableKontact34GroupDAVHack')"]; - return nil; - } - } - } - - // TODO: we might want to return the davEntityTag in the response - [self debugWithFormat:@"etag '%@' does not match: %@", etag, - [etags componentsJoinedByString:@","]]; - return [NSException exceptionWithHTTPStatus:412 /* Precondition Failed */ - reason:@"Precondition Failed"]; -} - -- (NSException *)checkIfNoneMatchCondition:(NSString *)_c inContext:(id)_ctx { - /* - If one of the etags is still the same, we can ignore the request. - - Can be used for PUT to ensure that the object does not exist in the store - and for GET to retrieve the content only if if the etag changed. - */ -#if 0 - if ([_c isEqualToString:@"*"]) - return nil; - - if ((a = [self parseETagList:_c]) == nil) - return nil; -#else - [self logWithFormat:@"TODO: implement if-none-match for etag: '%@'", _c]; -#endif - return nil; -} - -- (NSException *)matchesRequestConditionInContext:(id)_ctx { - NSException *error; - WORequest *rq; - NSString *c; - - if ((rq = [(WOContext *)_ctx request]) == nil) - return nil; /* be tolerant - no request, no condition */ - - if ((c = [rq headerForKey:@"if-match"]) != nil) { - if ((error = [self checkIfMatchCondition:c inContext:_ctx]) != nil) - return error; - } - if ((c = [rq headerForKey:@"if-none-match"]) != nil) { - if ((error = [self checkIfNoneMatchCondition:c inContext:_ctx]) != nil) - return error; - } - - return nil; -} - /* WebDAV */ - (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name diff --git a/SOGo/SoObjects/SOGo/SOGoObject.h b/SOGo/SoObjects/SOGo/SOGoObject.h index f4d18b8f..f04ad573 100644 --- a/SOGo/SoObjects/SOGo/SOGoObject.h +++ b/SOGo/SoObjects/SOGo/SOGoObject.h @@ -71,6 +71,10 @@ - (NSException *)delete; - (id)GETAction:(id)_ctx; +/* etag support */ + +- (NSException *)matchesRequestConditionInContext:(id)_ctx; + /* description */ - (void)appendAttributesToDescription:(NSMutableString *)_ms; diff --git a/SOGo/SoObjects/SOGo/SOGoObject.m b/SOGo/SoObjects/SOGo/SOGoObject.m index 77fbf6a5..3bf55bea 100644 --- a/SOGo/SoObjects/SOGo/SOGoObject.m +++ b/SOGo/SoObjects/SOGo/SOGoObject.m @@ -21,6 +21,7 @@ #include "SOGoObject.h" #include "SOGoUserFolder.h" +#include #include #include "common.h" @@ -30,10 +31,19 @@ @implementation SOGoObject +static BOOL kontactGroupDAV = YES; + + (int)version { return 0; } ++ (void)initialize { + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + kontactGroupDAV = + [ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"] ? NO : YES; +} + - (BOOL)doesRetainContainer { return YES; } @@ -182,6 +192,120 @@ return r; } +/* etag support */ + +- (NSArray *)parseETagList:(NSString *)_c { + NSMutableArray *ma; + NSArray *etags; + unsigned i, count; + + if ([_c length] == 0) + return nil; + if ([_c isEqualToString:@"*"]) + return nil; + + etags = [_c componentsSeparatedByString:@","]; + count = [etags count]; + ma = [NSMutableArray arrayWithCapacity:count]; + for (i = 0; i < count; i++) { + NSString *etag; + + etag = [[etags objectAtIndex:i] stringByTrimmingSpaces]; + if ([etag hasPrefix:@"\""] && [etag hasSuffix:@"\""]) + etag = [etag substringWithRange:NSMakeRange(1, [etag length] - 2)]; + + if (etag != nil) [ma addObject:etag]; + } + return ma; +} + +- (NSException *)checkIfMatchCondition:(NSString *)_c inContext:(id)_ctx { + /* only run the request if one of the etags matches the resource etag */ + NSArray *etags; + NSString *etag; + + if ([_c isEqualToString:@"*"]) + /* to ensure that the resource exists! */ + return nil; + + if ((etags = [self parseETagList:_c]) == nil) + return nil; + if ([etags count] == 0) /* no etags to check for? */ + return nil; + + etag = [self davEntityTag]; + if ([etag length] == 0) /* has no etag, ignore */ + return nil; + + if ([etags containsObject:etag]) { + [self debugWithFormat:@"etag '%@' matches: %@", etag, + [etags componentsJoinedByString:@","]]; + return nil; /* one etag matches, so continue with request */ + } + + /* hack for Kontact 3.4 */ + + if (kontactGroupDAV) { + WEClientCapabilities *cc; + + cc = [[(WOContext *)_ctx request] clientCapabilities]; + if ([[cc userAgentType] isEqualToString:@"Konqueror"]) { + if ([cc majorVersion] == 3 && [cc minorVersion] == 4) { + [self logWithFormat: + @"WARNING: applying Kontact 3.4 GroupDAV hack" + @" - etag check is disabled!" + @" (can be enabled using 'ZSDisableKontact34GroupDAVHack')"]; + return nil; + } + } + } + + // TODO: we might want to return the davEntityTag in the response + [self debugWithFormat:@"etag '%@' does not match: %@", etag, + [etags componentsJoinedByString:@","]]; + return [NSException exceptionWithHTTPStatus:412 /* Precondition Failed */ + reason:@"Precondition Failed"]; +} + +- (NSException *)checkIfNoneMatchCondition:(NSString *)_c inContext:(id)_ctx { + /* + If one of the etags is still the same, we can ignore the request. + + Can be used for PUT to ensure that the object does not exist in the store + and for GET to retrieve the content only if if the etag changed. + */ +#if 0 + if ([_c isEqualToString:@"*"]) + return nil; + + if ((a = [self parseETagList:_c]) == nil) + return nil; +#else + [self logWithFormat:@"TODO: implement if-none-match for etag: '%@'", _c]; +#endif + return nil; +} + +- (NSException *)matchesRequestConditionInContext:(id)_ctx { + NSException *error; + WORequest *rq; + NSString *c; + + if ((rq = [(WOContext *)_ctx request]) == nil) + return nil; /* be tolerant - no request, no condition */ + + if ((c = [rq headerForKey:@"if-match"]) != nil) { + if ((error = [self checkIfMatchCondition:c inContext:_ctx]) != nil) + return error; + } + if ((c = [rq headerForKey:@"if-none-match"]) != nil) { + if ((error = [self checkIfNoneMatchCondition:c inContext:_ctx]) != nil) + return error; + } + + return nil; +} + /* description */ - (void)appendAttributesToDescription:(NSMutableString *)_ms { diff --git a/SOGo/SoObjects/SOGo/Version b/SOGo/SoObjects/SOGo/Version index cf0769b0..6313547e 100644 --- a/SOGo/SoObjects/SOGo/Version +++ b/SOGo/SoObjects/SOGo/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=64 +SUBMINOR_VERSION:=65 # v0.9.63 requires libNGiCal v4.5.54 # v0.9.60 requires libNGiCal v4.5.49 -- 2.39.5