diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index 37c8a71..d160b0b 100644 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -52,6 +52,8 @@ 9BEEF0751D04EF3E00FC52B3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0731D04EF3E00FC52B3 /* PreferencesWindowController.swift */; }; 9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0771D04FE8A00FC52B3 /* LaunchAgentUtils.swift */; }; 9BEEF07B1D05631500FC52B3 /* AdvPreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0791D05631500FC52B3 /* AdvPreferencesWindowController.swift */; }; + C8E42A6C1D4F270A0074C7EA /* UserRulesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */; }; + C8E42A6E1D4F2CAF0074C7EA /* UserRulesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */; }; E0E57CCA7EB34B90F9D340F2 /* Pods_ShadowsocksX_NGTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 388120F062D7EB7DD0D8DDCA /* Pods_ShadowsocksX_NGTests.framework */; }; F0809FF1595BE2966343D3C7 /* libPods-proxy_conf_helper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E7783AEDB4A3BDDC9FF16AC /* libPods-proxy_conf_helper.a */; }; /* End PBXBuildFile section */ @@ -159,6 +161,9 @@ 9BEEF0771D04FE8A00FC52B3 /* LaunchAgentUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LaunchAgentUtils.swift; sourceTree = ""; }; 9BEEF0791D05631500FC52B3 /* AdvPreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvPreferencesWindowController.swift; sourceTree = ""; }; B4E6A97CA843F3943524B686 /* Pods-proxy_conf_helper.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-proxy_conf_helper.debug.xcconfig"; path = "Pods/Target Support Files/Pods-proxy_conf_helper/Pods-proxy_conf_helper.debug.xcconfig"; sourceTree = ""; }; + C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserRulesController.swift; sourceTree = ""; }; + C8E42A6F1D4F2CAF0074C7EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UserRulesController.xib; sourceTree = ""; }; + C8E42A721D4F2CB10074C7EA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/UserRulesController.strings"; sourceTree = ""; }; E9E9FB3855DA55D0710EE7BD /* Pods-ShadowsocksX-NG.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NG.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NG/Pods-ShadowsocksX-NG.release.xcconfig"; sourceTree = ""; }; FE3237E9FB24D9B924A0E630 /* Pods-ShadowsocksX-NG.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NG.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NG/Pods-ShadowsocksX-NG.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -307,6 +312,8 @@ 9B2491B91D0ACC3E003BBECC /* AdvPreferencesWindowController.xib */, 9BA04B241D24044D005AAD7F /* ProxyPreferencesController.swift */, 9B0D55481D2CC85400A4A8E2 /* ProxyPreferencesController.xib */, + C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */, + C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */, ); name = UI; sourceTree = ""; @@ -450,6 +457,7 @@ 9B0D55461D2CC85400A4A8E2 /* ProxyPreferencesController.xib in Resources */, 9B2491B41D0ACC3A003BBECC /* PreferencesWindowController.xib in Resources */, 9B3FFF291D08A1DF0019A709 /* user-rule.txt in Resources */, + C8E42A6E1D4F2CAF0074C7EA /* UserRulesController.xib in Resources */, 9BEEF06A1D04D4D500FC52B3 /* start_ss_local.sh in Resources */, 9B3FFF391D08CF110019A709 /* qrcode.min.js in Resources */, 9B3FFF3A1D08CF110019A709 /* qrcode.htm in Resources */, @@ -625,6 +633,7 @@ 9B0BFFE91D0460A70040E62B /* AppDelegate.swift in Sources */, 9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */, 9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */, + C8E42A6C1D4F270A0074C7EA /* UserRulesController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -705,6 +714,15 @@ name = AdvPreferencesWindowController.xib; sourceTree = ""; }; + C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */ = { + isa = PBXVariantGroup; + children = ( + C8E42A6F1D4F2CAF0074C7EA /* Base */, + C8E42A721D4F2CB10074C7EA /* zh-Hans */, + ); + name = UserRulesController.xib; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index 42f0430..3fc0af2 100644 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -16,7 +16,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele var preferencesWinCtrl: PreferencesWindowController! var advPreferencesWinCtrl: AdvPreferencesWindowController! var proxyPreferencesWinCtrl: ProxyPreferencesController! - + var editUserRulesWinCtrl: UserRulesController! + var launchAtLoginController: LaunchAtLoginController = LaunchAtLoginController() @IBOutlet weak var window: NSWindow! @@ -181,23 +182,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } @IBAction func editUserRulesForPAC(sender: NSMenuItem) { - let url = NSURL(fileURLWithPath: PACUserRuleFilePath) - NSWorkspace.sharedWorkspace().openURL(url) - } - - @IBAction func applyUserRulesForPAC(sender: NSMenuItem) { - if GeneratePACFile() { - // Popup a user notification - let notification = NSUserNotification() - notification.title = "PAC has been updated by User Rules.".localized - NSUserNotificationCenter.defaultUserNotificationCenter() - .deliverNotification(notification) - } else { - let notification = NSUserNotification() - notification.title = "It's failed to update PAC by User Rules.".localized - NSUserNotificationCenter.defaultUserNotificationCenter() - .deliverNotification(notification) + if editUserRulesWinCtrl != nil { + editUserRulesWinCtrl.close() } + let ctrl = UserRulesController(windowNibName: "UserRulesController") + editUserRulesWinCtrl = ctrl + + ctrl.showWindow(self) + NSApp.activateIgnoringOtherApps(true) + ctrl.window?.makeKeyAndOrderFront(self) } @IBAction func showQRCodeForCurrentServer(sender: NSMenuItem) { diff --git a/ShadowsocksX-NG/Base.lproj/MainMenu.xib b/ShadowsocksX-NG/Base.lproj/MainMenu.xib index 5f50952..381559a 100644 --- a/ShadowsocksX-NG/Base.lproj/MainMenu.xib +++ b/ShadowsocksX-NG/Base.lproj/MainMenu.xib @@ -76,12 +76,6 @@ - - - - - - diff --git a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib index 07f4c19..8142d87 100644 --- a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib +++ b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib @@ -1,5 +1,5 @@ - + @@ -24,16 +24,16 @@ - + - + - + - + @@ -84,7 +84,7 @@ - + @@ -241,39 +241,10 @@ - - - + - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + diff --git a/ShadowsocksX-NG/Base.lproj/UserRulesController.xib b/ShadowsocksX-NG/Base.lproj/UserRulesController.xib new file mode 100644 index 0000000..08a10c6 --- /dev/null +++ b/ShadowsocksX-NG/Base.lproj/UserRulesController.xib @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ShadowsocksX-NG/LaunchAgentUtils.swift b/ShadowsocksX-NG/LaunchAgentUtils.swift index a00a9c1..ca0deac 100644 --- a/ShadowsocksX-NG/LaunchAgentUtils.swift +++ b/ShadowsocksX-NG/LaunchAgentUtils.swift @@ -26,7 +26,14 @@ func getFileSHA1Sum(filepath: String) -> String { func generateSSLocalLauchAgentPlist() -> Bool { let sslocalPath = NSHomeDirectory() + APP_SUPPORT_DIR + "ss-local" let logFilePath = NSHomeDirectory() + "/Library/Logs/ss-local.log" - let plistFilepath = NSHomeDirectory() + LAUNCH_AGENT_DIR + LAUNCH_AGENT_CONF_NAME + let launchAgentDirPath = NSHomeDirectory() + LAUNCH_AGENT_DIR + let plistFilepath = launchAgentDirPath + LAUNCH_AGENT_CONF_NAME + + // Ensure launch agent directory is existed. + let fileMgr = NSFileManager.defaultManager() + if !fileMgr.fileExistsAtPath(launchAgentDirPath) { + try! fileMgr.createDirectoryAtPath(launchAgentDirPath, withIntermediateDirectories: true, attributes: nil) + } let oldSha1Sum = getFileSHA1Sum(plistFilepath) diff --git a/ShadowsocksX-NG/ProxyConfHelper.m b/ShadowsocksX-NG/ProxyConfHelper.m index 282bbc7..d18303d 100644 --- a/ShadowsocksX-NG/ProxyConfHelper.m +++ b/ShadowsocksX-NG/ProxyConfHelper.m @@ -136,7 +136,15 @@ } + (void)disableProxy { - NSMutableArray* args = [@[@"--mode", @"off"]mutableCopy]; + // 带上所有参数是为了判断是否原有代理设置是否由ssx-ng设置的。如果是用户手工设置的其他配置,则不进行清空。 + NSString* urlString = [NSString stringWithFormat:@"%@/.ShadowsocksX-NG/gfwlist.js", NSHomeDirectory()]; + NSURL* url = [NSURL fileURLWithPath:urlString]; + NSUInteger port = [[NSUserDefaults standardUserDefaults]integerForKey:@"LocalSocks5.ListenPort"]; + + NSMutableArray* args = [@[@"--mode", @"off" + , @"--port", [NSString stringWithFormat:@"%lu", (unsigned long)port] + , @"--pac-url", [url absoluteString] + ]mutableCopy]; [self addArguments4ManualSpecifyNetworkServices:args]; [self callHelper:args]; } diff --git a/ShadowsocksX-NG/UserRulesController.swift b/ShadowsocksX-NG/UserRulesController.swift new file mode 100644 index 0000000..3e020cc --- /dev/null +++ b/ShadowsocksX-NG/UserRulesController.swift @@ -0,0 +1,53 @@ +// +// UserRulesController.swift +// ShadowsocksX-NG +// +// Created by 周斌佳 on 16/8/1. +// Copyright © 2016年 qiuyuzhou. All rights reserved. +// + +import Cocoa + +class UserRulesController: NSWindowController { + + @IBOutlet var userRulesView: NSTextView! + + override func windowDidLoad() { + super.windowDidLoad() + + let fileMgr = NSFileManager.defaultManager() + if !fileMgr.fileExistsAtPath(PACUserRuleFilePath) { + let src = NSBundle.mainBundle().pathForResource("user-rule", ofType: "txt") + try! fileMgr.copyItemAtPath(src!, toPath: PACUserRuleFilePath) + } + + let str = try? String(contentsOfFile: PACUserRuleFilePath, encoding: NSUTF8StringEncoding) + userRulesView.string = str + } + + @IBAction func didCancel(sender: AnyObject) { + window?.performClose(self) + } + + @IBAction func didOK(sender: AnyObject) { + if let str = userRulesView.string { + do { + try str.dataUsingEncoding(NSUTF8StringEncoding)?.writeToFile(PACUserRuleFilePath, options: .DataWritingAtomic) + + if GeneratePACFile() { + // Popup a user notification + let notification = NSUserNotification() + notification.title = "PAC has been updated by User Rules.".localized + NSUserNotificationCenter.defaultUserNotificationCenter() + .deliverNotification(notification) + } else { + let notification = NSUserNotification() + notification.title = "It's failed to update PAC by User Rules.".localized + NSUserNotificationCenter.defaultUserNotificationCenter() + .deliverNotification(notification) + } + } catch {} + } + window?.performClose(self) + } +} diff --git a/ShadowsocksX-NG/proxy_conf_helper_version.h b/ShadowsocksX-NG/proxy_conf_helper_version.h index 95c2bbc..da95803 100644 --- a/ShadowsocksX-NG/proxy_conf_helper_version.h +++ b/ShadowsocksX-NG/proxy_conf_helper_version.h @@ -9,6 +9,6 @@ #ifndef proxy_conf_helper_version_h #define proxy_conf_helper_version_h -#define kProxyConfHelperVersion @"1.2.0" +#define kProxyConfHelperVersion @"1.3.1" #endif /* proxy_conf_helper_version_h */ diff --git a/ShadowsocksX-NG/zh-Hans.lproj/UserRulesController.strings b/ShadowsocksX-NG/zh-Hans.lproj/UserRulesController.strings new file mode 100644 index 0000000..c432a05 --- /dev/null +++ b/ShadowsocksX-NG/zh-Hans.lproj/UserRulesController.strings @@ -0,0 +1,9 @@ + +/* Class = "NSButtonCell"; title = "OK"; ObjectID = "0Sc-cm-Vyu"; */ +"0Sc-cm-Vyu.title" = "确定"; + +/* Class = "NSWindow"; title = "User Rules"; ObjectID = "F0z-JX-Cv5"; */ +"F0z-JX-Cv5.title" = "用户规则"; + +/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "QAR-9i-kmv"; */ +"QAR-9i-kmv.title" = "取消"; diff --git a/proxy_conf_helper/main.m b/proxy_conf_helper/main.m index 600cfe2..039846b 100644 --- a/proxy_conf_helper/main.m +++ b/proxy_conf_helper/main.m @@ -67,10 +67,6 @@ int main(int argc, const char * argv[]) if (!portString) { return 1; } - port = [portString integerValue]; - if (0 == port) { - return 1; - } } else if (![@"off" isEqualToString:mode]) { return 1; } @@ -79,6 +75,12 @@ int main(int argc, const char * argv[]) return 0; } + if (portString) { + port = [portString integerValue]; + if (0 == port) { + return 1; + } + } static AuthorizationRef authRef; static AuthorizationFlags authFlags; @@ -126,11 +128,16 @@ int main(int argc, const char * argv[]) if (modify) { + NSString* prefPath = [NSString stringWithFormat:@"/%@/%@/%@", kSCPrefNetworkServices + , key, kSCEntNetProxies]; + if ([mode isEqualToString:@"auto"]) { [proxies setObject:pacURL forKey:(NSString *)kCFNetworkProxiesProxyAutoConfigURLString]; [proxies setObject:[NSNumber numberWithInt:1] forKey:(NSString *)kCFNetworkProxiesProxyAutoConfigEnable]; + SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath + , (__bridge CFDictionaryRef)proxies); } else if ([mode isEqualToString:@"global"]) { @@ -142,9 +149,29 @@ int main(int argc, const char * argv[]) kCFNetworkProxiesSOCKSEnable]; [proxies setObject:@[@"127.0.0.1", @"localhost"] forKey:(NSString *)kCFNetworkProxiesExceptionsList]; + SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath + , (__bridge CFDictionaryRef)proxies); + } else if ([mode isEqualToString:@"off"]) { + if (pacURL != nil && portString != nil) { + // 取原来的配置,判断是否为shadowsocksX-NG设置的 + NSDictionary* oldProxies + = (__bridge NSDictionary*)SCPreferencesPathGetValue(prefRef + , (__bridge CFStringRef)prefPath); + + if (([oldProxies[(NSString *)kCFNetworkProxiesProxyAutoConfigURLString] isEqualToString:pacURL] + &&[oldProxies[(NSString *)kCFNetworkProxiesProxyAutoConfigEnable] isEqual:[NSNumber numberWithInt:1]]) + ||([oldProxies[(NSString*)kCFNetworkProxiesSOCKSProxy] isEqualToString:@"127.0.0.1"] + &&[oldProxies[(NSString*)kCFNetworkProxiesSOCKSPort] isEqualTo:[NSNumber numberWithInteger:port]] + &&[oldProxies[(NSString*)kCFNetworkProxiesSOCKSEnable] isEqual:[NSNumber numberWithInt:1]]) + ) { + SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath + , (__bridge CFDictionaryRef)proxies); + } + } else { + SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath + , (__bridge CFDictionaryRef)proxies); + } } - - SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)[NSString stringWithFormat:@"/%@/%@/%@", kSCPrefNetworkServices, key, kSCEntNetProxies], (__bridge CFDictionaryRef)proxies); } }