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 <NGExtensions/NSNull+misc.h>
23 #import <NGExtensions/NSObject+Logs.h>
24 #import <NGMail/NGMimeMessageParser.h>
26 #import "UIxMailFormatter.h"
28 @implementation UIxSubjectFormatter
30 static Class StrClass = Nil;
31 static Class DataClass = Nil;
34 StrClass = [NSString class];
35 DataClass = [NSData class];
39 if ((self = [super init])) {
47 - (unsigned int)maxLength {
48 return self->maxLength;
51 - (BOOL)shouldDecodeQP {
57 - (NSString *)missingSubjectLabel {
58 return [self labelForKey:@"no_subject"];
61 /* specific formatters */
63 - (NSString *)stringForStringValue:(NSString *)_subject {
66 /* quoted printable */
67 if ([self shouldDecodeQP] && [_subject hasPrefix:@"=?"]) {
69 Now this is interesting. An NSString should not contain QP markers since
70 it is already 'charset decoded'. This is also why the NGMime parser
74 =?iso-8859-1?q?Yannick=20DAmboise?=
76 Note: -stringByDecodingQuotedPrintable only expands =D0 like charcodes!
80 /* header field data should always be ASCII */
81 data = [_subject dataUsingEncoding:NSUTF8StringEncoding];
82 return [self stringForDataValue:data];
85 if ([_subject length] == 0)
86 return [self missingSubjectLabel];
88 if ([_subject length] <= [self maxLength])
91 s = [_subject substringToIndex:([self maxLength] - 3)];
92 return [s stringByAppendingString:@"..."];
95 - (NSString *)stringForDataValue:(NSData *)_subject {
99 if ((len = [_subject length]) == 0)
100 return [self missingSubjectLabel];
102 /* check for quoted printable */
104 if (len > 6 && [self shouldDecodeQP]) {
105 const unsigned char *b;
107 b = [_subject bytes];
108 if (b[0] == '=' && b[1] == '?') {
109 /* eg: '=?iso-8859-1?q?Yannick=20DAmboise?=' */
112 t = [_subject decodeQuotedPrintableValueOfMIMEHeaderField:@"subject"];
114 return [self stringForObjectValue:t];
116 [self warnWithFormat:@"decoding QP failed: '%@'", t];
120 /* continue NSData processing */
122 [self warnWithFormat:@"NSData subject, using UTF-8 to decode."];
124 // TODO: exception handler?
125 s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
127 [self errorWithFormat:@"could do not decode NSData subject!"];
128 return [self labelForKey:@"Error_CouldNotDecodeSubject"];
131 if ([s hasPrefix:@"=?"]) { // TODO: this should never happen?
132 [self warnWithFormat:@"subject still has QP signature: '%@'", s];
136 r = [[self stringForStringValue:s] copy];
138 return [r autorelease];
141 /* formatter entry function */
143 - (NSString *)stringForObjectValue:(id)_subject {
144 if (![_subject isNotNull])
145 return [self missingSubjectLabel];
147 if ([_subject isKindOfClass:StrClass])
148 return [self stringForStringValue:_subject];
149 if ([_subject isKindOfClass:DataClass])
150 return [self stringForDataValue:_subject];
152 return [self stringForStringValue:[_subject stringValue]];
155 @end /* UIxSubjectFormatter */