Updates for compatibility with buggy http servers/apps

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21359 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2005-06-25 14:03:27 +00:00
parent 50cc142ab4
commit b9bc4951a3
2 changed files with 77 additions and 22 deletions

View file

@ -1,3 +1,14 @@
2005-06-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSHTTPURLHandle.m:
Preserve case of http headers when writing remote request, so that
they can be tailored for remote servers which are buggy in having
case sensitivity.
When creating default http headers, capitalize the words in the
header name, as this is the most common way headers are presented
and documented, and thus the least likely to tickle case sensitivity
bugs at the remote end of a connection.
2005-06-23 Adam Fedor <fedor@gnu.org> 2005-06-23 Adam Fedor <fedor@gnu.org>
* Source/mframe.m (mframe_decode_return): Change return struct * Source/mframe.m (mframe_decode_return): Change return struct

View file

@ -39,8 +39,11 @@
#include "Foundation/NSHost.h" #include "Foundation/NSHost.h"
#include "Foundation/NSProcessInfo.h" #include "Foundation/NSProcessInfo.h"
#include "Foundation/NSPathUtilities.h" #include "Foundation/NSPathUtilities.h"
#include "Foundation/NSMapTable.h"
#include "GNUstepBase/GSMime.h" #include "GNUstepBase/GSMime.h"
#include "GNUstepBase/GSLock.h" #include "GNUstepBase/GSLock.h"
#include "NSCallBacks.h"
#include <string.h> #include <string.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
@ -51,6 +54,41 @@
#include <sys/fcntl.h> // For O_WRONLY, etc #include <sys/fcntl.h> // For O_WRONLY, etc
#endif #endif
/*
* Implement map keys for strings with case insensitive comparisons,
* so we can have case insensitive matching of http headers (correct
* behavior), but actually preserve case of headers stored and written
* in case the remote server is buggy and requires particular
* captialisation of headers (some http software is faulty like that).
*/
static unsigned int
_non_retained_id_hash(void *table, NSString* o)
{
return [[o uppercaseString] hash];
}
static BOOL
_non_retained_id_is_equal(void *table, NSString *o, NSString *p)
{
return ([o caseInsensitiveCompare: p] == NSOrderedSame) ? YES : NO;
}
typedef unsigned int (*NSMT_hash_func_t)(NSMapTable *, const void *);
typedef BOOL (*NSMT_is_equal_func_t)(NSMapTable *, const void *, const void *);
typedef void (*NSMT_retain_func_t)(NSMapTable *, const void *);
typedef void (*NSMT_release_func_t)(NSMapTable *, void *);
typedef NSString *(*NSMT_describe_func_t)(NSMapTable *, const void *);
const NSMapTableKeyCallBacks writeKeyCallBacks =
{
(NSMT_hash_func_t) _non_retained_id_hash,
(NSMT_is_equal_func_t) _non_retained_id_is_equal,
(NSMT_retain_func_t) _NS_non_retained_id_retain,
(NSMT_release_func_t) _NS_non_retained_id_release,
(NSMT_describe_func_t) _NS_non_retained_id_describe,
NSNotAPointerMapKey
};
static NSString *httpVersion = @"1.1"; static NSString *httpVersion = @"1.1";
@interface GSHTTPURLHandle : NSURLHandle @interface GSHTTPURLHandle : NSURLHandle
@ -65,7 +103,7 @@ static NSString *httpVersion = @"1.1";
GSMimeParser *parser; GSMimeParser *parser;
GSMimeDocument *document; GSMimeDocument *document;
NSMutableDictionary *pageInfo; NSMutableDictionary *pageInfo;
NSMutableDictionary *wProperties; NSMapTable *wProperties;
NSData *wData; NSData *wData;
NSMutableDictionary *request; NSMutableDictionary *request;
unsigned int bodyPos; unsigned int bodyPos;
@ -276,7 +314,10 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
DESTROY(document); DESTROY(document);
DESTROY(pageInfo); DESTROY(pageInfo);
DESTROY(wData); DESTROY(wData);
DESTROY(wProperties); if (wProperties != 0)
{
NSFreeMapTable(wProperties);
}
DESTROY(request); DESTROY(request);
[super dealloc]; [super dealloc];
} }
@ -288,7 +329,8 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
{ {
dat = [NSMutableData new]; dat = [NSMutableData new];
pageInfo = [NSMutableDictionary new]; pageInfo = [NSMutableDictionary new];
wProperties = [NSMutableDictionary new]; wProperties = NSCreateMapTable(writeKeyCallBacks,
NSObjectMapValueCallBacks, 8);
request = [NSMutableDictionary new]; request = [NSMutableDictionary new];
ASSIGN(url, newUrl); ASSIGN(url, newUrl);
@ -319,11 +361,12 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
- (void) bgdApply: (NSString*)basic - (void) bgdApply: (NSString*)basic
{ {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSEnumerator *wpEnumerator;
NSMutableString *s; NSMutableString *s;
NSString *key; NSString *key;
NSString *val;
NSMutableData *buf; NSMutableData *buf;
NSString *version; NSString *version;
NSMapEnumerator enumerator;
if (debug) NSLog(@"%@ %s", NSStringFromSelector(_cmd), keepalive?"K":""); if (debug) NSLog(@"%@ %s", NSStringFromSelector(_cmd), keepalive?"K":"");
@ -340,25 +383,26 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
} }
[s appendFormat: @" HTTP/%@\r\n", version]; [s appendFormat: @" HTTP/%@\r\n", version];
if ([wProperties objectForKey: @"host"] == nil) if ((id)NSMapGet(wProperties, (void*)@"Host") == nil)
{ {
[wProperties setObject: [u host] forKey: @"host"]; NSMapInsert(wProperties, (void*)@"Host", (void*)[u host]);
} }
if ([wData length] > 0) if ([wData length] > 0)
{ {
[wProperties setObject: [NSString stringWithFormat: @"%d", [wData length]] NSMapInsert(wProperties, (void*)@"Content-Length",
forKey: @"content-length"]; (void*)[NSString stringWithFormat: @"%d", [wData length]]);
/* /*
* Assume content type if not specified. * Assume content type if not specified.
*/ */
if ([wProperties objectForKey: @"content-type"] == nil) if ((id)NSMapGet(wProperties, (void*)@"Content-Type") == nil)
{ {
[wProperties setObject: @"application/x-www-form-urlencoded" NSMapInsert(wProperties, (void*)@"Content-Type",
forKey: @"content-type"]; (void*)@"application/x-www-form-urlencoded");
} }
} }
if ([wProperties objectForKey: @"authorization"] == nil) if ((id)NSMapGet(wProperties, (void*)@"Authorization") == nil)
{ {
if ([u user] != nil) if ([u user] != nil)
{ {
@ -375,16 +419,17 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
} }
auth = [NSString stringWithFormat: @"Basic %@", auth = [NSString stringWithFormat: @"Basic %@",
[GSMimeDocument encodeBase64String: auth]]; [GSMimeDocument encodeBase64String: auth]];
[wProperties setObject: auth NSMapInsert(wProperties, (void*)@"Authorization", (void*)auth);
forKey: @"authorization"];
} }
} }
wpEnumerator = [wProperties keyEnumerator]; enumerator = NSEnumerateMapTable(wProperties);
while ((key = [wpEnumerator nextObject])) while (NSNextMapEnumeratorPair(&enumerator, (void **)(&key), (void**)&val))
{ {
[s appendFormat: @"%@: %@\r\n", key, [wProperties objectForKey: key]]; [s appendFormat: @"%@: %@\r\n", key, val];
} }
NSEndMapTableEnumeration(&enumerator);
[s appendString: @"\r\n"]; [s appendString: @"\r\n"];
buf = [[s dataUsingEncoding: NSASCIIStringEncoding] mutableCopy]; buf = [[s dataUsingEncoding: NSASCIIStringEncoding] mutableCopy];
@ -533,7 +578,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
r = NSMakeRange(bodyPos, [d length] - bodyPos); r = NSMakeRange(bodyPos, [d length] - bodyPos);
bodyPos = 0; bodyPos = 0;
DESTROY(wData); DESTROY(wData);
[wProperties removeAllObjects]; NSResetMapTable(wProperties);
[self didLoadBytes: [d subdataWithRange: r] [self didLoadBytes: [d subdataWithRange: r]
loadComplete: YES]; loadComplete: YES];
} }
@ -611,7 +656,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
- (void) endLoadInBackground - (void) endLoadInBackground
{ {
DESTROY(wData); DESTROY(wData);
[wProperties removeAllObjects]; NSResetMapTable(wProperties);
if (connectionState != idle) if (connectionState != idle)
{ {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
@ -1200,12 +1245,11 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
{ {
if (property == nil) if (property == nil)
{ {
[wProperties removeObjectForKey: [propertyKey lowercaseString]]; NSMapRemove(wProperties, (void*)propertyKey);
} }
else else
{ {
[wProperties setObject: property NSMapInsert(wProperties, (void*)propertyKey, (void*)property);
forKey: [propertyKey lowercaseString]];
} }
} }
return YES; return YES;