2005-07-20 Helge Hess <helge.hess@opengroupware.org>
+ * v0.9.66
+
+ * SOGoContentObject.m: properly quote etag
+
+ * SOGoObject.m: changed to check etag when the content is accessed in
+ WebDAV mode and return a 304 if the tag stayed the same.
+ Do not strip quotes from etags in if-*match headers.
+ Properly implement if-none-match for GET requests.
+
* SOGoContentObject.m: moved generic etag checking to SOGoObject (to
share implementation with Mailer) (v0.9.65)
- (id)davEntityTag {
// TODO: cache tag in ivar? => if you do, remember to flush after PUT
GCSFolder *folder;
+ char buf[64];
if ((folder = [self ocsFolder]) == nil) {
[self errorWithFormat:@"Did not find folder of content object."];
return nil;
}
- return [folder versionOfContentWithName:[self nameInContainer]];
+ sprintf(buf, "\"gcs%08d\"",
+ [[folder versionOfContentWithName:[self nameInContainer]]
+ unsignedIntValue]);
+ return [NSString stringWithCString:buf];
}
/* WebDAV */
// default method)
WORequest *rq;
WOResponse *r;
- NSString *uri;
+ NSString *uri;
r = [(WOContext *)_ctx response];
rq = [(WOContext *)_ctx request];
if ([rq isSoWebDAVRequest]) {
if ([self respondsToSelector:@selector(contentAsString)]) {
+ NSException *error;
id etag;
+ if ((error = [self matchesRequestConditionInContext:_ctx]) != nil)
+ return error;
+
[r appendContentString:[self contentAsString]];
if ((etag = [self davEntityTag]) != nil)
NSString *etag;
etag = [[etags objectAtIndex:i] stringByTrimmingSpaces];
+#if 0 /* this is non-sense, right? */
if ([etag hasPrefix:@"\""] && [etag hasSuffix:@"\""])
etag = [etag substringWithRange:NSMakeRange(1, [etag length] - 2)];
+#endif
if (etag != nil) [ma addObject:etag];
}
}
- (NSException *)checkIfMatchCondition:(NSString *)_c inContext:(id)_ctx {
- /* only run the request if one of the etags matches the resource etag */
+ /*
+ Only run the request if one of the etags matches the resource etag,
+ usually used to ensure consistent PUTs.
+ */
NSArray *etags;
NSString *etag;
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 (![_c isEqualToString:@"*"] &&
+ [[[_ctx request] method] isEqualToString:@"GET"]) {
+ NSString *etag;
+ NSArray *etags;
+
+ 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;
+
+ [self logWithFormat:@"CHECK %@ vs %@", etag, etags];
+
+ if ([etags containsObject:etag]) {
+ [self logWithFormat:@"etag '%@' matches: %@", etag,
+ [etags componentsJoinedByString:@","]];
+ /* one etag matches, so stop the request */
+ return [NSException exceptionWithHTTPStatus:304 /* Not Modified */
+ reason:@"object was not modified"];
+ }
+
+ return nil;
+ }
+
#if 0
if ([_c isEqualToString:@"*"])
return nil;