2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #import <Foundation/NSString.h>
24 #import <NGObjWeb/WOComponent.h>
25 #import <NGExtensions/NSObject+Logs.h>
26 #import <NGExtensions/NSNull+misc.h>
28 #import <SoObjects/Mailer/SOGoMailObject.h>
30 #import "UIxMailRenderingContext.h"
32 @interface UIxMailRenderingContext (Private)
34 - (BOOL) _shouldDisplayAsAttachment: (NSDictionary *) info;
38 @implementation UIxMailRenderingContext (Private)
40 - (BOOL) _shouldDisplayAsAttachment: (NSDictionary *) info
44 s = [[info objectForKey:@"disposition"] objectForKey: @"type"];
46 return (s && [s caseInsensitiveCompare: @"ATTACHMENT"] == NSOrderedSame);
51 @implementation UIxMailRenderingContext
53 static BOOL showNamedTextAttachmentsInline = NO;
55 - (id) initWithViewer: (WOComponent *) _viewer
56 context: (WOContext *) _ctx
58 if ((self = [super init]))
69 return [self initWithViewer: nil context: nil];
74 [flatContents release];
80 [flatContents release];
86 - (NSDictionary *) flatContents
90 flatContents = [[viewer clientObject] fetchPlainTextParts];
91 [flatContents retain];
92 // [self debugWithFormat:@"CON: %@", flatContents];
98 - (NSData *) flatContentForPartPath: (NSArray *) _partPath
103 pid = _partPath ? [_partPath componentsJoinedByString: @"."] : @"";
104 content = [[self flatContents] objectForKey: pid];
105 if (!content && ![pid intValue])
106 content = [flatContents objectForKey: @""];
111 /* viewer components */
113 - (WOComponent *) mixedViewer
115 /* Note: we cannot cache the multipart viewers, because it can be nested */
116 return [viewer pageWithName: @"UIxMailPartMixedViewer"];
119 - (WOComponent *) signedViewer
121 /* Note: we cannot cache the multipart viewers, because it can be nested */
122 // TODO: temporary workaround (treat it like a plain mixed part)
124 return [self mixedViewer];
127 - (WOComponent *) alternativeViewer
129 /* Note: we cannot cache the multipart viewers, because it can be nested */
130 return [viewer pageWithName: @"UIxMailPartAlternativeViewer"];
133 - (WOComponent *) textViewer
135 return [viewer pageWithName: @"UIxMailPartTextViewer"];
138 - (WOComponent *) imageViewer
140 return [viewer pageWithName: @"UIxMailPartImageViewer"];
143 - (WOComponent *) linkViewer
145 return [viewer pageWithName: @"UIxMailPartLinkViewer"];
148 - (WOComponent *) htmlViewer
150 return [viewer pageWithName: @"UIxMailPartHTMLViewer"];
153 - (WOComponent *) messageViewer
155 return [viewer pageWithName: @"UIxMailPartMessageViewer"];
158 - (WOComponent *) iCalViewer
160 return [viewer pageWithName: @"UIxMailPartICalViewer"];
165 - (WOComponent *) kolabContactViewer
167 return [viewer pageWithName: @"UIxKolabPartContactViewer"];
170 - (WOComponent *) kolabEventViewer
172 return [viewer pageWithName: @"UIxKolabPartEventViewer"];
175 - (WOComponent *) kolabTodoViewer
177 return [viewer pageWithName: @"UIxKolabPartTodoViewer"];
180 - (WOComponent *) kolabNoteViewer
182 return [self textViewer]; // TODO
185 - (WOComponent *) kolabJournalViewer
187 return [self textViewer]; // TODO
190 - (WOComponent *) kolabDistributionListViewer
192 return [self textViewer]; // TODO
195 /* main viewer selection */
197 - (WOComponent *) viewerForBodyInfo: (id) _info
201 mt = [[_info valueForKey:@"type"] lowercaseString];
202 st = [[_info valueForKey:@"subtype"] lowercaseString];
204 if ([mt isEqualToString:@"multipart"])
206 if ([st isEqualToString:@"mixed"] || [st isEqualToString:@"related"] || [st isEqualToString: @"appledouble"])
207 return [self mixedViewer];
208 else if ([st isEqualToString:@"signed"])
209 return [self signedViewer];
210 else if ([st isEqualToString:@"alternative"])
211 return [self alternativeViewer];
213 if ([st isEqualToString:@"report"])
214 /* this is used by mail-delivery reports */
215 return [self mixedViewer];
217 else if ([mt isEqualToString:@"text"])
219 if ([st isEqualToString:@"plain"] || [st isEqualToString:@"html"]) {
220 if (!showNamedTextAttachmentsInline && [self _shouldDisplayAsAttachment: _info])
221 return [self linkViewer];
223 return [st isEqualToString:@"html"]
224 ? [self htmlViewer] : [self textViewer];
227 if ([st isEqualToString:@"calendar"])
228 return [self iCalViewer];
231 if ([mt isEqualToString:@"image"])
233 if ([self _shouldDisplayAsAttachment: _info])
234 return [self linkViewer];
236 return [self imageViewer];
239 if ([mt isEqualToString:@"message"] && [st isEqualToString:@"rfc822"])
240 return [self messageViewer];
242 if ([mt isEqualToString:@"message"] &&
243 [st isEqualToString:@"delivery-status"]) {
245 Content-Description: Delivery error report
246 Content-Type: message/delivery-status
248 Reporting-MTA: dns; mail.opengroupware.org
249 Arrival-Date: Mon, 18 Jul 2005 12:08:43 +0200 (CEST)
251 Final-Recipient: rfc822; ioioi@plop.com
254 Diagnostic-Code: X-Postfix; host plop.com[64.39.31.55] said: 550 5.7.1
255 <ioioi@plop.com>... Relaying denied
257 // Note: we cannot use the text viewer because the body is not pre-fetched
258 return [self linkViewer];
261 if ([mt isEqualToString:@"application"])
263 // octet-stream (generate download link?, autodetect type?)
265 if ([st hasPrefix:@"x-vnd.kolab."])
267 if ([st isEqualToString:@"x-vnd.kolab.contact"])
268 return [self kolabContactViewer];
269 if ([st isEqualToString:@"x-vnd.kolab.event"])
270 return [self kolabEventViewer];
271 if ([st isEqualToString:@"x-vnd.kolab.task"])
272 return [self kolabTodoViewer];
273 if ([st isEqualToString:@"x-vnd.kolab.note"])
274 return [self kolabNoteViewer];
275 if ([st isEqualToString:@"x-vnd.kolab.journal"])
276 return [self kolabJournalViewer];
277 if ([st isEqualToString:@"x-vnd.kolab.contact.distlist"])
278 return [self kolabDistributionListViewer];
280 [self errorWithFormat:@"found no viewer for Kolab type: %@/%@", mt, st];
281 return [self linkViewer];
283 else if ([st isEqualToString:@"ics"]) /* Cooqle K4lendahr - Google Calendar */
284 return [self iCalViewer];
286 #if 0 /* the link viewer looks better than plain text ;-) */
287 if ([st isEqualToString:@"pgp-signature"]) // TODO: real PGP viewer
288 return [self textViewer];
292 // TODO: always fallback to octet viewer?!
294 [self errorWithFormat:@"found no viewer for MIME type: %@/%@", mt, st];
297 return [self linkViewer];
302 - (BOOL)isDebuggingEnabled {
306 @end /* UIxMailRenderingContext */
309 @implementation WOContext(UIxMailPart)
311 static NSString *MRK = @"UIxMailRenderingContext";
313 - (void)pushMailRenderingContext:(UIxMailRenderingContext *)_mctx {
314 [self setObject:_mctx forKey:MRK];
316 - (UIxMailRenderingContext *)popMailRenderingContext {
317 UIxMailRenderingContext *mctx;
319 if ((mctx = [self objectForKey:MRK]) == nil)
322 mctx = [[mctx retain] autorelease];
323 [self removeObjectForKey:MRK];
326 - (UIxMailRenderingContext *)mailRenderingContext {
327 return [self objectForKey:MRK];
330 @end /* WOContext(UIxMailPart) */