diff --git a/ChangeLog b/ChangeLog index aad5147f9..f87e2d1a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-11-24 Francis Lachapelle + + * SoObjects/Mailer/NSData+Mail.m (-decodedString): renamed from + decodedSubject. The decoding algorithm is now recursive. + + * SoObjects/Mailer/NSString+Mail.m (-decodedHeader): renamed from + decodedSubject. The string is now decoded by parts. + 2009-11-24 Ludovic Marcotte * SoObjects/SOGo/SOGoGroup.m diff --git a/SoObjects/Mailer/NSData+Mail.h b/SoObjects/Mailer/NSData+Mail.h index 5ef48bc62..4aeb7afcc 100644 --- a/SoObjects/Mailer/NSData+Mail.h +++ b/SoObjects/Mailer/NSData+Mail.h @@ -30,7 +30,7 @@ @interface NSData (SOGoMailUtilities) - (NSData *) bodyDataFromEncoding: (NSString *) encoding; -- (NSString *) decodedSubject; +- (NSString *) decodedString; @end diff --git a/SoObjects/Mailer/NSData+Mail.m b/SoObjects/Mailer/NSData+Mail.m index 56a30e954..c7ece1ab7 100644 --- a/SoObjects/Mailer/NSData+Mail.m +++ b/SoObjects/Mailer/NSData+Mail.m @@ -54,73 +54,115 @@ return decodedData; } -- (NSString *) decodedSubject +/* + * Excpected form is: "=?charset?encoding?encoded text?=". + */ +- (NSString *) decodedString { - const char *cData, *endFlag; - unsigned int len; - NSString *decodedSubject; + const char *cData; + unsigned int len, i, j; + NSString *decodedString; cData = [self bytes]; len = [self length]; + decodedString = nil; if (len) { - decodedSubject = nil; if (len > 6) { - endFlag = cData + len - 2; - if (*cData == '=' && *(cData + 1) == '?' - && *endFlag == '?' && *(endFlag + 1) == '=') + // Find beginning of encoded text + i = 1; + while ((*cData != '=' || *(cData+1) != '?') && i < len) + { + cData++; + i++; + } + + if (*cData == '=' && *(cData+1) == '?') { NSString *enc; - int i; - cData += 2; - i = 2; - - while (*cData != '?' && i < len) + if (i > 1) + decodedString = [[[NSString alloc] initWithData: [self subdataWithRange: NSMakeRange(0, (i-1))] + encoding: NSASCIIStringEncoding] autorelease]; + cData += 2; // skip "=?" + i++; + j = i; + // Find next "?" + while (*cData != '?' && j < len) { cData++; - i++; + j++; } - - enc = [[[NSString alloc] initWithData:[self subdataWithRange: NSMakeRange(2, i-2)] + enc = [[[NSString alloc] initWithData:[self subdataWithRange: NSMakeRange(i, j-i)] encoding: NSASCIIStringEncoding] autorelease]; - if (i+3 < len) + i = j + 3; // skip "?q?" + if (i < (len-2)) { NSData *d; - - d = [self subdataWithRange: NSMakeRange(i+3, len-i-5)]; - + BOOL isQuotedPrintable = NO; + + cData++; // We check if we have a QP or Base64 encoding - if (*(cData+1) == 'q' || *(cData+1) == 'Q') + if (*cData == 'q' || *cData == 'Q') + isQuotedPrintable = YES; + + // Find end of encoded text + j = i; + cData += 2; // skip "q?" + while ((*cData != '?' || *(cData+1) != '=') && (j+1) < len) + { + cData++; + j++; + } + + d = [self subdataWithRange: NSMakeRange(i, j-i)]; + if (isQuotedPrintable) d = [d dataByDecodingQuotedPrintable]; else d = [d dataByDecodingBase64]; - - decodedSubject = [NSString stringWithData: d usingEncodingNamed: enc]; + + if (decodedString) + { + decodedString = [NSString stringWithFormat: @"%@%@", + decodedString, [NSString stringWithData: d + usingEncodingNamed: enc]]; + } + else + decodedString = [NSString stringWithData: d + usingEncodingNamed: enc]; + + j += 2; // skip "?=" + if (j < len) + { + // Recursively decode the remaining part + decodedString = [NSString stringWithFormat: @"%@%@", + decodedString, + [[self subdataWithRange: NSMakeRange(j, len-j)] decodedString]]; + } } else - decodedSubject = nil; + decodedString = nil; } } - if (!decodedSubject) + if (!decodedString) { - decodedSubject + decodedString = [[NSString alloc] initWithData: self encoding: NSUTF8StringEncoding]; - if (!decodedSubject) - decodedSubject + if (!decodedString) + decodedString = [[NSString alloc] initWithData: self encoding: NSISOLatin1StringEncoding]; - [decodedSubject autorelease]; + [decodedString autorelease]; } } else - decodedSubject = @""; + decodedString = @""; - return decodedSubject; + return decodedString; } @end diff --git a/SoObjects/Mailer/NSString+Mail.h b/SoObjects/Mailer/NSString+Mail.h index 7ed44b549..c99b6b57c 100644 --- a/SoObjects/Mailer/NSString+Mail.h +++ b/SoObjects/Mailer/NSString+Mail.h @@ -30,7 +30,7 @@ - (NSString *) htmlToText; - (NSString *) stringByConvertingCRLNToHTML; - (int) indexOf: (unichar) _c; -- (NSString *) decodedSubject; +- (NSString *) decodedHeader; @end diff --git a/SoObjects/Mailer/NSString+Mail.m b/SoObjects/Mailer/NSString+Mail.m index 3fb62d899..14b53e6f7 100644 --- a/SoObjects/Mailer/NSString+Mail.m +++ b/SoObjects/Mailer/NSString+Mail.m @@ -438,21 +438,16 @@ convertChars (const char *oldString, unsigned int oldLength, return -1; } -- (NSString *) decodedSubject +- (NSString *) decodedHeader { - NSString *decodedSubject; + NSString *decodedHeader; - if ([self hasPrefix: @"=?"] && [self hasSuffix: @"?="]) - { - decodedSubject = [[self dataUsingEncoding: NSASCIIStringEncoding] - decodedSubject]; - if (!decodedSubject) - decodedSubject = self; - } - else - decodedSubject = self; - - return decodedSubject; + decodedHeader = [[self dataUsingEncoding: NSASCIIStringEncoding] + decodedString]; + if (!decodedHeader) + decodedHeader = self; + + return decodedHeader; } @end diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index e352d1fcf..6c9b3c32f 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -271,7 +271,7 @@ static BOOL debugSoParts = NO; - (NSString *) decodedSubject { - return [[self subject] decodedSubject]; + return [[self subject] decodedHeader]; } - (NSCalendarDate *) date diff --git a/UI/MailPartViewers/UIxMailPartMessageViewer.m b/UI/MailPartViewers/UIxMailPartMessageViewer.m index 567c4b259..bead9d0da 100644 --- a/UI/MailPartViewers/UIxMailPartMessageViewer.m +++ b/UI/MailPartViewers/UIxMailPartMessageViewer.m @@ -145,7 +145,7 @@ { component = [[components objectAtIndex: count] email]; if (component) - [formattedComponents addObject: [component decodedSubject]]; + [formattedComponents addObject: [component decodedHeader]]; } return [formattedComponents componentsJoinedByString: @", "]; @@ -162,7 +162,7 @@ // -stringByDecodingQuotedPrintable for all details if ([baseSubject isKindOfClass: [NSString class]]) baseSubject = [baseSubject dataUsingEncoding: NSASCIIStringEncoding]; - subject = [baseSubject decodedSubject]; + subject = [baseSubject decodedString]; if (![subject length]) subject = [self labelForKey: @"Untitled"]; diff --git a/UI/MailerUI/UIxMailListView.m b/UI/MailerUI/UIxMailListView.m index 6c7726698..92b91d0e4 100644 --- a/UI/MailerUI/UIxMailListView.m +++ b/UI/MailerUI/UIxMailListView.m @@ -45,6 +45,7 @@ #import +#import #import #import #import @@ -202,7 +203,7 @@ static NSArray *udColumnOrder = nil; NSString *subject; baseSubject = [[message valueForKey: @"envelope"] subject]; - subject = [baseSubject decodedSubject]; + subject = [baseSubject decodedHeader]; if (![subject length]) subject = [self labelForKey: @"Untitled"];