]> err.no Git - scalable-opengroupware.org/blob - UI/MailPartViewers/UIxMailPartViewer.m
do not use Anais
[scalable-opengroupware.org] / UI / MailPartViewers / UIxMailPartViewer.m
1 /*
2   Copyright (C) 2004-2005 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "UIxMailPartViewer.h"
23 #include "UIxMailRenderingContext.h"
24 #include "UIxMailSizeFormatter.h"
25 #include "../MailerUI/WOContext+UIxMailer.h"
26 #include <NGExtensions/NSString+Encoding.h>
27 #include "common.h"
28
29 @implementation UIxMailPartViewer
30
31 - (void)dealloc {
32   [self->flatContent release];
33   [self->bodyInfo    release];
34   [self->partPath    release];
35   [super dealloc];
36 }
37
38 /* caches */
39
40 - (void)resetPathCaches {
41   /* this is called when -setPartPath: is called */
42   [self->flatContent release]; self->flatContent = nil;
43 }
44 - (void)resetBodyInfoCaches {
45 }
46
47 /* notifications */
48
49 - (void)sleep {
50   [self resetPathCaches];
51   [self resetBodyInfoCaches];
52   [self->partPath release]; self->partPath = nil;
53   [self->bodyInfo release]; self->bodyInfo = nil;
54   [super sleep];
55 }
56
57 /* accessors */
58
59 - (void)setPartPath:(NSArray *)_path {
60   if ([_path isEqual:self->partPath])
61     return;
62   
63   ASSIGN(self->partPath, _path);
64   [self resetPathCaches];
65 }
66 - (NSArray *)partPath {
67   return self->partPath;
68 }
69
70 - (void)setBodyInfo:(id)_info {
71   ASSIGN(self->bodyInfo, _info);
72 }
73 - (id)bodyInfo {
74   return self->bodyInfo;
75 }
76
77 - (NSData *)flatContent {
78   if (self->flatContent != nil)
79     return [self->flatContent isNotNull] ? self->flatContent : nil;
80   
81   self->flatContent = 
82     [[[[self context] mailRenderingContext] flatContentForPartPath:
83                                               [self partPath]] retain];
84   return self->flatContent;
85 }
86
87 - (NSData *)decodedFlatContent {
88   NSString *enc;
89   
90   enc = [[(NSDictionary *)[self bodyInfo] 
91                           objectForKey:@"encoding"] lowercaseString];
92   
93   if ([enc isEqualToString:@"7bit"])
94     return [self flatContent];
95   
96   if ([enc isEqualToString:@"8bit"]) // TODO: correct?
97     return [self flatContent];
98   
99   if ([enc isEqualToString:@"base64"])
100     return [[self flatContent] dataByDecodingBase64];
101
102   if ([enc isEqualToString:@"quoted-printable"])
103     return [[self flatContent] dataByDecodingQuotedPrintable];
104   
105   [self errorWithFormat:@"unsupported MIME encoding: %@", enc];
106   return [self flatContent];
107 }
108
109 - (NSString *)flatContentAsString {
110   /* Note: we even have the line count in the body-info! */
111   NSString *charset;
112   NSString *s;
113   NSData   *content;
114   
115   if ((content = [self decodedFlatContent]) == nil) {
116     [self errorWithFormat:@"got no text content: %@", 
117             [[self partPath] componentsJoinedByString:@"."]];
118     return nil;
119   }
120   
121   charset = [(NSDictionary *)
122               [(NSDictionary *)[self bodyInfo] objectForKey:@"parameterList"] 
123                                                objectForKey:@"charset"];
124   charset = [charset lowercaseString];
125   
126   // TODO: properly decode charset, might need to handle encoding?
127   
128   if ([charset length] > 0) {
129     s = [NSString stringWithData:content usingEncodingNamed:charset];
130   }
131   else {
132     s = [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding];
133     s = [s autorelease];
134   }
135   if (s == nil) {
136     [self errorWithFormat:@"could not convert content to text, charset: '%@'",
137             charset];
138   }
139   return s;
140 }
141
142 /* path extension */
143
144 - (NSString *)pathExtensionForType:(NSString *)_mt subtype:(NSString *)_st {
145   // TODO: support /etc/mime.types
146   
147   if (![_mt isNotNull] || ![_st isNotNull])
148     return nil;
149   if ([_mt length] == 0) return nil;
150   if ([_st length] == 0) return nil;
151   _mt = [_mt lowercaseString];
152   _st = [_st lowercaseString];
153   
154   if ([_mt isEqualToString:@"image"]) {
155     if ([_st isEqualToString:@"gif"])  return @"gif";
156     if ([_st isEqualToString:@"jpeg"]) return @"jpg";
157     if ([_st isEqualToString:@"png"])  return @"png";
158   }
159   else if ([_mt isEqualToString:@"text"]) {
160     if ([_st isEqualToString:@"plain"])    return @"txt";
161     if ([_st isEqualToString:@"xml"])      return @"xml";
162     if ([_st isEqualToString:@"calendar"]) return @"ics";
163     if ([_st isEqualToString:@"x-vcard"])  return @"vcf";
164   }
165   else if ([_mt isEqualToString:@"message"]) {
166     if ([_st isEqualToString:@"rfc822"]) return @"mail";
167   }
168   else if ([_mt isEqualToString:@"application"]) {
169     if ([_st isEqualToString:@"pdf"]) return @"pdf";
170   }
171   return nil;
172 }
173
174 - (NSString *)preferredPathExtension {
175   return [self pathExtensionForType:[[self bodyInfo] valueForKey:@"type"]
176                subtype:[[self bodyInfo] valueForKey:@"subtype"]];
177 }
178
179 - (NSString *)filename {
180   id tmp;
181   
182   tmp = [[self bodyInfo] valueForKey:@"parameterList"];
183   if (![tmp isNotNull])
184     return nil;
185   
186   tmp = [tmp valueForKey:@"name"];
187   if (![tmp isNotNull])
188     return nil;
189   if ([tmp length] == 0)
190     return nil;
191   
192   return tmp;
193 }
194
195 - (NSString *)filenameForDisplay {
196   NSString *s;
197   
198   if ((s = [self filename]) != nil)
199     return s;
200   
201   s = [[self partPath] componentsJoinedByString:@"-"];
202   return ([s length] > 0)
203     ? [@"untitled-" stringByAppendingString:s]
204     : @"untitled";
205 }
206
207 - (NSFormatter *)sizeFormatter {
208   return [UIxMailSizeFormatter sharedMailSizeFormatter];
209 }
210
211 /* URL generation */
212
213 - (NSString *)pathToAttachmentObject {
214   /* this points to the SoObject representing the part, no modifications */
215   NSString *url, *n, *pext;
216
217   /* path to mail controller object */
218   
219   url = [[self clientObject] baseURLInContext:[self context]];
220   if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
221   
222   /* mail relative path to body-part */
223   
224   if ([(n = [[self partPath] componentsJoinedByString:@"/"]) isNotNull]) {
225     /* eg this was nil for a draft containing an HTML message */
226     url = [url stringByAppendingString:n];
227   }
228   
229   /* we currently NEED the extension for SoObject lookup (should be fixed) */
230   
231   pext = [self preferredPathExtension];
232   if ([pext isNotNull] && [pext length] > 0) {
233     /* attach extension */
234     if ([url hasSuffix:@"/"]) {
235       /* this happens if the part is the root-content of the mail */
236       url = [url substringToIndex:([url length] - 1)];
237     }
238     url = [url stringByAppendingString:@"."];
239     url = [url stringByAppendingString:pext];
240   }
241   
242   return url;
243 }
244
245 - (NSString *)pathToAttachment {
246   /* this generates a more beautiful 'download' URL for a part */
247   NSString *url, *fn;
248
249   fn   = [self filename];
250   
251   if (![fn isNotNull] || ([fn length] == 0))
252     fn = nil;
253
254   /* get basic URL */
255
256   url = [self pathToAttachmentObject];
257   
258   /* 
259      If we have an attachment name, we attach it, this is properly handled by
260      SOGoMailBodyPart.
261   */
262   
263   if (fn != nil) {
264     if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
265     if (isdigit([fn characterAtIndex:0]))
266       url = [url stringByAppendingString:@"fn-"];
267     url = [url stringByAppendingString:[fn stringByEscapingURL]];
268     
269     // TODO: should we check for a proper extension?
270   }
271   
272   return url;
273 }
274
275 @end /* UIxMailPartViewer */