diff --git a/ChangeLog b/ChangeLog index 6a862f217..6335a8f4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,15 @@ contigure.ac: Add --enable-xslt option to require stylesheet support (in case we want to start uisng it to generate documentation) + * Headers/Foundation/NSURLHandle.h: + * Source/GSFileHandle.m: + * Source/GSHTTPURLHandle.m: + * Source/NSFileHandle.m: + * Source/NSURLHandle.m: + Support binding to specific local ip address for outgoing connections + in gnustep extensions. + * Source/GSMime.m: ([-setContent:]), ([-addContent:]) Check that + content of a multipart document consists of GSMimeDocument objects. 2004-03-29 Adrian Robert diff --git a/Headers/Foundation/NSURLHandle.h b/Headers/Foundation/NSURLHandle.h index 326ce52be..eb488f7b1 100644 --- a/Headers/Foundation/NSURLHandle.h +++ b/Headers/Foundation/NSURLHandle.h @@ -42,6 +42,7 @@ GS_EXPORT NSString * const NSHTTPPropertyRedirectionHeadersKey; GS_EXPORT NSString * const NSHTTPPropertyErrorPageDataKey; #ifndef NO_GNUSTEP +GS_EXPORT NSString * const GSHTTPPropertyLocalHostKey; GS_EXPORT NSString * const GSHTTPPropertyMethodKey; GS_EXPORT NSString * const GSHTTPPropertyProxyHostKey; GS_EXPORT NSString * const GSHTTPPropertyProxyPortKey; diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index d9222e8f1..e3fa57e72 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -3317,6 +3317,11 @@ static NSCharacterSet *tokenSet = nil; */ - (void) addContent: (id)newContent { + if ([newContent isKindOfClass: [GSMimeDocument class]] == NO) + { + [NSException raise: NSInvalidArgumentException + format: @"Content to add is not a GSMimeDocument"]; + } if (content == nil) { content = [NSMutableArray new]; @@ -4469,6 +4474,18 @@ static NSCharacterSet *tokenSet = nil; { if (newContent != content) { + unsigned c = [newContent count]; + + while (c-- > 0) + { + id o = [newContent objectAtIndex: c]; + + if ([o isKindOfClass: [GSMimeDocument class]] == NO) + { + [NSException raise: NSInvalidArgumentException + format: @"Content contains non-GSMimeDocument"]; + } + } newContent = [newContent mutableCopy]; ASSIGN(content, newContent); RELEASE(newContent); diff --git a/Source/GSFileHandle.m b/Source/GSFileHandle.m index 35229e37a..459f9fe10 100644 --- a/Source/GSFileHandle.m +++ b/Source/GSFileHandle.m @@ -685,6 +685,8 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr"; static BOOL beenHere = NO; SOCKET net; struct sockaddr_in sin; + struct sockaddr_in lsin; + NSString *lhost = nil; NSString *shost = nil; NSString *sport = nil; @@ -720,6 +722,30 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr"; return nil; } + if ([p hasPrefix: @"bind-"] == YES) + { + NSRange r; + + lhost = [p substringFromIndex: 5]; + r = [lhost rangeOfString: @":"]; + if (r.length > 0) + { + p = [lhost substringFromIndex: NSMaxRange(r)]; + lhost = [lhost substringToIndex: r.location]; + } + else + { + p = nil; + } + if (getAddr(lhost, p, @"tcp", &lsin) == NO) + { + NSLog(@"bad bind address specification"); + RELEASE(self); + return nil; + } + p = @"tcp"; + } + /** * A protocol fo the form 'socks-...' controls socks operation, * overriding defaults and environment variables.
@@ -795,6 +821,21 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr"; RELEASE(self); return nil; } + if (lhost != nil) + { + if (bind(net, (struct sockaddr *)&lsin, sizeof(lsin)) == SOCKET_ERROR) + { + NSLog(@"unable to bind to port %s:%d - %s", inet_ntoa(lsin.sin_addr), + GSSwapBigI16ToHost(sin.sin_port), GSLastErrorStr(errno)); +#if defined(__MINGW__) + (void) closesocket(net); +#else + (void) close(net); +#endif + RELEASE(self); + return nil; + } + } #if defined(__MINGW__) self = [self initWithNativeHandle: (void*)net closeOnDealloc: YES]; diff --git a/Source/GSHTTPURLHandle.m b/Source/GSHTTPURLHandle.m index d8a88cada..33564d19d 100644 --- a/Source/GSHTTPURLHandle.m +++ b/Source/GSHTTPURLHandle.m @@ -161,6 +161,12 @@ char emp[64] = { * secure connection when a proxy is specified, GSHTTPURLHandle will * attempt to open an SSL Tunnel through the proxy. *

+ *

+ * Requests to the remote server may be forced to be bound to a + * particular local IP address by using the key + * "GSHTTPPropertyLocalHostKey" which must contain the + * IP address of a network interface on the local host. + *

*/ @implementation GSHTTPURLHandle @@ -450,6 +456,7 @@ static void debugWrite(NSData *data) NSNotificationCenter *nc; NSString *host = nil; NSString *port = nil; + NSString *s; /* * Don't start a load if one is in progress. @@ -471,6 +478,20 @@ static void debugWrite(NSData *data) [sock closeFile]; DESTROY(sock); } + + /* + * If we have a local address specified, tell the file handle to bind to it. + */ + s = [request objectForKey: GSHTTPPropertyLocalHostKey]; + if ([s length] > 0) + { + s = [NSString stringWithFormat: @"bind-%@", s]; + } + else + { + s = @"tcp"; // Bind to any. + } + if ([[request objectForKey: GSHTTPPropertyProxyHostKey] length] == 0) { NSNumber *p; @@ -493,17 +514,15 @@ static void debugWrite(NSData *data) @"https not supported ... needs SSL bundle"]; return; } - sock = [sslClass - fileHandleAsClientInBackgroundAtAddress: host - service: port - protocol: @"tcp"]; + sock = [sslClass fileHandleAsClientInBackgroundAtAddress: host + service: port + protocol: s]; } else { - sock = [NSFileHandle - fileHandleAsClientInBackgroundAtAddress: host - service: port - protocol: @"tcp"]; + sock = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: host + service: port + protocol: s]; } } else @@ -522,19 +541,17 @@ static void debugWrite(NSData *data) } host = [request objectForKey: GSHTTPPropertyProxyHostKey]; port = [request objectForKey: GSHTTPPropertyProxyPortKey]; - sock = [sslClass - fileHandleAsClientInBackgroundAtAddress: host - service: port - protocol: @"tcp"]; + sock = [sslClass fileHandleAsClientInBackgroundAtAddress: host + service: port + protocol: s]; } else { host = [request objectForKey: GSHTTPPropertyProxyHostKey]; port = [request objectForKey: GSHTTPPropertyProxyPortKey]; - sock = [NSFileHandle - fileHandleAsClientInBackgroundAtAddress: host - service: port - protocol: @"tcp"]; + sock = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: host + service: port + protocol: s]; } } if (sock == nil) diff --git a/Source/NSFileHandle.m b/Source/NSFileHandle.m index 02ff4ef92..fe5218860 100644 --- a/Source/NSFileHandle.m +++ b/Source/NSFileHandle.m @@ -428,7 +428,10 @@ NSString * const NSFileHandleOperationException * is not made via a socks server.
* Otherwise, the text '...' must be the name of the host on which the * socks5 server is running, with an optional port number separated - * from the host name by a colon. + * from the host name by a colon.
+ * Alternatively a prefix of the form 'bind-' forllowed by an IP address + * may be used (for non-socks connections) to ensure that the connection + * is made from the specified address. * * * If modes is nil or empty, uses NSDefaultRunLoopMode. diff --git a/Source/NSURLHandle.m b/Source/NSURLHandle.m index 4afd8c9d3..1023d02cf 100644 --- a/Source/NSURLHandle.m +++ b/Source/NSURLHandle.m @@ -64,6 +64,9 @@ NSString * const NSHTTPPropertyErrorPageDataKey NSString * const GSHTTPPropertyMethodKey = @"GSHTTPPropertyMethodKey"; +NSString * const GSHTTPPropertyLocalHostKey + = @"GSHTTPPropertyLocalHostKey"; + NSString * const GSHTTPPropertyProxyHostKey = @"GSHTTPPropertyProxyHostKey";