From 7bb15d035264c105f7bd01b0e62cfbaa529f1072 Mon Sep 17 00:00:00 2001 From: helge Date: Sun, 3 Oct 2004 23:06:37 +0000 Subject: [PATCH] body part fetching git-svn-id: http://svn.opengroupware.org/SOGo/trunk@351 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/SoObjects/Mailer/ChangeLog | 3 + SOGo/SoObjects/Mailer/SOGoMailBodyPart.h | 10 +++ SOGo/SoObjects/Mailer/SOGoMailBodyPart.m | 110 ++++++++++++++++++----- SOGo/SoObjects/Mailer/SOGoMailObject.h | 2 + SOGo/SoObjects/Mailer/SOGoMailObject.m | 27 ++++++ SOGo/SoObjects/Mailer/Version | 2 +- 6 files changed, 132 insertions(+), 22 deletions(-) diff --git a/SOGo/SoObjects/Mailer/ChangeLog b/SOGo/SoObjects/Mailer/ChangeLog index 07a7a049..ab7fbe12 100644 --- a/SOGo/SoObjects/Mailer/ChangeLog +++ b/SOGo/SoObjects/Mailer/ChangeLog @@ -1,5 +1,8 @@ 2004-10-04 Helge Hess + * SOGoMailBodyPart.m, SOGoMailObject.m: finished first part fetching + support (v0.9.23) + * SOGoMailObject.m: added method to fetch core infos of a mail, added various methods to retrieve core info data (like subject or date) (v0.9.22) diff --git a/SOGo/SoObjects/Mailer/SOGoMailBodyPart.h b/SOGo/SoObjects/Mailer/SOGoMailBodyPart.h index 39e13038..606f1442 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailBodyPart.h +++ b/SOGo/SoObjects/Mailer/SOGoMailBodyPart.h @@ -33,10 +33,14 @@ commands in NGImap4. */ +@class NSString, NSArray; @class SOGoMailObject; @interface SOGoMailBodyPart : SOGoMailBaseObject { + NSArray *pathToPart; + NSString *identifier; + id partInfo; } /* hierarchy */ @@ -45,8 +49,14 @@ /* IMAP4 */ +- (NSString *)bodyPartName; +- (NSArray *)bodyPartPath; - (NSString *)bodyPartIdentifier; +/* part info */ + +- (id)partInfo; + @end #endif /* __Mailer_SOGoMailBodyPart_H__ */ diff --git a/SOGo/SoObjects/Mailer/SOGoMailBodyPart.m b/SOGo/SoObjects/Mailer/SOGoMailBodyPart.m index b326af03..828eb7a5 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailBodyPart.m +++ b/SOGo/SoObjects/Mailer/SOGoMailBodyPart.m @@ -27,6 +27,9 @@ @implementation SOGoMailBodyPart - (void)dealloc { + [self->partInfo release]; + [self->identifier release]; + [self->pathToPart release]; [super dealloc]; } @@ -38,29 +41,42 @@ /* IMAP4 */ -- (NSString *)bodyPartIdentifier { - NSMutableString *ms; +- (NSString *)bodyPartName { + NSString *s; + NSRange r; + + s = [self nameInContainer]; + r = [s rangeOfString:@"."]; /* strip extensions */ + if (r.length == 0) + return s; + return [s substringToIndex:r.location]; +} + +- (NSArray *)bodyPartPath { + NSMutableArray *p; id obj; - ms = [NSMutableString stringWithCapacity:16]; + if (self->pathToPart != nil) + return [self->pathToPart isNotNull] ? self->pathToPart : nil; + + p = [[NSMutableArray alloc] initWithCapacity:8]; for (obj = self; [obj isKindOfClass:[SOGoMailBodyPart class]]; obj = [obj container]) { - NSString *s; - NSRange r; - - s = [self nameInContainer]; - r = [s rangeOfString:@"."]; /* strip extensions */ - if (r.length > 0) - s = [s substringToIndex:r.location]; - - if ([ms length] > 0) { - [ms insertString:@"." atIndex:0]; - [ms insertString:s atIndex:0]; - } - else - [ms appendString:s]; + [p insertObject:[obj bodyPartName] atIndex:0]; } - return ms; + + self->pathToPart = [p copy]; + [p release]; + return self->pathToPart; +} + +- (NSString *)bodyPartIdentifier { + if (self->identifier != nil) + return [self->identifier isNotNull] ? self->identifier : nil; + + self->identifier = + [[[self bodyPartPath] componentsJoinedByString:@"."] copy]; + return self->identifier; } - (NSURL *)imap4URL { @@ -68,6 +84,17 @@ return [[self mailObject] imap4URL]; } +/* part info */ + +- (id)partInfo { + if (self->partInfo != nil) + return [self->partInfo isNotNull] ? self->partInfo : nil; + + self->partInfo = + [[[self mailObject] lookupInfoForBodyPart:[self bodyPartPath]] retain]; + return self->partInfo; +} + /* name lookup */ - (id)lookupImap4BodyPartKey:(NSString *)_key inContext:(id)_ctx { @@ -96,18 +123,57 @@ - (NSData *)fetchBLOB { // HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, TEXT - return [[self mailManager] fetchContentOfBodyPart:[self bodyPartIdentifier] + NSString *enc; + NSData *data; + + data = [[self mailManager] fetchContentOfBodyPart:[self bodyPartIdentifier] atURL:[self imap4URL] password:[self imap4Password]]; + if (data == nil) return nil; + + /* check for content encodings */ + + if ((enc = [[self partInfo] valueForKey:@"encoding"]) != nil) { + enc = [enc uppercaseString]; + + if ([enc isEqualToString:@"BASE64"]) + data = [data dataByDecodingBase64]; + else if ([enc isEqualToString:@"7BIT"]) + ; /* keep data as is */ // TODO: do we need to change encodings? + else + [self debugWithFormat:@"ERROR: unsupported encoding: %@", enc]; + } + + return data; } /* WebDAV */ +- (NSString *)contentTypeForBodyPartInfo:(id)_info { + NSString *mt, *st; + + if (![_info isNotNull]) + return nil; + + mt = [_info valueForKey:@"type"]; if (![mt isNotNull]) return nil; + st = [_info valueForKey:@"subtype"]; if (![st isNotNull]) return nil; + + // TODO: we could add the parameter list?! + return [[mt stringByAppendingString:@"/"] stringByAppendingString:st]; +} + - (NSString *)davContentType { // TODO: what about the content-type and other headers? // => we could pass them in as the extension? (eg generate 1.gif!) NSString *pe; + /* try type from body structure info */ + + if ((pe = [self contentTypeForBodyPartInfo:[self partInfo]]) != nil) + return pe; + + /* construct type */ + pe = [[self nameInContainer] pathExtension]; if ([pe length] == 0) return @"application/octet-stream"; @@ -134,9 +200,11 @@ return [NSException exceptionWithHTTPStatus:404 /* not found */ reason:@"did not find body part"]; } - - [self debugWithFormat:@" fetched %d bytes.", [data length]]; + [self debugWithFormat:@" fetched %d bytes: %@", [data length], + [self partInfo]]; + + // TODO: wrong, could be encoded r = [_ctx response]; [r setHeader:[self davContentType] forKey:@"content-type"]; [r setHeader:[NSString stringWithFormat:@"%d", [data length]] diff --git a/SOGo/SoObjects/Mailer/SOGoMailObject.h b/SOGo/SoObjects/Mailer/SOGoMailObject.h index 09c01a75..d727785a 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailObject.h +++ b/SOGo/SoObjects/Mailer/SOGoMailObject.h @@ -61,6 +61,8 @@ - (NSArray *)toEnvelopeAddresses; - (NSArray *)ccEnvelopeAddresses; +- (id)lookupInfoForBodyPart:(NSArray *)_path; + @end #endif /* __Mailer_SOGoMailObject_H__ */ diff --git a/SOGo/SoObjects/Mailer/SOGoMailObject.m b/SOGo/SoObjects/Mailer/SOGoMailObject.m index fb29a6a9..e22a5ca8 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailObject.m +++ b/SOGo/SoObjects/Mailer/SOGoMailObject.m @@ -80,6 +80,10 @@ static NSArray *coreInfoKeys = nil; return self->coreInfos; } +- (id)bodyStructure { + return [[self fetchCoreInfos] valueForKey:@"body"]; +} + - (NGImap4Envelope *)envelope { return [[self fetchCoreInfos] valueForKey:@"envelope"]; } @@ -99,6 +103,29 @@ static NSArray *coreInfoKeys = nil; return [[self envelope] cc]; } +- (id)lookupInfoForBodyPart:(NSArray *)_path { + NSEnumerator *pe; + NSString *p; + id info; + + info = [self bodyStructure]; + pe = [_path objectEnumerator]; + while ((p = [pe nextObject])) { + unsigned idx; + NSArray *parts; + + idx = [p intValue] - 1; + + parts = [info valueForKey:@"parts"]; + if (idx >= [parts count]) { + [self logWithFormat:@"ERROR: body part index out of bounds: %d", idx+1]; + return nil; + } + info = [parts objectAtIndex:idx]; + } + return [info isNotNull] ? info : nil; +} + /* name lookup */ - (BOOL)isBodyPartKey:(NSString *)_key inContext:(id)_ctx { diff --git a/SOGo/SoObjects/Mailer/Version b/SOGo/SoObjects/Mailer/Version index 78237daf..8a19b3e3 100644 --- a/SOGo/SoObjects/Mailer/Version +++ b/SOGo/SoObjects/Mailer/Version @@ -1,3 +1,3 @@ # $Id$ -SUBMINOR_VERSION:=22 +SUBMINOR_VERSION:=23 -- 2.39.5