diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj
index 571824f..509bb35 100644
--- a/Pods/Pods.xcodeproj/project.pbxproj
+++ b/Pods/Pods.xcodeproj/project.pbxproj
@@ -467,7 +467,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
- LastUpgradeCheck = 0700;
+ LastUpgradeCheck = 0730;
};
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2";
@@ -678,6 +678,7 @@
baseConfigurationReference = 054C3E84057CD06DB85D99E7AD207F48 /* Pods-proxy_conf_helper.debug.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
@@ -717,6 +718,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.9;
MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = "${PRODUCT_BUNDLE_IDENTIFIER}";
PRODUCT_NAME = Alamofire;
SDKROOT = macosx;
SKIP_INSTALL = YES;
@@ -747,6 +749,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.9;
MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "${PRODUCT_BUNDLE_IDENTIFIER}";
PRODUCT_NAME = Alamofire;
SDKROOT = macosx;
SKIP_INSTALL = YES;
@@ -795,6 +798,7 @@
baseConfigurationReference = 774723B57789DD1DBE95EC5F0BCBD551 /* BRLOptionParser.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
@@ -816,6 +820,7 @@
baseConfigurationReference = A5055B8EFFFBEDE50909E935D4BCA446 /* Pods-proxy_conf_helper.release.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
@@ -873,6 +878,7 @@
baseConfigurationReference = 774723B57789DD1DBE95EC5F0BCBD551 /* BRLOptionParser.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
diff --git a/Pods/Target Support Files/Alamofire/Info.plist b/Pods/Target Support Files/Alamofire/Info.plist
index ebdce25..99b3951 100644
--- a/Pods/Target Support Files/Alamofire/Info.plist
+++ b/Pods/Target Support Files/Alamofire/Info.plist
@@ -2,25 +2,25 @@
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- ${EXECUTABLE_NAME}
- CFBundleIdentifier
- ${PRODUCT_BUNDLE_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- ${PRODUCT_NAME}
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 3.4.0
- CFBundleSignature
- ????
- CFBundleVersion
- ${CURRENT_PROJECT_VERSION}
- NSPrincipalClass
-
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 3.4.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ ${CURRENT_PROJECT_VERSION}
+ NSPrincipalClass
+
diff --git a/ShadowsocksX-NG/Base.lproj/AdvPreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/AdvPreferencesWindowController.xib
index 7b76e43..e222c3d 100644
--- a/ShadowsocksX-NG/Base.lproj/AdvPreferencesWindowController.xib
+++ b/ShadowsocksX-NG/Base.lproj/AdvPreferencesWindowController.xib
@@ -1,5 +1,5 @@
-
+
diff --git a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib
index 8142d87..4a8296f 100644
--- a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib
+++ b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib
@@ -7,6 +7,10 @@
+
+
+
+
@@ -24,16 +28,16 @@
-
+
-
+
-
+
-
+
@@ -84,13 +88,13 @@
-
+
-
+
-
+
@@ -98,7 +102,7 @@
-
+
@@ -109,7 +113,7 @@
-
+
@@ -126,7 +130,7 @@
-
+
@@ -134,7 +138,7 @@
-
+
@@ -142,7 +146,7 @@
-
+
@@ -153,7 +157,7 @@
-
+
@@ -161,7 +165,7 @@
-
+
@@ -169,7 +173,7 @@
-
+
@@ -177,7 +181,7 @@
-
+
@@ -195,45 +199,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
@@ -241,6 +340,35 @@
+
+
@@ -284,44 +412,16 @@
-
-
+
-
-
+
+
@@ -336,7 +436,7 @@ DQ
-
+
diff --git a/ShadowsocksX-NG/Base.lproj/UserRulesController.xib b/ShadowsocksX-NG/Base.lproj/UserRulesController.xib
index 08a10c6..e1b94bd 100644
--- a/ShadowsocksX-NG/Base.lproj/UserRulesController.xib
+++ b/ShadowsocksX-NG/Base.lproj/UserRulesController.xib
@@ -16,7 +16,7 @@
-
+
@@ -51,17 +51,17 @@ Gw
-
+
-
+
-
+
-
+
@@ -72,7 +72,7 @@ Gw
-
+
diff --git a/ShadowsocksX-NG/LaunchAgentUtils.swift b/ShadowsocksX-NG/LaunchAgentUtils.swift
index ca0deac..c9d61f1 100644
--- a/ShadowsocksX-NG/LaunchAgentUtils.swift
+++ b/ShadowsocksX-NG/LaunchAgentUtils.swift
@@ -8,7 +8,7 @@
import Foundation
-let SS_LOCAL_VERSION = "2.4.6"
+let SS_LOCAL_VERSION = "2.4.8"
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"
diff --git a/ShadowsocksX-NG/PreferencesWindowController.swift b/ShadowsocksX-NG/PreferencesWindowController.swift
index 6cff2ce..64841c3 100644
--- a/ShadowsocksX-NG/PreferencesWindowController.swift
+++ b/ShadowsocksX-NG/PreferencesWindowController.swift
@@ -19,6 +19,11 @@ class PreferencesWindowController: NSWindowController
@IBOutlet weak var portTextField: NSTextField!
@IBOutlet weak var methodTextField: NSComboBox!
+ @IBOutlet weak var ProtocolTextField: NSComboBox!
+ @IBOutlet weak var ProtocolParamTextField: NSTextField!
+ @IBOutlet weak var ObfsTextField: NSComboBox!
+ @IBOutlet weak var ObfsParamTextField: NSTextField!
+
@IBOutlet weak var passwordTextField: NSTextField!
@IBOutlet weak var remarkTextField: NSTextField!
@@ -53,7 +58,20 @@ class PreferencesWindowController: NSWindowController
"rc4",
"table",
])
-
+ ProtocolTextField.addItemsWithObjectValues([
+ "origin",
+ "verify_simple",
+ "verify_sha1",
+ "auth_simple",
+ "auth_sha1",
+ "auth_sha1_v2",
+ ])
+ ObfsTextField.addItemsWithObjectValues([
+ "palin",
+ "http_simple",
+ "tls1.0_session_auth",
+ "tls1.2_ticket_auth",
+ ])
profilesTableView.reloadData()
updateProfileBoxVisible()
}
diff --git a/ShadowsocksX-NG/SWBApplication.m b/ShadowsocksX-NG/SWBApplication.m
index 171af4a..4ae63d2 100644
--- a/ShadowsocksX-NG/SWBApplication.m
+++ b/ShadowsocksX-NG/SWBApplication.m
@@ -28,7 +28,7 @@
return;
}
else if ([[event charactersIgnoringModifiers] isEqualToString:@"z"]) {
- if ([self sendAction:@selector(undo:) to:nil from:self])
+ if ([self sendAction:@selector(undo) to:nil from:self])
return;
}
else if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) {
@@ -38,7 +38,7 @@
}
else if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask)) {
if ([[event charactersIgnoringModifiers] isEqualToString:@"Z"]) {
- if ([self sendAction:@selector(redo:) to:nil from:self])
+ if ([self sendAction:@selector(redo) to:nil from:self])
return;
}
}
diff --git a/ShadowsocksX-NG/SWBQRCodeWindowController.xib b/ShadowsocksX-NG/SWBQRCodeWindowController.xib
index 623ae20..fa2f1ad 100644
--- a/ShadowsocksX-NG/SWBQRCodeWindowController.xib
+++ b/ShadowsocksX-NG/SWBQRCodeWindowController.xib
@@ -1,5 +1,5 @@
-
+
diff --git a/ShadowsocksX-NG/ServerProfile.swift b/ShadowsocksX-NG/ServerProfile.swift
index c71d717..05c618c 100644
--- a/ShadowsocksX-NG/ServerProfile.swift
+++ b/ShadowsocksX-NG/ServerProfile.swift
@@ -19,6 +19,10 @@ class ServerProfile: NSObject {
var password:String = ""
var remark:String = ""
var ota: Bool = false // onetime authentication
+ var ssrProtocol:String = ""
+ var ssrProtocolParam:String = ""
+ var ssrObfs:String = ""
+ var ssrObfsParam:String = ""
override init() {
uuid = NSUUID().UUIDString
@@ -41,6 +45,18 @@ class ServerProfile: NSObject {
if let ota = data["OTA"] {
profile.ota = ota as! Bool
}
+ if let ssrProtocol = data["ssrProtocol"]{
+ profile.ssrProtocol = ssrProtocol as! String
+ }
+ if let ssrProtocolParam = data["ssrProtocolParam"]{
+ profile.ssrProtocolParam = ssrProtocolParam as! String
+ }
+ if let ssrObfs = data["ssrObfs"]{
+ profile.ssrObfs = ssrObfs as! String
+ }
+ if let ssrObfsParam = data["ssrObfsParam"]{
+ profile.ssrObfsParam = ssrObfsParam as! String
+ }
}
if let id = data["Id"] as? String {
@@ -63,6 +79,10 @@ class ServerProfile: NSObject {
d["Password"] = password
d["Remark"] = remark
d["OTA"] = ota
+ d["ssrProtocol"] = ssrProtocol
+ d["ssrProtocolParam"] = ssrProtocolParam
+ d["ssrObfs"] = ssrObfs
+ d["ssrObfsParam"] = ssrObfsParam
return d
}
@@ -77,6 +97,12 @@ class ServerProfile: NSObject {
conf["local_address"] = defaults.stringForKey("LocalSocks5.ListenAddress")
conf["timeout"] = NSNumber(unsignedInt: UInt32(defaults.integerForKey("LocalSocks5.Timeout")))
conf["auth"] = NSNumber(bool: ota)
+ if(!ssrObfs.isEmpty){
+ conf["ssrProtocol"] = ssrProtocol
+ conf["ssrProtocolParam"] = ssrProtocolParam
+ conf["ssrObfs"] = ssrObfs
+ conf["ssrObfsParam"] = ssrObfsParam
+ }
return conf
}
@@ -117,16 +143,39 @@ class ServerProfile: NSObject {
return false
}
+ if (ssrProtocol.isEmpty && !ssrObfs.isEmpty)||(!ssrProtocol.isEmpty && ssrObfs.isEmpty){
+ return false
+ }
+
return true
}
func URL() -> NSURL? {
- let parts = "\(method):\(password)@\(serverHost):\(serverPort)"
- let base64String = parts.dataUsingEncoding(NSUTF8StringEncoding)?
- .base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
- if var s = base64String {
- s = s.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "="))
- return NSURL(string: "ss://\(s)")
+ if(ssrObfs==""){
+ let parts = "\(method):\(password)@\(serverHost):\(serverPort)"
+ let base64String = parts.dataUsingEncoding(NSUTF8StringEncoding)?
+ .base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
+ if var s = base64String {
+ s = s.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "="))
+ return NSURL(string: "ss://\(s)")
+ }
+ }else{
+ let firstParts = "\(serverHost):\(serverPort):\(ssrProtocol):\(method):\(ssrObfs):"
+ let secondParts = "\(password)"
+ //base64(abc.xyz:12345:auth_sha1_v2:rc4-md5:tls1.2_ticket_auth:{base64(password)}/?obfsparam={base64(混淆参数(网址))}&remarks={base64(节点名称)})
+ let base64PasswordString = secondParts.dataUsingEncoding(NSUTF8StringEncoding)?
+ .base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
+
+ let base64ssrObfsParamString = ssrObfsParam.dataUsingEncoding(NSUTF8StringEncoding)?
+ .base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
+
+ let base64RemarkString = remark.dataUsingEncoding(NSUTF8StringEncoding)?
+ .base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
+
+ var s = firstParts + base64PasswordString! + "/?" + "obfsparam=" + base64ssrObfsParamString! + "&remarks=" + base64RemarkString!
+ s = (s.dataUsingEncoding(NSUTF8StringEncoding)?
+ .base64EncodedStringWithOptions(NSDataBase64EncodingOptions()))!
+ return NSURL(string: "ssr://\(s)")
}
return nil
}
diff --git a/ShadowsocksX-NG/Utils.m b/ShadowsocksX-NG/Utils.m
index d6f3402..c5c633a 100644
--- a/ShadowsocksX-NG/Utils.m
+++ b/ShadowsocksX-NG/Utils.m
@@ -73,6 +73,9 @@ void ScanQRCodeOnScreen() {
}
// 解析SS URL,如果成功则返回一个与ServerProfile类兼容的dict
+// 或SSR URL,ServerProfile类已经默认添加SSR参数,默认放空,如果URL为SSR://则改变解析方法
+// ss:// + base64(method:password@domain:port)
+// ssr:// + base64(abc.xyz:12345:auth_sha1_v2:rc4-md5:tls1.2_ticket_auth:{base64(password)}/?obfsparam={base64(混淆参数(网址))}&remarks={base64(节点名称)})
NSDictionary* ParseSSURL(NSURL* url) {
if (!url.host) {
return nil;
@@ -81,53 +84,58 @@ NSDictionary* ParseSSURL(NSURL* url) {
NSString *urlString = [url absoluteString];
int i = 0;
NSString *errorReason = nil;
- while(i < 2) {
- if (i == 1) {
- NSString* host = url.host;
- if ([host length]%4!=0) {
- int n = 4 - [host length]%4;
- if (1==n) {
- host = [host stringByAppendingString:@"="];
- } else if (2==n) {
- host = [host stringByAppendingString:@"=="];
+ if([[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL ] hasPrefix:@"ss://"]){
+ while(i < 2) {
+ if (i == 1) {
+ NSString* host = url.host;
+ if ([host length]%4!=0) {
+ int n = 4 - [host length]%4;
+ if (1==n) {
+ host = [host stringByAppendingString:@"="];
+ } else if (2==n) {
+ host = [host stringByAppendingString:@"=="];
+ }
}
+ NSData *data = [[NSData alloc] initWithBase64EncodedString:host options:0];
+ NSString *decodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ urlString = decodedString;
}
- NSData *data = [[NSData alloc] initWithBase64EncodedString:host options:0];
- NSString *decodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- urlString = decodedString;
+ i++;
+ urlString = [urlString stringByReplacingOccurrencesOfString:@"ss://" withString:@"" options:NSAnchoredSearch range:NSMakeRange(0, urlString.length)];
+ NSRange firstColonRange = [urlString rangeOfString:@":"];
+ NSRange lastColonRange = [urlString rangeOfString:@":" options:NSBackwardsSearch];
+ NSRange lastAtRange = [urlString rangeOfString:@"@" options:NSBackwardsSearch];
+ if (firstColonRange.length == 0) {
+ errorReason = @"colon not found";
+ continue;
+ }
+ if (firstColonRange.location == lastColonRange.location) {
+ errorReason = @"only one colon";
+ continue;
+ }
+ if (lastAtRange.length == 0) {
+ errorReason = @"at not found";
+ continue;
+ }
+ if (!((firstColonRange.location < lastAtRange.location) && (lastAtRange.location < lastColonRange.location))) {
+ errorReason = @"wrong position";
+ continue;
+ }
+ NSString *method = [urlString substringWithRange:NSMakeRange(0, firstColonRange.location)];
+ NSString *password = [urlString substringWithRange:NSMakeRange(firstColonRange.location + 1, lastAtRange.location - firstColonRange.location - 1)];
+ NSString *IP = [urlString substringWithRange:NSMakeRange(lastAtRange.location + 1, lastColonRange.location - lastAtRange.location - 1)];
+ NSString *port = [urlString substringWithRange:NSMakeRange(lastColonRange.location + 1, urlString.length - lastColonRange.location - 1)];
+
+
+ return @{@"ServerHost": IP,
+ @"ServerPort": @([port integerValue]),
+ @"Method": method,
+ @"Password": password,
+ };
}
- i++;
- urlString = [urlString stringByReplacingOccurrencesOfString:@"ss://" withString:@"" options:NSAnchoredSearch range:NSMakeRange(0, urlString.length)];
- NSRange firstColonRange = [urlString rangeOfString:@":"];
- NSRange lastColonRange = [urlString rangeOfString:@":" options:NSBackwardsSearch];
- NSRange lastAtRange = [urlString rangeOfString:@"@" options:NSBackwardsSearch];
- if (firstColonRange.length == 0) {
- errorReason = @"colon not found";
- continue;
- }
- if (firstColonRange.location == lastColonRange.location) {
- errorReason = @"only one colon";
- continue;
- }
- if (lastAtRange.length == 0) {
- errorReason = @"at not found";
- continue;
- }
- if (!((firstColonRange.location < lastAtRange.location) && (lastAtRange.location < lastColonRange.location))) {
- errorReason = @"wrong position";
- continue;
- }
- NSString *method = [urlString substringWithRange:NSMakeRange(0, firstColonRange.location)];
- NSString *password = [urlString substringWithRange:NSMakeRange(firstColonRange.location + 1, lastAtRange.location - firstColonRange.location - 1)];
- NSString *IP = [urlString substringWithRange:NSMakeRange(lastAtRange.location + 1, lastColonRange.location - lastAtRange.location - 1)];
- NSString *port = [urlString substringWithRange:NSMakeRange(lastColonRange.location + 1, urlString.length - lastColonRange.location - 1)];
+
+ }else if ([[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL ] hasPrefix:@"ssr://"]){
-
- return @{@"ServerHost": IP,
- @"ServerPort": @([port integerValue]),
- @"Method": method,
- @"Password": password,
- };
}
- return nil;
+ return nil;
}
diff --git a/ShadowsocksX-NG/install_ss_local.sh b/ShadowsocksX-NG/install_ss_local.sh
index dc9cbaa..41d78f9 100755
--- a/ShadowsocksX-NG/install_ss_local.sh
+++ b/ShadowsocksX-NG/install_ss_local.sh
@@ -8,10 +8,10 @@
cd `dirname "${BASH_SOURCE[0]}"`
-mkdir -p "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.6"
-cp -f ss-local "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.6/"
+mkdir -p "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.8"
+cp -f ss-local "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.8/"
rm -f "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local"
-ln -s "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.6/ss-local" "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local"
+ln -s "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local-2.4.8/ss-local" "$HOME/Library/Application Support/ShadowsocksX-NG/ss-local"
cp -f libcrypto.1.0.0.dylib "$HOME/Library/Application Support/ShadowsocksX-NG/"
diff --git a/ShadowsocksX-NG/ss-local b/ShadowsocksX-NG/ss-local
index c254766..68206e0 100755
Binary files a/ShadowsocksX-NG/ss-local and b/ShadowsocksX-NG/ss-local differ
diff --git a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings
index afd97be..7158303 100644
--- a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings
+++ b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings
@@ -34,3 +34,18 @@
/* Class = "NSButtonCell"; title = "OK"; ObjectID = "zPE-oD-PwK"; */
"zPE-oD-PwK.title" = "确定";
+
+/* Class = "NSTextFieldCell"; title = "SSR Settings (Left empty if not sure what it is"; ObjectID = "Vtp-4J-er7.title";*/
+"Vtp-4J-er7.title" = "SSR设置,不清楚请留空";
+
+/* Class = "NSTextFieldCell"; title = "Obfs"; ObjectID = "Vtp-4J-er7.title";*/
+"aQj-D7-XWZ.title" = "混淆"
+
+/* Class = "NSTextFieldCell"; title = "Obfs Param"; ObjectID = "Vtp-4J-er7.title";*/
+"g7c-fW-7J4.title" = "混淆参数"
+
+/* Class = "NSTextFieldCell"; title = "Protocol"; ObjectID = "nmk-Ue-wYb,title";*/
+"nmk-Ue-wYb,title" = "协议"
+
+/* Class = "NSTextFieldCell"; title = "Protocol Param"; ObjectID = "Vtp-4J-er7.title";*/
+"dCk-qx-L1X.title" = "协议参数"