2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
23 #import "NGMimePartGenerator.h"
24 #import "NGMimeHeaderFieldGenerator.h"
25 #import "NGMimeBodyGenerator.h"
26 #import "NGMimeJoinedData.h"
27 #import <NGMime/NGMimeType.h>
30 @implementation NGMimePartGenerator
36 + (id)mimePartGenerator {
37 return [[[self alloc] init] autorelease];
41 if ((self = [super init])) {
44 self->appendBytes = NULL;
50 [self->result release];
52 self->appendBytes = NULL;
56 /* setting the delegate */
58 - (void)setDelegate:(id)_delegate {
59 self->delegate = _delegate;
61 self->delegateRespondsTo.generatorGenerateDataForHeaderField =
62 [self->delegate respondsToSelector:
63 @selector(mimePartGenerator:generateDataForHeaderField:value:)];
65 self->delegateRespondsTo.generatorGeneratorForBodyOfPart =
66 [self->delegate respondsToSelector:
67 @selector(mimePartGenerator:generatorForBodyOfPart:)];
69 self->delegateRespondsTo.generatorGenerateDataForBodyOfPart =
70 [self->delegate respondsToSelector:
71 @selector(mimePartGenerator:generateDataForBodyOfPart:additionalHeaders:)];
75 return self->delegate;
78 - (BOOL)prepareForGenerationOfPart:(id<NGMimePart>)_part {
85 [tmp release]; tmp = nil;
88 [self->result release];
91 self->result = (self->useMimeData)
92 ? [[NGMimeJoinedData alloc] init]
93 : [[NSMutableData alloc] initWithCapacity:4096];
96 if ([self->result respondsToSelector:@selector(methodForSelector:)])
97 self->appendBytes = (void(*)(id,SEL,const void *, unsigned))
98 [self->result methodForSelector:
99 @selector(appendBytes:length:)];
101 self->appendBytes = NULL;
105 - (BOOL)generatePrefix {
109 - (void)generateSuffix {
112 - (id<NGMimeHeaderFieldGenerator>)generatorForHeaderField:(NSString *)_name {
113 return [NGMimeHeaderFieldGeneratorSet defaultRfc822HeaderFieldGeneratorSet];
116 - (NSData *)generateDataForHeaderField:(NSString *)_headerField
121 if (self->delegateRespondsTo.generatorGenerateDataForHeaderField)
122 data = [self->delegate mimePartGenerator:self
123 generateDataForHeaderField:_headerField
126 data = [[self generatorForHeaderField:_headerField]
127 generateDataForHeaderFieldNamed:_headerField
133 - (NSData *)generateDataWithHeaderField:(NSString *)_headerField
134 values:(NSEnumerator *)_values
136 NSMutableData *res = nil;
139 const char *bytes = NULL;
142 res = [NSMutableData dataWithCapacity:64];
143 bytes = [_headerField cString];
144 len = [_headerField length];
151 while ((value = [_values nextObject])) {
152 data = [self generateDataForHeaderField:(NSString *)_headerField
154 [res appendBytes:bytes length:len];
155 [res appendBytes:": " length:2];
156 [res appendData:data];
157 [res appendBytes:"\n" length:1];
163 - (NSData *)generateHeaderData:(NGHashMap *)_additionalHeaders {
164 NSEnumerator *headerFieldNames = nil;
165 NSString *headerFieldName = nil;
166 NGMutableHashMap *addHeaders = nil;
167 NSMutableData *data = nil;
169 data = (self->useMimeData)
170 ? [[[NGMimeJoinedData alloc] init] autorelease]
171 : [NSMutableData dataWithCapacity:2048];
173 headerFieldNames = [self->part headerFieldNames];
174 addHeaders = [_additionalHeaders mutableCopy];
176 while ((headerFieldName = [headerFieldNames nextObject])) {
177 NSData *headerFieldData = nil;
178 NSEnumerator *enumerator = nil;
181 if ([[_additionalHeaders objectsForKey:headerFieldName] count] > 0) {
182 enumerator = [addHeaders objectEnumeratorForKey:headerFieldName];
187 enumerator = [self->part valuesOfHeaderFieldWithName:headerFieldName];
189 headerFieldData = [self generateDataWithHeaderField:headerFieldName
192 [addHeaders removeAllObjectsForKey:headerFieldName];
195 [data appendData:headerFieldData];
197 headerFieldNames = [addHeaders keyEnumerator];
198 while ((headerFieldName = [headerFieldNames nextObject])) {
199 NSData *headerFieldData = nil;
200 headerFieldData = [self generateDataWithHeaderField:headerFieldName
201 values:[addHeaders objectEnumeratorForKey:
204 [data appendData:headerFieldData];
206 [addHeaders release]; addHeaders = nil;
210 - (NGMimeType *)defaultContentTypeForPart:(id<NGMimePart>)_part {
211 return [NGMimeType mimeType:@"application/octet"];
214 - (id<NGMimeBodyGenerator>)defaultBodyGenerator {
215 id<NGMimeBodyGenerator> gen;
217 gen = [[[NGMimeBodyGenerator alloc] init] autorelease];
218 [(id)gen setUseMimeData:self->useMimeData];
222 - (id<NGMimeBodyGenerator>)generatorForBodyOfPart:(id<NGMimePart>)_part {
223 id<NGMimeBodyGenerator> bodyGen = nil;
224 NGMimeType *contentType = nil;
225 NSString *type = nil;
227 if (self->delegateRespondsTo.generatorGeneratorForBodyOfPart)
228 bodyGen = [self->delegate mimePartGenerator:self
229 generatorForBodyOfPart:self->part];
232 contentType = [_part contentType];
233 if (contentType == nil) {
234 contentType = [self defaultContentTypeForPart:_part];
236 if (contentType == nil) {
237 NSLog(@"WARNING(%s): no content-type", __PRETTY_FUNCTION__);
240 type = [contentType type];
242 if ([type isEqualToString:NGMimeTypeMultipart]) {
243 bodyGen = [[[NGMimeMultipartBodyGenerator alloc] init] autorelease];
245 else if ([type isEqualToString:NGMimeTypeText]) {
246 bodyGen = [[[NGMimeTextBodyGenerator alloc] init] autorelease];
248 else if (([type isEqualToString:NGMimeTypeMessage]) &&
249 [[contentType subType] isEqualToString:@"rfc822"]) {
250 bodyGen = [[[NGMimeRfc822BodyGenerator alloc] init] autorelease];
253 [(id)bodyGen setUseMimeData:self->useMimeData];
257 - (NSData *)generateBodyData:(NGMutableHashMap *)_additionalHeaders {
259 id<NGMimeBodyGenerator> bodyGen = nil;
261 if (self->delegateRespondsTo.generatorGenerateDataForBodyOfPart) {
262 data = [self->delegate mimePartGenerator:self
263 generateDataForBodyOfPart:self->part
264 additionalHeaders:_additionalHeaders];
267 bodyGen = [self generatorForBodyOfPart:self->part];
269 if (bodyGen == nil) // no generator for body
270 bodyGen = [self defaultBodyGenerator];
272 [(id)bodyGen setUseMimeData:self->useMimeData];
274 if (bodyGen == nil) {
275 id body = [self->part body];
276 NSLog(@"WARNING(%s): no defaultBodyGenerator", __PRETTY_FUNCTION__);
277 if ([body isKindOfClass:[NSData class]]) {
280 else if ([body isKindOfClass:[NSString class]]) {
281 data = [body dataUsingEncoding:[NSString defaultCStringEncoding]];
285 data = [bodyGen generateBodyOfPart:self->part
286 additionalHeaders:_additionalHeaders
287 delegate:self->delegate];
293 - (void)generateData {
294 NGMutableHashMap *additionalHeaders = nil;
295 NSData *bodyData = nil;
296 NSData *headerData = nil;
298 additionalHeaders = [[NGMutableHashMap alloc] initWithCapacity:16];
300 bodyData = [self generateBodyData:additionalHeaders];
301 headerData = [self generateHeaderData:additionalHeaders];
303 if (headerData != nil) {
304 [self->result appendData:headerData];
305 [self->result appendBytes:"\n" length:1];
307 [self->result appendData:bodyData];
309 [additionalHeaders release];
312 - (NSData *)generateMimeFromPart:(id<NGMimePart>)_part {
313 [self prepareForGenerationOfPart:_part];
314 if ([self generatePrefix]) {
318 [self generateSuffix];
321 return [data autorelease];
326 - (NSString *)generateMimeFromPartToFile:(id<NGMimePart>)_part {
327 NSString *filename = nil;
329 static NSString *TmpPath = nil;
330 static NSProcessInfo *Pi = nil;
332 if (TmpPath == nil) {
333 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
335 TmpPath = [ud stringForKey:@"NGMimeBuildMimeTempDirectory"];
338 TmpPath = [[TmpPath stringByAppendingPathComponent:@"OGo"] copy];
341 Pi = [[NSProcessInfo processInfo] retain];
343 filename = [Pi temporaryFileName:TmpPath];
345 [self setUseMimeData:YES];
347 if (![[self generateMimeFromPart:_part]
348 writeToFile:filename atomically:YES]) {
349 NSLog(@"ERROR[%s] couldn`t write data to temorary file %@",
350 __PRETTY_FUNCTION__, filename);
356 - (id<NGMimePart>)part {
360 - (BOOL)useMimeData {
361 return self->useMimeData;
364 - (void)setUseMimeData:(BOOL)_b {
365 self->useMimeData = _b;
368 @end /* NGMimePartGenerator */