+2005-07-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * SOGoContentObject.m: moved generic etag checking to SOGoObject (to
+ share implementation with Mailer) (v0.9.65)
+
2005-07-19 Marcus Mueller <znek@mulle-kybernetik.com>
* AgenorUserManager.m: properly implemented internet/intranet vacation
/* etag support */
- (id)davEntityTag;
-- (NSException *)matchesRequestConditionInContext:(id)_ctx;
/* message type */
#include "SOGoContentObject.h"
#include "SOGoFolder.h"
-#include <NGObjWeb/WEClientCapabilities.h>
#include "common.h"
#include <GDLContentStore/GCSFolder.h>
@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];
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
- (NSException *)delete;
- (id)GETAction:(id)_ctx;
+/* etag support */
+
+- (NSException *)matchesRequestConditionInContext:(id)_ctx;
+
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms;
#include "SOGoObject.h"
#include "SOGoUserFolder.h"
+#include <NGObjWeb/WEClientCapabilities.h>
#include <NGObjWeb/SoObject+SoDAV.h>
#include "common.h"
@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;
}
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 {
# version file
-SUBMINOR_VERSION:=64
+SUBMINOR_VERSION:=65
# v0.9.63 requires libNGiCal v4.5.54
# v0.9.60 requires libNGiCal v4.5.49