From f7f7aa058950e8b5772e86047348585a526291b1 Mon Sep 17 00:00:00 2001 From: Timothy Qiu Date: Wed, 1 Nov 2017 14:04:32 +0800 Subject: [PATCH] Enables plugins config in Server Preferences --- .../PreferencesWindowController.xib | 90 ++++++++++++++----- .../PreferencesWindowController.swift | 7 ++ ShadowsocksX-NG/ServerProfile.swift | 34 +++++++ .../PreferencesWindowController.strings | 6 ++ 4 files changed, 114 insertions(+), 23 deletions(-) diff --git a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib index b8940d8..6411dda 100644 --- a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib +++ b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib @@ -26,6 +26,8 @@ + + @@ -39,20 +41,20 @@ - + - + - + - + - + @@ -99,13 +101,13 @@ - + - + - + @@ -113,7 +115,7 @@ - + @@ -124,7 +126,7 @@ - + @@ -132,7 +134,7 @@ - + @@ -140,23 +142,47 @@ - + + + + + + + + + + + + + + + + + - + + + + + + + + + - + @@ -164,23 +190,23 @@ - + - + @@ -401,7 +427,7 @@ - + @@ -415,7 +441,7 @@ - + @@ -466,7 +492,7 @@ - + + + + + + + + + + + + + + + @@ -520,11 +560,15 @@ + + + + + - diff --git a/ShadowsocksX-NG/PreferencesWindowController.swift b/ShadowsocksX-NG/PreferencesWindowController.swift index 21b3951..eb9514d 100644 --- a/ShadowsocksX-NG/PreferencesWindowController.swift +++ b/ShadowsocksX-NG/PreferencesWindowController.swift @@ -27,6 +27,8 @@ class PreferencesWindowController: NSWindowController @IBOutlet weak var passwordTextField: NSTextField! @IBOutlet weak var passwordSecureTextField: NSSecureTextField! @IBOutlet weak var togglePasswordVisibleButton: NSButton! + @IBOutlet weak var pluginTextField: NSTextField! + @IBOutlet weak var pluginOptionsTextField: NSTextField! @IBOutlet weak var remarkTextField: NSTextField! @@ -264,6 +266,11 @@ class PreferencesWindowController: NSWindowController , options: [NSBindingOption.continuouslyUpdatesValue: true]) passwordSecureTextField.bind(NSBindingName(rawValue: "value"), to: editingProfile, withKeyPath: "password" , options: [NSBindingOption.continuouslyUpdatesValue: true]) + + pluginTextField.bind(NSBindingName(rawValue: "value"), to: editingProfile, withKeyPath: "plugin" + , options: [NSBindingOption.continuouslyUpdatesValue: true]) + pluginOptionsTextField.bind(NSBindingName(rawValue: "value"), to: editingProfile, withKeyPath: "pluginOptions" + , options: [NSBindingOption.continuouslyUpdatesValue: true]) remarkTextField.bind(NSBindingName(rawValue: "value"), to: editingProfile, withKeyPath: "remark" , options: [NSBindingOption.continuouslyUpdatesValue: true]) diff --git a/ShadowsocksX-NG/ServerProfile.swift b/ShadowsocksX-NG/ServerProfile.swift index 6770954..c8adf24 100644 --- a/ShadowsocksX-NG/ServerProfile.swift +++ b/ShadowsocksX-NG/ServerProfile.swift @@ -23,6 +23,10 @@ class ServerProfile: NSObject, NSCopying { @objc var enabledKcptun: Bool = false @objc var kcptunProfile = KcptunProfile() + // SIP003 Plugin + @objc var plugin: String = "" // empty string disables plugin + @objc var pluginOptions: String = "" + override init() { uuid = UUID().uuidString } @@ -113,6 +117,15 @@ class ServerProfile: NSObject, NSCopying { self.kcptunProfile.loadUrlQueryItems(items: items) } } + + if let pluginStr = parsedUrl.queryItems? + .filter({ $0.name == "plugin" }).first?.value { + let parts = pluginStr.split(separator: ";", maxSplits: 1) + if parts.count == 2 { + plugin = String(parts[0]) + pluginOptions = String(parts[1]) + } + } } public func copy(with zone: NSZone? = nil) -> Any { @@ -126,6 +139,8 @@ class ServerProfile: NSObject, NSCopying { copy.enabledKcptun = self.enabledKcptun copy.kcptunProfile = self.kcptunProfile.copy() as! KcptunProfile + copy.plugin = self.plugin + copy.pluginOptions = self.pluginOptions return copy; } @@ -148,6 +163,12 @@ class ServerProfile: NSObject, NSCopying { if let kcptunData = data["KcptunProfile"] { profile.kcptunProfile = KcptunProfile.fromDictionary(kcptunData as! [String:Any?]) } + if let plugin = data["Plugin"] as? String { + profile.plugin = plugin + } + if let pluginOptions = data["PluginOptions"] as? String { + profile.pluginOptions = pluginOptions + } } if let id = data["Id"] as? String { @@ -172,6 +193,8 @@ class ServerProfile: NSObject, NSCopying { d["OTA"] = ota as AnyObject? d["EnabledKcptun"] = NSNumber(value: enabledKcptun) d["KcptunProfile"] = kcptunProfile.toDictionary() as AnyObject + d["Plugin"] = plugin as AnyObject + d["PluginOptions"] = pluginOptions as AnyObject return d } @@ -198,6 +221,13 @@ class ServerProfile: NSObject, NSCopying { conf["server_port"] = NSNumber(value: serverPort as UInt16) } + if !plugin.isEmpty { + // all plugin binaries should be located in the plugins dir + // so that we don't have to mess up with PATH envvars + conf["plugin"] = "plugins/\(plugin)" as AnyObject + conf["plugin_opts"] = pluginOptions as AnyObject + } + return conf } @@ -298,6 +328,10 @@ class ServerProfile: NSObject, NSCopying { items.append(URLQueryItem(name: "Kcptun", value: enabledKcptun.description)) items.append(contentsOf: kcptunProfile.urlQueryItems()) } + if !plugin.isEmpty { + let value = "\(plugin);\(pluginOptions)" + items.append(URLQueryItem(name: "plugin", value: value)) + } var comps = URLComponents() diff --git a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings index a18ea8f..c3ee3a4 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings @@ -37,3 +37,9 @@ /* Class = "NSMenuItem"; title = "Clone"; ObjectID = "bl9-lq-u9V"; */ "bl9-lq-u9V.title" = "克隆"; + +/* Class = "NSTextFieldCell"; title = "Plugin:"; ObjectID = "gDt-yZ-Mqs"; */ +"gDt-yZ-Mqs.title" = "插件:"; + +/* Class = "NSTextFieldCell"; title = "Plugin Opts:"; ObjectID = "orT-7j-dxE"; */ +"orT-7j-dxE.title" = "插件选项:";