diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index f94bd4e..20be029 100644 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -413,7 +413,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele whiteListDomainMenuItem.state = 0 whiteListIPMenuItem.state = 0 } else if mode == "whiteListDomain" { - proxyMenuItem.title = "Proxy - WhiteList Domain".localized + proxyMenuItem.title = "Proxy - White List Domain".localized autoModeMenuItem.state = 0 globalModeMenuItem.state = 0 manualModeMenuItem.state = 0 @@ -421,7 +421,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele whiteListDomainMenuItem.state = 1 whiteListIPMenuItem.state = 0 } else if mode == "whiteListIP" { - proxyMenuItem.title = "Proxy - WhiteList IP".localized + proxyMenuItem.title = "Proxy - White List IP".localized autoModeMenuItem.state = 0 globalModeMenuItem.state = 0 manualModeMenuItem.state = 0 diff --git a/ShadowsocksX-NG/Base.lproj/Localizable.strings b/ShadowsocksX-NG/Base.lproj/Localizable.strings index 8512d27..bdbb480 100644 --- a/ShadowsocksX-NG/Base.lproj/Localizable.strings +++ b/ShadowsocksX-NG/Base.lproj/Localizable.strings @@ -1,27 +1,39 @@ + + + + + + /* * SHARED STRINGS */ /* - * ./PACUtils.swift + * ./ShadowsocksX-NG/PACUtils.swift */ "PAC has been updated by latest GFW List." = "PAC has been updated by latest GFW List."; "Failed to download latest GFW List." = "Failed to download latest GFW List."; -"White List updated succeed." = "White List updated succeed."; +"White List update succeed." = "White List update succeed."; "Failed to download latest White List update succeed." = "Failed to download latest White List update succeed."; /* - * ./PreferencesWindowController.swift + * ./ShadowsocksX-NG/BunchImportUtils.swift */ -"New Server" = "New Server"; +"Import Server Profile succeed!" = "Import Server Profile succeed!"; + +"Successful import \(configsCount) items" = "Successful import \(configsCount) items"; + +"Import Server Profile failed!" = "Import Server Profile failed!"; + +"Invalid config file!" = "Invalid config file!"; /* - * ./AppDelegate.swift + * ./ShadowsocksX-NG/AppDelegate.swift */ "Add Shadowsocks Server Profile" = "Add Shadowsocks Server Profile"; @@ -36,6 +48,16 @@ "No current server profile." = "No current server profile."; +"Proxy - Auto By PAC" = "Proxy - Auto By PAC"; + +"Proxy - Global" = "Proxy - Global"; + +"Proxy - Manual" = "Proxy - Manual"; + +"Proxy - White List Domain" = "Proxy - White List Domain"; + +"Proxy - White List IP" = "Proxy - White List IP"; + "Shadowsocks: On" = "Shadowsocks: On"; "Turn Shadowsocks Off" = "Turn Shadowsocks Off"; @@ -44,34 +66,17 @@ "Turn Shadowsocks On" = "Turn Shadowsocks On"; -"Proxy - Auto By PAC" = "Proxy - Auto By PAC"; - -"Proxy - Global" = "Proxy - Global"; - -"Proxy - Manual" = "Proxy - Manual"; - -"Proxy - WhiteList" = "Proxy - WhiteList"; - -"Proxy - WhiteList Domain" = "Proxy - WhiteList Domain"; - -"Proxy - WhiteList IP" = "Proxy - WhiteList IP"; - -"White List Mode" = "White List Mode"; - -"White List Domain" = "White List Domain"; - -"White List IP" = "White List IP"; - -"Import Server Profile succeed!" = "Import Server Profile succeed!"; - -"Import Server Profile failed!" = "Import Server Profile failed!"; - /* - * ./BunchImportUtils.swift + * ./ShadowsocksX-NG/PreferencesWindowController.swift */ -"Import Server Profile succeed!" = "Import Server Profile succeed!"; +"New Server" = "New Server"; -"Import Server Profile failed!" = "Import Server Profile failed!"; +/* + * ./ShadowsocksX-NG/UserRulesController.swift + */ +"PAC has been updated by User Rules." = "PAC has been updated by User Rules."; + +"It's failed to update PAC by User Rules." = "It's failed to update PAC by User Rules."; diff --git a/ShadowsocksX-NG/BunchImportUtils.swift b/ShadowsocksX-NG/BunchImportUtils.swift index d7bb0f1..b410b51 100644 --- a/ShadowsocksX-NG/BunchImportUtils.swift +++ b/ShadowsocksX-NG/BunchImportUtils.swift @@ -7,6 +7,9 @@ // import Foundation + +var profileMgr: ServerProfileManager! + //Todo: function 1 showExampleFile, 调用fileManager 拷贝 json 到Downloads文件夹,然后打开Downloads文件夹 //拷贝json配置文件到~/Downloads文件夹 @@ -28,6 +31,7 @@ func showExampleConfigFile() { //调用fileManager,读取json文件,对configs for循环调用 profileManager 生成 profile并保存 func importConfigFile() { let openPanel = NSOpenPanel() + openPanel.title = "Choose Config Json File".localized openPanel.allowsMultipleSelection = false openPanel.canChooseDirectories = false openPanel.canCreateDirectories = false @@ -54,21 +58,28 @@ func importConfigFile() { profile.remark = item["remarks"] as! String if (item["obfs"] != nil) { profile.ssrObfs = item["obfs"] as! String - profile.ssrObfsParam = item["obfsparam"] as! String profile.ssrProtocol = item["protocol"] as! String - profile.ssrProtocolParam = "" + if (item["obfsparam"] != nil){ + profile.ssrObfsParam = item["obfsparam"] as! String + } + if (item["protocolparam"] != nil){ + profile.ssrProtocolParam = item["protocolparam"] as! String + } } profileMgr.profiles.append(profile) profileMgr.save() NSNotificationCenter.defaultCenter().postNotificationName(NOTIFY_SERVER_PROFILES_CHANGED, object: nil) } + let configsCount = jsonArr1.objectForKey("configs")?.count let notification = NSUserNotification() notification.title = "Import Server Profile succeed!".localized + notification.informativeText = "Successful import \(configsCount) items".localized NSUserNotificationCenter.defaultUserNotificationCenter() .deliverNotification(notification) }else{ let notification = NSUserNotification() notification.title = "Import Server Profile failed!".localized + notification.informativeText = "Invalid config file!".localized NSUserNotificationCenter.defaultUserNotificationCenter() .deliverNotification(notification) return @@ -79,17 +90,52 @@ func importConfigFile() { func exportConfigFile() { //读取example文件,删掉configs里面的配置,再用NSDictionary填充到configs里面 + profileMgr = ServerProfileManager.instance let fileManager = NSFileManager.defaultManager() + let filePath:String = NSBundle.mainBundle().bundlePath + "/Contents/Resources/example-gui-config.json" let data = fileManager.contentsAtPath(filePath) let readString = NSString(data: data!, encoding: NSUTF8StringEncoding)! let readStringData = readString.dataUsingEncoding(NSUTF8StringEncoding) let jsonArr1 = try! NSJSONSerialization.JSONObjectWithData(readStringData!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary - jsonArr1.setValue(nil, forKey: "configs") + + var configsArray:NSMutableArray = [] + + for profile in profileMgr.profiles{ + var configProfile:NSMutableDictionary = [:] + //standard ss profile + configProfile.setValue(1, forKey: "enable") + configProfile.setValue(profile.serverHost, forKey: "server") + configProfile.setValue(NSNumber(unsignedShort:profile.serverPort), forKey: "server_port")//not work + configProfile.setValue(profile.password, forKey: "password") + configProfile.setValue(profile.method, forKey: "method") + configProfile.setValue(profile.remark, forKey: "remarks") + configProfile.setValue(profile.remark.dataUsingEncoding(NSUTF8StringEncoding)?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)), forKey: "remarks_base64") + //ssr + if 1 == 1 { + configProfile.setValue(profile.ssrObfs, forKey: "obfs") + configProfile.setValue(profile.ssrProtocol, forKey: "protocol") + if 2 == 2 { + configProfile.setValue(profile.ssrObfsParam, forKey: "obfsparam") + } + if 3 == 3 { + configProfile.setValue(profile.ssrProtocolParam, forKey: "protoclparam") + } + } + configsArray.addObject(configProfile) + } + jsonArr1.setValue(configsArray, forKey: "configs") + let jsonData = try! NSJSONSerialization.dataWithJSONObject(jsonArr1, options: NSJSONWritingOptions.PrettyPrinted) + let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String let savePanel = NSSavePanel() + savePanel.title = "Export Config Json File".localized savePanel.canCreateDirectories = true + savePanel.allowedFileTypes = ["json"] + savePanel.nameFieldStringValue = "export.json" savePanel.beginWithCompletionHandler { (result) -> Void in if (result == NSFileHandlingPanelOKButton && (savePanel.URL) != nil) { + //write jsonArr1 back to file + try! jsonString.writeToFile((savePanel.URL?.path)!, atomically: true, encoding: NSUTF8StringEncoding) } } -} \ No newline at end of file +} diff --git a/ShadowsocksX-NG/PreferencesWindowController.swift b/ShadowsocksX-NG/PreferencesWindowController.swift index f9e8723..842640f 100644 --- a/ShadowsocksX-NG/PreferencesWindowController.swift +++ b/ShadowsocksX-NG/PreferencesWindowController.swift @@ -150,7 +150,10 @@ class PreferencesWindowController: NSWindowController if oldProfileIndex >= 0 { let oldProfile = profileMgr.profiles[oldProfileIndex] profilesTableView.beginUpdates() - let newProfile = ServerProfile.fromDictionary(oldProfile.toDictionary()) + var newProfile = ServerProfile() + let newUUID = newProfile.uuid + newProfile = ServerProfile.fromDictionary(oldProfile.toDictionary())//here 因为UUID重复了 + newProfile.uuid = newUUID profileMgr.profiles.append(newProfile) let index = NSIndexSet(index: profileMgr.profiles.count-1) profilesTableView.insertRowsAtIndexes(index, withAnimation: .EffectFade) @@ -158,6 +161,8 @@ class PreferencesWindowController: NSWindowController self.profilesTableView.selectRowIndexes(index, byExtendingSelection: false) profilesTableView.endUpdates() updateProfileBoxVisible() + NSNotificationCenter.defaultCenter() + .postNotificationName(NOTIFY_SERVER_PROFILES_CHANGED, object: nil) } } diff --git a/ShadowsocksX-NG/zh-Hans.lproj/Localizable.strings b/ShadowsocksX-NG/zh-Hans.lproj/Localizable.strings index a71b0a1..7037028 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/Localizable.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/Localizable.strings @@ -9,7 +9,7 @@ */ /* - * ./PACUtils.swift + * ./ShadowsocksX-NG/PACUtils.swift */ "PAC has been updated by latest GFW List." = "已经使用最新的 GFW List 更新PAC"; @@ -21,25 +21,45 @@ "Failed to download latest White List update succeed." = "下载白名单失败"; /* - * ./PreferencesWindowController.swift + * ./ShadowsocksX-NG/BunchImportUtils.swift */ -"New Server" = "新服务器"; +"Import Server Profile succeed!" = "导入服务器配置文件成功!"; + +"Successful import \(configsCount) items" = "成功导入 \(configsCount) 个纪录"; + +"Import Server Profile failed!" = "导入服务器配置文件失败!"; + +"Invalid config file!" = "配置文件无效!"; /* - * ./AppDelegate.swift + * ./ShadowsocksX-NG/AppDelegate.swift */ "Add Shadowsocks Server Profile" = "已添加新Shaodwsocks服务器配置"; "By scan QR Code" = "通过扫描二维码"; +"By Handle SS URL" = "处理 SS URL"; + " Encription Method: \(profile.method)" = " 加密方法: \(profile.method)"; "Current server profile is not valid." = "当前服务器配置无效"; "No current server profile." = "未设置当前服务器配置"; +"Proxy - Auto By PAC" = "代理 - PAC自动"; + +"Proxy - Global" = "代理 - 全局"; + +"Proxy - Manual" = "代理 - 手动"; + +"Proxy - White List" = "代理 - 白名单"; + +"Proxy - White List Domain" = "代理 - 域名白名单"; + +"Proxy - White List IP" = "代理 - IP白名单"; + "Shadowsocks: On" = "Shadowsocks: On"; "Turn Shadowsocks Off" = "关闭 Shadowsocks"; @@ -48,32 +68,17 @@ "Turn Shadowsocks On" = "打开 Shadowsocks"; -"Proxy - Auto By PAC" = "代理 - PAC自动"; - -"Proxy - Global" = "代理 - 全局"; - -"Proxy - Manual" = "代理 - 手动"; - -"Proxy - WhiteList" = "代理 - 白名单"; - -"Proxy - WhiteList Domain" = "代理 - 域名白名单"; - -"Proxy - WhiteList IP" = "代理 - IP白名单"; - -"White List Mode" = "白名单模式"; - -"White List Domain" = "域名白名单"; - -"White List IP" = "IP白名单"; - -"Import Server Profile succeed!" = "导入服务器配置文件成功!"; - -"Import Server Profile failed!" = "导入服务器配置文件失败!"; - /* - * ./BunchImportUtils.swift + * ./ShadowsocksX-NG/PreferencesWindowController.swift */ -"Import Server Profile succeed!" = "导入服务器配置文件成功!"; +"New Server" = "新服务器"; + +/* + * ./ShadowsocksX-NG/UserRulesController.swift + */ + +"PAC has been updated by User Rules." = "PAC has been updated by User Rules."; + +"It's failed to update PAC by User Rules." = "It's failed to update PAC by User Rules."; -"Import Server Profile failed!" = "导入服务器配置文件失败!";