mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-26 02:01:03 +00:00
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:
parent
50cc142ab4
commit
b9bc4951a3
2 changed files with 77 additions and 22 deletions
11
ChangeLog
11
ChangeLog
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue