Make checks of 8bit and 7bit content more rigorous

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@16920 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2003-06-14 09:40:17 +00:00
parent 94ea53aae9
commit 8331e53453

View file

@ -2088,7 +2088,7 @@ NSDebugMLLog(@"GSMime", @"Header parsed - %@", info);
{ {
hdr = [document headerNamed: @"content-transfer-encoding"]; hdr = [document headerNamed: @"content-transfer-encoding"];
} }
else if ([[[hdr value] lowercaseString] isEqual: @"chunked"] == YES) else if ([[[hdr value] lowercaseString] isEqualToString: @"chunked"])
{ {
/* /*
* Chunked transfer encoding overrides any content length spec. * Chunked transfer encoding overrides any content length spec.
@ -3289,7 +3289,7 @@ static NSCharacterSet *tokenSet = nil;
{ {
NSString *name = [info name]; NSString *name = [info name];
if (name == nil || [name isEqual: @"unknown"] == YES) if (name == nil || [name isEqualToString: @"unknown"] == YES)
{ {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"[%@ -%@] header with invalid name", format: @"[%@ -%@] header with invalid name",
@ -3831,6 +3831,7 @@ static NSCharacterSet *tokenSet = nil;
GSMimeHeader *enc; GSMimeHeader *enc;
GSMimeHeader *hdr; GSMimeHeader *hdr;
NSData *boundary; NSData *boundary;
BOOL contentIsBinary = NO;
BOOL contentIs7bit = YES; BOOL contentIs7bit = YES;
unsigned int count; unsigned int count;
unsigned int i; unsigned int i;
@ -3866,7 +3867,7 @@ static NSCharacterSet *tokenSet = nil;
/* /*
* If any part of a multipart document is not 7bit then * If any part of a multipart document is not 7bit then
* the document as a whole must not be 7bit either. * the document as a whole must not be 7bit either.
* It is important tol chack this *after* the part has been * It is important to check this *after* the part has been
* processed by -rawMimeData:, so we know that the encoding * processed by -rawMimeData:, so we know that the encoding
* set for the part is valid. * set for the part is valid.
*/ */
@ -3876,9 +3877,14 @@ static NSCharacterSet *tokenSet = nil;
enc = [part headerNamed: @"content-transfer-encoding"]; enc = [part headerNamed: @"content-transfer-encoding"];
v = [enc value]; v = [enc value];
if ([v isEqual: @"8bit"] == YES || [v isEqual: @"binary"] == YES) if ([v isEqualToString: @"8bit"] == YES
|| [v isEqualToString: @"binary"] == YES)
{ {
contentIs7bit = NO; contentIs7bit = NO;
if ([v isEqualToString: @"binary"] == YES)
{
contentIsBinary = YES;
}
} }
} }
} }
@ -3920,13 +3926,24 @@ static NSCharacterSet *tokenSet = nil;
enc = [self headerNamed: @"content-transfer-encoding"]; enc = [self headerNamed: @"content-transfer-encoding"];
v = [enc value]; v = [enc value];
if ([v isEqualToString: @"8bit"] || [v isEqualToString: @"binary"]) if ([v isEqualToString: @"binary"])
{ {
/* /*
* For 8bit/binary encoding, we can just accept the setting. * For binary encoding, we can just accept the setting.
*/ */
shouldSet = NO; shouldSet = NO;
} }
else if ([v isEqualToString: @"8bit"])
{
if (contentIsBinary == YES)
{
shouldSet = YES; // Need to promote from 8bit to binary
}
else
{
shouldSet = NO;
}
}
else if (v == nil || [v isEqualToString: @"7bit"] == YES) else if (v == nil || [v isEqualToString: @"7bit"] == YES)
{ {
/* /*
@ -3954,15 +3971,36 @@ static NSCharacterSet *tokenSet = nil;
if (shouldSet == YES) if (shouldSet == YES)
{ {
NSString *encoding;
/* /*
* Force a change to the current transfer encoding setting. * Force a change to the current transfer encoding setting.
*/ */
enc = [GSMimeHeader alloc]; if (contentIs7bit == YES)
enc = [enc initWithName: @"content-transfer-encoding" {
value: ((contentIs7bit == YES) ? @"7bit" : @"8bit") encoding = @"7bit";
parameters: nil]; }
[self setHeader: enc]; else if (contentIsBinary == YES)
RELEASE(enc); {
encoding = @"binary";
}
else
{
encoding = @"8bit";
}
if (enc == nil)
{
enc = [GSMimeHeader alloc];
enc = [enc initWithName: @"content-transfer-encoding"
value: encoding
parameters: nil];
[self setHeader: enc];
RELEASE(enc);
}
else
{
[enc setValue: encoding];
}
} }
v = [type parameterForKey: @"boundary"]; v = [type parameterForKey: @"boundary"];
@ -3974,7 +4012,7 @@ static NSCharacterSet *tokenSet = nil;
boundary = [v dataUsingEncoding: NSASCIIStringEncoding]; boundary = [v dataUsingEncoding: NSASCIIStringEncoding];
v = [type objectForKey: @"Subtype"]; v = [type objectForKey: @"Subtype"];
if ([v isEqual: @"related"] == YES) if ([v isEqualToString: @"related"] == YES)
{ {
GSMimeDocument *start; GSMimeDocument *start;
@ -4021,38 +4059,102 @@ static NSCharacterSet *tokenSet = nil;
} }
else else
{ {
NSString *encoding;
d = [self convertToData]; d = [self convertToData];
enc = [self headerNamed: @"content-transfer-encoding"]; enc = [self headerNamed: @"content-transfer-encoding"];
if (enc == nil) encoding = [enc value];
if (encoding == nil)
{ {
enc = [GSMimeHeader alloc]; if ([[type objectForKey: @"Type"] isEqualToString: @"text"] == YES)
if ([[type objectForKey: @"Type"] isEqual: @"text"] == YES)
{ {
NSString *charset = [type parameterForKey: @"charset"]; NSString *charset = [type parameterForKey: @"charset"];
if (charset == nil if (charset != nil
|| [charset isEqual: @"ascii"] && [charset isEqualToString: @"ascii"] == NO
|| [charset isEqual: @"us-ascii"]) && [charset isEqualToString: @"us-ascii"] == NO)
{ {
encoding = @"8bit";
enc = [GSMimeHeader alloc];
enc = [enc initWithName: @"content-transfer-encoding" enc = [enc initWithName: @"content-transfer-encoding"
value: @"7bit" value: encoding
parameters: nil];
}
else
{
enc = [enc initWithName: @"content-transfer-encoding"
value: @"8bit"
parameters: nil]; parameters: nil];
[self addHeader: enc];
RELEASE(enc);
} }
} }
else else
{ {
enc = [GSMimeHeader alloc];
enc = [enc initWithName: @"content-transfer-encoding" enc = [enc initWithName: @"content-transfer-encoding"
value: @"base64" value: @"base64"
parameters: nil]; parameters: nil];
[self addHeader: enc];
RELEASE(enc);
}
}
if (encoding == nil
|| [encoding isEqualToString: @"7bit"] == YES
|| [encoding isEqualToString: @"8bit"] == YES)
{
unsigned char *bytes = (unsigned char*)[d bytes];
unsigned length = [d length];
BOOL hadCarriageReturn = NO;
unsigned lineLength = 0;
unsigned i;
for (i = 0; i < length; i++)
{
unsigned char c = bytes[i];
if (hadCarriageReturn == YES)
{
if (c != '\n')
{
encoding = @"binary"; // CR not part of CRLF
break;
}
hadCarriageReturn = NO;
lineLength = 0;
}
else if (c == '\r')
{
hadCarriageReturn = YES;
}
else if (++lineLength > 998)
{
encoding = @"binary"; // Line of more than 998
break;
}
if (c == 0)
{
encoding = @"binary";
break;
}
else if (c > 127)
{
encoding = @"8bit"; // Not 7bit data
}
}
if (encoding != nil)
{
if (enc == nil)
{
enc = [GSMimeHeader alloc];
enc = [enc initWithName: @"content-transfer-encoding"
value: encoding
parameters: nil];
[self addHeader: enc];
RELEASE(enc);
}
else
{
[enc setValue: encoding];
}
} }
[self addHeader: enc];
RELEASE(enc);
} }
} }
@ -4079,7 +4181,8 @@ static NSCharacterSet *tokenSet = nil;
enc = [part headerNamed: @"content-transport-encoding"]; enc = [part headerNamed: @"content-transport-encoding"];
v = [enc value]; v = [enc value];
if (v != nil && ([v isEqual: @"8bit"] || [v isEqual: @"binary"])) if (v != nil && ([v isEqualToString: @"8bit"]
|| [v isEqualToString: @"binary"]))
{ {
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[%@ -%@] bad part encoding for 7bit container", format: @"[%@ -%@] bad part encoding for 7bit container",
@ -4106,7 +4209,7 @@ static NSCharacterSet *tokenSet = nil;
*/ */
[md appendBytes: "\r\n" length: 2]; [md appendBytes: "\r\n" length: 2];
if ([[enc value] isEqual: @"base64"] == YES) if ([[enc value] isEqualToString: @"base64"] == YES)
{ {
const char *ptr; const char *ptr;
unsigned len; unsigned len;
@ -4220,15 +4323,15 @@ static NSCharacterSet *tokenSet = nil;
type = @"text"; type = @"text";
} }
if ([type isEqual: @"text"] == YES) if ([type isEqualToString: @"text"] == YES)
{ {
subtype = @"plain"; subtype = @"plain";
} }
else if ([type isEqual: @"multipart"] == YES) else if ([type isEqualToString: @"multipart"] == YES)
{ {
subtype = @"mixed"; subtype = @"mixed";
} }
else if ([type isEqual: @"application"] == YES) else if ([type isEqualToString: @"application"] == YES)
{ {
subtype = @"octet-stream"; subtype = @"octet-stream";
} }