2005-12-13 Helge Hess <helge.hess@opengroupware.org>
+ * NGMail: some code cleanups / reorgs (v4.5.239)
+
* v4.5.238
* NGImap4: fixed QP handling in IMAP4 envelopes (#1587)
+2005-12-13 Helge Hess <helge.hess@opengroupware.org>
+
+ * NGMimeMessageParser.m: moved NSData QP category to own file
+ (NSData+MimeQP.m)
+
2005-07-20 Helge Hess <helge.hess@opengroupware.org>
* NGMimeMessage.m: added some convinience methods to access the header
NGMimeMessageTextBodyGenerator.m \
\
NGMailBase64Encoding.m \
+ NSData+MimeQP.m \
-include GNUmakefile.preamble
ifneq ($(frameworks),yes)
#include "common.h"
#include <string.h>
-
-
@interface NGMimeMessageParserDelegate : NSObject
@end
@implementation NGMimeMessageParserDelegate
-static int UseFoundationStringEncodingForMimeHeader = -1;
-static Class NGMimeMessageParserClass = NULL;
+static Class NGMimeMessageParserClass = Nil;
+ (void)initialize {
- if (UseFoundationStringEncodingForMimeHeader == -1) {
- UseFoundationStringEncodingForMimeHeader
- = [[NSUserDefaults standardUserDefaults]
- boolForKey:@"UseFoundationStringEncodingForMimeHeader"]
- ? 1 : 0;
- }
- if (NGMimeMessageParserClass == NULL) {
+ if (NGMimeMessageParserClass == Nil)
NGMimeMessageParserClass = [NGMimeMessageParser class];
- }
}
- (id)parser:(NGMimePartParser *)_p parseHeaderField:(NSString *)_field
@end /* NGMimeMessageParser */
-@implementation NSData(MimeQPHeaderFieldDecoding)
-
-- (id)decodeQuotedPrintableValueOfMIMEHeaderField:(NSString *)_name {
- // check data for 8-bit headerfields (RFC 2047 (MIME PART III))
- static Class NGMimeTypeClass = Nil;
- enum {
- NGMimeMessageParser_quoted_start = 1,
- NGMimeMessageParser_quoted_charSet = 2,
- NGMimeMessageParser_quoted_qpData = 3,
- NGMimeMessageParser_quoted_end = 4
- } status = NGMimeMessageParser_quoted_start;
- unsigned int length;
- const unsigned char *bytes, *firstEq;
- BOOL foundQP = NO;
-
- if (NSStringClass == Nil) NSStringClass = [NSString class];
- if (NGMimeTypeClass == Nil) NGMimeTypeClass = [NGMimeType class];
-
- length = [self length];
-
- /* check whether the string is long enough to be quoted etc */
- if (length <= 6)
- return self;
-
- /* check whether the string contains QP tokens ... */
- bytes = [self bytes];
-
- if ((firstEq = memchr(bytes, '=', length)) == NULL)
- return self;
-
- /* process data ... (quoting etc) */
- {
- unichar *buffer;
- unsigned int bufLen, maxBufLen;
- NSString *charset;
- BOOL appendLC;
- int cnt, tmp;
- unsigned char encoding;
-
- buffer = calloc(length + 13, sizeof(unichar));
-
- maxBufLen = length + 3;
- buffer[maxBufLen - 1] = '\0';
- bufLen = 0;
-
- encoding = 0;
- tmp = -1;
- appendLC = YES;
- charset = nil;
- status = NGMimeMessageParser_quoted_start;
-
- /* copy data up to first '=' sign */
- if ((cnt = (firstEq - bytes)) > 0) {
- for (; bufLen < cnt; bufLen++)
- buffer[bufLen] = bytes[bufLen];
- }
-
- for (; cnt < (length-1); cnt++) {
- appendLC = YES;
-
- if (status == NGMimeMessageParser_quoted_start) {
- if ((bytes[cnt] == '=') && (bytes[cnt + 1] == '?')) { // found begin
- cnt++;
- status = NGMimeMessageParser_quoted_charSet;
- }
- else { // other char
- if (bytes[cnt + 1] != '=') {
- buffer[bufLen++] = bytes[cnt];
- buffer[bufLen++] = bytes[cnt+1];
- cnt++;
- if (cnt >= length - 1)
- appendLC = NO;
- }
- else {
- buffer[bufLen++] = bytes[cnt];
- }
- }
- }
- else if (status == NGMimeMessageParser_quoted_charSet) {
- if (tmp == -1)
- tmp = cnt;
-
- if (bytes[cnt] == '?') {
- charset =
- [NSStringClass stringWithCString:(char *)(bytes + tmp)
- length:(cnt - tmp)];
- tmp = -1;
-
- if ((length - cnt) > 2) {
- // set encoding (eg 'q' for quoted printable)
- cnt++; // skip '?'
- encoding = bytes[cnt];
- cnt++; // skip encoding
- status = NGMimeMessageParser_quoted_qpData;
- }
- else { // unexpected end
- NSLog(@"WARNING: unexpected end of header");
- appendLC = NO;
- break;
- }
- }
- }
- else if (status == NGMimeMessageParser_quoted_qpData) {
- if (tmp == -1)
- tmp = cnt;
-
- if ((bytes[cnt] == '?') && (bytes[cnt + 1] == '=')) {
- NSData *tmpData;
- NSString *tmpStr;
- unsigned int tmpLen;
-
- tmpData = _rfc2047Decoding(encoding, (char *)bytes + tmp, cnt - tmp);
- foundQP = YES;
-
- /*
- create a temporary string for charset conversion ...
- Note: the headerfield is currently held in ISO Latin 1
- */
- tmpStr = nil;
-
- if (!UseFoundationStringEncodingForMimeHeader) {
- tmpStr = [NSStringClass stringWithData:tmpData
- usingEncodingNamed:charset];
- }
- if (tmpStr == nil) {
- NSStringEncoding enc;
-
- enc = [NGMimeTypeClass stringEncodingForCharset:charset];
- tmpStr = [[[NSStringClass alloc] initWithData:tmpData encoding:enc]
- autorelease];
- }
- tmpLen = [tmpStr length];
-
- if ((tmpLen + bufLen) < maxBufLen) {
- [tmpStr getCharacters:(buffer + bufLen)];
- bufLen += tmpLen;
- }
- else {
- NSLog(@"ERROR[%s]: quoted data to large --> ignored %@",
- __PRETTY_FUNCTION__, tmpStr);
- }
- tmp = -1;
- cnt++;
- appendLC = YES;
- status = NGMimeMessageParser_quoted_start;
- }
- }
- }
- if (appendLC) {
- if (cnt < length) {
- buffer[bufLen] = bytes[cnt];
- bufLen++;
- }
- }
- buffer[bufLen] = '\0';
- {
- id data;
-
- data = nil;
-
- if (buffer && foundQP) {
- data = [[[NSString alloc] initWithCharacters:buffer length:bufLen]
- autorelease];
- if (data == nil) {
- NSLog(@"%s: got no string for buffer '%s', length '%i' !",
- __PRETTY_FUNCTION__,
- buffer, bufLen);
- }
- }
- if (!data) {
- data = self;
- }
- free(buffer); buffer = NULL;
- return data;
- }
- }
- return self;
-}
-@end /* NSData(MimeQPHeaderFieldDecoding) */
@implementation NGMimeRfc822BodyParser
--- /dev/null
+/*
+ Copyright (C) 2000-2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE 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.
+
+ SOPE 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 SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "common.h"
+#include <string.h>
+
+@implementation NSData(MimeQPHeaderFieldDecoding)
+
+static Class NSStringClass = Nil;
+static Class NGMimeTypeClass = Nil;
+
+static int UseFoundationStringEncodingForMimeHeader = -1;
+
+- (id)decodeQuotedPrintableValueOfMIMEHeaderField:(NSString *)_name {
+ // check data for 8-bit headerfields (RFC 2047 (MIME PART III))
+ /*
+ TODO: document
+
+ This method returns an NSString or an NSData object (or nil).
+ */
+ enum {
+ NGMimeMessageParser_quoted_start = 1,
+ NGMimeMessageParser_quoted_charSet = 2,
+ NGMimeMessageParser_quoted_qpData = 3,
+ NGMimeMessageParser_quoted_end = 4
+ } status = NGMimeMessageParser_quoted_start;
+ unsigned int length;
+ const unsigned char *bytes, *firstEq;
+ BOOL foundQP = NO;
+
+ /* setup statics */
+
+ if (UseFoundationStringEncodingForMimeHeader == -1) {
+ UseFoundationStringEncodingForMimeHeader
+ = [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"UseFoundationStringEncodingForMimeHeader"]
+ ? 1 : 0;
+ }
+
+ if (NSStringClass == Nil) NSStringClass = [NSString class];
+ if (NGMimeTypeClass == Nil) NGMimeTypeClass = [NGMimeType class];
+
+
+ /* begin */
+
+ length = [self length];
+
+ /* check whether the string is long enough to be quoted etc */
+ if (length <= 6)
+ return self;
+
+ /* check whether the string contains QP tokens ... */
+ bytes = [self bytes];
+
+ if ((firstEq = memchr(bytes, '=', length)) == NULL)
+ return self;
+
+ /* process data ... (quoting etc) */
+ {
+ unichar *buffer;
+ unsigned int bufLen, maxBufLen;
+ NSString *charset;
+ BOOL appendLC;
+ int cnt, tmp;
+ unsigned char encoding;
+
+ buffer = calloc(length + 13, sizeof(unichar));
+
+ maxBufLen = length + 3;
+ buffer[maxBufLen - 1] = '\0';
+ bufLen = 0;
+
+ encoding = 0;
+ tmp = -1;
+ appendLC = YES;
+ charset = nil;
+ status = NGMimeMessageParser_quoted_start;
+
+ /* copy data up to first '=' sign */
+ if ((cnt = (firstEq - bytes)) > 0) {
+ for (; bufLen < cnt; bufLen++)
+ buffer[bufLen] = bytes[bufLen];
+ }
+
+ for (; cnt < (length - 1); cnt++) {
+ appendLC = YES;
+
+ if (status == NGMimeMessageParser_quoted_start) {
+ if ((bytes[cnt] == '=') && (bytes[cnt + 1] == '?')) { // found begin
+ cnt++;
+ status = NGMimeMessageParser_quoted_charSet;
+ }
+ else { // other char
+ if (bytes[cnt + 1] != '=') {
+ buffer[bufLen++] = bytes[cnt];
+ buffer[bufLen++] = bytes[cnt+1];
+ cnt++;
+ if (cnt >= length - 1)
+ appendLC = NO;
+ }
+ else {
+ buffer[bufLen++] = bytes[cnt];
+ }
+ }
+ }
+ else if (status == NGMimeMessageParser_quoted_charSet) {
+ if (tmp == -1)
+ tmp = cnt;
+
+ if (bytes[cnt] == '?') {
+ charset =
+ [NSStringClass stringWithCString:(char *)(bytes + tmp)
+ length:(cnt - tmp)];
+ tmp = -1;
+
+ if ((length - cnt) > 2) {
+ // set encoding (eg 'q' for quoted printable)
+ cnt++; // skip '?'
+ encoding = bytes[cnt];
+ cnt++; // skip encoding
+ status = NGMimeMessageParser_quoted_qpData;
+ }
+ else { // unexpected end
+ NSLog(@"WARNING: unexpected end of header");
+ appendLC = NO;
+ break;
+ }
+ }
+ }
+ else if (status == NGMimeMessageParser_quoted_qpData) {
+ if (tmp == -1)
+ tmp = cnt;
+
+ if ((bytes[cnt] == '?') && (bytes[cnt + 1] == '=')) {
+ NSData *tmpData;
+ NSString *tmpStr;
+ unsigned int tmpLen;
+
+ tmpData = _rfc2047Decoding(encoding, (char *)bytes + tmp, cnt - tmp);
+ foundQP = YES;
+
+ /*
+ create a temporary string for charset conversion ...
+ Note: the headerfield is currently held in ISO Latin 1
+ */
+ tmpStr = nil;
+
+ if (!UseFoundationStringEncodingForMimeHeader) {
+ tmpStr = [NSStringClass stringWithData:tmpData
+ usingEncodingNamed:charset];
+ }
+ if (tmpStr == nil) {
+ NSStringEncoding enc;
+
+ enc = [NGMimeTypeClass stringEncodingForCharset:charset];
+ tmpStr = [[[NSStringClass alloc] initWithData:tmpData encoding:enc]
+ autorelease];
+ }
+ tmpLen = [tmpStr length];
+
+ if ((tmpLen + bufLen) < maxBufLen) {
+ [tmpStr getCharacters:(buffer + bufLen)];
+ bufLen += tmpLen;
+ }
+ else {
+ [self errorWithFormat:@"%s: quoted data to large --> ignored %@",
+ __PRETTY_FUNCTION__, tmpStr];
+ }
+ tmp = -1;
+ cnt++;
+ appendLC = YES;
+ status = NGMimeMessageParser_quoted_start;
+ }
+ }
+ }
+ if (appendLC) {
+ if (cnt < length) {
+ buffer[bufLen] = bytes[cnt];
+ bufLen++;
+ }
+ }
+ buffer[bufLen] = '\0';
+ {
+ id data;
+
+ data = nil;
+
+ if (buffer && foundQP) {
+ data = [[[NSStringClass alloc] initWithCharacters:buffer length:bufLen]
+ autorelease];
+ if (data == nil) {
+ [self warnWithFormat:
+ @"%s: got no string for buffer '%s', length '%i' !",
+ __PRETTY_FUNCTION__, buffer, bufLen];
+ }
+ }
+
+ if (data == nil)
+ data = self; /* we return an NSData */
+
+ if (buffer != NULL) free(buffer); buffer = NULL;
+ return data;
+ }
+ }
+ return self;
+}
+
+@end /* NSData(MimeQPHeaderFieldDecoding) */
NSData *data = nil;
if ((_enc == 'b') || (_enc == 'B')) { // use BASE64 decoding
+ // TODO: improve efficiency (directly decode buffers w/o NSData)
NSData *tmp;
tmp = [[NSData alloc] initWithBytes:_bytes length:_length];
data = [tmp dataByDecodingBase64];
- RELEASE(tmp);
+ [tmp release]; tmp = nil;
}
else if ((_enc == 'q') || (_enc == 'Q')) { // use quoted-printable decoding
char *dest = NULL;
size_t resSize = 0;
destSize = _length;
- dest = NGMallocAtomic(destSize * sizeof(char));
+ dest = calloc(destSize + 2, sizeof(char));
resSize = NGDecodeQuotedPrintable(_bytes, _length, dest, destSize);
if ((int)resSize != -1) {
data = [NSData dataWithBytesNoCopy:dest length:resSize];
else {
NSLog(@"WARNING(%s): An error occour during quoted-printable decoding",
__PRETTY_FUNCTION__);
- NGFree(dest); dest = NULL;
+ if (dest != NULL) free(dest); dest = NULL;
data = [NSData dataWithBytes:_bytes length:_length];
}
}
MAJOR_VERSION:=4
MINOR_VERSION:=5
-SUBMINOR_VERSION:=238
+SUBMINOR_VERSION:=239
# v4.5.214 requires libNGExtensions v4.5.146
# v4.2.149 requires libNGStreams v4.2.34