From 4dcb480eeb4d18e9e07b70948ac26955a07ad718 Mon Sep 17 00:00:00 2001 From: helge Date: Thu, 24 Mar 2005 18:17:35 +0000 Subject: [PATCH] fixed OGo bug #1324 git-svn-id: http://svn.opengroupware.org/SOPE/trunk@698 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-mime/ChangeLog | 3 + sope-mime/NGImap4/ChangeLog | 4 + sope-mime/NGImap4/EOQualifier+IMAPAdditions.m | 2 + sope-mime/NGMail/ChangeLog | 5 + sope-mime/NGMail/NGMimeMessageGenerator.h | 2 +- sope-mime/NGMail/NGMimeMessageGenerator.m | 33 +++++ sope-mime/NGMime/ChangeLog | 5 + sope-mime/NGMime/NGMimePartGenerator.h | 8 +- sope-mime/NGMime/NGMimePartGenerator.m | 114 +++++++++++------- sope-mime/Version | 2 +- 10 files changed, 127 insertions(+), 51 deletions(-) diff --git a/sope-mime/ChangeLog b/sope-mime/ChangeLog index 2cfeee07..90118a35 100644 --- a/sope-mime/ChangeLog +++ b/sope-mime/ChangeLog @@ -1,5 +1,8 @@ 2005-03-24 Helge Hess + * NGMime, NGMail: fixed OGo bug #1324 by adding support for multivalue + header fields (v4.5.219) + * NGMime: minor code cleanups (v4.5.218) 2005-03-05 Helge Hess diff --git a/sope-mime/NGImap4/ChangeLog b/sope-mime/NGImap4/ChangeLog index d3b24499..f544c861 100644 --- a/sope-mime/NGImap4/ChangeLog +++ b/sope-mime/NGImap4/ChangeLog @@ -1,3 +1,7 @@ +2005-03-24 Helge Hess + + * EOQualifier+IMAPAdditions.m: fixed a warning + 2005-03-05 Helge Hess * NGImap4Folder.m: properly create NSURL if the absolute name doesn't diff --git a/sope-mime/NGImap4/EOQualifier+IMAPAdditions.m b/sope-mime/NGImap4/EOQualifier+IMAPAdditions.m index 87b86e44..0b6cd671 100644 --- a/sope-mime/NGImap4/EOQualifier+IMAPAdditions.m +++ b/sope-mime/NGImap4/EOQualifier+IMAPAdditions.m @@ -31,6 +31,8 @@ insertNot:(BOOL)_insertNot; - (NSException *)appendToImap4SearchString:(NSMutableString *)_search; +- (id)imap4SearchString; + @end @implementation EOQualifier(IMAPAdditions) diff --git a/sope-mime/NGMail/ChangeLog b/sope-mime/NGMail/ChangeLog index 96648451..e1ef34ce 100644 --- a/sope-mime/NGMail/ChangeLog +++ b/sope-mime/NGMail/ChangeLog @@ -1,3 +1,8 @@ +2005-03-24 Helge Hess + + * NGMimeMessageGenerator.m: mark To, Cc and Bcc as multivalue header + fields to fix #1324 + 2005-03-24 Helge Hess * NGMimeMessageGenerator.m: minor code cleanups diff --git a/sope-mime/NGMail/NGMimeMessageGenerator.h b/sope-mime/NGMail/NGMimeMessageGenerator.h index 2b4635bb..01573585 100644 --- a/sope-mime/NGMail/NGMimeMessageGenerator.h +++ b/sope-mime/NGMail/NGMimeMessageGenerator.h @@ -26,7 +26,7 @@ #include /* - Parses Rfc822 Mime Message Parts + Generates RFC 2822 MIME message parts. */ @interface NGMimeMessageBodyGenerator : NGMimeBodyGenerator diff --git a/sope-mime/NGMail/NGMimeMessageGenerator.m b/sope-mime/NGMail/NGMimeMessageGenerator.m index 50820cf0..736a9da1 100644 --- a/sope-mime/NGMail/NGMimeMessageGenerator.m +++ b/sope-mime/NGMail/NGMimeMessageGenerator.m @@ -45,6 +45,39 @@ static BOOL debugOn = NO; /* header field specifics */ +- (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField { + /* + This is called by the superclass when generating fields. + + Currently checks for: to, cc, bcc + */ + unsigned len; + unichar c0, c1; + + if ((len = [_headerField length]) < 2) + return [super isMultiValueCommaHeaderField:_headerField]; + + c0 = [_headerField characterAtIndex:0]; + c1 = [_headerField characterAtIndex:1]; + + switch (len) { + case 2: + if ((c0 == 't' || c0 == 'T') && ((c1 == 'o' || c1 == 'O'))) + return YES; + if ((c0 == 'c' || c0 == 'C') && ((c1 == 'c' || c1 == 'C'))) + return YES; + break; + case 3: + if ((c0 == 'b' || c0 == 'B') && ((c1 == 'c' || c1 == 'C'))) { + c0 = [_headerField characterAtIndex:2]; + if (c0 == 'c' || c0 == 'C') + return YES; + } + break; + } + return [super isMultiValueCommaHeaderField:_headerField]; +} + - (id)_escapeHeaderFieldValue:(NSData *)_data { const char *bytes = NULL; unsigned int length = 0; diff --git a/sope-mime/NGMime/ChangeLog b/sope-mime/NGMime/ChangeLog index 7f0e2c61..5e02edef 100644 --- a/sope-mime/NGMime/ChangeLog +++ b/sope-mime/NGMime/ChangeLog @@ -1,3 +1,8 @@ +2005-03-24 Helge Hess + + * NGMimePartGenerator.m: minor improvement in field generation API, + added support for multivalue headers (related to #1324) + 2005-03-05 Helge Hess * NGMimePartGenerator.m: properly terminate header fields with \r\n diff --git a/sope-mime/NGMime/NGMimePartGenerator.h b/sope-mime/NGMime/NGMimePartGenerator.h index 973f7779..a5fc4926 100644 --- a/sope-mime/NGMime/NGMimePartGenerator.h +++ b/sope-mime/NGMime/NGMimePartGenerator.h @@ -26,7 +26,8 @@ #import #import -@class NSMutableData, NSData, NSString, NGHashMap, NGMutableHashMap; +@class NSMutableData, NSData, NSString, NSEnumerator; +@class NGHashMap, NGMutableHashMap; @class NGMimeType, NGMimePartGenerator; @interface NGMimePartGenerator : NSObject @@ -95,8 +96,9 @@ /* build data with the specified header; */ -- (NSData *)generateDataWithHeaderField:(NSString *)_headerField - values:(NSEnumerator *)_enumerator; +- (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField; +- (BOOL)appendHeaderField:(NSString *)_field values:(NSEnumerator *)_values + toData:(NSMutableData *)_data; /* looking for a NGMimeBodyGenerator in dependece to the content-type */ - (id)generatorForBodyOfPart:(id)_part; diff --git a/sope-mime/NGMime/NGMimePartGenerator.m b/sope-mime/NGMime/NGMimePartGenerator.m index 0e915e7e..bd3015e4 100644 --- a/sope-mime/NGMime/NGMimePartGenerator.m +++ b/sope-mime/NGMime/NGMimePartGenerator.m @@ -29,7 +29,7 @@ @implementation NGMimePartGenerator static NSProcessInfo *Pi = nil; -static BOOL debugOn = NO; +static BOOL debugOn = NO; + (int)version { return 2; @@ -122,12 +122,13 @@ static BOOL debugOn = NO; - (NSData *)generateDataForHeaderField:(NSString *)_headerField value:(id)_value { - NSData *data = nil; + NSData *data; - if (self->delegateRespondsTo.generatorGenerateDataForHeaderField) + if (self->delegateRespondsTo.generatorGenerateDataForHeaderField) { data = [self->delegate mimePartGenerator:self generateDataForHeaderField:_headerField value:_value]; + } else { data = [[self generatorForHeaderField:_headerField] generateDataForHeaderFieldNamed:_headerField @@ -136,54 +137,77 @@ static BOOL debugOn = NO; return data; } -- (NSData *)generateDataWithHeaderField:(NSString *)_headerField - values:(NSEnumerator *)_values +- (BOOL)isMultiValueCommaHeaderField:(NSString *)_headerField { + /* + This is used by NGMimeMessageGenerator to encode multivalue To/Cc/Bcc + in a single line. + */ + return NO; +} + +- (BOOL)appendHeaderField:(NSString *)_field values:(NSEnumerator *)_values + toData:(NSMutableData *)_data { - NSMutableData *res = nil; - NSData *data = nil; - id value = nil; - const char *bytes = NULL; - unsigned len = 0; + /* returns whether data was generated */ + const unsigned char *fcname; + id value = nil; + unsigned len; + BOOL isMultiValue, isFirst; - res = [NSMutableData dataWithCapacity:64]; - bytes = [_headerField cString]; - len = [_headerField length]; - while (len > 0) { - if (*bytes != ' ') + /* get field name and strip leading spaces */ + fcname = [_field cString]; + for (len = [_field cStringLength]; len > 0; fcname++, len--) { + if (*fcname != ' ') break; - bytes++; - len--; } + + isMultiValue = [self isMultiValueCommaHeaderField:_field]; + isFirst = YES; while ((value = [_values nextObject]) != nil) { - data = [self generateDataForHeaderField:(NSString *)_headerField - value:value]; - [res appendBytes:bytes length:len]; - [res appendBytes:": " length:2]; - [res appendData:data]; - [res appendBytes:"\r\n" length:2]; + NSData *data; + + if ((data = [self generateDataForHeaderField:_field value:value]) == nil) + continue; + + if (isMultiValue) { + if (isFirst) { + [_data appendBytes:fcname length:len]; + [_data appendBytes:": " length:2]; + isFirst = NO; + } + else + [_data appendBytes:", " length:2]; + + [_data appendData:data]; + } + else { + [_data appendBytes:fcname length:len]; + [_data appendBytes:": " length:2]; + [_data appendData:data]; + [_data appendBytes:"\r\n" length:2]; + } } - return res; + if (!isFirst && isMultiValue) [_data appendBytes:"\r\n" length:2]; + return isFirst; } - - (NSData *)generateHeaderData:(NGHashMap *)_additionalHeaders { NSEnumerator *headerFieldNames = nil; NSString *headerFieldName = nil; NGMutableHashMap *addHeaders = nil; - NSMutableData *data = nil; - + NSMutableData *data; + data = (self->useMimeData) ? [[[NGMimeJoinedData alloc] init] autorelease] : [NSMutableData dataWithCapacity:2048]; headerFieldNames = [self->part headerFieldNames]; addHeaders = [_additionalHeaders mutableCopy]; - - while ((headerFieldName = [headerFieldNames nextObject])) { - NSData *headerFieldData = nil; - NSEnumerator *enumerator = nil; + + while ((headerFieldName = [headerFieldNames nextObject]) != nil) { + NSEnumerator *enumerator; BOOL reset; - + if ([[_additionalHeaders objectsForKey:headerFieldName] count] > 0) { enumerator = [addHeaders objectEnumeratorForKey:headerFieldName]; reset = YES; @@ -192,29 +216,27 @@ static BOOL debugOn = NO; reset = NO; enumerator = [self->part valuesOfHeaderFieldWithName:headerFieldName]; } - headerFieldData = [self generateDataWithHeaderField:headerFieldName - values:enumerator]; - if (reset) - [addHeaders removeAllObjectsForKey:headerFieldName]; - if (headerFieldData) - [data appendData:headerFieldData]; + [self appendHeaderField:headerFieldName values:enumerator toData:data]; + + if (reset) [addHeaders removeAllObjectsForKey:headerFieldName]; } + headerFieldNames = [addHeaders keyEnumerator]; - while ((headerFieldName = [headerFieldNames nextObject])) { - NSData *headerFieldData = nil; - headerFieldData = [self generateDataWithHeaderField:headerFieldName - values:[addHeaders objectEnumeratorForKey: - headerFieldName]]; - if (headerFieldData) - [data appendData:headerFieldData]; + while ((headerFieldName = [headerFieldNames nextObject]) != nil) { + [self appendHeaderField:headerFieldName + values:[addHeaders objectEnumeratorForKey:headerFieldName] + toData:data]; } [addHeaders release]; addHeaders = nil; return data; } - (NGMimeType *)defaultContentTypeForPart:(id)_part { - return [NGMimeType mimeType:@"application/octet-stream"]; + static NGMimeType *octetStreamType = nil; + if (octetStreamType == nil) + octetStreamType = [[NGMimeType mimeType:@"application/octet-stream"] copy]; + return octetStreamType; } - (id)defaultBodyGenerator { diff --git a/sope-mime/Version b/sope-mime/Version index f805eb4d..6f8c65aa 100644 --- a/sope-mime/Version +++ b/sope-mime/Version @@ -2,7 +2,7 @@ MAJOR_VERSION:=4 MINOR_VERSION:=5 -SUBMINOR_VERSION:=218 +SUBMINOR_VERSION:=219 # v4.5.214 requires libNGExtensions v4.5.146 # v4.2.149 requires libNGStreams v4.2.34 -- 2.39.5