]> err.no Git - scalable-opengroupware.org/blob - UI/MailerUI/UIxSubjectFormatter.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1092 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / MailerUI / UIxSubjectFormatter.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 "UIxMailFormatter.h"
23 #include "common.h"
24
25 #include <NGMail/NGMimeMessageParser.h>
26
27 @implementation UIxSubjectFormatter
28
29 static Class StrClass  = Nil;
30 static Class DataClass = Nil;
31
32 + (void)initialize {
33   StrClass  = [NSString class];
34   DataClass = [NSData   class];
35 }
36
37 - (id)init {
38   if ((self = [super init])) {
39     self->maxLength = 64;
40   }
41   return self;
42 }
43
44 /* configuration */
45
46 - (unsigned int)maxLength {
47   return self->maxLength;
48 }
49
50 - (BOOL)shouldDecodeQP {
51   return YES;
52 }
53
54 /* labels */
55
56 - (NSString *)missingSubjectLabel {
57   return [self labelForKey:@"no_subject"];
58 }
59
60 /* specific formatters */
61
62 - (NSString *)stringForStringValue:(NSString *)_subject {
63   NSString *s;
64   
65   /* quoted printable */
66   if ([self shouldDecodeQP] && [_subject hasPrefix:@"=?"]) {
67     /* 
68        Now this is interesting. An NSString should not contain QP markers since
69        it is already 'charset decoded'. This is also why the NGMime parser
70        expects an NSData.
71        
72        Sample:
73          =?iso-8859-1?q?Yannick=20DAmboise?=
74
75        Note: -stringByDecodingQuotedPrintable only expands =D0 like charcodes!
76     */
77     NSData *data;
78     
79     /* header field data should always be ASCII */
80     data = [_subject dataUsingEncoding:NSUTF8StringEncoding];
81     return [self stringForDataValue:data];
82   }
83   
84   if ([_subject length] == 0)
85     return [self missingSubjectLabel];
86   
87   if ([_subject length] <= [self maxLength])
88     return _subject;
89   
90   s = [_subject substringToIndex:([self maxLength] - 3)];
91   return [s stringByAppendingString:@"..."];
92 }
93
94 - (NSString *)stringForDataValue:(NSData *)_subject {
95   NSString *s, *r;
96   unsigned len;
97   
98   if ((len = [_subject length]) == 0)
99     return [self missingSubjectLabel];
100   
101   /* check for quoted printable */
102   
103   if (len > 6 && [self shouldDecodeQP]) {
104     const unsigned char *b;
105     
106     b = [_subject bytes];
107     if (b[0] == '=' && b[1] == '?') {
108       /* eg: '=?iso-8859-1?q?Yannick=20DAmboise?=' */
109       id t;
110       
111       t = [_subject decodeQuotedPrintableValueOfMIMEHeaderField:@"subject"];
112       if ([t isNotNull])
113         return [self stringForObjectValue:t];
114       else
115         [self warnWithFormat:@"decoding QP failed: '%@'", t];
116     }
117   }
118   
119   /* continue NSData processing */
120   
121   [self warnWithFormat:@"NSData subject, using UTF-8 to decode."];
122   
123   // TODO: exception handler?
124   s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
125   if (s == nil) {
126     [self errorWithFormat:@"could do not decode NSData subject!"];
127     return [self labelForKey:@"Error_CouldNotDecodeSubject"];
128   }
129   
130   if ([s hasPrefix:@"=?"]) { // TODO: this should never happen?
131     [self warnWithFormat:@"subject still has QP signature: '%@'", s];
132     r = [s copy];
133   }
134   else
135     r = [[self stringForStringValue:s] copy];
136   [s release];
137   return [r autorelease];
138 }
139
140 /* formatter entry function */
141
142 - (NSString *)stringForObjectValue:(id)_subject {
143   if (![_subject isNotNull])
144     return [self missingSubjectLabel];
145   
146   if ([_subject isKindOfClass:StrClass])
147     return [self stringForStringValue:_subject];
148   if ([_subject isKindOfClass:DataClass])
149     return [self stringForDataValue:_subject];
150   
151   return [self stringForStringValue:[_subject stringValue]];
152 }
153
154 @end /* UIxSubjectFormatter */