2016-06-09 00:30:08 +08:00
|
|
|
|
//
|
|
|
|
|
// ServerProfileManager.swift
|
|
|
|
|
// ShadowsocksX-NG
|
|
|
|
|
//
|
2016-09-12 17:05:28 +08:00
|
|
|
|
// Created by 邱宇舟 on 16/6/6. Modified by 秦宇航 16/9/12
|
2016-06-09 00:30:08 +08:00
|
|
|
|
// Copyright © 2016年 qiuyuzhou. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
|
|
|
|
|
|
class ServerProfileManager: NSObject {
|
|
|
|
|
|
2016-06-18 13:38:58 +08:00
|
|
|
|
static let instance:ServerProfileManager = ServerProfileManager()
|
|
|
|
|
|
2016-06-09 00:30:08 +08:00
|
|
|
|
var profiles:[ServerProfile]
|
|
|
|
|
var activeProfileId: String?
|
|
|
|
|
|
2016-10-02 01:17:07 +08:00
|
|
|
|
fileprivate override init() {
|
2016-06-09 00:30:08 +08:00
|
|
|
|
profiles = [ServerProfile]()
|
|
|
|
|
|
2016-10-02 01:17:07 +08:00
|
|
|
|
let defaults = UserDefaults.standard
|
|
|
|
|
if let _profiles = defaults.array(forKey: "ServerProfiles") {
|
2016-06-09 00:30:08 +08:00
|
|
|
|
for _profile in _profiles {
|
2017-01-07 09:26:32 +08:00
|
|
|
|
let profile = ServerProfile.fromDictionary(_profile as! [String: Any])
|
2016-06-09 00:30:08 +08:00
|
|
|
|
profiles.append(profile)
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-10-02 01:17:07 +08:00
|
|
|
|
activeProfileId = defaults.string(forKey: "ActiveServerProfileId")
|
2016-06-09 00:30:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 01:17:07 +08:00
|
|
|
|
func setActiveProfiledId(_ id: String) {
|
2016-06-09 00:30:08 +08:00
|
|
|
|
activeProfileId = id
|
2016-10-02 01:17:07 +08:00
|
|
|
|
let defaults = UserDefaults.standard
|
|
|
|
|
defaults.set(id, forKey: "ActiveServerProfileId")
|
2016-06-09 00:30:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func save() {
|
2016-10-02 01:17:07 +08:00
|
|
|
|
let defaults = UserDefaults.standard
|
2016-06-09 00:30:08 +08:00
|
|
|
|
var _profiles = [AnyObject]()
|
|
|
|
|
for profile in profiles {
|
2016-06-09 05:44:18 +08:00
|
|
|
|
if profile.isValid() {
|
2016-06-09 00:30:08 +08:00
|
|
|
|
let _profile = profile.toDictionary()
|
2016-10-02 01:17:07 +08:00
|
|
|
|
_profiles.append(_profile as AnyObject)
|
2016-06-09 00:30:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-10-02 01:17:07 +08:00
|
|
|
|
defaults.set(_profiles, forKey: "ServerProfiles")
|
2016-06-09 00:30:08 +08:00
|
|
|
|
|
2016-06-10 03:59:27 +08:00
|
|
|
|
if getActiveProfile() == nil {
|
|
|
|
|
activeProfileId = nil
|
|
|
|
|
}
|
2016-06-09 00:30:08 +08:00
|
|
|
|
|
|
|
|
|
if activeProfileId != nil {
|
2016-10-02 01:17:07 +08:00
|
|
|
|
defaults.set(activeProfileId, forKey: "ActiveServerProfileId")
|
2016-12-11 15:39:56 +08:00
|
|
|
|
_ = writeSSLocalConfFile((getActiveProfile()?.toJsonConfig())!)
|
2016-06-09 00:30:08 +08:00
|
|
|
|
} else {
|
2016-10-02 01:17:07 +08:00
|
|
|
|
defaults.removeObject(forKey: "ActiveServerProfileId")
|
2016-06-09 00:30:08 +08:00
|
|
|
|
removeSSLocalConfFile()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getActiveProfile() -> ServerProfile? {
|
|
|
|
|
if let id = activeProfileId {
|
|
|
|
|
for p in profiles {
|
|
|
|
|
if p.uuid == id {
|
|
|
|
|
return p
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
} else {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-12 17:05:28 +08:00
|
|
|
|
|
|
|
|
|
func importConfigFile() {
|
|
|
|
|
let openPanel = NSOpenPanel()
|
|
|
|
|
openPanel.title = "Choose Config Json File".localized
|
|
|
|
|
openPanel.allowsMultipleSelection = false
|
|
|
|
|
openPanel.canChooseDirectories = false
|
|
|
|
|
openPanel.canCreateDirectories = false
|
|
|
|
|
openPanel.canChooseFiles = true
|
|
|
|
|
openPanel.becomeKey()
|
2017-01-17 02:07:33 +08:00
|
|
|
|
let result = openPanel.runModal()
|
|
|
|
|
if (result == NSFileHandlingPanelOKButton && (openPanel.url) != nil) {
|
|
|
|
|
let fileManager = FileManager.default
|
|
|
|
|
let filePath:String = (openPanel.url?.path)!
|
|
|
|
|
if (fileManager.fileExists(atPath: filePath) && filePath.hasSuffix("json")) {
|
|
|
|
|
let data = fileManager.contents(atPath: filePath)
|
|
|
|
|
let readString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
|
|
|
|
|
let readStringData = readString.data(using: String.Encoding.utf8.rawValue)
|
|
|
|
|
|
|
|
|
|
let jsonArr1 = try! JSONSerialization.jsonObject(with: readStringData!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
|
|
|
|
|
|
|
|
|
|
for item in jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]{
|
|
|
|
|
let profile = ServerProfile()
|
|
|
|
|
profile.serverHost = item["server"] as! String
|
|
|
|
|
profile.serverPort = UInt16((item["server_port"]?.integerValue)!)
|
|
|
|
|
profile.method = item["method"] as! String
|
|
|
|
|
profile.password = item["password"] as! String
|
|
|
|
|
profile.remark = item["remarks"] as! String
|
2016-09-12 17:05:28 +08:00
|
|
|
|
|
2017-01-17 02:07:33 +08:00
|
|
|
|
// Kcptun
|
|
|
|
|
profile.enabledKcptun = item["enabled_kcptun"]?.boolValue ?? false
|
|
|
|
|
if let kcptun = item["kcptun"] {
|
|
|
|
|
profile.kcptunProfile = KcptunProfile.fromDictionary(kcptun as! [String : Any?])
|
2016-09-12 17:05:28 +08:00
|
|
|
|
}
|
2017-01-17 02:07:33 +08:00
|
|
|
|
|
|
|
|
|
self.profiles.append(profile)
|
|
|
|
|
self.save()
|
2016-09-12 17:05:28 +08:00
|
|
|
|
}
|
2017-03-18 12:20:51 +08:00
|
|
|
|
NotificationCenter.default.post(name: NOTIFY_SERVER_PROFILES_CHANGED, object: nil)
|
2017-01-17 02:07:33 +08:00
|
|
|
|
let configsCount = (jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]).count
|
|
|
|
|
let notification = NSUserNotification()
|
|
|
|
|
notification.title = "Import Server Profile succeed!".localized
|
|
|
|
|
notification.informativeText = "Successful import \(configsCount) items".localized
|
|
|
|
|
NSUserNotificationCenter.default
|
|
|
|
|
.deliver(notification)
|
|
|
|
|
}else{
|
|
|
|
|
let notification = NSUserNotification()
|
|
|
|
|
notification.title = "Import Server Profile failed!".localized
|
|
|
|
|
notification.informativeText = "Invalid config file!".localized
|
|
|
|
|
NSUserNotificationCenter.default
|
|
|
|
|
.deliver(notification)
|
|
|
|
|
return
|
2016-09-12 17:05:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func exportConfigFile() {
|
|
|
|
|
//读取example文件,删掉configs里面的配置,再用NSDictionary填充到configs里面
|
|
|
|
|
let fileManager = FileManager.default
|
|
|
|
|
|
2017-01-10 15:02:54 +08:00
|
|
|
|
let filePath:String = Bundle.main.path(forResource: "example-gui-config", ofType: "json")!
|
2016-09-12 17:05:28 +08:00
|
|
|
|
let data = fileManager.contents(atPath: filePath)
|
|
|
|
|
let readString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
|
|
|
|
|
let readStringData = readString.data(using: String.Encoding.utf8.rawValue)
|
|
|
|
|
let jsonArr1 = try! JSONSerialization.jsonObject(with: readStringData!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
|
|
|
|
|
|
|
|
|
|
let configsArray:NSMutableArray = [] //not using var?
|
|
|
|
|
|
|
|
|
|
for profile in profiles{
|
|
|
|
|
let configProfile:NSMutableDictionary = [:] //not using var?
|
|
|
|
|
//standard ss profile
|
|
|
|
|
configProfile.setValue(true, forKey: "enable")
|
|
|
|
|
configProfile.setValue(profile.serverHost, forKey: "server")
|
|
|
|
|
configProfile.setValue(NSNumber(value: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.data(using: String.Encoding.utf8)?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)), forKey: "remarks_base64")
|
2017-01-17 01:57:49 +08:00
|
|
|
|
|
|
|
|
|
// Kcptun
|
|
|
|
|
configProfile.setValue(profile.enabledKcptun, forKey: "enabled_kcptun")
|
|
|
|
|
configProfile.setValue(profile.kcptunProfile.toDictionary(), forKey: "kcptun")
|
|
|
|
|
|
2016-09-12 17:05:28 +08:00
|
|
|
|
configsArray.add(configProfile)
|
|
|
|
|
}
|
|
|
|
|
jsonArr1.setValue(configsArray, forKey: "configs")
|
|
|
|
|
let jsonData = try! JSONSerialization.data(withJSONObject: jsonArr1, options: JSONSerialization.WritingOptions.prettyPrinted)
|
|
|
|
|
let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String
|
|
|
|
|
let savePanel = NSSavePanel()
|
|
|
|
|
savePanel.title = "Export Config Json File".localized
|
|
|
|
|
savePanel.canCreateDirectories = true
|
|
|
|
|
savePanel.allowedFileTypes = ["json"]
|
|
|
|
|
savePanel.nameFieldStringValue = "export.json"
|
|
|
|
|
savePanel.becomeKey()
|
2017-01-17 02:07:33 +08:00
|
|
|
|
let result = savePanel.runModal()
|
|
|
|
|
if (result == NSFileHandlingPanelOKButton && (savePanel.url) != nil) {
|
|
|
|
|
//write jsonArr1 back to file
|
|
|
|
|
try! jsonString.write(toFile: (savePanel.url?.path)!, atomically: true, encoding: String.Encoding.utf8)
|
|
|
|
|
NSWorkspace.shared().selectFile((savePanel.url?.path)!, inFileViewerRootedAtPath: (savePanel.directoryURL?.path)!)
|
|
|
|
|
let notification = NSUserNotification()
|
|
|
|
|
notification.title = "Export Server Profile succeed!".localized
|
|
|
|
|
notification.informativeText = "Successful Export \(self.profiles.count) items".localized
|
|
|
|
|
NSUserNotificationCenter.default
|
|
|
|
|
.deliver(notification)
|
2016-09-12 17:05:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class func showExampleConfigFile() {
|
|
|
|
|
//copy file to ~/Downloads folder
|
2017-01-10 15:02:54 +08:00
|
|
|
|
let filePath:String = Bundle.main.path(forResource: "example-gui-config", ofType: "json")!
|
2016-09-12 17:05:28 +08:00
|
|
|
|
let fileMgr = FileManager.default
|
|
|
|
|
let dataPath = NSHomeDirectory() + "/Downloads"
|
|
|
|
|
let destPath = dataPath + "/example-gui-config.json"
|
|
|
|
|
//检测文件是否已经存在,如果存在直接用sharedWorkspace显示
|
|
|
|
|
if fileMgr.fileExists(atPath: destPath) {
|
|
|
|
|
NSWorkspace.shared().selectFile(destPath, inFileViewerRootedAtPath: dataPath)
|
|
|
|
|
}else{
|
|
|
|
|
try! fileMgr.copyItem(atPath: filePath, toPath: destPath)
|
|
|
|
|
NSWorkspace.shared().selectFile(destPath, inFileViewerRootedAtPath: dataPath)
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-09 00:30:08 +08:00
|
|
|
|
}
|