From e5b342c1346035f28df352074d8571039e5c6ef9 Mon Sep 17 00:00:00 2001 From: Charlie Qiu Date: Wed, 19 Oct 2016 00:24:45 +0800 Subject: [PATCH] Monitor PAC file. Disable then enable the system pac configure after it has been modified. --- ShadowsocksX-NG/AppDelegate.swift | 1 + ShadowsocksX-NG/ProxyConfHelper.h | 4 +-- ShadowsocksX-NG/ProxyConfHelper.m | 56 +++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index 40f58ff..c1ca927 100755 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -162,6 +162,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele updateLaunchAtLoginMenu() ProxyConfHelper.install() + ProxyConfHelper.startMonitorPAC() applyConfig() SyncSSLocal() } diff --git a/ShadowsocksX-NG/ProxyConfHelper.h b/ShadowsocksX-NG/ProxyConfHelper.h index 0f0dfa0..65e34a0 100644 --- a/ShadowsocksX-NG/ProxyConfHelper.h +++ b/ShadowsocksX-NG/ProxyConfHelper.h @@ -20,8 +20,6 @@ + (void)disableProxy; -//+ (void)startPACServer:(NSString*) PACFilePath; -// -//+ (void)stopPACServer; ++ (void)startMonitorPAC; @end diff --git a/ShadowsocksX-NG/ProxyConfHelper.m b/ShadowsocksX-NG/ProxyConfHelper.m index dbe0128..05187c6 100644 --- a/ShadowsocksX-NG/ProxyConfHelper.m +++ b/ShadowsocksX-NG/ProxyConfHelper.m @@ -14,6 +14,7 @@ @implementation ProxyConfHelper GCDWebServer *webServer =nil; +FSEventStreamRef fsEventStream; + (BOOL)isVersionOk { NSTask *task; @@ -114,10 +115,14 @@ GCDWebServer *webServer =nil; } } ++ (NSString*)getPACFilePath { + return [NSString stringWithFormat:@"%@/%@", NSHomeDirectory(), @".ShadowsocksX-NG/gfwlist.js"]; +} + + (void)enablePACProxy { //start server here and then using the string next line //next two lines can open gcdwebserver and work around pac file - NSString* PACFilePath = [NSString stringWithFormat:@"%@/%@", NSHomeDirectory(), @".ShadowsocksX-NG/gfwlist.js"]; + NSString* PACFilePath = [self getPACFilePath]; [self startPACServer: PACFilePath]; NSURL* url = [NSURL URLWithString: [self getHttpPACUrl]]; @@ -172,22 +177,20 @@ GCDWebServer *webServer =nil; } + (void)startPACServer:(NSString*) PACFilePath { - //接受参数为以后使用定制PAC文件 + [self stopPACServer]; NSString * routerPath = @"/proxy.pac"; - [self stopPACServer]; + NSData* originalPACData = [NSData dataWithContentsOfFile:PACFilePath]; + webServer = [[GCDWebServer alloc] init]; [webServer addHandlerForMethod:@"GET" path:routerPath requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest *request) { - NSLog(@"get proxy.pac"); - NSData* originalPACData = [NSData dataWithContentsOfFile:PACFilePath]; GCDWebServerDataResponse* resp = [GCDWebServerDataResponse responseWithData:originalPACData contentType:@"application/x-ns-proxy-autoconfig"]; - resp.cacheControlMaxAge = 0; return resp; } ]; @@ -206,4 +209,45 @@ GCDWebServer *webServer =nil; } } +void onPACChange( + ConstFSEventStreamRef streamRef, + void *clientCallBackInfo, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) +{ + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + if ([defaults boolForKey:@"ShadowsocksOn"]) { + if ([[defaults stringForKey:@"ShadowsocksRunningMode"] isEqualToString:@"auto"]) { + [ProxyConfHelper disableProxy]; + [ProxyConfHelper enablePACProxy]; + } + } +} + ++ (void)startMonitorPAC { + NSString* PACFilePath = [self getPACFilePath]; + + if (fsEventStream) { + return; + } + CFStringRef mypath = (__bridge CFStringRef)(PACFilePath); + CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL); + void *callbackInfo = NULL; // could put stream-specific data here. + CFAbsoluteTime latency = 3.0; /* Latency in seconds */ + + /* Create the stream, passing in a callback */ + fsEventStream = FSEventStreamCreate(NULL, + &onPACChange, + callbackInfo, + pathsToWatch, + kFSEventStreamEventIdSinceNow, /* Or a previous event ID */ + latency, + kFSEventStreamCreateFlagNone /* Flags explained in reference */ + ); + FSEventStreamScheduleWithRunLoop(fsEventStream, [[NSRunLoop mainRunLoop] getCFRunLoop], (__bridge CFStringRef)NSDefaultRunLoopMode); + FSEventStreamStart(fsEventStream); +} + @end