diff --git a/ChangeLog b/ChangeLog index 9b29f9e4a..c5e86515b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,8 +2,13 @@ * Headers/Foundation/GSMime.h: Tidy up and add convenience methods. * Source/Additions/GSMime.m: Tidy up and add convenience methods. + Added methods to convert content between string and data for ease + of use from java. * Source/NSBundle.m: ([+allBundles]) Don't enumeraste if map table has not been created yet. + * Source/NSLog.m: Allow output descriptor to be changed. + * Source/NSProcessInfo.m: Add method to change log output to go to + another file for applications where stderr has been hijacked. 2002-05-26 Fred Kiefer diff --git a/Headers/gnustep/base/GSMime.h b/Headers/gnustep/base/GSMime.h index 5c2f501e9..3a814bb6c 100644 --- a/Headers/gnustep/base/GSMime.h +++ b/Headers/gnustep/base/GSMime.h @@ -97,6 +97,8 @@ - (NSString*) contentName; - (NSString*) contentSubType; - (NSString*) contentType; +- (NSData*) convertToData; +- (NSString*) convertToText; - (void) deleteHeader: (GSMimeHeader*)aHeader; - (void) deleteHeaderNamed: (NSString*)name; - (GSMimeHeader*) headerNamed: (NSString*)name; diff --git a/Headers/gnustep/base/NSProcessInfo.h b/Headers/gnustep/base/NSProcessInfo.h index 9d52874bb..6d7ed283f 100644 --- a/Headers/gnustep/base/NSProcessInfo.h +++ b/Headers/gnustep/base/NSProcessInfo.h @@ -78,7 +78,7 @@ enum { @interface NSProcessInfo (GNUstep) - (NSMutableSet*) debugSet; - +- (BOOL) setLogFile: (NSString*)path; + (void) initializeWithArguments: (char**)argv count: (int)argc environment: (char**)env; diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index 006e7f3d5..3367f37c4 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -964,6 +964,16 @@ parseCharacterSet(NSString *token) * passed all the data to it ... this tells it that the data * is complete. *

+ *

+ * A multipart document will be parsed to content consisting of an + * NSArray of GSMimeDocument instances representing each part.
+ * Otherwise, a document will become content of type NSData, unless + * it is of content type text, in which case it will be an + * NSString.
+ * If a document has no content type specified, it will be treated as + * text, unless it is identifiable as a file + * (eg. t has a content-disposition header containing a filename parameter). + *

*/ - (BOOL) parse: (NSData*)d { @@ -1264,6 +1274,42 @@ parseCharacterSet(NSString *token) return [document addHeader: info]; } +- (BOOL) scanHeaderParameters: (NSScanner*)scanner into: (GSMimeHeader*)info +{ + [self scanPastSpace: scanner]; + while ([scanner scanString: @";" intoString: 0] == YES) + { + NSString *paramName; + + paramName = [self scanToken: scanner]; + if ([paramName length] == 0) + { + NSLog(@"Invalid Mime %@ field (parameter name)", [info name]); + return NO; + } + [self scanPastSpace: scanner]; + if ([scanner scanString: @"=" intoString: 0] == YES) + { + NSString *paramValue; + + [self scanPastSpace: scanner]; + paramValue = [self scanToken: scanner]; + [self scanPastSpace: scanner]; + if (paramValue == nil) + { + paramValue = @""; + } + [info setParameter: paramValue forKey: paramName]; + } + else + { + NSLog(@"Ignoring Mime %@ field parameter (%@)", + [info name], paramName); + } + } + return YES; +} + /** *

* This method is called to parse a header line and split its @@ -1449,32 +1495,7 @@ parseCharacterSet(NSString *token) value = type; } - while ([scanner scanString: @";" intoString: 0] == YES) - { - NSString *paramName; - - paramName = [self scanToken: scanner]; - if ([paramName length] == 0) - { - NSLog(@"Invalid Mime content-type (parameter name)"); - return NO; - } - if ([scanner scanString: @"=" intoString: 0] == YES) - { - NSString *paramValue; - - paramValue = [self scanToken: scanner]; - if (paramValue == nil) - { - paramValue = @""; - } - [info setParameter: paramValue forKey: paramName]; - } - else - { - NSLog(@"Ignoring Mime content-type parameter (%@)", paramName); - } - } + [self scanHeaderParameters: scanner into: info]; } else if ([name isEqualToString: @"content-disposition"] == YES) { @@ -1497,33 +1518,7 @@ parseCharacterSet(NSString *token) /* * Expect anything else to be 'name=value' parameters. */ - while ([scanner scanString: @";" intoString: 0] == YES) - { - NSString *paramName; - - paramName = [self scanToken: scanner]; - if ([paramName length] == 0) - { - NSLog(@"Invalid Mime content-type (parameter name)"); - return NO; - } - if ([scanner scanString: @"=" intoString: 0] == YES) - { - NSString *paramValue; - - paramValue = [self scanToken: scanner]; - if (paramValue == nil) - { - paramValue = @""; - } - [info setParameter: paramValue forKey: paramName]; - } - else - { - NSLog(@"Ignoring Mime content-disposition parameter (%@)", - paramName); - } - } + [self scanHeaderParameters: scanner into: info]; } else { @@ -1650,7 +1645,7 @@ parseCharacterSet(NSString *token) done = YES; } } - [scanner setScanLocation: r.length + 1]; + [scanner setScanLocation: r.location + 1]; length = r.location - start; if (length == 0) { @@ -1947,9 +1942,22 @@ parseCharacterSet(NSString *token) NSDebugMLLog(@"GSMime", @"Parse body complete"); /* - * If no content type is supplied, we assume text. + * If no content type is supplied, we assume text ... unless + * we have something that's known to be a file. */ - if (type == nil || [type isEqualToString: @"text"] == YES) + if (type == nil) + { + if ([document contentFile] != nil) + { + type = @"application"; + } + else + { + type = @"text"; + } + } + + if ([type isEqualToString: @"text"] == YES) { NSDictionary *params; NSString *charset; @@ -2673,12 +2681,14 @@ static NSCharacterSet *tokenSet = nil; } /** - * Search the content of this document to locate a part whose content name - * matches the specified key. Recursively descend into other documents.
+ * Search the content of this document to locate a part whose content-type + * name or content-disposition name matches the specified key. + * Recursively descend into other documents.
* Return nil if no match is found, the matching GSMimeDocument otherwise. */ - (id) contentByName: (NSString*)key { + if ([content isKindOfClass: [NSArray class]] == YES) { NSEnumerator *e = [content objectEnumerator]; @@ -2686,7 +2696,15 @@ static NSCharacterSet *tokenSet = nil; while ((d = [e nextObject]) != nil) { - if ([[d contentName] isEqualToString: key] == YES) + GSMimeHeader *hdr; + + hdr = [d headerNamed: @"content-type"]; + if ([[hdr parameterForKey: @"name"] isEqualToString: key] == YES) + { + return d; + } + hdr = [d headerNamed: @"content-disposition"]; + if ([[hdr parameterForKey: @"name"] isEqualToString: key] == YES) { return d; } @@ -2750,6 +2768,47 @@ static NSCharacterSet *tokenSet = nil; return [hdr objectForKey: @"Type"]; } +/** + * Return the content as an NSData object (unless it is multipart) + */ +- (NSData*) convertToData +{ + NSData *d = nil; + + if ([content isKindOfClass: [NSString class]] == YES) + { + NSStringEncoding enc = NSUTF8StringEncoding; + + d = [content dataUsingEncoding: enc]; + } + else if ([content isKindOfClass: [NSData class]] == YES) + { + d = content; + } + return d; +} + +/** + * Return the content as an NSString object (unless it is multipart) + */ +- (NSString*) convertToText +{ + NSString *s = nil; + + if ([content isKindOfClass: [NSString class]] == YES) + { + s = content; + } + else if ([content isKindOfClass: [NSData class]] == YES) + { + NSStringEncoding enc = NSUTF8StringEncoding; + + s = [[NSString alloc] initWithData: content encoding: enc]; + AUTORELEASE(s); + } + return s; +} + - (id) copyWithZone: (NSZone*)z { return RETAIN(self); diff --git a/Source/NSLog.m b/Source/NSLog.m index e58b117f6..2e408e37d 100644 --- a/Source/NSLog.m +++ b/Source/NSLog.m @@ -46,6 +46,8 @@ #include "GSPrivate.h" +int _NSLogDescriptor = 2; // Default descriptor for logging + static void _NSLog_standard_printf_handler (NSString* message) { @@ -78,7 +80,8 @@ _NSLog_standard_printf_handler (NSString* message) #ifdef HAVE_SYSLOG - if (GSUserDefaultsFlag(GSLogSyslog) == YES || write(2, buf, len) != len) + if (GSUserDefaultsFlag(GSLogSyslog) == YES + || write(_NSLogDescriptor, buf, len) != len) { int mask; @@ -98,7 +101,7 @@ _NSLog_standard_printf_handler (NSString* message) syslog(mask, "%s", buf); } #else - write(2, buf, len); + write(_NSLogDescriptor, buf, len); #endif } diff --git a/Source/NSProcessInfo.m b/Source/NSProcessInfo.m index 5367a5f37..8e3c595c2 100644 --- a/Source/NSProcessInfo.m +++ b/Source/NSProcessInfo.m @@ -67,6 +67,8 @@ #include #include #include +#include + #include #include #include @@ -760,6 +762,28 @@ int main(int argc, char *argv[], char *env[]) return _debug_set; } +/** + * Set the file to which NSLog output should be directed.
+ * Returns YES on success, NO on failure.
+ * By default logging goes to standard error. + */ +- (BOOL) setLogFile: (NSString*)path +{ + extern int _NSLogDescriptor; + int desc; + + desc = open([path fileSystemRepresentation], O_RDWR|O_CREAT|O_APPEND, 0644); + if (desc >= 0) + { + if (_NSLogDescriptor >= 0 && _NSLogDescriptor != 2) + { + close(_NSLogDescriptor); + } + _NSLogDescriptor = desc; + return YES; + } + return NO; +} @end /**