/* Copyright (C) 2000-2004 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: NGMimeMessageGenerator.m 11 2004-08-20 19:20:03Z helge $ #include "NGMimeMessageGenerator.h" #include "NGMimeMessage.h" #include #include "common.h" /* Defaults Mail_Use_8bit_Encoding_For_Text[BOOL] -- Use 8bit content-transfer-encoding for text messages */ NSData * _base64Encoding(NGMimeBodyGenerator *self, NSData *_data_, id_part, NGMutableHashMap *_addHeaders) { NSString *transEnc = nil; const char *bytes = NULL; unsigned length = 0; if ([_data_ isKindOfClass:[NGMimeFileData class]]) return _data_; bytes = [_data_ bytes]; length = [_data_ length]; while (length > 0) { if ((unsigned char)*bytes > 127) { break; } bytes++; length--; } if (length > 0) { // should be encoded NGMimeType *type; type = [_part contentType]; if ([[type type] isEqualToString:@"text"] == YES) { BOOL use8bit; use8bit = [[NSUserDefaults standardUserDefaults] boolForKey: @"Mail_Use_8bit_Encoding_For_Text"]; if (use8bit) { transEnc = @"8bit"; } else { _data_ = [_data_ dataByEncodingQuotedPrintable]; transEnc = @"quoted-printable"; } } else { _data_ = [_data_ dataByEncodingBase64]; transEnc = @"base64"; if (type == nil) { [_addHeaders setObject:[NGMimeType mimeType:@"application" subType:@"octet-stream"] forKey:@"content-type"]; } } } else { // no encoding transEnc = @"7bit"; } [_addHeaders setObject:transEnc forKey:@"content-transfer-encoding"]; [_addHeaders setObject:[NSNumber numberWithInt:[_data_ length]] forKey:@"content-length"]; return _data_; } @implementation NGMimeMessageGenerator + (int)version { return 2; } + (void)initialize { NSAssert2([super version] == 2, @"invalid superclass (%@) version %i !", NSStringFromClass([self superclass]), [super version]); } /* header field specifics */ - (NSData *)generateDataForHeaderField:(NSString *)_headerField value:(id)_value { NSData *data = nil; data = [super generateDataForHeaderField:_headerField value:_value]; { const char *bytes = NULL; unsigned int length = 0; unsigned int desLen = 0; char *des = NULL; unsigned int cnt = 0; BOOL doEnc = NO; NSString *str; #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY str = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding]; #else str = [[NSString alloc] initWithData:data encoding:NSISOLatin9StringEncoding]; #endif str = [str autorelease]; bytes = [str cString]; length = [str cStringLength]; while (cnt < length) { if ((unsigned char)bytes[cnt] > 127) { doEnc = YES; break; } cnt++; } if (doEnc) { char iso[] = "=?iso-8859-15?q?"; unsigned isoLen = 16; char isoEnd[] = "?="; unsigned isoEndLen = 2; desLen = length * 3 + 20; des = NGMallocAtomic(sizeof(char) * desLen + 2); // memcpy(des, bytes, cnt); memcpy(des, iso, isoLen); desLen = NGEncodeQuotedPrintableMime(bytes, length, des + isoLen, desLen - isoLen); if ((int)desLen != -1) { memcpy(des + isoLen + desLen, isoEnd, isoEndLen); data = [NSData dataWithBytesNoCopy:des length:(isoLen + desLen + isoEndLen)]; } else { NSLog(@"WARNING: An error occour during quoted-printable decoding"); if (des) NGFree(des); } } } return data; } /* content-transfer-encoding */ - (id)defaultBodyGenerator { id gen; gen = [[NGMimeMessageBodyGenerator allocWithZone:[self zone]] init]; [gen setUseMimeData:self->useMimeData]; return gen; } - (id)generatorForBodyOfPart:(id)_part { id bodyGen = nil; NGMimeType *contentType = nil; NSString *type = nil; if (self->delegateRespondsTo.generatorGeneratorForBodyOfPart) bodyGen = [self->delegate mimePartGenerator:self generatorForBodyOfPart:self->part]; if (bodyGen) return bodyGen; contentType = [_part contentType]; if (contentType == nil) { contentType = [self defaultContentTypeForPart:_part]; } if (contentType == nil) { NSLog(@"WARNING: no content-type"); return nil; } type = [contentType type]; if ([type isEqualToString:NGMimeTypeMultipart]) { bodyGen = [[[NGMimeMessageMultipartBodyGenerator alloc] init] autorelease]; } else if ([type isEqualToString:NGMimeTypeText]) { bodyGen = [[[NGMimeMessageTextBodyGenerator alloc] init] autorelease]; } else if (([type isEqualToString:NGMimeTypeMessage]) && [[contentType subType] isEqualToString:@"rfc822"]) { bodyGen = [[[NGMimeMessageRfc822BodyGenerator alloc] init] autorelease]; } [(id)bodyGen setUseMimeData:self->useMimeData]; return bodyGen; } @end /* NGMimeMessageGenerator */