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
This commit is contained in:
rfm 2008-02-20 09:22:43 +00:00
parent e8e914434d
commit 9168f3c85d
7 changed files with 164 additions and 95 deletions

View file

@ -3,6 +3,12 @@
* Source/Additions/Unicode.m: * Source/Additions/Unicode.m:
* Headers/Additions/GNUstepBase/GSVersionMacros.h: * Headers/Additions/GNUstepBase/GSVersionMacros.h:
Minor tweaks for building under leopard. 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 <nicola.pero@meta-innovation.com> 2008-02-19 Nicola Pero <nicola.pero@meta-innovation.com>

View file

@ -226,6 +226,7 @@ extern "C" {
- (BOOL) isInHeaders; - (BOOL) isInHeaders;
- (GSMimeDocument*) mimeDocument; - (GSMimeDocument*) mimeDocument;
- (BOOL) parse: (NSData*)d; - (BOOL) parse: (NSData*)d;
- (BOOL) parseHeaders: (NSData*)d remaining: (NSData**)body;
- (BOOL) parseHeader: (NSString*)aHeader; - (BOOL) parseHeader: (NSString*)aHeader;
- (BOOL) scanHeaderBody: (NSScanner*)scanner into: (GSMimeHeader*)info; - (BOOL) scanHeaderBody: (NSScanner*)scanner into: (GSMimeHeader*)info;
- (NSString*) scanName: (NSScanner*)scanner; - (NSString*) scanName: (NSScanner*)scanner;

View file

@ -1361,101 +1361,19 @@ wordData(NSString *word)
*/ */
- (BOOL) parse: (NSData*)d - (BOOL) parse: (NSData*)d
{ {
unsigned l = [d length];
if (flags.complete == 1) if (flags.complete == 1)
{ {
return NO; /* Already completely parsed! */ 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) if (flags.inBody == 0)
{ {
[data appendBytes: [d bytes] length: [d length]]; if ([self parseHeaders: d remaining: &d] == YES)
bytes = (unsigned char*)[data mutableBytes]; {
dataEnd = [data length]; return YES;
}
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 ([d length] > 0) if ([d length] > 0)
{ {
if (flags.inBody == 1) 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
}
/** /**
* <p> * <p>
* This method is called to parse a header line <em>for the * This method is called to parse a header line <em>for the

View file

@ -2022,6 +2022,9 @@ GSPrivateDefaultCStringEncoding()
if (defEnc == GSUndefinedEncoding) if (defEnc == GSUndefinedEncoding)
{ {
char *encoding; char *encoding;
#if HAVE_LANGINFO_CODESET
char encbuf[BUFSIZ];
#endif
unsigned int count; unsigned int count;
GSSetupEncodingTable(); GSSetupEncodingTable();
@ -2035,10 +2038,16 @@ GSPrivateDefaultCStringEncoding()
if (natEnc == GSUndefinedEncoding) if (natEnc == GSUndefinedEncoding)
{ {
/* Encoding not set */ /* Encoding not set */
#if HAVE_LANGINFO_CODESET #if HAVE_LANGINFO_CODESET
/* Take it from the system locale information. */ /* 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() ... * First handle the fallback response from nl_langinfo() ...
* if we are getting the default value we can't assume that * if we are getting the default value we can't assume that

View file

@ -51,7 +51,7 @@
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> /* for gethostname() */ #include <unistd.h>
#endif #endif
#include <sys/param.h> /* for MAXHOSTNAMELEN */ #include <sys/param.h> /* for MAXHOSTNAMELEN */

View file

@ -1349,10 +1349,10 @@ NSUserName(void)
if (theUserName == nil || uid != olduid) if (theUserName == nil || uid != olduid)
{ {
const char *loginName = 0; const char *loginName = 0;
char buf[BUFSIZ*10];
#if defined(HAVE_GETPWUID_R) #if defined(HAVE_GETPWUID_R)
struct passwd pwent; struct passwd pwent;
struct passwd *p; struct passwd *p;
char buf[BUFSIZ*10];
if (getpwuid_r(uid, &pwent, buf, sizeof(buf), &p) == 0) if (getpwuid_r(uid, &pwent, buf, sizeof(buf), &p) == 0)
{ {
@ -1360,8 +1360,13 @@ NSUserName(void)
} }
#else #else
#if defined(HAVE_GETPWUID) #if defined(HAVE_GETPWUID)
struct passwd *pwent = getpwuid (uid); struct passwd *pwent;
loginName = pwent->pw_name;
[gnustep_global_lock lock];
pwent = getpwuid (uid);
strcpy(buf, pwent->pw_name);
[gnustep_global_lock unlock];
loginName = buf;
#endif /* HAVE_GETPWUID */ #endif /* HAVE_GETPWUID */
#endif /* HAVE_GETPWUID_R */ #endif /* HAVE_GETPWUID_R */
olduid = uid; olduid = uid;

View file

@ -49,7 +49,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> /* for gethostname() */ #include <unistd.h>
#endif #endif
#ifdef __MINGW32__ #ifdef __MINGW32__