From 1cacd62eb67ac9ed00231adceed1c55ccc13e116 Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 9 Feb 2005 12:22:14 +0000 Subject: [PATCH] added quoting of plain/text content for replies git-svn-id: http://svn.opengroupware.org/SOGo/trunk@537 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/SoObjects/Mailer/ChangeLog | 12 ++++ SOGo/SoObjects/Mailer/SOGoMailObject.h | 4 +- SOGo/SoObjects/Mailer/SOGoMailObject.m | 88 +++++++++++++++++++++++--- SOGo/SoObjects/Mailer/Version | 2 +- SOGo/UI/Mailer/ChangeLog | 4 ++ SOGo/UI/Mailer/UIxMailReplyAction.m | 75 ++++++++++++++++++++-- SOGo/UI/Mailer/Version | 6 +- 7 files changed, 174 insertions(+), 17 deletions(-) diff --git a/SOGo/SoObjects/Mailer/ChangeLog b/SOGo/SoObjects/Mailer/ChangeLog index eb33a837..36ed42f0 100644 --- a/SOGo/SoObjects/Mailer/ChangeLog +++ b/SOGo/SoObjects/Mailer/ChangeLog @@ -1,5 +1,17 @@ +2005-02-09 Helge Hess + + * v0.9.71 + + * SOGoMailObject.m: -lookupInfoForBodyPart: can now deal with string + parameters (eg 1.2.3) in addition to arrays and returns the full + body structure for empty strings ("") + added support for fetching parts as NSString's (by applying the + charset in the body structure) + 2005-02-08 Helge Hess + * SOGoMailObject.m: added method to fetch individual plain/text parts + * v0.9.70 * SOGoMailManager.m: only perform IMAP4 select if the folder changes diff --git a/SOGo/SoObjects/Mailer/SOGoMailObject.h b/SOGo/SoObjects/Mailer/SOGoMailObject.h index 22588182..d653b741 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailObject.h +++ b/SOGo/SoObjects/Mailer/SOGoMailObject.h @@ -61,7 +61,7 @@ - (NSArray *)ccEnvelopeAddresses; - (id)bodyStructure; -- (id)lookupInfoForBodyPart:(NSArray *)_path; +- (id)lookupInfoForBodyPart:(id)_path; /* content */ @@ -71,7 +71,9 @@ /* bulk fetching of plain/text content */ - (NSArray *)plainTextContentFetchKeys; +- (NSDictionary *)fetchPlainTextParts:(NSArray *)_fetchKeys; - (NSDictionary *)fetchPlainTextParts; +- (NSDictionary *)fetchPlainTextStrings:(NSArray *)_fetchKeys; /* flags */ diff --git a/SOGo/SoObjects/Mailer/SOGoMailObject.m b/SOGo/SoObjects/Mailer/SOGoMailObject.m index 51ee3e7f..13b8b397 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailObject.m +++ b/SOGo/SoObjects/Mailer/SOGoMailObject.m @@ -175,15 +175,27 @@ static BOOL debugBodyStructure = NO; return [[self envelope] cc]; } -- (id)lookupInfoForBodyPart:(NSArray *)_path { +- (id)lookupInfoForBodyPart:(id)_path { NSEnumerator *pe; NSString *p; id info; + + if (![_path isNotNull]) + return nil; if ((info = [self bodyStructure]) == nil) { [self errorWithFormat:@"got no body part structure!"]; return nil; } + + /* ensure array argument */ + + if ([_path isKindOfClass:[NSString class]]) { + if ([_path length] == 0) + return info; + + _path = [_path componentsSeparatedByString:@"."]; + } /* For each path component, eg 1,1,3 @@ -370,26 +382,24 @@ static BOOL debugBodyStructure = NO; return ma; } -- (NSDictionary *)fetchPlainTextParts { +- (NSDictionary *)fetchPlainTextParts:(NSArray *)_fetchKeys { NSMutableDictionary *flatContents; unsigned i, count; - NSArray *keys; id result; - keys = [self plainTextContentFetchKeys]; - [self debugWithFormat:@"fetch keys: %@", keys]; + [self debugWithFormat:@"fetch keys: %@", _fetchKeys]; - result = [self fetchParts:keys]; + result = [self fetchParts:_fetchKeys]; result = [result valueForKey:@"RawResponse"]; // hackish result = [result objectForKey:@"fetch"]; // Note: -valueForKey: doesn't work! - count = [keys count]; + count = [_fetchKeys count]; flatContents = [NSMutableDictionary dictionaryWithCapacity:count]; for (i = 0; i < count; i++) { NSString *key; NSData *data; - key = [keys objectAtIndex:i]; + key = [_fetchKeys objectAtIndex:i]; data = [[result objectForKey:key] objectForKey:@"data"]; if (![data isNotNull]) { @@ -412,6 +422,68 @@ static BOOL debugBodyStructure = NO; return flatContents; } +- (NSDictionary *)fetchPlainTextParts { + return [self fetchPlainTextParts:[self plainTextContentFetchKeys]]; +} + +/* convert parts to strings */ + +- (NSString *)stringForData:(NSData *)_data partInfo:(NSDictionary *)_info { + NSString *charset; + NSString *s; + + if (![_data isNotNull]) + return nil; + + s = nil; + + charset = [[_info valueForKey:@"parameterList"] valueForKey:@"charset"]; + if ([charset isNotNull] && [charset length] > 0) + s = [NSString stringWithData:_data usingEncodingNamed:charset]; + + if (s == nil) { /* no charset provided, fall back to UTF-8 */ + s = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding]; + s = [s autorelease]; + } + + return s; +} + +- (NSDictionary *)stringifyTextParts:(NSDictionary *)_datas { + NSMutableDictionary *md; + NSEnumerator *keys; + NSString *key; + + md = [NSMutableDictionary dictionaryWithCapacity:4]; + keys = [_datas keyEnumerator]; + while ((key = [keys nextObject]) != nil) { + NSDictionary *info; + NSString *s; + + info = [self lookupInfoForBodyPart:key]; + if ((s = [self stringForData:[_datas objectForKey:key] partInfo:info])) + [md setObject:s forKey:key]; + } + return md; +} +- (NSDictionary *)fetchPlainTextStrings:(NSArray *)_fetchKeys { + /* + The fetched parts are NSData objects, this method converts them into + NSString objects based on the information inside the bodystructure. + + The fetch-keys are body fetch-keys like: body[text] or body[1.2.3]. + The keys in the result dictionary are "" for 'text' and 1.2.3 for parts. + */ + NSDictionary *datas; + + if ((datas = [self fetchPlainTextParts:_fetchKeys]) == nil) + return nil; + if ([datas isKindOfClass:[NSException class]]) + return datas; + + return [self stringifyTextParts:datas]; +} + /* flags */ - (NSException *)addFlags:(id)_flags { diff --git a/SOGo/SoObjects/Mailer/Version b/SOGo/SoObjects/Mailer/Version index 49a93192..f6d238fc 100644 --- a/SOGo/SoObjects/Mailer/Version +++ b/SOGo/SoObjects/Mailer/Version @@ -1,6 +1,6 @@ # Version file -SUBMINOR_VERSION:=70 +SUBMINOR_VERSION:=71 # v0.9.69 requires libNGMime v4.5.210 # v0.9.55 requires libNGExtensions v4.5.136 diff --git a/SOGo/UI/Mailer/ChangeLog b/SOGo/UI/Mailer/ChangeLog index 5d757542..c5de300d 100644 --- a/SOGo/UI/Mailer/ChangeLog +++ b/SOGo/UI/Mailer/ChangeLog @@ -1,3 +1,7 @@ +2005-02-09 Helge Hess + + * UIxMailReplyAction.m: implemented a content-reply (v0.9.97) + 2005-02-08 Helge Hess * v0.9.96 diff --git a/SOGo/UI/Mailer/UIxMailReplyAction.m b/SOGo/UI/Mailer/UIxMailReplyAction.m index fae09af2..0b0b1dc7 100644 --- a/SOGo/UI/Mailer/UIxMailReplyAction.m +++ b/SOGo/UI/Mailer/UIxMailReplyAction.m @@ -110,12 +110,77 @@ } } +- (NSString *)contentForReplyOnParts:(NSDictionary *)_prts keys:(NSArray *)_k { + static NSString *textPartSeparator = @"\n---\n"; + NSMutableString *ms; + unsigned i, count; + + ms = [NSMutableString stringWithCapacity:16000]; + + for (i = 0, count = [_k count]; i < count; i++) { + NSString *k, *v; + + k = [_k objectAtIndex:i]; + + // TODO: this is DUP code to SOGoMailObject + if ([k isEqualToString:@"body[text]"]) + k = @""; + else if ([k hasPrefix:@"body["]) { + k = [k substringFromIndex:5]; + if ([k length] > 0) k = [k substringToIndex:([k length] - 1)]; + } + + v = [_prts objectForKey:k]; + if (![v isKindOfClass:[NSString class]]) { + [self logWithFormat:@"Note: cannot show part %@", k]; + continue; + } + if ([v length] == 0) + continue; + + if (i != 0) [ms appendString:textPartSeparator]; + [ms appendString:[v stringByApplyingMailQuoting]]; + } + return ms; +} + - (NSString *)contentForReply { - // TODO: add quoted content - [self logWithFormat:@"keys: %@", - [[self clientObject] plainTextContentFetchKeys]]; - [self logWithFormat:@"texts: %@", [[self clientObject] fetchPlainTextParts]]; - return nil; + NSArray *keys; + NSDictionary *parts; + + keys = [[self clientObject] plainTextContentFetchKeys]; + if ([keys count] == 0) + return nil; + + if ([keys count] > 1) { + /* filter keys, only include top-level, or if none, the first */ + NSMutableArray *topLevelKeys = nil; + unsigned i; + + for (i = 0; i < [keys count]; i++) { + NSRange r; + + r = [[keys objectAtIndex:i] rangeOfString:@"."]; + if (r.length > 0) + continue; + + if (topLevelKeys == nil) + topLevelKeys = [NSMutableArray arrayWithCapacity:4]; + [topLevelKeys addObject:[keys objectAtIndex:i]]; + } + + if ([topLevelKeys count] > 0) { + /* use top-level keys if we have some */ + keys = topLevelKeys; + } + else { + /* just take the first part */ + keys = [NSArray arrayWithObject:[keys objectAtIndex:0]]; + } + } + + parts = [[self clientObject] fetchPlainTextStrings:keys]; + return [self contentForReplyOnParts:parts keys:keys]; } - (id)replyToAll:(BOOL)_replyToAll { diff --git a/SOGo/UI/Mailer/Version b/SOGo/UI/Mailer/Version index be40fed5..4021447e 100644 --- a/SOGo/UI/Mailer/Version +++ b/SOGo/UI/Mailer/Version @@ -1,7 +1,9 @@ # version file -SUBMINOR_VERSION:=96 +SUBMINOR_VERSION:=97 +# v0.9.97 requires SoObjects/Mailer v0.9.71 +# v0.9.97 requires libNGExtensions v4.5.142 # v0.9.94 requires SoObjects/Mailer v0.9.69 # v0.9.94 requires libNGMime v4.5.210 # v0.9.91 requires SoObjects/Mailer v0.9.68 @@ -15,7 +17,7 @@ SUBMINOR_VERSION:=96 # v0.9.78 requires SoObjects/Mailer v0.9.58 # v0.9.77 requires SoObjects/Mailer v0.9.57 # v0.9.74 requires SoObjects/Mailer v0.9.56 -# v0.9.70 requires NGExtensions v4.5.136 +# v0.9.70 requires libNGExtensions v4.5.136 # v0.9.69 requires libNGMime v4.5.203 # v0.9.50 requires libNGMime v4.3.190 # v0.9.43 requires libNGObjWeb v4.3.73 -- 2.39.5