networking improvements

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25887 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2008-01-07 17:51:02 +00:00
parent 3d12feda98
commit 14b54a6b44
10 changed files with 549 additions and 368 deletions

View file

@ -1,3 +1,15 @@
2008-01-07 Richard Frith-Macdonald <rfm@gnu.org>
* Source\GSSocketStream.h: simplify socket address handling
* Source\GSSocketStream.m: ditto + more work on socks
* Source\GSStream.h: minor tweaks
* Source\GSStream.m:minor tweaks
* Source\unix\NSStream.m: simplified socket address handling
* Source\GSNetwork.h: add macro to get socket address length
* Source\GSHTTPAuthentication.m: Handle arg classh check in init
* Source\NSURLRequest.m: ditto
* Source\NSURLProtocol.m: attempt to add support for authentication
2008-01-07 Fred Kiefer <FredKiefer@gmx.de> 2008-01-07 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSFileManager.m (-fileSystemAttributesAtPath:): Correct * Source/NSFileManager.m (-fileSystemAttributesAtPath:): Correct

View file

@ -150,7 +150,7 @@ static GSMimeParser *mimeParser = nil;
+ (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth + (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth
requestURL: (NSURL*)URL; requestURL: (NSURL*)URL;
{ {
if (auth != nil) if ([auth isKindOfClass: [NSString class]] == YES)
{ {
NSString *method = nil; NSString *method = nil;
NSURLProtectionSpace *space; NSURLProtectionSpace *space;

View file

@ -50,6 +50,11 @@
#define BADSOCKET(X) ((X) == INVALID_SOCKET) #define BADSOCKET(X) ((X) == INVALID_SOCKET)
#define GSNETERROR WSAGetLastError() #define GSNETERROR WSAGetLastError()
#define GSWOULDBLOCK (GSNETERROR == WSAEWOULDBLOCK || GSNETERROR == WSAEINPROGRESS) #define GSWOULDBLOCK (GSNETERROR == WSAEWOULDBLOCK || GSNETERROR == WSAEINPROGRESS)
#ifdef AF_INET6
#define SOCKLEN(X) ((X->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
#else
#define SOCKLEN(X) sizeof(struct sockaddr_in)
#endif
#else #else
@ -66,6 +71,7 @@
#endif #endif
#define SOCKET int /* Socket type */ #define SOCKET int /* Socket type */
#define SOCKLEN(X) (X->sa_len)
#define BADSOCKET(X) ((X) < 0) #define BADSOCKET(X) ((X) < 0)
#define GSNETERROR errno #define GSNETERROR errno
#define GSWOULDBLOCK (errno == EINPROGRESS) #define GSWOULDBLOCK (errno == EINPROGRESS)

View file

@ -37,6 +37,7 @@
BOOL _closing; /* Must close on next failure. */\ BOOL _closing; /* Must close on next failure. */\
SOCKET _sock; /* Needed for ms-windows. */\ SOCKET _sock; /* Needed for ms-windows. */\
id _handler; /* TLS/SOCKS handler. */\ id _handler; /* TLS/SOCKS handler. */\
struct sockaddr *_address; /* Socket address info. */\
} }
/* The semi-abstract GSSocketStream class is not intended to be subclassed /* The semi-abstract GSSocketStream class is not intended to be subclassed
@ -48,7 +49,12 @@ SOCKIVARS
/** /**
* get the sockaddr * get the sockaddr
*/ */
- (struct sockaddr*) _peerAddr; - (struct sockaddr*) _address;
/**
* set the sockaddr
*/
- (void) _setAddress: (struct sockaddr*)address;
/** /**
* setter for closing flag ... the remote end has stopped either sending * setter for closing flag ... the remote end has stopped either sending
@ -82,11 +88,6 @@ SOCKIVARS
*/ */
- (SOCKET) _sock; - (SOCKET) _sock;
/**
* Get the length of the socket addr
*/
- (socklen_t) _sockLen;
@end @end
/** /**
@ -98,7 +99,8 @@ SOCKIVARS
SOCKIVARS SOCKIVARS
@end @end
@interface GSSocketInputStream (AddedBehaviors) @interface GSSocketInputStream (AddedBehaviors)
- (struct sockaddr*) _peerAddr; - (struct sockaddr*) _address;
- (void) _setAddress: (struct sockaddr*)address;
- (int) _read: (uint8_t *)buffer maxLength: (unsigned int)len; - (int) _read: (uint8_t *)buffer maxLength: (unsigned int)len;
- (void) _setClosing: (BOOL)passive; - (void) _setClosing: (BOOL)passive;
- (void) _setHandler: (id)h; - (void) _setHandler: (id)h;
@ -106,14 +108,9 @@ SOCKIVARS
- (void) _setSibling: (GSSocketStream*)sibling; - (void) _setSibling: (GSSocketStream*)sibling;
- (void) _setSock: (SOCKET)sock; - (void) _setSock: (SOCKET)sock;
- (SOCKET) _sock; - (SOCKET) _sock;
- (socklen_t) _sockLen;
@end @end
@interface GSInetInputStream : GSSocketInputStream @interface GSInetInputStream : GSSocketInputStream
{
@private
struct sockaddr_in _peerAddr;
}
/** /**
* the designated initializer * the designated initializer
@ -124,12 +121,6 @@ SOCKIVARS
@interface GSInet6InputStream : GSSocketInputStream @interface GSInet6InputStream : GSSocketInputStream
{
@private
#if defined(AF_INET6)
struct sockaddr_in6 _peerAddr;
#endif
}
/** /**
* the designated initializer * the designated initializer
@ -147,22 +138,18 @@ SOCKIVARS
SOCKIVARS SOCKIVARS
@end @end
@interface GSSocketOutputStream (AddedBehaviors) @interface GSSocketOutputStream (AddedBehaviors)
- (struct sockaddr*) _peerAddr; - (struct sockaddr*) _address;
- (void) _setAddress: (struct sockaddr*)address;
- (void) _setClosing: (BOOL)passive; - (void) _setClosing: (BOOL)passive;
- (void) _setHandler: (id)h; - (void) _setHandler: (id)h;
- (void) _setPassive: (BOOL)passive; - (void) _setPassive: (BOOL)passive;
- (void) _setSibling: (GSSocketStream*)sibling; - (void) _setSibling: (GSSocketStream*)sibling;
- (void) _setSock: (SOCKET)sock; - (void) _setSock: (SOCKET)sock;
- (SOCKET) _sock; - (SOCKET) _sock;
- (socklen_t) _sockLen;
- (int) _write: (const uint8_t *)buffer maxLength: (unsigned int)len; - (int) _write: (const uint8_t *)buffer maxLength: (unsigned int)len;
@end @end
@interface GSInetOutputStream : GSSocketOutputStream @interface GSInetOutputStream : GSSocketOutputStream
{
@private
struct sockaddr_in _peerAddr;
}
/** /**
* the designated initializer * the designated initializer
@ -172,12 +159,6 @@ SOCKIVARS
@end @end
@interface GSInet6OutputStream : GSSocketOutputStream @interface GSInet6OutputStream : GSSocketOutputStream
{
@private
#if defined(AF_INET6)
struct sockaddr_in6 _peerAddr;
#endif
}
/** /**
* the designated initializer * the designated initializer
@ -208,37 +189,22 @@ SOCKIVARS
*/ */
- (Class) _outputStreamClass; - (Class) _outputStreamClass;
/**
* Return the sockaddr for this server
*/
- (struct sockaddr*) _serverAddr;
@end @end
@interface GSSocketServerStream (AddedBehaviors) @interface GSSocketServerStream (AddedBehaviors)
- (struct sockaddr*) _peerAddr; - (struct sockaddr*) _address;
- (void) _setAddress: (struct sockaddr*)address;
- (void) _setClosing: (BOOL)passive; - (void) _setClosing: (BOOL)passive;
- (void) _setHandler: (id)h; - (void) _setHandler: (id)h;
- (void) _setPassive: (BOOL)passive; - (void) _setPassive: (BOOL)passive;
- (void) _setSibling: (GSSocketStream*)sibling; - (void) _setSibling: (GSSocketStream*)sibling;
- (void) _setSock: (SOCKET)sock; - (void) _setSock: (SOCKET)sock;
- (SOCKET) _sock; - (SOCKET) _sock;
- (socklen_t) _sockLen;
@end @end
@interface GSInetServerStream : GSSocketServerStream @interface GSInetServerStream : GSSocketServerStream
{
@private
struct sockaddr_in _serverAddr;
}
@end @end
@interface GSInet6ServerStream : GSSocketServerStream @interface GSInet6ServerStream : GSSocketServerStream
{
@private
#if defined(AF_INET6)
struct sockaddr_in6 _serverAddr;
#endif
}
@end @end
#endif #endif

View file

@ -56,16 +56,16 @@
*/ */
@interface GSStreamHandler : NSObject @interface GSStreamHandler : NSObject
{ {
GSSocketInputStream *input; // Not retained GSSocketInputStream *istream; // Not retained
GSSocketOutputStream *output; // Not retained GSSocketOutputStream *ostream; // Not retained
BOOL initialised; BOOL initialised;
BOOL handshake; BOOL handshake;
BOOL active; BOOL active;
} }
- (id) initWithInput: (GSSocketInputStream*)i - (id) initWithInput: (GSSocketInputStream*)i
output: (GSSocketOutputStream*)o; output: (GSSocketOutputStream*)o;
- (GSSocketInputStream*) input; - (GSSocketInputStream*) istream;
- (GSSocketOutputStream*) output; - (GSSocketOutputStream*) ostream;
- (void) bye; /* Close down the handled session. */ - (void) bye; /* Close down the handled session. */
- (BOOL) handshake; /* A handshake/hello is in progress. */ - (BOOL) handshake; /* A handshake/hello is in progress. */
@ -96,19 +96,19 @@
- (id) initWithInput: (GSSocketInputStream*)i - (id) initWithInput: (GSSocketInputStream*)i
output: (GSSocketOutputStream*)o output: (GSSocketOutputStream*)o
{ {
input = i; istream = i;
output = o; ostream = o;
return self; return self;
} }
- (GSSocketInputStream*) input - (GSSocketInputStream*) istream
{ {
return input; return istream;
} }
- (GSSocketOutputStream*) output - (GSSocketOutputStream*) ostream
{ {
return output; return ostream;
} }
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len - (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
@ -184,14 +184,14 @@ GSTLSPull(gnutls_transport_ptr_t handle, void *buffer, size_t len)
ssize_t result; ssize_t result;
GSTLS *tls = (GSTLS*)handle; GSTLS *tls = (GSTLS*)handle;
result = [[tls input] _read: buffer maxLength: len]; result = [[tls istream] _read: buffer maxLength: len];
if (result < 0) if (result < 0)
{ {
int e; int e;
if ([[tls input] streamStatus] == NSStreamStatusError) if ([[tls istream] streamStatus] == NSStreamStatusError)
{ {
e = [[[(GSTLS*)handle input] streamError] code]; e = [[[(GSTLS*)handle istream] streamError] code];
} }
else else
{ {
@ -211,14 +211,14 @@ GSTLSPush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
ssize_t result; ssize_t result;
GSTLS *tls = (GSTLS*)handle; GSTLS *tls = (GSTLS*)handle;
result = [[tls output] _write: buffer maxLength: len]; result = [[tls ostream] _write: buffer maxLength: len];
if (result < 0) if (result < 0)
{ {
int e; int e;
if ([[tls output] streamStatus] == NSStreamStatusError) if ([[tls ostream] streamStatus] == NSStreamStatusError)
{ {
e = [[[tls output] streamError] code]; e = [[[tls ostream] streamError] code];
} }
else else
{ {
@ -418,14 +418,14 @@ static gnutls_anon_client_credentials_t anoncred;
return self; return self;
} }
- (GSSocketInputStream*) input - (GSSocketInputStream*) istream
{ {
return input; return istream;
} }
- (GSSocketOutputStream*) output - (GSSocketOutputStream*) ostream
{ {
return output; return ostream;
} }
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len - (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
@ -442,8 +442,8 @@ static gnutls_anon_client_credentials_t anoncred;
[self hello]; /* try to complete the handshake */ [self hello]; /* try to complete the handshake */
if (handshake == NO) if (handshake == NO)
{ {
[input _sendEvent: NSStreamEventOpenCompleted]; [istream _sendEvent: NSStreamEventOpenCompleted];
[output _sendEvent: NSStreamEventOpenCompleted]; [ostream _sendEvent: NSStreamEventOpenCompleted];
} }
} }
} }
@ -484,44 +484,126 @@ static NSString * const GSSOCKSAckAuth = @"GSSOCKSAckAuth";
static NSString * const GSSOCKSSendConn = @"GSSOCKSSendConn"; static NSString * const GSSOCKSSendConn = @"GSSOCKSSendConn";
static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn"; static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
@interface GSSOCKS : NSObject @interface GSSOCKS : GSStreamHandler
{ {
NSString *state; NSString *state; /* Not retained */
NSString *addr; NSString *address;
int port; NSString *port;
int roffset; int roffset;
int woffset; int woffset;
int rwant; int rwant;
unsigned char rbuffer[128]; unsigned char rbuffer[128];
NSInputStream *istream;
NSOutputStream *ostream;
} }
- (NSString*) addr; - (void) stream: (NSStream*)stream handleEvent: (NSStreamEvent)event;
- (id) initToAddr: (NSString*)_addr port: (int)_port;
- (int) port;
- (NSString*) stream: (NSStream*)stream SOCKSEvent: (NSStreamEvent)event;
@end @end
@implementation GSSOCKS @implementation GSSOCKS
- (NSString*) addr - (void) bye
{ {
return addr; if (handshake == YES)
{
NSString *tls;
GSTLS *t = nil;
handshake = NO;
tls = [ostream propertyForKey: NSStreamSocketSecurityLevelKey];
if (tls == nil && istream != nil)
{
tls = [istream propertyForKey: NSStreamSocketSecurityLevelKey];
if (tls != nil)
{
[ostream setProperty: tls forKey: NSStreamSocketSecurityLevelKey];
}
}
if (tls != nil)
{
t = [[GSTLS alloc] initWithInput: istream output: ostream];
}
if (t == nil)
{
GSSocketInputStream *is = RETAIN(istream);
GSSocketOutputStream *os = RETAIN(ostream);
/* No TLS required ... simply remove SOCKS handler from streams
* and let the streams know that the open has completed.
* NB. Removing SOCKS handle from streams may cause it to be
* deallocated, so we work with local variables to hold the
* streams long enough to send events to them.
*/
[is _setHandler: nil];
[os _setHandler: nil];
[is _sendEvent: NSStreamEventOpenCompleted];
[os _sendEvent: NSStreamEventOpenCompleted];
RELEASE(is);
RELEASE(os);
}
else
{
/* Replace SOCKS handler wth TLS handler and start TLS handshake.
*/
[istream _setHandler: t];
[ostream _setHandler: t];
[t hello];
RELEASE(t);
}
}
} }
- (id) initToAddr: (NSString*)_addr port: (int)_port - (void) dealloc
{ {
ASSIGNCOPY(addr, _addr); RELEASE(address);
port = _port; RELEASE(port);
state = GSSOCKSOfferAuth; [super dealloc];
}
- (void) hello
{
if (handshake == NO)
{
handshake = YES;
/* Now send self an event to say we can write, to kick off the
* handshake with the SOCKS server.
*/
[self stream: ostream handleEvent: NSStreamEventHasSpaceAvailable];
}
}
- (id) initWithInput: (GSSocketInputStream*)i
output: (GSSocketOutputStream*)o
{
if ((self = [super initWithInput: i output: o]) != nil)
{
if ([istream isKindOfClass: [GSInetInputStream class]] == NO)
{
NSLog(@"Attempt to use SOCKS with non-INET stream ignored");
DESTROY(self);
}
#if defined(AF_INET6)
else if ([istream isKindOfClass: [GSInet6InputStream class]] == YES)
{
GSOnceMLog(@"INET6 not supported with SOCKS yet...");
DESTROY(self);
}
#endif /* AF_INET6 */
else
{
struct sockaddr_in *addr = (struct sockaddr_in*)[istream _address];
address = [[NSString alloc] initWithUTF8String:
(char*)inet_ntoa(addr->sin_addr)];
port = [[NSString alloc] initWithFormat: @"%d",
(int)GSSwapBigI16ToHost(addr->sin_port)];
}
}
return self; return self;
} }
- (int) port - (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
{ {
return port; return [istream _read: buffer maxLength: len];
} }
- (NSString*) stream: (NSStream*)stream SOCKSEvent: (NSStreamEvent)event - (void) stream: (NSStream*)stream handleEvent: (NSStreamEvent)event
{ {
NSString *error = nil; NSString *error = nil;
NSDictionary *conf; NSDictionary *conf;
@ -532,7 +614,8 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
|| [stream streamStatus] == NSStreamStatusError || [stream streamStatus] == NSStreamStatusError
|| [stream streamStatus] == NSStreamStatusClosed) || [stream streamStatus] == NSStreamStatusClosed)
{ {
return @"SOCKS errur during negotiation"; [self bye];
return;
} }
conf = [stream propertyForKey: NSStreamSOCKSProxyConfigurationKey]; conf = [stream propertyForKey: NSStreamSOCKSProxyConfigurationKey];
@ -574,12 +657,8 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
want = 3; want = 3;
} }
result = [ostream write: buf + woffset maxLength: 4 - woffset]; result = [ostream _write: buf + woffset maxLength: 4 - woffset];
if (result == 0) if (result > 0)
{
error = @"end-of-file during SOCKS negotiation";
}
else if (result > 0)
{ {
woffset += result; woffset += result;
if (woffset == want) if (woffset == want)
@ -594,7 +673,7 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
{ {
int result; int result;
result = [istream read: rbuffer + roffset maxLength: 2 - roffset]; result = [istream _read: rbuffer + roffset maxLength: 2 - roffset];
if (result == 0) if (result == 0)
{ {
error = @"SOCKS end-of-file during negotiation"; error = @"SOCKS end-of-file during negotiation";
@ -652,7 +731,8 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
memcpy(buf + 2, [u bytes], ul); memcpy(buf + 2, [u bytes], ul);
buf[ul + 2] = pl; buf[ul + 2] = pl;
memcpy(buf + ul + 3, [p bytes], pl); memcpy(buf + ul + 3, [p bytes], pl);
result = [ostream write: buf + woffset maxLength: want - woffset]; result = [ostream _write: buf + woffset
maxLength: want - woffset];
if (result == 0) if (result == 0)
{ {
error = @"SOCKS end-of-file during negotiation"; error = @"SOCKS end-of-file during negotiation";
@ -672,7 +752,7 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
{ {
int result; int result;
result = [istream read: rbuffer + roffset maxLength: 2 - roffset]; result = [istream _read: rbuffer + roffset maxLength: 2 - roffset];
if (result == 0) if (result == 0)
{ {
error = @"SOCKS end-of-file during negotiation"; error = @"SOCKS end-of-file during negotiation";
@ -719,7 +799,7 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
buf[1] = 1; // Connect command buf[1] = 1; // Connect command
buf[2] = 0; // Reserved buf[2] = 0; // Reserved
buf[3] = 1; // Address type (IPV4) buf[3] = 1; // Address type (IPV4)
ptr = [addr lossyCString]; ptr = [address UTF8String];
buf[4] = atoi(ptr); buf[4] = atoi(ptr);
while (isdigit(*ptr)) while (isdigit(*ptr))
ptr++; ptr++;
@ -733,10 +813,11 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
ptr++; ptr++;
ptr++; ptr++;
buf[7] = atoi(ptr); buf[7] = atoi(ptr);
buf[8] = ((port & 0xff00) >> 8); result = [port intValue];
buf[9] = (port & 0xff); buf[8] = ((result & 0xff00) >> 8);
buf[9] = (result & 0xff);
result = [ostream write: buf + woffset maxLength: want - woffset]; result = [ostream _write: buf + woffset maxLength: want - woffset];
if (result == 0) if (result == 0)
{ {
error = @"SOCKS end-of-file during negotiation"; error = @"SOCKS end-of-file during negotiation";
@ -756,7 +837,7 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
{ {
int result; int result;
result = [istream read: rbuffer + roffset maxLength: rwant - roffset]; result = [istream _read: rbuffer + roffset maxLength: rwant - roffset];
if (result == 0) if (result == 0)
{ {
error = @"SOCKS end-of-file during negotiation"; error = @"SOCKS end-of-file during negotiation";
@ -861,8 +942,22 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
a = [NSString stringWithUTF8String: a = [NSString stringWithUTF8String:
(const char*)buf]; (const char*)buf];
} }
ASSIGN(addr, a);
port = rbuffer[rwant-1] * 256 * rbuffer[rwant-2]; [istream setProperty: a
forKey: GSStreamRemoteAddressKey];
[ostream setProperty: a
forKey: GSStreamRemoteAddressKey];
a = [NSString stringWithFormat: @"%d",
rbuffer[rwant-1] * 256 * rbuffer[rwant-2]];
[istream setProperty: a
forKey: GSStreamRemotePortKey];
[ostream setProperty: a
forKey: GSStreamRemotePortKey];
/* Return immediately after calling -bye as it
* will cause this instance to be deallocted.
*/
[self bye];
return;
} }
} }
} }
@ -870,7 +965,29 @@ static NSString * const GSSOCKSAckConn = @"GSSOCKSAckConn";
} }
} }
return error; if ([error length] > 0)
{
NSError *theError;
theError = [NSError errorWithDomain: NSCocoaErrorDomain
code: 0
userInfo: [NSDictionary dictionaryWithObject: error
forKey: NSLocalizedDescriptionKey]];
if ([istream streamStatus] != NSStreamStatusError)
{
[istream _recordError: theError];
}
if ([ostream streamStatus] != NSStreamStatusError)
{
[ostream _recordError: theError];
}
[self bye];
}
}
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
{
return [ostream _write: buffer maxLength: len];
} }
@end @end
@ -930,6 +1047,10 @@ setNonBlocking(SOCKET fd)
[_sibling _setSibling: nil]; [_sibling _setSibling: nil];
_sibling = nil; _sibling = nil;
DESTROY(_handler); DESTROY(_handler);
if (_address != 0)
{
NSZoneFree(NSDefaultMallocZone(), _address);
}
[super dealloc]; [super dealloc];
} }
@ -953,10 +1074,9 @@ setNonBlocking(SOCKET fd)
return self; return self;
} }
- (struct sockaddr*) _peerAddr - (struct sockaddr*) _address
{ {
[self subclassResponsibility: _cmd]; return (struct sockaddr*)_address;
return NULL;
} }
- (int) _read: (uint8_t *)buffer maxLength: (unsigned int)len - (int) _read: (uint8_t *)buffer maxLength: (unsigned int)len
@ -988,6 +1108,21 @@ setNonBlocking(SOCKET fd)
} }
} }
- (void) _setAddress: (struct sockaddr*)address
{
if (_address != 0 && SOCKLEN(_address) != SOCKLEN(address))
{
NSZoneFree(NSDefaultMallocZone(), _address);
_address = 0;
}
if (_address == 0)
{
_address = (struct sockaddr*)
NSZoneMalloc(NSDefaultMallocZone(), SOCKLEN(address));
}
memcpy(_address, address, SOCKLEN(address));
}
- (void) _setLoopID: (void *)ref - (void) _setLoopID: (void *)ref
{ {
#if !defined(__MINGW32__) #if !defined(__MINGW32__)
@ -1038,12 +1173,6 @@ setNonBlocking(SOCKET fd)
return _sock; return _sock;
} }
- (socklen_t) _sockLen
{
[self subclassResponsibility: _cmd];
return 0;
}
- (int) _write: (const uint8_t *)buffer maxLength: (unsigned int)len - (int) _write: (const uint8_t *)buffer maxLength: (unsigned int)len
{ {
[self subclassResponsibility: _cmd]; [self subclassResponsibility: _cmd];
@ -1080,7 +1209,7 @@ setNonBlocking(SOCKET fd)
{ {
int result; int result;
result = connect([self _sock], [self _peerAddr], [self _sockLen]); result = connect([self _sock], _address, SOCKLEN(_address));
if (socketError(result)) if (socketError(result))
{ {
if (!socketWouldBlock()) if (!socketWouldBlock())
@ -1523,7 +1652,7 @@ setNonBlocking(SOCKET fd)
{ {
int result; int result;
result = connect([self _sock], [self _peerAddr], [self _sockLen]); result = connect([self _sock], _address, SOCKLEN(_address));
if (socketError(result)) if (socketError(result))
{ {
if (!socketWouldBlock()) if (!socketWouldBlock())
@ -1859,12 +1988,6 @@ setNonBlocking(SOCKET fd)
return Nil; return Nil;
} }
- (struct sockaddr*) _serverAddr
{
[self subclassResponsibility: _cmd];
return 0;
}
#define SOCKET_BACKLOG 256 #define SOCKET_BACKLOG 256
- (void) open - (void) open
@ -1885,7 +2008,7 @@ setNonBlocking(SOCKET fd)
(char *)&status, sizeof(status)); (char *)&status, sizeof(status));
#endif #endif
bindReturn = bind([self _sock], [self _serverAddr], [self _sockLen]); bindReturn = bind([self _sock], _address, SOCKLEN(_address));
if (socketError(bindReturn)) if (socketError(bindReturn))
{ {
[self _recordError]; [self _recordError];
@ -1934,9 +2057,12 @@ setNonBlocking(SOCKET fd)
{ {
GSSocketStream *ins = AUTORELEASE([[self _inputStreamClass] new]); GSSocketStream *ins = AUTORELEASE([[self _inputStreamClass] new]);
GSSocketStream *outs = AUTORELEASE([[self _outputStreamClass] new]); GSSocketStream *outs = AUTORELEASE([[self _outputStreamClass] new]);
socklen_t len = [ins _sockLen]; uint8_t buf[BUFSIZ];
int acceptReturn = accept([self _sock], [ins _peerAddr], &len); struct sockaddr *addr = (struct sockaddr*)buf;
socklen_t len = sizeof(buf);
int acceptReturn;
acceptReturn = accept([self _sock], addr, &len);
_events &= ~NSStreamEventHasBytesAvailable; _events &= ~NSStreamEventHasBytesAvailable;
if (socketError(acceptReturn)) if (socketError(acceptReturn))
{ // test for real error { // test for real error
@ -1953,7 +2079,8 @@ setNonBlocking(SOCKET fd)
[ins _setPassive: YES]; [ins _setPassive: YES];
[outs _setPassive: YES]; [outs _setPassive: YES];
// copy the addr to outs // copy the addr to outs
memcpy([outs _peerAddr], [ins _peerAddr], len); [ins _setAddress: addr];
[outs _setAddress: addr];
[ins _setSock: acceptReturn]; [ins _setSock: acceptReturn];
[outs _setSock: acceptReturn]; [outs _setSock: acceptReturn];
} }
@ -2097,16 +2224,6 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
@implementation GSInetInputStream @implementation GSInetInputStream
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in);
}
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
int ptonReturn; int ptonReturn;
@ -2114,24 +2231,30 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin_family = AF_INET; struct sockaddr_in peer;
_peerAddr.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr)); peer.sin_family = AF_INET;
peer.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &peer.sin_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
} }
else
{
[self _setAddress: (struct sockaddr*)&peer];
}
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key - (id) propertyForKey: (NSString *)key
{ {
id result = propertyForInet4Stream((intptr_t)_loopID, key); id result = [super propertyForKey: key];
if (result == nil) if (result == nil)
{ {
result = [super propertyForKey: key]; result = propertyForInet4Stream((intptr_t)_loopID, key);
} }
return result; return result;
} }
@ -2140,15 +2263,6 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
@implementation GSInet6InputStream @implementation GSInet6InputStream
#if defined(AF_INET6) #if defined(AF_INET6)
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in6);
}
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
@ -2157,24 +2271,30 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin6_family = AF_INET6; struct sockaddr_in6 peer;
_peerAddr.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr)); peer.sin6_family = AF_INET6;
peer.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &peer.sin6_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
} }
else
{
[self _setAddress: (struct sockaddr*)&peer];
}
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key - (id) propertyForKey: (NSString *)key
{ {
id result = propertyForInet6Stream((intptr_t)_loopID, key); id result = [super propertyForKey: key];
if (result == nil) if (result == nil)
{ {
result = [super propertyForKey: key]; result = propertyForInet6Stream((intptr_t)_loopID, key);
} }
return result; return result;
} }
@ -2190,16 +2310,6 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
@implementation GSInetOutputStream @implementation GSInetOutputStream
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in);
}
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
int ptonReturn; int ptonReturn;
@ -2207,24 +2317,30 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin_family = AF_INET; struct sockaddr_in peer;
_peerAddr.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr)); peer.sin_family = AF_INET;
peer.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &peer.sin_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
} }
else
{
[self _setAddress: (struct sockaddr*)&peer];
}
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key - (id) propertyForKey: (NSString *)key
{ {
id result = propertyForInet4Stream((intptr_t)_loopID, key); id result = [super propertyForKey: key];
if (result == nil) if (result == nil)
{ {
result = [super propertyForKey: key]; result = propertyForInet4Stream((intptr_t)_loopID, key);
} }
return result; return result;
} }
@ -2233,15 +2349,6 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
@implementation GSInet6OutputStream @implementation GSInet6OutputStream
#if defined(AF_INET6) #if defined(AF_INET6)
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in6);
}
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
@ -2250,24 +2357,30 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin6_family = AF_INET6; struct sockaddr_in6 peer;
_peerAddr.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr)); peer.sin6_family = AF_INET6;
peer.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &peer.sin6_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
} }
else
{
[self _setAddress: (struct sockaddr*)&peer];
}
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key - (id) propertyForKey: (NSString *)key
{ {
id result = propertyForInet6Stream((intptr_t)_loopID, key); id result = [super propertyForKey: key];
if (result == nil) if (result == nil)
{ {
result = [super propertyForKey: key]; result = propertyForInet6Stream((intptr_t)_loopID, key);
} }
return result; return result;
} }
@ -2293,30 +2406,21 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
return [GSInetOutputStream class]; return [GSInetOutputStream class];
} }
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in);
}
- (struct sockaddr*) _serverAddr
{
return (struct sockaddr*)&_serverAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
int ptonReturn; int ptonReturn;
const char *addr_c = [addr cStringUsingEncoding: NSUTF8StringEncoding]; const char *addr_c = [addr cStringUsingEncoding: NSUTF8StringEncoding];
struct sockaddr_in addr;
_serverAddr.sin_family = AF_INET; addr.sin_family = AF_INET;
_serverAddr.sin_port = GSSwapHostI16ToBig(port); addr.sin_port = GSSwapHostI16ToBig(port);
if (addr_c == 0) if (addr_c == 0)
{ {
addr_c = "0.0.0.0"; /* Bind on all addresses */ addr_c = "0.0.0.0"; /* Bind on all addresses */
} }
ptonReturn = inet_pton(AF_INET, addr_c, &(_serverAddr.sin_addr)); ptonReturn = inet_pton(AF_INET, addr_c, &addr.sin_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
@ -2332,6 +2436,7 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
} }
else else
{ {
[self _setAddress: (struct sockaddr*)&addr];
[self _setSock: s]; [self _setSock: s];
} }
} }
@ -2353,30 +2458,21 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
return [GSInet6OutputStream class]; return [GSInet6OutputStream class];
} }
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_in6);
}
- (struct sockaddr*) _serverAddr
{
return (struct sockaddr*)&_serverAddr;
}
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
if ([super init] != nil) if ([super init] != nil)
{ {
int ptonReturn; int ptonReturn;
const char *addr_c = [addr cStringUsingEncoding: NSUTF8StringEncoding]; const char *addr_c = [addr cStringUsingEncoding: NSUTF8StringEncoding];
struct sockaddr_in6 addr;
_serverAddr.sin6_family = AF_INET6; addr.sin6_family = AF_INET6;
_serverAddr.sin6_port = GSSwapHostI16ToBig(port); addr.sin6_port = GSSwapHostI16ToBig(port);
if (addr_c == 0) if (addr_c == 0)
{ {
addr_c = "0:0:0:0:0:0:0:0"; /* Bind on all addresses */ addr_c = "0:0:0:0:0:0:0:0"; /* Bind on all addresses */
} }
ptonReturn = inet_pton(AF_INET6, addr_c, &(_serverAddr.sin6_addr)); ptonReturn = inet_pton(AF_INET6, addr_c, &addr.sin6_addr);
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
DESTROY(self); DESTROY(self);
@ -2392,6 +2488,7 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
} }
else else
{ {
[self _setAddress: (struct sockaddr*)&addr];
[self _setSock: s]; [self _setSock: s];
} }
} }

View file

@ -137,6 +137,7 @@ IVARS
* record an error based on errno * record an error based on errno
*/ */
- (void) _recordError; - (void) _recordError;
- (void) _recordError: (NSError*)anError;
/** /**
* say whether there is unhandled data for the stream. * say whether there is unhandled data for the stream.

View file

@ -335,6 +335,11 @@ static RunLoopEventType typeForStream(NSStream *aStream)
{ {
} }
- (void) _recordError: (NSError*)anError
{
return;
}
- (void) _schedule - (void) _schedule
{ {
} }
@ -381,8 +386,13 @@ static RunLoopEventType typeForStream(NSStream *aStream)
NSError *theError; NSError *theError;
theError = [NSError _last]; theError = [NSError _last];
// NSLog(@"%@ - %@", self, theError); [self _recordError: theError];
ASSIGN(_lastError, theError); }
- (void) _recordError: (NSError*)anError
{
// NSLog(@"%@ - %@", self, anError);
ASSIGN(_lastError, anError);
_currentStatus = NSStreamStatusError; _currentStatus = NSStreamStatusError;
} }

View file

@ -43,6 +43,7 @@
@end @end
@interface _NSHTTPURLProtocol : NSURLProtocol @interface _NSHTTPURLProtocol : NSURLProtocol
<NSURLAuthenticationChallengeSender>
{ {
GSMimeParser *_parser; // Parser handling incoming data GSMimeParser *_parser; // Parser handling incoming data
unsigned _parseOffset; // Bytes of body loaded in parser. unsigned _parseOffset; // Bytes of body loaded in parser.
@ -55,6 +56,9 @@
BOOL _debug; BOOL _debug;
BOOL _isLoading; BOOL _isLoading;
BOOL _shouldClose; BOOL _shouldClose;
NSURLAuthenticationChallenge *_challenge;
NSURLCredential *_credential;
NSHTTPURLResponse *_response;
} }
@end @end
@ -295,6 +299,23 @@ static NSURLProtocol *placeholder = nil;
return request; return request;
} }
- (void) cancelAuthenticationChallenge: (NSURLAuthenticationChallenge*)c
{
if (c == _challenge)
{
DESTROY(_challenge); // We should cancel the download
}
}
- (void) continueWithoutCredentialForAuthenticationChallenge:
(NSURLAuthenticationChallenge*)c
{
if (c == _challenge)
{
DESTROY(_credential); // We download the challenge page
}
}
- (void) _didInitializeOutputStream: (NSOutputStream*)stream - (void) _didInitializeOutputStream: (NSOutputStream*)stream
{ {
return; return;
@ -304,6 +325,9 @@ static NSURLProtocol *placeholder = nil;
{ {
[_parser release]; // received headers [_parser release]; // received headers
[_body release]; // for sending the body [_body release]; // for sending the body
[_response release];
[_credential release];
[_credential release];
[super dealloc]; [super dealloc];
} }
@ -348,6 +372,7 @@ static NSURLProtocol *placeholder = nil;
return; return;
} }
_statusCode = 0; /* No status returned yet. */
_isLoading = YES; _isLoading = YES;
_complete = NO; _complete = NO;
_debug = NO; _debug = NO;
@ -357,7 +382,6 @@ static NSURLProtocol *placeholder = nil;
*/ */
if ([[[this->request URL] path] length] == 0) if ([[[this->request URL] path] length] == 0)
{ {
NSURLRequest *request;
NSString *s = [[this->request URL] absoluteString]; NSString *s = [[this->request URL] absoluteString];
NSURL *url; NSURL *url;
@ -374,8 +398,7 @@ static NSURLProtocol *placeholder = nil;
s = [s stringByAppendingString: @"/"]; s = [s stringByAppendingString: @"/"];
} }
url = [NSURL URLWithString: s]; url = [NSURL URLWithString: s];
request = [NSURLRequest requestWithURL: url]; if (url == nil)
if (request == nil)
{ {
NSError *e; NSError *e;
@ -388,6 +411,10 @@ static NSURLProtocol *placeholder = nil;
} }
else else
{ {
NSMutableURLRequest *request;
request = [this->request mutableCopy];
[request setURL: url];
[this->client URLProtocol: self [this->client URLProtocol: self
wasRedirectedToRequest: request wasRedirectedToRequest: request
redirectResponse: nil]; redirectResponse: nil];
@ -546,7 +573,6 @@ static NSURLProtocol *placeholder = nil;
if (wasInHeaders == YES && isInHeaders == NO) if (wasInHeaders == YES && isInHeaders == NO)
{ {
NSHTTPURLResponse *response;
GSMimeHeader *info; GSMimeHeader *info;
NSString *enc; NSString *enc;
int len = -1; int len = -1;
@ -585,13 +611,14 @@ static NSURLProtocol *placeholder = nil;
enc = [[document headerNamed: @"transfer-encoding"] value]; enc = [[document headerNamed: @"transfer-encoding"] value];
} }
response = [[NSHTTPURLResponse alloc] initWithURL: [this->request URL] _response = [[NSHTTPURLResponse alloc]
MIMEType: nil initWithURL: [this->request URL]
expectedContentLength: len MIMEType: nil
textEncodingName: nil]; expectedContentLength: len
[response _setStatusCode: _statusCode text: s]; textEncodingName: nil];
[_response _setStatusCode: _statusCode text: s];
[document deleteHeaderNamed: @"http"]; [document deleteHeaderNamed: @"http"];
[response _setHeaders: [document allHeaders]]; [_response _setHeaders: [document allHeaders]];
if (_statusCode == 204 || _statusCode == 304) if (_statusCode == 204 || _statusCode == 304)
{ {
@ -606,17 +633,18 @@ static NSURLProtocol *placeholder = nil;
_complete = YES; // Had EOF ... terminate _complete = YES; // Had EOF ... terminate
} }
/* Check for a redirect. if (_statusCode == 401)
*/
s = [[document headerNamed: @"location"] value];
if ([s length] > 0)
{ {
NSURLRequest *request; /* This is an authentication challenge, so we keep reading
NSURL *url; * until the challenge is complete, then try to deal with it.
*/
}
else if ((s = [[document headerNamed: @"location"] value]) != nil)
{
NSURL *url;
url = [NSURL URLWithString: s]; url = [NSURL URLWithString: s];
request = [NSURLRequest requestWithURL: url]; if (url == nil)
if (request == nil)
{ {
NSError *e; NSError *e;
@ -629,9 +657,13 @@ static NSURLProtocol *placeholder = nil;
} }
else else
{ {
NSMutableURLRequest *request;
request = [this->request mutableCopy];
[request setURL: url];
[this->client URLProtocol: self [this->client URLProtocol: self
wasRedirectedToRequest: request wasRedirectedToRequest: request
redirectResponse: response]; redirectResponse: _response];
} }
} }
else else
@ -660,13 +692,173 @@ static NSURLProtocol *placeholder = nil;
} }
} }
[this->client URLProtocol: self [this->client URLProtocol: self
didReceiveResponse: response didReceiveResponse: _response
cacheStoragePolicy: policy]; cacheStoragePolicy: policy];
} }
} }
if (_complete == YES) if (_complete == YES)
{ {
if (_statusCode == 401)
{
NSURLProtectionSpace *space;
NSString *hdr;
NSURL *url;
int failures = 0;
/* This was an authentication challenge.
*/
hdr = [[document headerNamed: @"WWW-Authenticate"] value];
url = [this->request URL];
space = [GSHTTPAuthentication
protectionSpaceForAuthentication: hdr requestURL: url];
DESTROY(_credential);
if (space != nil)
{
/* Create credential from user and password
* stored in the URL.
* Returns nil if we have no username or password.
*/
_credential = [[NSURLCredential alloc]
initWithUser: [url user]
password: [url password]
persistence: NSURLCredentialPersistenceForSession];
if (_credential == nil)
{
/* No credential from the URL, so we try using the
* default credential for the protection space.
*/
ASSIGN(_credential,
[[NSURLCredentialStorage sharedCredentialStorage]
defaultCredentialForProtectionSpace: space]);
}
}
if (_challenge != nil)
{
/* The failure count is incremented if we have just
* tried a request in the same protection space.
*/
if (YES == [[_challenge protectionSpace] isEqual: space])
{
failures = [_challenge previousFailureCount] + 1;
}
}
else if ([this->request valueForHTTPHeaderField:@"Authorization"])
{
/* Our request had an authorization header, so we should
* count that as a failure or we wouldn't have been
* challenged.
*/
failures = 1;
}
DESTROY(_challenge);
_challenge = [[NSURLAuthenticationChallenge alloc]
initWithProtectionSpace: space
proposedCredential: _credential
previousFailureCount: failures
failureResponse: _response
error: nil
sender: self];
/* Allow the client to control the credential we send
* or whether we actually send at all.
*/
[this->client URLProtocol: self
didReceiveAuthenticationChallenge: _challenge];
if (_challenge == nil)
{
NSError *e;
/* The client cancelled the authentication challenge
* so we must cancel the download.
*/
e = [NSError errorWithDomain: @"Authentication cancelled"
code: 0
userInfo: nil];
[self stopLoading];
[this->client URLProtocol: self
didFailWithError: e];
}
else
{
NSString *auth = nil;
if (_credential != nil)
{
GSHTTPAuthentication *authentication;
/* Get information about basic or
* digest authentication.
*/
authentication = [GSHTTPAuthentication
authenticationWithCredential: _credential
inProtectionSpace: space];
/* Generate authentication header value for the
* authentication type in the challenge.
*/
auth = [authentication
authorizationForAuthentication: hdr
method: [this->request HTTPMethod]
path: [url path]];
}
if (auth == nil)
{
NSURLCacheStoragePolicy policy;
/* We have no authentication credentials so we
* treat this as a download of the challenge page.
*/
/* Tell the client that we have a response and how
* it should be cached.
*/
policy = [this->request cachePolicy];
if (policy == NSURLRequestUseProtocolCachePolicy)
{
if ([self isKindOfClass: [_NSHTTPSURLProtocol class]])
{
/* For HTTPS we should not allow caching unless
* the request explicitly wants it.
*/
policy = NSURLCacheStorageNotAllowed;
}
else
{
/* For HTTP we allow caching unless the request
* specifically denies it.
*/
policy = NSURLCacheStorageAllowed;
}
}
[this->client URLProtocol: self
didReceiveResponse: _response
cacheStoragePolicy: policy];
/* Fall through to code providing page data.
*/
}
else
{
NSMutableURLRequest *request;
/* To answer the authentication challenge,
* we must retry with a modified request and
* with the cached response cleared.
*/
request = [this->request mutableCopy];
[request setValue: auth
forHTTPHeaderField: @"Authorization"];
[self stopLoading];
DESTROY(this->cachedResponse);
[self startLoading];
}
}
}
[self _unschedule]; [self _unschedule];
if (_shouldClose == YES) if (_shouldClose == YES)
{ {
@ -676,88 +868,6 @@ static NSURLProtocol *placeholder = nil;
DESTROY(this->output); DESTROY(this->output);
} }
#if 0
/*
* Retrieve essential keys from document
*/
if (_statusCode == 401 && self->challenged < 2)
{
GSMimeHeader *ah;
self->challenged++; // Prevent repeated challenge/auth
if ((ah = [document headerNamed: @"WWW-Authenticate"]) != nil)
{
NSURLProtectionSpace *space;
NSString *ac;
GSHTTPAuthentication *authentication;
NSString *method;
NSString *auth;
ac = [ah value];
space = [GSHTTPAuthentication
protectionSpaceForAuthentication: ac requestURL: url];
if (space == nil)
{
authentication = nil;
}
else
{
NSURLCredential *cred;
/*
* Create credential from user and password
* stored in the URL.
* Returns nil if we have no username or password.
*/
cred = [[NSURLCredential alloc]
initWithUser: [url user]
password: [url password]
persistence: NSURLCredentialPersistenceForSession];
if (cred == nil)
{
authentication = nil;
}
else
{
/*
* Get the digest object and ask it for a header
* to use for authorisation.
* Returns nil if we have no credential.
*/
authentication = [GSHTTPAuthentication
authenticationWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
}
}
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)
{
if ([wData length] > 0)
{
method = @"POST";
}
else
{
method = @"GET";
}
}
auth = [authentication authorizationForAuthentication: ac
method: method
path: [url path]];
if (auth != nil)
{
[self writeProperty: auth forKey: @"Authorization"];
[self _tryLoadInBackground: u];
return; // Retrying.
}
}
}
#endif
/* /*
* Tell superclass that we have successfully loaded the data * Tell superclass that we have successfully loaded the data
* (as long as we haven't had the load terminated by the client). * (as long as we haven't had the load terminated by the client).
@ -787,7 +897,7 @@ static NSURLProtocol *placeholder = nil;
} }
} }
} }
else if (_isLoading == YES) else if (_isLoading == YES && _statusCode != 401)
{ {
/* /*
* Report partial data if possible. * Report partial data if possible.
@ -1074,6 +1184,14 @@ static NSURLProtocol *placeholder = nil;
[this->client URLProtocol: self didFailWithError: [stream streamError]]; [this->client URLProtocol: self didFailWithError: [stream streamError]];
} }
- (void) useCredential: (NSURLCredential*)credential
forAuthenticationChallenge: (NSURLAuthenticationChallenge*)challenge
{
if (challenge == _challenge)
{
ASSIGN(_credential, credential);
}
}
@end @end
@implementation _NSHTTPSURLProtocol @implementation _NSHTTPSURLProtocol

View file

@ -183,7 +183,11 @@ typedef struct {
cachePolicy: (NSURLRequestCachePolicy)cachePolicy cachePolicy: (NSURLRequestCachePolicy)cachePolicy
timeoutInterval: (NSTimeInterval)timeoutInterval timeoutInterval: (NSTimeInterval)timeoutInterval
{ {
if ((self = [super init]) != nil) if ([URL isKindOfClass: [NSURL class]] == NO)
{
DESTROY(self);
}
else if ((self = [super init]) != nil)
{ {
this->URL = RETAIN(URL); this->URL = RETAIN(URL);
this->cachePolicy = cachePolicy; this->cachePolicy = cachePolicy;

View file

@ -49,11 +49,6 @@
@end @end
@interface GSLocalInputStream : GSSocketInputStream @interface GSLocalInputStream : GSSocketInputStream
{
@private
struct sockaddr_un _peerAddr;
}
/** /**
* the designated initializer * the designated initializer
*/ */
@ -73,11 +68,6 @@
@end @end
@interface GSLocalOutputStream : GSSocketOutputStream @interface GSLocalOutputStream : GSSocketOutputStream
{
@private
struct sockaddr_un _peerAddr;
}
/** /**
* the designated initializer * the designated initializer
*/ */
@ -218,29 +208,22 @@
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sun_family = AF_LOCAL; struct sockaddr_un peer;
if (strlen(real_addr)>sizeof(_peerAddr.sun_path)-1) // too long
peer.sun_family = AF_LOCAL;
if (strlen(real_addr) > sizeof(peer.sun_path)-1) // too long
{ {
DESTROY(self); DESTROY(self);
} }
else else
{ {
strncpy(_peerAddr.sun_path, real_addr, sizeof(_peerAddr.sun_path)-1); strncpy(peer.sun_path, real_addr, sizeof(peer.sun_path)-1);
[self _setAddress: (struct sockaddr)&peer];
} }
} }
return self; return self;
} }
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_un);
}
@end @end
@implementation GSFileOutputStream @implementation GSFileOutputStream
@ -364,29 +347,22 @@
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sun_family = AF_LOCAL; struct sockaddr_un peer;
if (strlen(real_addr) > sizeof(_peerAddr.sun_path)-1) // too long
peer.sun_family = AF_LOCAL;
if (strlen(real_addr) > sizeof(peer.sun_path)-1) // too long
{ {
DESTROY(self); DESTROY(self);
} }
else else
{ {
strncpy(_peerAddr.sun_path, real_addr, sizeof(_peerAddr.sun_path)-1); strncpy(peer.sun_path, real_addr, sizeof(peer.sun_path)-1);
[self _setAddress: (struct sockaddr*)&peer];
} }
} }
return self; return self;
} }
- (struct sockaddr*) _peerAddr
{
return (struct sockaddr*)&_peerAddr;
}
- (socklen_t) sockLen
{
return sizeof(struct sockaddr_un);
}
@end @end
@implementation NSStream @implementation NSStream
@ -657,23 +633,14 @@
return [GSLocalOutputStream class]; return [GSLocalOutputStream class];
} }
- (socklen_t) _sockLen
{
return sizeof(struct sockaddr_un);
}
- (struct sockaddr*) _serverAddr
{
return (struct sockaddr*)&_serverAddr;
}
- (id) initToAddr: (NSString*)addr - (id) initToAddr: (NSString*)addr
{ {
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
const char* real_addr = [addr fileSystemRepresentation]; const char* real_addr = [addr fileSystemRepresentation];
struct sockaddr_un addr;
if (strlen(real_addr) > sizeof(_serverAddr.sun_path)-1) if (strlen(real_addr) > sizeof(addr.sun_path)-1)
{ {
DESTROY(self); DESTROY(self);
} }
@ -681,7 +648,7 @@
{ {
SOCKET s; SOCKET s;
_serverAddr.sun_family = AF_LOCAL; addr.sun_family = AF_LOCAL;
s = socket(AF_LOCAL, SOCK_STREAM, 0); s = socket(AF_LOCAL, SOCK_STREAM, 0);
if (s < 0) if (s < 0)
{ {
@ -690,8 +657,8 @@
else else
{ {
[(GSSocketStream*)self _setSock: s]; [(GSSocketStream*)self _setSock: s];
strncpy(_serverAddr.sun_path, real_addr, strncpy(addr.sun_path, real_addr, sizeof(addr.sun_path)-1);
sizeof(_serverAddr.sun_path)-1); [self _setAddress: (struct sockaddr)&addr];
} }
} }
} }