2005-07-20 Helge Hess <helge.hess@opengroupware.org>
+ * v0.9.115
+
+ * SOGoMailObject.m: do not use clientObject when fetching the
+ coreinfos, added a -doesMailExist method to cheaply check for
+ mail existance
+
+ * SOGoMailBodyPart.m, SOGoMailObject.m: added a constant etag for
+ content (possible for IMAP4 content), check etag prior delivering
+ content (return a 304 in case the constant etag is supplied)
+
* SOGoMailObject.m: added handling for some specific headers (v0.9.114)
2005-07-19 Helge Hess <helge.hess@opengroupware.org>
# compilation settings
+
+ADDITIONAL_CPPFLAGS += \
+ -Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \
+ -DUIX_MAILER_MAJOR_VERSION=$(MAJOR_VERSION) \
+ -DUIX_MAILER_MINOR_VERSION=$(MINOR_VERSION) \
+ -DUIX_MAILER_SUBMINOR_VERSION=$(SUBMINOR_VERSION)
@implementation SOGoMailBodyPart
+static NSString *mailETag = nil;
static BOOL debugOn = NO;
+ (int)version {
NSAssert2([super version] == 1,
@"invalid superclass (%@) version %i !",
NSStringFromClass([self superclass]), [super version]);
+
+ mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"",
+ UIX_MAILER_MAJOR_VERSION,
+ UIX_MAILER_MINOR_VERSION,
+ UIX_MAILER_SUBMINOR_VERSION];
+ NSLog(@"Note: using constant etag for mail parts: '%@'", mailETag);
}
- (void)dealloc {
/* actions */
- (id)GETAction:(id)_ctx {
+ NSException *error;
WOResponse *r;
NSData *data;
+ NSString *etag;
+ if ((error = [self matchesRequestConditionInContext:_ctx]) != nil) {
+ // TODO: currently we fetch the body structure to get here - check this!
+ /* check whether the mail still exists */
+ if (![[self mailObject] doesMailExist]) {
+ return [NSException exceptionWithHTTPStatus:404 /* Not Found */
+ reason:@"mail was deleted"];
+ }
+ return error; /* return 304 or 416 */
+ }
+
[self debugWithFormat:@"should fetch body part: %@",
[self bodyPartIdentifier]];
[r setHeader:[self davContentType] forKey:@"content-type"];
[r setHeader:[NSString stringWithFormat:@"%d", [data length]]
forKey:@"content-length"];
+
+ if ((etag = [self davEntityTag]) != nil)
+ [r setHeader:etag forKey:@"etag"];
+
[r setContent:data];
return r;
}
return self;
}
+/* etag support */
+
+- (id)davEntityTag {
+ return mailETag;
+}
+
/* debugging */
- (BOOL)isDebuggingEnabled {
/* core infos */
+- (BOOL)doesMailExist;
- (id)fetchCoreInfos; // TODO: what does it do?
- (NGImap4Envelope *)envelope;
/* core infos */
+- (BOOL)doesMailExist {
+ static NSArray *existsKey = nil;
+ id msgs;
+
+ if (existsKey == nil) /* we use size, other suggestions? */
+ existsKey = [[NSArray alloc] initWithObjects:@"RFC822.SIZE", nil];
+
+ msgs = [self fetchParts:existsKey]; // returns dict
+ msgs = [msgs valueForKey:@"fetch"];
+ return [msgs count] > 0 ? YES : NO;
+}
+
- (id)fetchCoreInfos {
id msgs;
if (self->coreInfos != nil)
return [self->coreInfos isNotNull] ? self->coreInfos : nil;
-
+
+#if 0 // TODO: old code, why was it using clientObject??
msgs = [[self clientObject] fetchParts:coreInfoKeys]; // returns dict
+#else
+ msgs = [self fetchParts:coreInfoKeys]; // returns dict
+#endif
if (heavyDebug) [self logWithFormat:@"M: %@", msgs];
msgs = [msgs valueForKey:@"fetch"];
if ([msgs count] == 0)
/* actions */
- (id)GETAction:(id)_ctx {
- WOResponse *r;
- NSData *content;
+ NSException *error;
+ WOResponse *r;
+ NSData *content;
+
+ if ((error = [self matchesRequestConditionInContext:_ctx]) != nil) {
+ /* check whether the mail still exists */
+ if (![self doesMailExist]) {
+ return [NSException exceptionWithHTTPStatus:404 /* Not Found */
+ reason:@"mail was deleted"];
+ }
+ return error; /* return 304 or 416 */
+ }
content = [self content];
if ([content isKindOfClass:[NSException class]])
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:@","]];
+ [self debugWithFormat:@"etag '%@' matches: %@", etag,
+ [etags componentsJoinedByString:@","]];
/* one etag matches, so stop the request */
return [NSException exceptionWithHTTPStatus:304 /* Not Modified */
reason:@"object was not modified"];