+2005-02-09 Helge Hess <helge.hess@opengroupware.org>
+
+ * 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 <helge.hess@opengroupware.org>
+ * SOGoMailObject.m: added method to fetch individual plain/text parts
+
* v0.9.70
* SOGoMailManager.m: only perform IMAP4 select if the folder changes
- (NSArray *)ccEnvelopeAddresses;
- (id)bodyStructure;
-- (id)lookupInfoForBodyPart:(NSArray *)_path;
+- (id)lookupInfoForBodyPart:(id)_path;
/* content */
/* bulk fetching of plain/text content */
- (NSArray *)plainTextContentFetchKeys;
+- (NSDictionary *)fetchPlainTextParts:(NSArray *)_fetchKeys;
- (NSDictionary *)fetchPlainTextParts;
+- (NSDictionary *)fetchPlainTextStrings:(NSArray *)_fetchKeys;
/* flags */
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
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]) {
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 {
# Version file
-SUBMINOR_VERSION:=70
+SUBMINOR_VERSION:=71
# v0.9.69 requires libNGMime v4.5.210
# v0.9.55 requires libNGExtensions v4.5.136
+2005-02-09 Helge Hess <helge.hess@opengroupware.org>
+
+ * UIxMailReplyAction.m: implemented a content-reply (v0.9.97)
+
2005-02-08 Helge Hess <helge.hess@opengroupware.org>
* v0.9.96
}
}
+- (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 {
# 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
# 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