]> err.no Git - sope/blob - sope-mime/NGImap4/NGImap4Message+BodyStructure.h
new Xcode projects
[sope] / sope-mime / NGImap4 / NGImap4Message+BodyStructure.h
1 /*
2   Copyright (C) 2000-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  // $Id$
22
23 #ifndef __NGImap4Message_BodyStructure_H__
24 #define __NGImap4Message_BodyStructure_H__
25
26
27 @interface NSCalendarDate(RFC822Dates)
28 + (NSCalendarDate *)calendarDateWithRfc822DateString:(NSString *)_str;
29 @end /* NSString(RFC822Dates) */
30
31 @interface NGImap4Message(BodyStructure)
32
33 static id _buildMultipartMessage(id self, NSURL *_baseUrl, NSDictionary *_dict,
34                                  id<NGMimePart>_part);
35 static id _buildMessage(id self, NSURL *_baseUrl, NSDictionary *_dict);
36 static id _buildPart(id self, NSURL *_baseUrl, NSDictionary *_dict);
37 static id _buildMimeBodyPart(id self, NSDictionary *_dict);
38 static id _buildMimeMessageBody(id self, NSURL *_baseUrl, NSDictionary *_dict,
39                                 id<NGMimePart>_part);
40 @end  /* NGImap4Message(BodyStructure) */
41
42 @implementation NGImap4Message(BodyStructure)
43        
44 static id _buildMultipartMessage(id self, NSURL *_baseUrl, NSDictionary *_dict,
45                                  id<NGMimePart>_part) {
46   NGMimeMultipartBody *body;
47   NSEnumerator        *enumerator;
48   NSDictionary        *part;
49   int                 cnt;
50   
51   body = [[NGMimeMultipartBody alloc] initWithPart:_part];
52   enumerator = [[_dict objectForKey:@"parts"] objectEnumerator];
53
54   cnt = 1;
55   while ((part = [enumerator nextObject])) {
56     NSURL *url;
57
58     {
59       NSString *baseStr;
60
61       baseStr = [_baseUrl absoluteString];
62
63       if ([baseStr hasSuffix:@"="])
64         url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%d",
65                                              baseStr, cnt]];
66       else
67         url = [NSURL URLWithString:[NSString stringWithFormat:@"%@.%d",
68                                              baseStr, cnt]];
69     }
70     [body addBodyPart:_buildPart(self, url, part)];
71     cnt++;
72   }
73   return [body autorelease];
74 }
75
76 static id _buildMessage(id self, NSURL *_baseUrl, NSDictionary *_dict) {
77   NGMutableHashMap *map;
78   NGMimeMessage    *message;
79   NSString         *value;
80
81   static NGMimeHeaderNames *Fields = NULL;
82
83   if (!Fields)
84     Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames];
85   
86
87   map = [NGMutableHashMap hashMapWithCapacity:4];
88
89   if ((value = [_dict objectForKey:@"subject"])) {
90     [map setObject:value forKey:Fields->subject];
91   }
92   if ((value = [_dict objectForKey:@"messageId"])) {
93     [map setObject:value forKey:Fields->messageID];
94   }
95   if ((value = [_dict objectForKey:@"in-reply-to"])) {
96     [map setObject:value forKey:@"in-reply-to"];
97   }
98   if ((value = [_dict objectForKey:Fields->contentLength])) {
99     [map setObject:value forKey:Fields->contentLength];
100   }
101   if ((value = [_dict objectForKey:@"date"])) {
102     NSCalendarDate *d;
103
104     if ((d = [NSCalendarDate calendarDateWithRfc822DateString:value])) 
105       [map setObject:d forKey:Fields->date];
106   }
107   {
108     NSEnumerator   *enumerator;
109     id             obj;
110     static NSArray *Array = nil;
111
112     if (Array == nil) {
113       Array = [[NSArray alloc] initWithObjects:
114                                Fields->from,
115                                @"sender",
116                                Fields->replyTo,
117                                Fields->to,
118                                Fields->cc,
119                                @"bcc", nil];
120     }
121     enumerator = [Array objectEnumerator];
122     while ((obj = [enumerator nextObject])) {
123       NSArray *addrs;
124
125       if ((addrs = [_dict objectForKey:obj])) {
126         NSEnumerator *addrEnum;
127         NSDictionary *addr;
128         NSMutableString *str;
129
130         addrEnum = [addrs objectEnumerator];
131         str      = nil;
132         while ((addr = [addrEnum nextObject])) {
133           NSString *personalName, *mailboxName, *hostName;
134           if (!str) {
135             str = [NSMutableString stringWithCapacity:32];
136           }
137           else {
138             [str appendString:@", "];
139           }
140           personalName = [addr objectForKey:@"personalName"];
141           mailboxName  = [addr objectForKey:@"mailboxName"];
142           hostName     = [addr objectForKey:@"hostName"];
143
144           if ([personalName length]) {
145             [str appendFormat:@"\"%@\" <%@@%@>", personalName,
146                  mailboxName, hostName];
147           }
148           else {
149             [str appendFormat:@"%@@%@", mailboxName, hostName];
150           }
151         }
152         if (str)
153           [map setObject:str forKey:obj];
154       }
155     }
156   }
157   {
158     id part, tmp, body;
159
160     part = _buildPart(self, _baseUrl, [_dict objectForKey:@"body"]);
161
162     [map setObject:[part contentType] forKey:Fields->contentType];
163
164     if (![[map valueForKey:Fields->contentTransferEncoding] length]) {
165       if ((tmp = [[part valuesOfHeaderFieldWithName:
166                         Fields->contentTransferEncoding] nextObject])) {
167         [map setObject:tmp forKey:Fields->contentTransferEncoding];
168       }
169     }
170     if (![[map valueForKey:Fields->contentLength] intValue]) {
171       if ((tmp = [[part valuesOfHeaderFieldWithName:Fields->contentLength]
172                   nextObject])) {
173         [map setObject:tmp forKey:Fields->contentLength];
174       }
175     }
176     message = [NGMimeMessage messageWithHeader:map];
177
178     if ([(body = [part body]) isKindOfClass:[NSURL class]]) {
179       NSString *baseStr;
180
181       baseStr = [body absoluteString];
182
183       if ([baseStr hasPrefix:@"="]) {
184         body = [NSURL URLWithString:[NSString stringWithFormat:@"%@1",
185                                               baseStr]];
186       }
187       else
188         body = [NSURL URLWithString:[NSString stringWithFormat:@"%@.1",
189                                               baseStr]];
190     }
191     [message setBody:body];
192   }
193   return message;
194 }
195
196 static id _buildPart(id self, NSURL *_baseUrl, NSDictionary *_dict) {
197   NSString       *type, *subType;
198   NGMimeBodyPart *part;
199   NSURL          *url;
200
201   url     = _baseUrl;
202   type    = [[_dict objectForKey:@"type"] lowercaseString]; 
203   subType = [[_dict objectForKey:@"subtype"] lowercaseString];
204  
205   part = _buildMimeBodyPart(self, _dict);
206     
207   if ([type isEqualToString:@"multipart"]) {
208     [part setBody:_buildMultipartMessage(self, url, _dict, part)];
209   }
210   else if ([type isEqualToString:@"message"] &&
211            [subType isEqualToString:@"rfc822"]) {
212     [part setBody:_buildMessage(self, url, _dict)];
213   }
214   else {
215     [part setBody:url];
216   }
217   return part;
218 }
219
220 static id _buildMimeBodyPart(id self, NSDictionary *_dict)
221 {
222   NGMutableHashMap *dict;
223   NSString         *value;
224   NGMimeType       *type;
225   static NGMimeHeaderNames *Fields = NULL;
226
227   if (!Fields)
228     Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames];
229   
230
231   dict = [NGMutableHashMap hashMapWithCapacity:8];
232
233   type = [NGMimeType mimeType:[[_dict objectForKey:@"type"] lowercaseString]
234                      subType:[[_dict objectForKey:@"subtype"] lowercaseString]
235                      parameters:[_dict objectForKey:@"parameterList"]];
236
237   [dict setObject:type forKey:Fields->contentType];
238
239   if (([value = [_dict objectForKey:@"bodyId"] length])) {
240     [dict setObject:value forKey:Fields->messageID];
241   }
242
243   if (([value = [_dict objectForKey:@"size"] length])) {
244     [dict setObject:value forKey:Fields->contentLength];
245   }
246   if (([value = [_dict objectForKey:@"encoding"] length])) {
247     [dict setObject:[value lowercaseString]
248           forKey:Fields->contentTransferEncoding];
249   }
250   return [NGMimeBodyPart bodyPartWithHeader:dict];
251 }
252
253
254 static id _buildMimeMessageBody(id self, NSURL *_baseUrl, NSDictionary *_dict,
255                                 id<NGMimePart>_part)
256 {
257   NSString *type, *subType;
258   NSURL    *url;
259   id       result;
260
261   type    = [[_dict objectForKey:@"type"] lowercaseString];
262   subType = [[_dict objectForKey:@"subtype"] lowercaseString];
263
264   url = [NSURL URLWithString:[[_baseUrl absoluteString]
265                                         stringByAppendingString:@"?part="]];
266   if ([type isEqualToString:@"multipart"]) {
267     result = _buildMultipartMessage(self, url, _dict, _part);
268   }
269   else {
270     if ([type isEqualToString:@"message"] &&
271         [subType isEqualToString:@"rfc822"]) {
272       result = _buildMessage(self, url, _dict);
273     }
274     else {
275       result = [NSURL URLWithString:[[_baseUrl absoluteString]
276                                         stringByAppendingString:@"?part=1"]];
277     }
278   }
279   return result;
280 }
281
282 @end /* NGImap4Message(BodyStructure) */
283
284 #endif /* __NGImap4Message_BodyStructure_H__ */