Ben Copsey

Added support for PAC scripts, plus two tests for same

... ... @@ -275,6 +275,8 @@ extern NSString* const NetworkRequestErrorDomain;
// Details on the proxy to use - you could set these yourself, but it's probably best to let ASIHTTPRequest detect the system proxy settings
NSString *proxyHost;
int proxyPort;
NSURL *PACurl;
}
#pragma mark init / dealloc
... ... @@ -437,6 +439,11 @@ extern NSString* const NetworkRequestErrorDomain;
// Is only used when you have specified a Bundle Display Name (CFDisplayBundleName) or Bundle Name (CFBundleName) in your plist
+ (NSString *)defaultUserAgentString;
#pragma mark proxy autoconfiguration
// Returns an array of proxies to use for a particular url, given the url of a PAC script
+ (NSArray *)proxiesForURL:(NSURL *)theURL fromPAC:(NSURL *)pacScriptURL;
@property (retain) NSString *username;
@property (retain) NSString *password;
@property (retain) NSString *domain;
... ... @@ -495,4 +502,6 @@ extern NSString* const NetworkRequestErrorDomain;
@property (assign) BOOL shouldRedirect;
@property (assign) BOOL validatesSecureCertificate;
@property (assign) BOOL shouldCompressRequestBody;
@property (assign) BOOL needsProxyAuthentication;
@property (retain) NSURL *PACurl;
@end
... ...
... ... @@ -76,7 +76,6 @@ static NSError *ASITooMuchRedirectionError;
@property (retain, nonatomic) NSOutputStream *fileDownloadOutputStream;
@property (assign, nonatomic) int authenticationRetryCount;
@property (assign, nonatomic) int proxyAuthenticationRetryCount;
@property (assign, nonatomic) BOOL needsProxyAuthentication;
@property (assign, nonatomic) BOOL updatedProgress;
@property (assign, nonatomic) BOOL needsRedirect;
@property (assign, nonatomic) int redirectCount;
... ... @@ -518,9 +517,23 @@ static NSError *ASITooMuchRedirectionError;
}
// Handle proxy settings
// Have details of the proxy been set on this request
if (![self proxyHost] && ![self proxyPort]) {
// If not, we need to figure out what they'll be
NSArray *proxies = nil;
// Have we been given a proxy auto config file?
if ([self PACurl]) {
proxies = [ASIHTTPRequest proxiesForURL:[self url] fromPAC:[self PACurl]];
// Detect proxy settings and apply them
} else {
#if TARGET_OS_IPHONE
#if !defined(TARGET_IPHONE_SIMULATOR) || __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_2_2
NSDictionary *proxySettings = [(NSDictionary *)CFNetworkCopySystemProxySettings() autorelease];
... ... @@ -532,8 +545,16 @@ static NSError *ASITooMuchRedirectionError;
NSDictionary *proxySettings = [(NSDictionary *)SCDynamicStoreCopyProxies(NULL) autorelease];
#endif
NSArray *proxies = [(NSArray *)CFNetworkCopyProxiesForURL((CFURLRef)[self url], (CFDictionaryRef)proxySettings) autorelease];
if (proxies == NULL) {
proxies = [(NSArray *)CFNetworkCopyProxiesForURL((CFURLRef)[self url], (CFDictionaryRef)proxySettings) autorelease];
// Now check to see if the proxy settings contained a PAC url, we need to run the script to get the real list of proxies if so
NSDictionary *settings = [proxies objectAtIndex:0];
if ([settings objectForKey:(NSString *)kCFProxyAutoConfigurationURLKey]) {
proxies = [ASIHTTPRequest proxiesForURL:[self url] fromPAC:[settings objectForKey:(NSString *)kCFProxyAutoConfigurationURLKey]];
}
}
if (!proxies) {
CFRelease(readStream);
readStream = NULL;
[[self cancelledLock] unlock];
... ... @@ -546,8 +567,6 @@ static NSError *ASITooMuchRedirectionError;
NSDictionary *settings = [proxies objectAtIndex:0];
[self setProxyHost:[settings objectForKey:(NSString *)kCFProxyHostNameKey]];
[self setProxyPort:[[settings objectForKey:(NSString *)kCFProxyPortNumberKey] intValue]];
//NSLog(@"%@",proxySettings);
//NSLog(@"%@",[proxies objectAtIndex:0]);
}
}
if ([self proxyHost] && [self proxyPort]) {
... ... @@ -2173,6 +2192,31 @@ static NSError *ASITooMuchRedirectionError;
return [NSString stringWithFormat:@"%@ %@ (%@; %@ %@; %@)", appName, appVersion, deviceName, OSName, OSVersion, locale];
}
#pragma mark proxy autoconfiguration
// Returns an array of proxies to use for a particular url, given the url of a PAC script
+ (NSArray *)proxiesForURL:(NSURL *)theURL fromPAC:(NSURL *)pacScriptURL
{
// From: http://developer.apple.com/samplecode/CFProxySupportTool/listing1.html
// Work around <rdar://problem/5530166>. This dummy call to
// CFNetworkCopyProxiesForURL initialise some state within CFNetwork
// that is required by CFNetworkCopyProxiesForAutoConfigurationScript.
(void) CFNetworkCopyProxiesForURL((CFURLRef)theURL, NULL);
NSStringEncoding encoding;
NSError *err = nil;
NSString *script = [NSString stringWithContentsOfURL:pacScriptURL usedEncoding:&encoding error:&err];
if (err) {
return nil;
}
CFErrorRef err2 = NULL;
// Obtain the list of proxies by running the autoconfiguration script
NSArray *proxies = [(NSArray *)CFNetworkCopyProxiesForAutoConfigurationScript((CFStringRef)script,(CFURLRef)theURL, &err2) autorelease];
if (err2) {
return nil;
}
return proxies;
}
@synthesize username;
... ... @@ -2249,4 +2293,5 @@ static NSError *ASITooMuchRedirectionError;
@synthesize proxyHost;
@synthesize proxyPort;
@synthesize PACurl;
@end
... ...
... ... @@ -18,6 +18,37 @@ static NSString *proxyPassword = @"";
@implementation ProxyTests
- (void)testAutoConfigureWithPAC
{
// To run this test, specify the location of the pac script that is available at http://developer.apple.com/samplecode/CFProxySupportTool/listing1.html
NSString *pacurl = @"file:///Users/ben/Desktop/test.pac";
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setPACurl:[NSURL URLWithString:pacurl]];
[request start];
NSLog(@"%@",[request proxyHost]);
BOOL success = [[request proxyHost] isEqualToString:@"proxy1.apple.com"];
GHAssertTrue(success,@"Failed to use the correct proxy");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]];
[request setPACurl:[NSURL URLWithString:pacurl]];
[request start];
GHAssertNil([request proxyHost],@"Used a proxy when the script told us to go direct");
}
- (void)testAutoConfigureWithSystemPAC
{
// To run this test, specify the pac script above in your network settings
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request start];
NSLog(@"%@",[request proxyHost]);
BOOL success = [[request proxyHost] isEqualToString:@"proxy1.apple.com"];
GHAssertTrue(success,@"Failed to use the correct proxy");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]];
[request start];
GHAssertNil([request proxyHost],@"Used a proxy when the script told us to go direct");
}
- (void)testProxy
{
BOOL success = (![proxyHost isEqualToString:@""] && proxyPort > 0);
... ...
... ... @@ -217,8 +217,13 @@
- (void)authSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
ASIHTTPRequest *request = (ASIHTTPRequest *)contextInfo;
if (returnCode == NSOKButton) {
if ([request needsProxyAuthentication]) {
[request setProxyUsername:[[[username stringValue] copy] autorelease]];
[request setProxyPassword:[[[password stringValue] copy] autorelease]];
} else {
[request setUsername:[[[username stringValue] copy] autorelease]];
[request setPassword:[[[password stringValue] copy] autorelease]];
}
[request retryWithAuthentication];
} else {
[request cancelLoad];
... ...