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:
Richard Frith-MacDonald 2008-02-20 09:22:43 +00:00
parent eb73c50d13
commit 726b05507e
7 changed files with 164 additions and 95 deletions

View file

@ -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 <nicola.pero@meta-innovation.com>

View file

@ -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;

View file

@ -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
}
/**
* <p>
* This method is called to parse a header line <em>for the

View file

@ -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

View file

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

View file

@ -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;

View file

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