diff --git a/README.md b/README.md index 89fb73e..32dc8a2 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ ref: [GitFlow](http://nvie.com/posts/a-successful-git-branching-model/) ## TODO List -- [ ] Embed the http proxy server [privoxy](http://www.privoxy.org/). +- [x] Embed the http proxy server [privoxy](http://www.privoxy.org/), [get it](https://homebrew.bintray.com/bottles/privoxy-3.0.26.sierra.bottle.tar.gz). ## License diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index f186387..2afa29a 100644 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -52,6 +52,14 @@ 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 */; }; + C6D429931DA75988002A5711 /* install_privoxy.sh in Resources */ = {isa = PBXBuildFile; fileRef = C6D4298E1DA75988002A5711 /* install_privoxy.sh */; }; + C6D429941DA75988002A5711 /* privoxy in Resources */ = {isa = PBXBuildFile; fileRef = C6D4298F1DA75988002A5711 /* privoxy */; }; + C6D429951DA75988002A5711 /* reload_conf_privoxy.sh in Resources */ = {isa = PBXBuildFile; fileRef = C6D429901DA75988002A5711 /* reload_conf_privoxy.sh */; }; + C6D429961DA75988002A5711 /* start_privoxy.sh in Resources */ = {isa = PBXBuildFile; fileRef = C6D429911DA75988002A5711 /* start_privoxy.sh */; }; + C6D429971DA75988002A5711 /* stop_privoxy.sh in Resources */ = {isa = PBXBuildFile; fileRef = C6D429921DA75988002A5711 /* stop_privoxy.sh */; }; + C6D429991DA76FBC002A5711 /* privoxy.config.example in Resources */ = {isa = PBXBuildFile; fileRef = C6D429981DA76FBC002A5711 /* privoxy.config.example */; }; + C6E28E921DA79380004F8330 /* HTTPPreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E28E911DA79380004F8330 /* HTTPPreferencesWindowController.swift */; }; + C6E28E951DA79705004F8330 /* HTTPPreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C6E28E971DA79705004F8330 /* HTTPPreferencesWindowController.xib */; }; 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 */; }; @@ -88,6 +96,18 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 083BF8311D82731900831C68 /* SimplePing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePing.h; sourceTree = ""; }; + 083BF8321D82731900831C68 /* SimplePing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePing.m; sourceTree = ""; }; + 083BF8341D82742200831C68 /* NetWorkMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetWorkMonitor.swift; sourceTree = ""; }; + 083BF8351D82742200831C68 /* PingClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PingClient.swift; sourceTree = ""; }; + 083BF8381D82759600831C68 /* StatusItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusItemView.swift; sourceTree = ""; }; + 083BF83A1D8275A800831C68 /* SystemThemeChangeHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemThemeChangeHelper.swift; sourceTree = ""; }; + 085641E91D7188C400116B27 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 08805F181D878CA5009B53E7 /* PingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PingTest.swift; sourceTree = ""; }; + 0880CE3F1D6FE6D900BD39E2 /* example-gui-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "example-gui-config.json"; sourceTree = ""; }; + 088EC3961D5F5B8600E40791 /* whitelist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whitelist.pac; sourceTree = ""; }; + 088EC3981D5F5BA300E40791 /* whiteiplist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whiteiplist.pac; sourceTree = ""; }; + 08AF56C01D6AFA7C00DC4F46 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = ""; }; 19083CFCED87354F006967FF /* Pods_ShadowsocksX_NGUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShadowsocksX_NGUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1E7783AEDB4A3BDDC9FF16AC /* libPods-proxy_conf_helper.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-proxy_conf_helper.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 283ED1A8E9B711AC65670031 /* Pods_ShadowsocksX_NG.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShadowsocksX_NG.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -161,6 +181,16 @@ 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 = ""; }; + C6D4298E1DA75988002A5711 /* install_privoxy.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = install_privoxy.sh; sourceTree = ""; }; + C6D4298F1DA75988002A5711 /* privoxy */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = privoxy; sourceTree = ""; }; + C6D429901DA75988002A5711 /* reload_conf_privoxy.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = reload_conf_privoxy.sh; sourceTree = ""; }; + C6D429911DA75988002A5711 /* start_privoxy.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = start_privoxy.sh; sourceTree = ""; }; + C6D429921DA75988002A5711 /* stop_privoxy.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = stop_privoxy.sh; sourceTree = ""; }; + C6D429981DA76FBC002A5711 /* privoxy.config.example */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = privoxy.config.example; sourceTree = ""; }; + C6E28E911DA79380004F8330 /* HTTPPreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPPreferencesWindowController.swift; sourceTree = ""; }; + C6E28E961DA79705004F8330 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/HTTPPreferencesWindowController.xib; sourceTree = ""; }; + C6E28E991DA79709004F8330 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/HTTPPreferencesWindowController.strings"; sourceTree = ""; }; + C6E28E9B1DA79FB9004F8330 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; 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 = ""; }; @@ -215,6 +245,11 @@ 9B07EFB01D048E900052D9DF /* Support Files */ = { isa = PBXGroup; children = ( + C6D4298E1DA75988002A5711 /* install_privoxy.sh */, + C6D4298F1DA75988002A5711 /* privoxy */, + C6D429901DA75988002A5711 /* reload_conf_privoxy.sh */, + C6D429911DA75988002A5711 /* start_privoxy.sh */, + C6D429921DA75988002A5711 /* stop_privoxy.sh */, 9BE8FBBD1D0B1FB900CAFD01 /* libcrypto.1.0.0.dylib */, 9B172A6C1D0ADDDD00B87B9A /* Localizable.strings */, 9B3FFF4B1D09D8F70019A709 /* install_helper.sh */, @@ -233,6 +268,7 @@ 9BEEF0661D04CE8D00FC52B3 /* start_ss_local.sh */, 9BEEF0671D04CE9A00FC52B3 /* stop_ss_local.sh */, 9BEEF0681D04CFE500FC52B3 /* reload_conf_ss_local.sh */, + C6D429981DA76FBC002A5711 /* privoxy.config.example */, ); name = "Support Files"; sourceTree = ""; @@ -314,6 +350,8 @@ 9B0D55481D2CC85400A4A8E2 /* ProxyPreferencesController.xib */, C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */, C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */, + C6E28E911DA79380004F8330 /* HTTPPreferencesWindowController.swift */, + C6E28E971DA79705004F8330 /* HTTPPreferencesWindowController.xib */, ); name = UI; sourceTree = ""; @@ -455,26 +493,34 @@ files = ( 9BE8FBBF1D0B211600CAFD01 /* libcrypto.1.0.0.dylib in Resources */, 9B3FFF541D09E2D10019A709 /* proxy_conf_helper in Resources */, + C6E28E951DA79705004F8330 /* HTTPPreferencesWindowController.xib in Resources */, 9BEEF0691D04D4D500FC52B3 /* install_ss_local.sh in Resources */, 9B0D55461D2CC85400A4A8E2 /* ProxyPreferencesController.xib in Resources */, 9B2491B41D0ACC3A003BBECC /* PreferencesWindowController.xib in Resources */, 9B3FFF291D08A1DF0019A709 /* user-rule.txt in Resources */, + C6D429971DA75988002A5711 /* stop_privoxy.sh 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 */, + C6D429941DA75988002A5711 /* privoxy in Resources */, + C6D429991DA76FBC002A5711 /* privoxy.config.example in Resources */, + 0880CE401D6FE6D900BD39E2 /* example-gui-config.json in Resources */, 9BEEF06B1D04D4D500FC52B3 /* stop_ss_local.sh in Resources */, 9B3FFF341D08CEF70019A709 /* SWBQRCodeWindowController.xib in Resources */, 9BEEF06C1D04D4D500FC52B3 /* reload_conf_ss_local.sh in Resources */, 9B3FFF231D088E8D0019A709 /* abp.js in Resources */, 9B07EFAD1D048E880052D9DF /* menu_icon.png in Resources */, + C6D429951DA75988002A5711 /* reload_conf_privoxy.sh in Resources */, 9B0BFFEB1D0460A70040E62B /* Assets.xcassets in Resources */, 9B2491B71D0ACC3E003BBECC /* AdvPreferencesWindowController.xib in Resources */, 9B3FFF381D08CF110019A709 /* jquery.min.js in Resources */, 9B3FFF271D0898EB0019A709 /* gfwlist.txt in Resources */, + C6D429931DA75988002A5711 /* install_privoxy.sh in Resources */, 9BC70EDC1D2E3E3100EDA4CA /* Localizable.strings in Resources */, 9B0BFFEE1D0460A70040E62B /* MainMenu.xib in Resources */, 9B3FFF4C1D09D8F70019A709 /* install_helper.sh in Resources */, + C6D429961DA75988002A5711 /* start_privoxy.sh in Resources */, 9B07EFAC1D048E880052D9DF /* menu_icon@2x.png in Resources */, 9B07EFA71D048BBB0052D9DF /* ss-local in Resources */, 9B07EFAF1D048E880052D9DF /* menu_icon_disabled@2x.png in Resources */, @@ -635,6 +681,7 @@ 9B0BFFE91D0460A70040E62B /* AppDelegate.swift in Sources */, 9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */, 9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */, + C6E28E921DA79380004F8330 /* HTTPPreferencesWindowController.swift in Sources */, C8E42A6C1D4F270A0074C7EA /* UserRulesController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -676,6 +723,7 @@ children = ( 9B0BFFED1D0460A70040E62B /* Base */, 9B0D55451D2CC1B800A4A8E2 /* zh-Hans */, + C6E28E9B1DA79FB9004F8330 /* zh-Hans */, ); name = MainMenu.xib; sourceTree = ""; @@ -716,6 +764,15 @@ name = AdvPreferencesWindowController.xib; sourceTree = ""; }; + C6E28E971DA79705004F8330 /* HTTPPreferencesWindowController.xib */ = { + isa = PBXVariantGroup; + children = ( + C6E28E961DA79705004F8330 /* Base */, + C6E28E991DA79709004F8330 /* zh-Hans */, + ); + name = HTTPPreferencesWindowController.xib; + sourceTree = ""; + }; C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index a2c91d5..faaeccc 100644 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -17,7 +17,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele var advPreferencesWinCtrl: AdvPreferencesWindowController! var proxyPreferencesWinCtrl: ProxyPreferencesController! var editUserRulesWinCtrl: UserRulesController! - + var httpPreferencesWinCtrl : HTTPPreferencesWindowController! + var launchAtLoginController: LaunchAtLoginController = LaunchAtLoginController() @IBOutlet weak var window: NSWindow! @@ -46,7 +47,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele // Prepare ss-local InstallSSLocal() - + InstallPrivoxy() // Prepare defaults let defaults = UserDefaults.standard defaults.register(defaults: [ @@ -60,7 +61,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele "LocalSocks5.EnableUDPRelay": NSNumber(value: false as Bool), "LocalSocks5.EnableVerboseMode": NSNumber(value: false as Bool), "GFWListURL": "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt", - "AutoConfigureNetworkServices": NSNumber(value: true as Bool) + "AutoConfigureNetworkServices": NSNumber(value: true as Bool), + "AutoConfigureNetworkServices": NSNumber(value: true as Bool), + "LocalHTTP.ListenAddress": "127.0.0.1", + "LocalHTTP.ListenPort": NSNumber(value: 1087 as UInt16), + "LocalHTTPOn": true ]) statusItem = NSStatusBar.system().statusItem(withLength: 20) @@ -98,6 +103,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele self.applyConfig() } ) + notifyCenter.addObserver(forName: NSNotification.Name(rawValue: NOTIFY_HTTP_CONF_CHANGED), object: nil, queue: nil + , using: { + (note) in + SyncPrivoxy() + } + ) notifyCenter.addObserver(forName: NSNotification.Name(rawValue: "NOTIFY_FOUND_SS_URL"), object: nil, queue: nil) { (note: Notification) in if let userInfo = (note as NSNotification).userInfo { @@ -291,6 +302,18 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele ctrl.window?.makeKeyAndOrderFront(self) } + @IBAction func editHTTPPreferences(_ sender: NSMenuItem) { + if httpPreferencesWinCtrl != nil { + httpPreferencesWinCtrl.close() + } + let ctrl = HTTPPreferencesWindowController(windowNibName: "HTTPPreferencesWindowController") + httpPreferencesWinCtrl = ctrl + + ctrl.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + ctrl.window?.makeKeyAndOrderFront(self) + } + @IBAction func editProxyPreferences(_ sender: NSObject) { if proxyPreferencesWinCtrl != nil { proxyPreferencesWinCtrl.close() diff --git a/ShadowsocksX-NG/Base.lproj/HTTPPreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/HTTPPreferencesWindowController.xib new file mode 100644 index 0000000..36e83d5 --- /dev/null +++ b/ShadowsocksX-NG/Base.lproj/HTTPPreferencesWindowController.xib @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ShadowsocksX-NG/Base.lproj/MainMenu.xib b/ShadowsocksX-NG/Base.lproj/MainMenu.xib index 381559a..68818b7 100644 --- a/ShadowsocksX-NG/Base.lproj/MainMenu.xib +++ b/ShadowsocksX-NG/Base.lproj/MainMenu.xib @@ -1,7 +1,8 @@ - + + @@ -118,6 +119,12 @@ + + + + + + @@ -151,5 +158,18 @@ + + + + + + + + + + + + + diff --git a/ShadowsocksX-NG/HTTPPreferencesWindowController.swift b/ShadowsocksX-NG/HTTPPreferencesWindowController.swift new file mode 100644 index 0000000..36326e6 --- /dev/null +++ b/ShadowsocksX-NG/HTTPPreferencesWindowController.swift @@ -0,0 +1,27 @@ +// +// HTTPPreferencesWindowController.swift +// ShadowsocksX-NG +// +// Created by 王晨 on 2016/10/7. +// Copyright © 2016年 qiuyuzhou. All rights reserved. +// + +import Cocoa + +class HTTPPreferencesWindowController: NSWindowController, NSWindowDelegate { + + override func windowDidLoad() { + super.windowDidLoad() + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + self.window?.delegate = self + } + + //------------------------------------------------------------ + // NSWindowDelegate + func windowWillClose(_ notification: Notification) { + NotificationCenter.default + .post(name: Notification.Name(rawValue: NOTIFY_HTTP_CONF_CHANGED), object: nil) + } + +} diff --git a/ShadowsocksX-NG/LaunchAgentUtils.swift b/ShadowsocksX-NG/LaunchAgentUtils.swift index ad44279..a894a96 100644 --- a/ShadowsocksX-NG/LaunchAgentUtils.swift +++ b/ShadowsocksX-NG/LaunchAgentUtils.swift @@ -9,9 +9,11 @@ import Foundation let SS_LOCAL_VERSION = "2.4.6" +let PRIVOXY_VERSION = "3.0.26" let APP_SUPPORT_DIR = "/Library/Application Support/ShadowsocksX-NG/" let LAUNCH_AGENT_DIR = "/Library/LaunchAgents/" -let LAUNCH_AGENT_CONF_NAME = "com.qiuyuzhou.shadowsocksX-NG.local.plist" +let LAUNCH_AGENT_CONF_SSLOCAL_NAME = "com.qiuyuzhou.shadowsocksX-NG.local.plist" +let LAUNCH_AGENT_CONF_PRIVOXY_NAME = "com.qiuyuzhou.shadowsocksX-NG.http.plist" func getFileSHA1Sum(_ filepath: String) -> String { @@ -23,11 +25,14 @@ func getFileSHA1Sum(_ filepath: String) -> String { // Ref: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html // Genarate the mac launch agent service plist + +// MARK: sslocal + func generateSSLocalLauchAgentPlist() -> Bool { let sslocalPath = NSHomeDirectory() + APP_SUPPORT_DIR + "ss-local" let logFilePath = NSHomeDirectory() + "/Library/Logs/ss-local.log" let launchAgentDirPath = NSHomeDirectory() + LAUNCH_AGENT_DIR - let plistFilepath = launchAgentDirPath + LAUNCH_AGENT_CONF_NAME + let plistFilepath = launchAgentDirPath + LAUNCH_AGENT_CONF_SSLOCAL_NAME // Ensure launch agent directory is existed. let fileMgr = FileManager.default @@ -168,4 +173,150 @@ func SyncSSLocal() { StopSSLocal() } SyncPac() + SyncPrivoxy() +} + +// MARK: privoxy + +func generatePrivoxyLauchAgentPlist() -> Bool { + let privoxyPath = NSHomeDirectory() + APP_SUPPORT_DIR + "privoxy" + let logFilePath = NSHomeDirectory() + "/Library/Logs/privoxy.log" + let launchAgentDirPath = NSHomeDirectory() + LAUNCH_AGENT_DIR + let plistFilepath = launchAgentDirPath + LAUNCH_AGENT_CONF_PRIVOXY_NAME + + // Ensure launch agent directory is existed. + let fileMgr = FileManager.default + if !fileMgr.fileExists(atPath: launchAgentDirPath) { + try! fileMgr.createDirectory(atPath: launchAgentDirPath, withIntermediateDirectories: true, attributes: nil) + } + + let oldSha1Sum = getFileSHA1Sum(plistFilepath) + + let arguments = [privoxyPath, "--no-daemon", "privoxy.config"] + + // For a complete listing of the keys, see the launchd.plist manual page. + let dict: NSMutableDictionary = [ + "Label": "com.qiuyuzhou.shadowsocksX-NG.http", + "WorkingDirectory": NSHomeDirectory() + APP_SUPPORT_DIR, + "KeepAlive": true, + "StandardOutPath": logFilePath, + "StandardErrorPath": logFilePath, + "ProgramArguments": arguments + ] + dict.write(toFile: plistFilepath, atomically: true) + let Sha1Sum = getFileSHA1Sum(plistFilepath) + if oldSha1Sum != Sha1Sum { + return true + } else { + return false + } +} + + +func ReloadConfPrivoxy() { + let bundle = Bundle.main + let installerPath = bundle.path(forResource: "reload_conf_privoxy.sh", ofType: nil) + let task = Process.launchedProcess(launchPath: installerPath!, arguments: [""]) + task.waitUntilExit() + if task.terminationStatus == 0 { + NSLog("reload privoxy succeeded.") + } else { + NSLog("reload privoxy failed.") + } +} + +func StartPrivoxy() { + let bundle = Bundle.main + let installerPath = bundle.path(forResource: "start_privoxy.sh", ofType: nil) + let task = Process.launchedProcess(launchPath: installerPath!, arguments: [""]) + task.waitUntilExit() + if task.terminationStatus == 0 { + NSLog("Start privoxy succeeded.") + } else { + NSLog("Start privoxy failed.") + } +} + +func StopPrivoxy() { + let bundle = Bundle.main + let installerPath = bundle.path(forResource: "stop_privoxy.sh", ofType: nil) + let task = Process.launchedProcess(launchPath: installerPath!, arguments: [""]) + task.waitUntilExit() + if task.terminationStatus == 0 { + NSLog("Stop privoxy succeeded.") + } else { + NSLog("Stop privoxy failed.") + } +} + +func InstallPrivoxy() { + let fileMgr = FileManager.default + let homeDir = NSHomeDirectory() + let appSupportDir = homeDir+APP_SUPPORT_DIR + if !fileMgr.fileExists(atPath: appSupportDir + "privoxy-\(PRIVOXY_VERSION)/privoxy") { + let bundle = Bundle.main + let installerPath = bundle.path(forResource: "install_privoxy.sh", ofType: nil) + let task = Process.launchedProcess(launchPath: installerPath!, arguments: [""]) + task.waitUntilExit() + if task.terminationStatus == 0 { + NSLog("Install privoxy succeeded.") + } else { + NSLog("Install privoxy failed.") + } + } +} + +func writePrivoxyConfFile() -> Bool { + do { + let defaults = UserDefaults.standard + let bundle = Bundle.main + let examplePath = bundle.path(forResource: "privoxy.config.example", ofType: nil) + var example = try String(contentsOfFile: examplePath!, encoding: .utf8) + example = example.replacingOccurrences(of: "{http}", with: defaults.string(forKey: "LocalHTTP.ListenAddress")! + ":" + String(defaults.integer(forKey: "LocalHTTP.ListenPort"))) + example = example.replacingOccurrences(of: "{socks5}", with: defaults.string(forKey: "LocalSocks5.ListenAddress")! + ":" + String(defaults.integer(forKey: "LocalSocks5.ListenPort"))) + let data = example.data(using: .utf8) + + let filepath = NSHomeDirectory() + APP_SUPPORT_DIR + "privoxy.config" + + let oldSum = getFileSHA1Sum(filepath) + try data?.write(to: URL(fileURLWithPath: filepath), options: .atomic) + let newSum = getFileSHA1Sum(filepath) + + if oldSum == newSum { + return false + } + + return true + } catch { + NSLog("Write privoxy file failed.") + } + return false +} + +func removePrivoxyConfFile() { + do { + let filepath = NSHomeDirectory() + APP_SUPPORT_DIR + "privoxy.config" + try FileManager.default.removeItem(atPath: filepath) + } catch { + + } +} + +func SyncPrivoxy() { + var changed: Bool = false + changed = changed || generatePrivoxyLauchAgentPlist() + let mgr = ServerProfileManager.instance + if mgr.activeProfileId != nil { + changed = changed || writePrivoxyConfFile() + + let on = UserDefaults.standard.bool(forKey: "LocalHTTPOn") + if on { +// StartPrivoxy() + ReloadConfPrivoxy() + } + else { + removePrivoxyConfFile() + StopPrivoxy() + } + } } diff --git a/ShadowsocksX-NG/Notifications.swift b/ShadowsocksX-NG/Notifications.swift index 69b798f..09da2db 100644 --- a/ShadowsocksX-NG/Notifications.swift +++ b/ShadowsocksX-NG/Notifications.swift @@ -10,4 +10,6 @@ import Foundation let NOTIFY_SERVER_PROFILES_CHANGED = "NOTIFY_SERVER_PROFILES_CHANGED" let NOTIFY_ADV_PROXY_CONF_CHANGED = "NOTIFY_ADV_PROXY_CONF_CHANGED" -let NOTIFY_ADV_CONF_CHANGED = "NOTIFY_ADV_CONF_CHANGED" \ No newline at end of file +let NOTIFY_ADV_CONF_CHANGED = "NOTIFY_ADV_CONF_CHANGED" +let NOTIFY_HTTP_CONF_CHANGED = "NOTIFY_HTTP_CONF_CHANGED" +let NOTIFY_INVALIDE_QR = "NOTIFY_INVALIDE_QR" diff --git a/ShadowsocksX-NG/install_privoxy.sh b/ShadowsocksX-NG/install_privoxy.sh new file mode 100755 index 0000000..2b56af9 --- /dev/null +++ b/ShadowsocksX-NG/install_privoxy.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# install_privoxy.sh +# ShadowsocksX-NG +# +# Created by 王晨 on 16/10/7. +# Copyright © 2016年 zhfish. All rights reserved. + + +cd `dirname "${BASH_SOURCE[0]}"` +privoxyVersion=3.0.26 +mkdir -p "$HOME/Library/Application Support/ShadowsocksX-NG/privoxy-$privoxyVersion" +cp -f privoxy "$HOME/Library/Application Support/ShadowsocksX-NG/privoxy-$privoxyVersion/" +rm -f "$HOME/Library/Application Support/ShadowsocksX-NG/privoxy" +ln -s "$HOME/Library/Application Support/ShadowsocksX-NG/privoxy-$privoxyVersion/privoxy" "$HOME/Library/Application Support/ShadowsocksX-NG/privoxy" + +echo done diff --git a/ShadowsocksX-NG/privoxy b/ShadowsocksX-NG/privoxy new file mode 100755 index 0000000..8c5688a Binary files /dev/null and b/ShadowsocksX-NG/privoxy differ diff --git a/ShadowsocksX-NG/privoxy.config.example b/ShadowsocksX-NG/privoxy.config.example new file mode 100644 index 0000000..41fa850 --- /dev/null +++ b/ShadowsocksX-NG/privoxy.config.example @@ -0,0 +1,18 @@ +listen-address {http} +toggle 1 +enable-remote-toggle 1 +enable-remote-http-toggle 1 +enable-edit-actions 0 +enforce-blocks 0 +buffer-limit 4096 +forwarded-connect-retries 0 +accept-intercepted-requests 0 +allow-cgi-request-crunching 0 +split-large-forms 0 +keep-alive-timeout 5 +socket-timeout 60 + +forward-socks5 / {socks5} . +forward 192.168.*.*/ . +forward 10.*.*.*/ . +forward 127.*.*.*/ . diff --git a/ShadowsocksX-NG/reload_conf_privoxy.sh b/ShadowsocksX-NG/reload_conf_privoxy.sh new file mode 100755 index 0000000..f8e435c --- /dev/null +++ b/ShadowsocksX-NG/reload_conf_privoxy.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# reload_privoxy.sh +# ShadowsocksX-NG +# +# Created by 王晨 on 16/10/7. +# Copyright © 2016年 zhfish. All rights reserved. + +#launchctl kill SIGHUP "$HOME/Library/LaunchAgents/com.qiuyuzhou.shadowsocksX-NG.http.plist" + +launchctl unload "$HOME/Library/LaunchAgents/com.qiuyuzhou.shadowsocksX-NG.http.plist" +launchctl load "$HOME/Library/LaunchAgents/com.qiuyuzhou.shadowsocksX-NG.http.plist" diff --git a/ShadowsocksX-NG/start_privoxy.sh b/ShadowsocksX-NG/start_privoxy.sh new file mode 100755 index 0000000..bedef6a --- /dev/null +++ b/ShadowsocksX-NG/start_privoxy.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# start_privoxy.sh +# ShadowsocksX-NG +# +# Created by 王晨 on 16/10/7. +# Copyright © 2016年 zhfish. All rights reserved. + +launchctl load "$HOME/Library/LaunchAgents/com.qiuyuzhou.shadowsocksX-NG.http.plist" diff --git a/ShadowsocksX-NG/stop_privoxy.sh b/ShadowsocksX-NG/stop_privoxy.sh new file mode 100755 index 0000000..8cb6a2b --- /dev/null +++ b/ShadowsocksX-NG/stop_privoxy.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# stop_privoxy.sh +# ShadowsocksX-NG +# +# Created by 王晨 on 16/10/7. +# Copyright © 2016年 zhfish. All rights reserved. + + + +launchctl unload "$HOME/Library/LaunchAgents/com.qiuyuzhou.shadowsocksX-NG.http.plist" diff --git a/ShadowsocksX-NG/zh-Hans.lproj/HTTPPreferencesWindowController.strings b/ShadowsocksX-NG/zh-Hans.lproj/HTTPPreferencesWindowController.strings new file mode 100644 index 0000000..df2f7a1 --- /dev/null +++ b/ShadowsocksX-NG/zh-Hans.lproj/HTTPPreferencesWindowController.strings @@ -0,0 +1,12 @@ + +/* Class = "NSTextFieldCell"; title = "HTTP Proxy Listen Port:"; ObjectID = "2Sd-yn-gdY"; */ +"2Sd-yn-gdY.title" = "HTTP 代理 监听端口:"; + +/* Class = "NSButtonCell"; title = "HTTP Proxy Enable"; ObjectID = "dqU-MG-Sum"; */ +"dqU-MG-Sum.title" = "HTTP 代理 开启"; + +/* Class = "NSTextFieldCell"; title = "HTTP Proxy Listen Address:"; ObjectID = "qd0-kc-ttB"; */ +"qd0-kc-ttB.title" = "HTTP 代理 监听地址:"; + +/* Class = "NSWindow"; title = "HTTP Proxy Preferences"; ObjectID = "vS3-DL-Nq3"; */ +"vS3-DL-Nq3.title" = "HTTP 代理 设置"; diff --git a/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings b/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings index 29dde32..99145f2 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings @@ -67,3 +67,16 @@ /* Class = "NSMenuItem"; title = "退出"; ObjectID = "vJS-JW-byz"; */ "vJS-JW-byz.title" = "退出"; + +/* Class = "NSMenuItem"; title = "Ping server"; ObjectID = "zfR-Jt-GmS"; */ +"zfR-Jt-GmS.title" = "服务器测速"; + +/* Class = "NSMenuItem"; title = "Show network speed"; ObjectID = "a3h-uQ-DuO"; */ +"a3h-uQ-DuO.title" = "显示网速"; + +/* Class = "NSMenuItem"; title = "Connect At Launch"; ObjectID = "aB3-cf-5j0"; */ +"aB3-cf-5j0.title" = "打开时自动连接"; + +/* Class = "NSMenuItem"; title = "HTTP Proxy Preference ..."; ObjectID = "uEp-Gz-cu0"; */ +"uEp-Gz-cu0.title" = "HTTP代理设置..."; +