static BOOL debugOn = NO;
static BOOL debugDataOn = NO;
static NSStringEncoding encoding;
-static Class StrClass = Nil;
-static Class NumClass = Nil;
+static Class StrClass = Nil;
+static Class NumClass = Nil;
+static Class DataClass = Nil;
static NSStringEncoding defCStringEncoding;
static NSNumber *YesNum = nil;
static NSNumber *NoNum = nil;
/* Note: this should be larger than a usual header size! */
Imap4MMDataBoundary = 2 * LaSize;
- StrClass = [NSString class];
- NumClass = [NSNumber class];
- YesNum = [[NumClass numberWithBool:YES] retain];
- NoNum = [[NumClass numberWithBool:NO] retain];
+ StrClass = [NSString class];
+ NumClass = [NSNumber class];
+ DataClass = [NSData class];
+ YesNum = [[NumClass numberWithBool:YES] retain];
+ NoNum = [[NumClass numberWithBool:NO] retain];
}
+ (id)parserWithStream:(id<NGActiveSocket>)_stream {
[stream close];
[stream release]; stream = nil;
- result = [NSData dataWithContentsOfMappedFile:path];
+ result = [DataClass dataWithContentsOfMappedFile:path];
[[NSFileManager defaultManager] removeFileAtPath:path handler:nil];
return result;
cnt++;
}
- result = [NSData dataWithBytesNoCopy:tmpBuf length:tmpBufCnt];
+ result = [DataClass dataWithBytesNoCopy:tmpBuf length:tmpBufCnt];
if (buf != NULL) free(buf); buf = NULL;
return result;
return nil;
}
+- (id)_decodeQP:(id)_string headerField:(NSString *)_field {
+ if (![_string isNotNull])
+ return _string;
+
+ if ([_string isKindOfClass:DataClass])
+ return [_string decodeQuotedPrintableValueOfMIMEHeaderField:_field];
+
+ if ([_string isKindOfClass:StrClass]) {
+ if ([_string length] <= 6 /* minimum size */)
+ return _string;
+ if ([_string characterAtIndex:0] == '=' &&
+ [_string characterAtIndex:1] == '?') {
+ NSData *data;
+
+ if (debugOn)
+ [self debugWithFormat:@"WARNING: string with quoted printable info!"];
+
+ // TODO: this is really expensive ...
+ data = [_string dataUsingEncoding:NSUTF8StringEncoding];
+ if (data != nil) {
+ NSData *qpData;
+
+ qpData = [data decodeQuotedPrintableValueOfMIMEHeaderField:_field];
+ if (qpData != data) return qpData;
+ }
+ }
+ return _string;
+ }
+
+ return _string;
+}
+
- (NGImap4EnvelopeAddress *)_parseEnvelopeAddressStructure {
/*
Note: returns retained object!
return nil;
}
_consume(self, 1); // '('
+
+ /* parse personal name, can be with quoted printable encoding! */
+
+ pname = [self _parseQuotedStringOrNIL];
+ if ([pname isNotNull])
+ pname = [self _decodeQP:pname headerField:@"subject"];
+ [self _consumeOptionalSpace];
- pname = [[self _parseQuotedStringOrNIL] copy]; [self _consumeOptionalSpace];
- route = [[self _parseQuotedStringOrNIL] copy]; [self _consumeOptionalSpace];
- mailbox = [[self _parseQuotedStringOrNIL] copy];[self _consumeOptionalSpace];
- host = [[self _parseQuotedStringOrNIL] copy]; [self _consumeOptionalSpace];
+ // TODO: I think those forbid QP encoding?
+ route = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
+ mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
+ host = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
if (_la(self, 0) != ')') {
[self logWithFormat:@"WARNING: IMAP4 envelope "
/* parse subject */
- if ((tmp = [self _parseQuotedStringOrDataOrNIL])) {
+ if ((tmp = [self _parseQuotedStringOrDataOrNIL]) != nil) {
// TODO: that one is an issue, the client does know the requested charset
// but doesn't pass it down to the parser? Requiring the client to
// deal with NSData's is a bit overkill?
- env->subject = [tmp isNotNull] ? [tmp copy] : nil;
+ env->subject = [tmp isNotNull]
+ ? [[self _decodeQP:tmp headerField:@"subject"] copy]
+ : nil;
[self _consumeOptionalSpace];
}
else {
static NSString *_parseBodyString(NGImap4ResponseParser *self,
BOOL _convertString)
{
- return _parseBodyDecodeString(self, _convertString, NO);
+ return _parseBodyDecodeString(self, _convertString, NO /* no decode */);
}
static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self)