From 9168f3c85d27ce94ac50eb20f68879050ac51cce Mon Sep 17 00:00:00 2001 From: rfm Date: Wed, 20 Feb 2008 09:22:43 +0000 Subject: [PATCH] Minor tweaks plus added method for parsing mime headers. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26109 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 6 + Headers/Additions/GNUstepBase/GSMime.h | 1 + Source/Additions/GSMime.m | 226 +++++++++++++++---------- Source/Additions/Unicode.m | 11 +- Source/NSMessagePort.m | 2 +- Source/NSPathUtilities.m | 11 +- Source/NSSocketPort.m | 2 +- 7 files changed, 164 insertions(+), 95 deletions(-) diff --git a/ChangeLog b/ChangeLog index 231078c20..cd0963d74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,12 @@ * Source/Additions/Unicode.m: * Headers/Additions/GNUstepBase/GSVersionMacros.h: Minor tweaks for building under leopard. + * Source/NSPathUtilities.m: minor thread safety fix. + * Source/NSSocketPort.m: remove bogus comment + * Source/NSMessagePort.m: remove bogus comment + * Source/Additions/Unicode.m: add lockign for nl_langinfo + * Source/Additions/GSMime.m: New method to parse headers + * Headers/Additions/GNUstepBase/GSMime.h: ditto 2008-02-19 Nicola Pero diff --git a/Headers/Additions/GNUstepBase/GSMime.h b/Headers/Additions/GNUstepBase/GSMime.h index 299f0dc34..ded8fb8d6 100644 --- a/Headers/Additions/GNUstepBase/GSMime.h +++ b/Headers/Additions/GNUstepBase/GSMime.h @@ -226,6 +226,7 @@ extern "C" { - (BOOL) isInHeaders; - (GSMimeDocument*) mimeDocument; - (BOOL) parse: (NSData*)d; +- (BOOL) parseHeaders: (NSData*)d remaining: (NSData**)body; - (BOOL) parseHeader: (NSString*)aHeader; - (BOOL) scanHeaderBody: (NSScanner*)scanner into: (GSMimeHeader*)info; - (NSString*) scanName: (NSScanner*)scanner; diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index 0172b50c6..6937c349b 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -1361,101 +1361,19 @@ wordData(NSString *word) */ - (BOOL) parse: (NSData*)d { - unsigned l = [d length]; - if (flags.complete == 1) { return NO; /* Already completely parsed! */ } - if (l > 0) + if ([d length] > 0) { - NSDebugMLLog(@"GSMime", @"Parse %u bytes - '%*.*s'", l, l, l, [d bytes]); if (flags.inBody == 0) - { - [data appendBytes: [d bytes] length: [d length]]; - bytes = (unsigned char*)[data mutableBytes]; - dataEnd = [data length]; - - while (flags.inBody == 0) - { - if ([self _unfoldHeader] == NO) - { - return YES; /* Needs more data to fill line. */ - } - if (flags.inBody == 0) - { - NSString *header; - - header = [self _decodeHeader]; - if (header == nil) - { - return NO; /* Couldn't handle words. */ - } - if ([self parseHeader: header] == NO) - { - flags.hadErrors = 1; - return NO; /* Header not parsed properly. */ - } - } - else - { - NSDebugMLLog(@"GSMime", @"Parsed end of headers", ""); - } - } - /* - * All headers have been parsed, so we empty our internal buffer - * (which we will now use to store decoded data) and place unused - * information back in the incoming data object to act as input. - */ - d = AUTORELEASE([data copy]); - [data setLength: 0]; - - /* - * If we have finished parsing the headers, we may have http - * continuation header(s), in which case, we must start parsing - * headers again. - */ - if (flags.inBody == 1) - { - NSDictionary *info; - GSMimeHeader *hdr; - - info = [[document headersNamed: @"http"] lastObject]; - if (info != nil && flags.isHttp == 1) - { - NSString *val; - - val = [info objectForKey: NSHTTPPropertyStatusCodeKey]; - if (val != nil) - { - int v = [val intValue]; - - if (v >= 100 && v < 200) - { - /* - * This is an intermediary response ... so we have - * to restart the parsing operation! - */ - NSDebugMLLog(@"GSMime", - @"Parsed http continuation", ""); - flags.inBody = 0; - } - } - } - /* - * If there is a zero content length, parsing is complete. - */ - hdr = [document headerNamed: @"content-length"]; - if (hdr != nil && [[hdr value] intValue] == 0) - { - [document setContent: @""]; - flags.inBody = 0; - flags.complete = 1; - return NO; // No more data needed - } - } - } - + { + if ([self parseHeaders: d remaining: &d] == YES) + { + return YES; + } + } if ([d length] > 0) { if (flags.inBody == 1) @@ -1499,6 +1417,136 @@ wordData(NSString *word) } } +- (BOOL) parseHeaders: (NSData*)d remaining: (NSData**)body +{ + NSDictionary *info; + GSMimeHeader *hdr; + unsigned l = [d length]; + + if (flags.complete == 1 || flags.inBody == 1) + { + return NO; /* Headers already parsed! */ + } + if (body != 0) + { + *body = nil; + } + if (l == 0) + { + /* Add a CRLF to either end the current header line or act as + * the blank linme terminating the headers. + */ + if ([self parseHeaders: [NSData dataWithBytes: "\r\n" length: 2] + remaining: body] == YES) + { + /* Still in headers ... so we add a CRLF to terminate them. + */ + [self parseHeaders: [NSData dataWithBytes: "\r\n" length: 2] + remaining: body]; + } + flags.wantEndOfLine = 0; + flags.inBody = 0; + flags.complete = 1; /* Finished parsing */ + return NO; /* Want no more data */ + } + + NSDebugMLLog(@"GSMime", @"Parse %u bytes - '%*.*s'", l, l, l, [d bytes]); + + [data appendBytes: [d bytes] length: [d length]]; + bytes = (unsigned char*)[data mutableBytes]; + dataEnd = [data length]; + + while (flags.inBody == 0) + { + if ([self _unfoldHeader] == NO) + { + return YES; /* Needs more data to fill line. */ + } + if (flags.inBody == 0) + { + NSString *header; + + header = [self _decodeHeader]; + if (header == nil) + { + flags.hadErrors = 1; + return NO; /* Couldn't handle words. */ + } + if ([self parseHeader: header] == NO) + { + flags.hadErrors = 1; + return NO; /* Header not parsed properly. */ + } + } + else + { + NSDebugMLLog(@"GSMime", @"Parsed end of headers", ""); + } + } + + /* + * All headers have been parsed, so we empty our internal buffer + * (which we will now use to store decoded data) and place unused + * information back in the incoming data object to act as input. + */ + d = AUTORELEASE([data copy]); + if (body != 0) + { + *body = d; + } + [data setLength: 0]; + + /* + * We have finished parsing the headers, but we may have http + * continuation header(s), in which case, we must start parsing + * headers again. + */ + info = [[document headersNamed: @"http"] lastObject]; + if (info != nil && flags.isHttp == 1) + { + NSString *val; + + val = [info objectForKey: NSHTTPPropertyStatusCodeKey]; + if (val != nil) + { + int v = [val intValue]; + + if (v >= 100 && v < 200) + { + /* + * This is an intermediary response ... so we have + * to restart the parsing operation! + */ + NSDebugMLLog(@"GSMime", + @"Parsed http continuation", ""); + flags.inBody = 0; + if ([d length] == 0) + { + /* We need more data, so we have to return YES + * to ask our caller to provide it. + */ + return YES; + } + return [self parseHeaders: d remaining: body]; + } + } + } + + /* + * If there is a zero content length, all parsing is complete, + * not just header parsing. + */ + hdr = [document headerNamed: @"content-length"]; + if (hdr != nil && [[hdr value] intValue] == 0) + { + [document setContent: @""]; + flags.inBody = 0; + flags.complete = 1; + } + + return NO; // No more data needed +} + /** *

* This method is called to parse a header line for the diff --git a/Source/Additions/Unicode.m b/Source/Additions/Unicode.m index 4b4894e0d..c7b96eb5e 100644 --- a/Source/Additions/Unicode.m +++ b/Source/Additions/Unicode.m @@ -2022,6 +2022,9 @@ GSPrivateDefaultCStringEncoding() if (defEnc == GSUndefinedEncoding) { char *encoding; +#if HAVE_LANGINFO_CODESET + char encbuf[BUFSIZ]; +#endif unsigned int count; GSSetupEncodingTable(); @@ -2035,10 +2038,16 @@ GSPrivateDefaultCStringEncoding() if (natEnc == GSUndefinedEncoding) { + /* Encoding not set */ #if HAVE_LANGINFO_CODESET /* Take it from the system locale information. */ - encoding = nl_langinfo(CODESET); + [gnustep_global_lock lock]; + strncpy(encbuf, nl_langinfo(CODESET), sizeof(encbuf)-1); + [gnustep_global_lock unlock]; + encbuf[sizeof(encbuf)-1] = '\0'; + encoding = encbuf; + /* * First handle the fallback response from nl_langinfo() ... * if we are getting the default value we can't assume that diff --git a/Source/NSMessagePort.m b/Source/NSMessagePort.m index 4d5159fff..6cc16397e 100644 --- a/Source/NSMessagePort.m +++ b/Source/NSMessagePort.m @@ -51,7 +51,7 @@ #include #ifdef HAVE_UNISTD_H -#include /* for gethostname() */ +#include #endif #include /* for MAXHOSTNAMELEN */ diff --git a/Source/NSPathUtilities.m b/Source/NSPathUtilities.m index 607f136a4..96718f12e 100644 --- a/Source/NSPathUtilities.m +++ b/Source/NSPathUtilities.m @@ -1349,10 +1349,10 @@ NSUserName(void) if (theUserName == nil || uid != olduid) { const char *loginName = 0; + char buf[BUFSIZ*10]; #if defined(HAVE_GETPWUID_R) struct passwd pwent; struct passwd *p; - char buf[BUFSIZ*10]; if (getpwuid_r(uid, &pwent, buf, sizeof(buf), &p) == 0) { @@ -1360,8 +1360,13 @@ NSUserName(void) } #else #if defined(HAVE_GETPWUID) - struct passwd *pwent = getpwuid (uid); - loginName = pwent->pw_name; + struct passwd *pwent; + + [gnustep_global_lock lock]; + pwent = getpwuid (uid); + strcpy(buf, pwent->pw_name); + [gnustep_global_lock unlock]; + loginName = buf; #endif /* HAVE_GETPWUID */ #endif /* HAVE_GETPWUID_R */ olduid = uid; diff --git a/Source/NSSocketPort.m b/Source/NSSocketPort.m index 7d58a8df5..3b02ac714 100644 --- a/Source/NSSocketPort.m +++ b/Source/NSSocketPort.m @@ -49,7 +49,7 @@ #include #include #ifdef HAVE_UNISTD_H -#include /* for gethostname() */ +#include #endif #ifdef __MINGW32__