]> err.no Git - scalable-opengroupware.org/blob - SOGo/UI/Mailer/UIxSubjectFormatter.m
changes to use NGLogging in all places
[scalable-opengroupware.org] / SOGo / UI / Mailer / UIxSubjectFormatter.m
1 /*
2   Copyright (C) 2004 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     }
115   }
116   
117   /* continue NSData processing */
118   
119   [self warnWithFormat:@"NSData subject! (using UTF-8 to decode!)"];
120
121   // TODO: exception handler?
122   s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
123   if (s == nil) {
124     [self errorWithFormat:@"could do not decode NSData subject!"];
125     return [self labelForKey:@"Error_CouldNotDecodeSubject"];
126   }
127   
128   r = [[self stringForStringValue:s] copy];
129   [s release];
130   return [r autorelease];
131 }
132
133 /* formatter entry function */
134
135 - (NSString *)stringForObjectValue:(id)_subject {
136   if (![_subject isNotNull])
137     return [self missingSubjectLabel];
138   
139   if ([_subject isKindOfClass:StrClass])
140     return [self stringForStringValue:_subject];
141   if ([_subject isKindOfClass:DataClass])
142     return [self stringForDataValue:_subject];
143   
144   return [self stringForStringValue:[_subject stringValue]];
145 }
146
147 @end /* UIxSubjectFormatter */