Skip to content
Browse files

Added support for PAC scripts, plus two tests for same

  • Loading branch information...
1 parent 87f6031 commit a6b463d26479d5dcfaedb6dba04999fdfeb5b3c3 @pokeb pokeb committed Aug 2, 2009
Showing with 109 additions and 19 deletions.
  1. +9 −0 Classes/ASIHTTPRequest.h
  2. +62 −17 Classes/ASIHTTPRequest.m
  3. +31 −0 Classes/Tests/ProxyTests.m
  4. +7 −2 Mac Sample/AppDelegate.m
View
9 Classes/ASIHTTPRequest.h
@@ -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
View
79 Classes/ASIHTTPRequest.m
@@ -76,7 +76,6 @@ - (BOOL)askDelegateForProxyCredentials;
@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;
@@ -517,23 +516,45 @@ - (void)startRequest
CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, [NSMutableDictionary dictionaryWithObject:(NSString *)kCFBooleanFalse forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]);
}
+
+ // Handle proxy settings
+ // Have details of the proxy been set on this request
if (![self proxyHost] && ![self proxyPort]) {
- // Detect proxy settings and apply them
- #if TARGET_OS_IPHONE
- #if !defined(TARGET_IPHONE_SIMULATOR) || __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_2_2
- NSDictionary *proxySettings = [(NSDictionary *)CFNetworkCopySystemProxySettings() autorelease];
- #else
- // Can't detect proxies in 2.2.1 Simulator
- NSDictionary *proxySettings = [NSMutableDictionary dictionary];
- #endif
- #else
- NSDictionary *proxySettings = [(NSDictionary *)SCDynamicStoreCopyProxies(NULL) autorelease];
- #endif
-
- NSArray *proxies = [(NSArray *)CFNetworkCopyProxiesForURL((CFURLRef)[self url], (CFDictionaryRef)proxySettings) autorelease];
- if (proxies == NULL) {
+ // 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];
+ #else
+ // Can't detect proxies in 2.2.1 Simulator
+ NSDictionary *proxySettings = [NSMutableDictionary dictionary];
+ #endif
+ #else
+ NSDictionary *proxySettings = [(NSDictionary *)SCDynamicStoreCopyProxies(NULL) autorelease];
+ #endif
+
+ 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 @@ - (void)startRequest
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 @@ + (NSString *)defaultUserAgentString
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 @@ + (NSString *)defaultUserAgentString
@synthesize proxyHost;
@synthesize proxyPort;
+@synthesize PACurl;
@end
View
31 Classes/Tests/ProxyTests.m
@@ -18,6 +18,37 @@
@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);
View
9 Mac Sample/AppDelegate.m
@@ -217,8 +217,13 @@ - (IBAction)dismissAuthSheet:(id)sender {
- (void)authSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
ASIHTTPRequest *request = (ASIHTTPRequest *)contextInfo;
if (returnCode == NSOKButton) {
- [request setUsername:[[[username stringValue] copy] autorelease]];
- [request setPassword:[[[password stringValue] copy] autorelease]];
+ 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];

0 comments on commit a6b463d

Please sign in to comment.
Something went wrong with that request. Please try again.