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 #include "UIxMailPartViewer.h"
23 #include "UIxMailRenderingContext.h"
24 #include "UIxMailSizeFormatter.h"
25 #include "../MailerUI/WOContext+UIxMailer.h"
26 #include <NGExtensions/NSString+Encoding.h>
29 @implementation UIxMailPartViewer
32 [self->flatContent release];
33 [self->bodyInfo release];
34 [self->partPath release];
40 - (void)resetPathCaches {
41 /* this is called when -setPartPath: is called */
42 [self->flatContent release]; self->flatContent = nil;
44 - (void)resetBodyInfoCaches {
50 [self resetPathCaches];
51 [self resetBodyInfoCaches];
52 [self->partPath release]; self->partPath = nil;
53 [self->bodyInfo release]; self->bodyInfo = nil;
59 - (void)setPartPath:(NSArray *)_path {
60 if ([_path isEqual:self->partPath])
63 ASSIGN(self->partPath, _path);
64 [self resetPathCaches];
66 - (NSArray *)partPath {
67 return self->partPath;
70 - (void)setBodyInfo:(id)_info {
71 ASSIGN(self->bodyInfo, _info);
74 return self->bodyInfo;
77 - (NSData *)flatContent {
78 if (self->flatContent != nil)
79 return [self->flatContent isNotNull] ? self->flatContent : nil;
82 [[[[self context] mailRenderingContext] flatContentForPartPath:
83 [self partPath]] retain];
84 return self->flatContent;
87 - (NSData *)decodedFlatContent {
90 enc = [[(NSDictionary *)[self bodyInfo]
91 objectForKey:@"encoding"] lowercaseString];
93 if ([enc isEqualToString:@"7bit"])
94 return [self flatContent];
96 if ([enc isEqualToString:@"8bit"]) // TODO: correct?
97 return [self flatContent];
99 if ([enc isEqualToString:@"base64"])
100 return [[self flatContent] dataByDecodingBase64];
102 if ([enc isEqualToString:@"quoted-printable"])
103 return [[self flatContent] dataByDecodingQuotedPrintable];
105 [self errorWithFormat:@"unsupported MIME encoding: %@", enc];
106 return [self flatContent];
109 - (NSString *)flatContentAsString {
110 /* Note: we even have the line count in the body-info! */
115 if ((content = [self decodedFlatContent]) == nil) {
116 [self errorWithFormat:@"got no text content: %@",
117 [[self partPath] componentsJoinedByString:@"."]];
121 charset = [(NSDictionary *)
122 [(NSDictionary *)[self bodyInfo] objectForKey:@"parameterList"]
123 objectForKey:@"charset"];
124 charset = [charset lowercaseString];
126 // TODO: properly decode charset, might need to handle encoding?
128 if ([charset length] > 0) {
129 s = [NSString stringWithData:content usingEncodingNamed:charset];
132 s = [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding];
136 [self errorWithFormat:@"could not convert content to text, charset: '%@'",
144 - (NSString *)pathExtensionForType:(NSString *)_mt subtype:(NSString *)_st {
145 // TODO: support /etc/mime.types
147 if (![_mt isNotNull] || ![_st isNotNull])
149 if ([_mt length] == 0) return nil;
150 if ([_st length] == 0) return nil;
151 _mt = [_mt lowercaseString];
152 _st = [_st lowercaseString];
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";
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";
165 else if ([_mt isEqualToString:@"message"]) {
166 if ([_st isEqualToString:@"rfc822"]) return @"mail";
168 else if ([_mt isEqualToString:@"application"]) {
169 if ([_st isEqualToString:@"pdf"]) return @"pdf";
174 - (NSString *)preferredPathExtension {
175 return [self pathExtensionForType:[[self bodyInfo] valueForKey:@"type"]
176 subtype:[[self bodyInfo] valueForKey:@"subtype"]];
179 - (NSString *)filename {
182 tmp = [[self bodyInfo] valueForKey:@"parameterList"];
183 if (![tmp isNotNull])
186 tmp = [tmp valueForKey:@"name"];
187 if (![tmp isNotNull])
189 if ([tmp length] == 0)
195 - (NSString *)filenameForDisplay {
198 if ((s = [self filename]) != nil)
201 s = [[self partPath] componentsJoinedByString:@"-"];
202 return ([s length] > 0)
203 ? [@"untitled-" stringByAppendingString:s]
207 - (NSFormatter *)sizeFormatter {
208 return [UIxMailSizeFormatter sharedMailSizeFormatter];
213 - (NSString *)pathToAttachmentObject {
214 /* this points to the SoObject representing the part, no modifications */
215 NSString *url, *n, *pext;
217 /* path to mail controller object */
219 url = [[self clientObject] baseURLInContext:[self context]];
220 if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
222 /* mail relative path to body-part */
224 if ([(n = [[self partPath] componentsJoinedByString:@"/"]) isNotNull]) {
225 /* eg this was nil for a draft containing an HTML message */
226 url = [url stringByAppendingString:n];
229 /* we currently NEED the extension for SoObject lookup (should be fixed) */
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)];
238 url = [url stringByAppendingString:@"."];
239 url = [url stringByAppendingString:pext];
245 - (NSString *)pathToAttachment {
246 /* this generates a more beautiful 'download' URL for a part */
249 fn = [self filename];
251 if (![fn isNotNull] || ([fn length] == 0))
256 url = [self pathToAttachmentObject];
259 If we have an attachment name, we attach it, this is properly handled by
264 if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
265 if (isdigit([fn characterAtIndex:0]))
266 url = [url stringByAppendingString:@"fn-"];
267 url = [url stringByAppendingString:[fn stringByEscapingURL]];
269 // TODO: should we check for a proper extension?
275 @end /* UIxMailPartViewer */