diff --git a/V2rayU.xcodeproj/project.pbxproj b/V2rayU.xcodeproj/project.pbxproj index 8e80ecc..9fddd2a 100644 --- a/V2rayU.xcodeproj/project.pbxproj +++ b/V2rayU.xcodeproj/project.pbxproj @@ -30,11 +30,11 @@ 66784B0021704E1300AD307F /* V2rayCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66784AFF21704E1300AD307F /* V2rayCore.swift */; }; 66973EB721797719001FEA1E /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66973EB621797719001FEA1E /* ServiceManagement.framework */; }; 66ACB1A021757D5B005B5881 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66ACB19F21757D5B005B5881 /* MainMenu.swift */; }; + 66BC2B87228C537F00FBB716 /* PreferencePac.xib in Resources */ = {isa = PBXBuildFile; fileRef = 66BC2B86228C537F00FBB716 /* PreferencePac.xib */; }; 66F411B121CA49EE007AAC10 /* pac in Copy Files */ = {isa = PBXBuildFile; fileRef = 6683B1EA21C2AD1A004A1C5F /* pac */; }; 66F411B221CA49F4007AAC10 /* v2ray-core in Copy Files */ = {isa = PBXBuildFile; fileRef = 667029CF21AFB5730079EF41 /* v2ray-core */; }; 66F411B521CA8921007AAC10 /* cmd.sh in Resources */ = {isa = PBXBuildFile; fileRef = 66F411B421CA8921007AAC10 /* cmd.sh */; }; 66FEAD53217EE14C009DECF9 /* ConfigWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 66FEAD4E217EE14C009DECF9 /* ConfigWindow.xib */; }; - 6D6DF06E32A1DC263EDF1A8E /* PacUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF62A40417837EA751D88 /* PacUtils.swift */; }; 6D6DF16BC49BBF5F3D4B12CF /* PreferenceGeneral.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DFD8EB18FBEA30274ED0D /* PreferenceGeneral.xib */; }; 6D6DF2CF13D9FD3C7C6492A4 /* QrcodeWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF12EA09D2D80788666D0 /* QrcodeWindow.swift */; }; 6D6DF2F2DFB2234541488BBD /* PreferenceSubscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF5345E4582EE0EBD468D /* PreferenceSubscript.swift */; }; @@ -42,17 +42,14 @@ 6D6DF5F67A917F78FF652D45 /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DF8F5112A8407EE959998 /* .gitignore */; }; 6D6DF6553CF221AEB71913EE /* PreferenceGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DFFB29020127E034AD168 /* PreferenceGeneral.swift */; }; 6D6DF6F065067CD879201FF9 /* Scanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF87840CDA04AF0E9D36E /* Scanner.swift */; }; - 6D6DF75A00BCDA0C2733A718 /* PreferencePac.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DFBC0F08C2F7D573B93B7 /* PreferencePac.xib */; }; 6D6DF7C2F627A8BABECA4C32 /* tmp1.json in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DFCE2F5044A1164CB14E3 /* tmp1.json */; }; 6D6DF807BE591BE396221EF3 /* PreferenceAdvance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF701C75D8D416096D717 /* PreferenceAdvance.swift */; }; 6D6DF872C0DECC082122D783 /* tmp.json in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DF8E42F7E29CCBEFF5468 /* tmp.json */; }; 6D6DF87497313615AFE3320A /* PreferencePac.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF3151BBA6E56836AF6DE /* PreferencePac.swift */; }; 6D6DF8BFC33F97E9AFCA5A4B /* V2rayConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DFD9F5991B38B128888D6 /* V2rayConfig.swift */; }; 6D6DF93B58B654D86ACC490E /* PreferenceAbout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF870C8E334815FBA78B2 /* PreferenceAbout.swift */; }; - 6D6DFB41BC9692C90A47F31B /* UserRulesWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF587B6AF8CEE029E48BC /* UserRulesWindow.swift */; }; 6D6DFBB73E90918ED212F138 /* PreferenceAbout.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DFCD202C8F28474E9ED3C /* PreferenceAbout.xib */; }; 6D6DFD181802BAFE2933B9C9 /* PreferenceSubscript.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DFBD3C6A7344A44DDE16D /* PreferenceSubscript.xib */; }; - 6D6DFD4A3A226788760150F8 /* UserRulesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D6DF010124783F31646A895 /* UserRulesWindow.xib */; }; F260898E336CFA5EAB07ADC9 /* Pods_V2rayU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66A5CE4521706B5A009B08B2 /* Pods_V2rayU.framework */; }; /* End PBXBuildFile section */ @@ -146,6 +143,7 @@ 66973EB621797719001FEA1E /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 66A5CE4521706B5A009B08B2 /* Pods_V2rayU.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Pods_V2rayU.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66ACB19F21757D5B005B5881 /* MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = ""; }; + 66BC2B86228C537F00FBB716 /* PreferencePac.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencePac.xib; sourceTree = ""; }; 66F411B421CA8921007AAC10 /* cmd.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cmd.sh; sourceTree = ""; }; 66FEAD45217D75FC009DECF9 /* release.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = release.sh; sourceTree = ""; }; 66FEAD4F217EE14C009DECF9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ConfigWindow.xib; sourceTree = ""; }; @@ -155,16 +153,12 @@ 6D6DF3C1564D0EBC5A99C9C1 /* gfwlist.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = gfwlist.txt; sourceTree = ""; }; 6D6DF4CCA47DCA0A592BCE60 /* PreferenceAdvance.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferenceAdvance.xib; sourceTree = ""; }; 6D6DF5345E4582EE0EBD468D /* PreferenceSubscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferenceSubscript.swift; sourceTree = ""; }; - 6D6DF57E4CB6D7998F746068 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UserRulesWindow.xib; sourceTree = ""; }; - 6D6DF587B6AF8CEE029E48BC /* UserRulesWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserRulesWindow.swift; sourceTree = ""; }; - 6D6DF62A40417837EA751D88 /* PacUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacUtils.swift; sourceTree = ""; }; 6D6DF69C7CA7EBEFFE8E22D1 /* abp.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = abp.js; sourceTree = ""; }; 6D6DF701C75D8D416096D717 /* PreferenceAdvance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferenceAdvance.swift; sourceTree = ""; }; 6D6DF870C8E334815FBA78B2 /* PreferenceAbout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferenceAbout.swift; sourceTree = ""; }; 6D6DF87840CDA04AF0E9D36E /* Scanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scanner.swift; sourceTree = ""; }; 6D6DF8E42F7E29CCBEFF5468 /* tmp.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tmp.json; sourceTree = ""; }; 6D6DF8F5112A8407EE959998 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = file.gitignore; path = .gitignore; sourceTree = ""; }; - 6D6DFBC0F08C2F7D573B93B7 /* PreferencePac.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferencePac.xib; sourceTree = ""; }; 6D6DFBD3C6A7344A44DDE16D /* PreferenceSubscript.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferenceSubscript.xib; sourceTree = ""; }; 6D6DFCD202C8F28474E9ED3C /* PreferenceAbout.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferenceAbout.xib; sourceTree = ""; }; 6D6DFCE2F5044A1164CB14E3 /* tmp1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tmp1.json; sourceTree = ""; }; @@ -301,9 +295,6 @@ 664EB37B216C9A5F00B6AE0D /* Info.plist */, 667029D121AFB86E0079EF41 /* QrcodeWindow.xib */, 6D6DF12EA09D2D80788666D0 /* QrcodeWindow.swift */, - 6D6DF62A40417837EA751D88 /* PacUtils.swift */, - 6D6DF587B6AF8CEE029E48BC /* UserRulesWindow.swift */, - 6D6DF010124783F31646A895 /* UserRulesWindow.xib */, 6D6DFBED570A0D1FDED0BD53 /* Preference */, ); path = V2rayU; @@ -325,7 +316,7 @@ 6D6DF870C8E334815FBA78B2 /* PreferenceAbout.swift */, 6D6DFCD202C8F28474E9ED3C /* PreferenceAbout.xib */, 6D6DF3151BBA6E56836AF6DE /* PreferencePac.swift */, - 6D6DFBC0F08C2F7D573B93B7 /* PreferencePac.xib */, + 66BC2B86228C537F00FBB716 /* PreferencePac.xib */, 6D6DF5345E4582EE0EBD468D /* PreferenceSubscript.swift */, 6D6DFBD3C6A7344A44DDE16D /* PreferenceSubscript.xib */, 6D6DFFB29020127E034AD168 /* PreferenceGeneral.swift */, @@ -525,13 +516,12 @@ 66F411B521CA8921007AAC10 /* cmd.sh in Resources */, 664EB377216C9A5F00B6AE0D /* Assets.xcassets in Resources */, 66FEAD53217EE14C009DECF9 /* ConfigWindow.xib in Resources */, - 6D6DFD4A3A226788760150F8 /* UserRulesWindow.xib in Resources */, 6D6DF872C0DECC082122D783 /* tmp.json in Resources */, 6D6DF7C2F627A8BABECA4C32 /* tmp1.json in Resources */, 6D6DF5F67A917F78FF652D45 /* .gitignore in Resources */, - 6D6DF75A00BCDA0C2733A718 /* PreferencePac.xib in Resources */, 6D6DF16BC49BBF5F3D4B12CF /* PreferenceGeneral.xib in Resources */, 6D6DFD181802BAFE2933B9C9 /* PreferenceSubscript.xib in Resources */, + 66BC2B87228C537F00FBB716 /* PreferencePac.xib in Resources */, 6D6DFBB73E90918ED212F138 /* PreferenceAbout.xib in Resources */, 6D6DF43A6898B0A8CB50C241 /* PreferenceAdvance.xib in Resources */, ); @@ -638,8 +628,6 @@ 6D6DF8BFC33F97E9AFCA5A4B /* V2rayConfig.swift in Sources */, 6D6DF6F065067CD879201FF9 /* Scanner.swift in Sources */, 6D6DF2CF13D9FD3C7C6492A4 /* QrcodeWindow.swift in Sources */, - 6D6DF06E32A1DC263EDF1A8E /* PacUtils.swift in Sources */, - 6D6DFB41BC9692C90A47F31B /* UserRulesWindow.swift in Sources */, 6D6DF93B58B654D86ACC490E /* PreferenceAbout.swift in Sources */, 6D6DF87497313615AFE3320A /* PreferencePac.swift in Sources */, 6D6DF2F2DFB2234541488BBD /* PreferenceSubscript.swift in Sources */, @@ -688,14 +676,6 @@ name = ConfigWindow.xib; sourceTree = ""; }; - 6D6DF010124783F31646A895 /* UserRulesWindow.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D6DF57E4CB6D7998F746068 /* Base */, - ); - name = UserRulesWindow.xib; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/V2rayU/MainMenu.swift b/V2rayU/MainMenu.swift index 7df5a71..e5b519f 100644 --- a/V2rayU/MainMenu.swift +++ b/V2rayU/MainMenu.swift @@ -28,12 +28,11 @@ let preferencesWindowController = PreferencesWindowController( PreferenceGeneralViewController(), PreferenceAdvanceViewController(), PreferenceSubscriptViewController(), - PreferencePacController(), - PreferenceAboutController(), + PreferencePacViewController(), + PreferenceAboutViewController(), ] ) var qrcodeWindow = QrcodeWindowController() -var editUserRulesWinCtrl = UserRulesWindowController() // menu controller class MenuController: NSObject, NSMenuDelegate { diff --git a/V2rayU/PacUtils.swift b/V2rayU/PacUtils.swift index e0c57d1..047902f 100644 --- a/V2rayU/PacUtils.swift +++ b/V2rayU/PacUtils.swift @@ -7,131 +7,3 @@ import Foundation import Alamofire - - -let PACRulesDirPath = AppResourcesPath + "/pac/" -let PACUserRuleFilePath = PACRulesDirPath + "user-rule.txt" -let PACFilePath = PACRulesDirPath + "pac.js" -let PACUrl = "http://127.0.0.1:" + String(httpServerPort) + "/pac/pac.js" -let PACAbpFile = PACRulesDirPath + "abp.js" -let GFWListFilePath = PACRulesDirPath + "gfwlist.txt" -let GFWListURL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt" - -// Because of LocalSocks5.ListenPort may be changed -func GeneratePACFile() -> Bool { - print("GeneratePACFile") - let socks5Address = "127.0.0.1" - - let v2ray = V2rayServer.loadSelectedItem() - var sockPort = "1080" - if v2ray != nil && v2ray!.isValid { - let cfg = V2rayConfig() - cfg.parseJson(jsonText: v2ray!.json) - sockPort = cfg.socksPort - } - - // permission - _ = shell(launchPath: "/bin/bash", arguments: ["-c", "cd " + AppResourcesPath + " && /bin/chmod -R 755 ./pac"]) - - do { - let gfwlist = try String(contentsOfFile: GFWListFilePath, encoding: String.Encoding.utf8) - if let data = Data(base64Encoded: gfwlist, options: .ignoreUnknownCharacters) { - let str = String(data: data, encoding: String.Encoding.utf8) - var lines = str!.components(separatedBy: CharacterSet.newlines) - - // read userRules from UserDefaults - let userRules = UserDefaults.get(forKey: .userRules) - if userRules != nil { - try userRules!.data(using: String.Encoding.utf8)?.write(to: URL(fileURLWithPath: PACUserRuleFilePath), options: .atomic) - } - - do { - let userRuleStr = try String(contentsOfFile: PACUserRuleFilePath, encoding: String.Encoding.utf8) - let userRuleLines = userRuleStr.components(separatedBy: CharacterSet.newlines) - - lines = userRuleLines + lines - } catch { - NSLog("Not found user-rule.txt") - } - // Filter empty and comment lines - lines = lines.filter({ (s: String) -> Bool in - if s.isEmpty { - return false - } - let c = s[s.startIndex] - if c == "!" || c == "[" { - return false - } - return true - }) - - do { - // rule lines to json array - let rulesJsonData: Data = try JSONSerialization.data(withJSONObject: lines, options: .prettyPrinted) - let rulesJsonStr = String(data: rulesJsonData, encoding: String.Encoding.utf8) - - // Get raw pac js - let jsData = try? Data(contentsOf: URL.init(fileURLWithPath: PACAbpFile)) - var jsStr = String(data: jsData!, encoding: String.Encoding.utf8) - - // Replace rules placeholder in pac js - jsStr = jsStr!.replacingOccurrences(of: "__RULES__", with: rulesJsonStr!) - // Replace __SOCKS5PORT__ palcholder in pac js - jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5PORT__", with: "\(sockPort)") - // Replace __SOCKS5ADDR__ palcholder in pac js - var sin6 = sockaddr_in6() - if socks5Address.withCString({ cstring in inet_pton(AF_INET6, cstring, &sin6.sin6_addr) }) == 1 { - jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5ADDR__", with: "[\(socks5Address)]") - } else { - jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5ADDR__", with: socks5Address) - } - - // Write the pac js to file. - try jsStr!.data(using: String.Encoding.utf8)?.write(to: URL(fileURLWithPath: PACFilePath), options: .atomic) - return true - } catch { - - } - } - - } catch { - NSLog("Not found gfwlist.txt") - } - return false -} - -func UpdatePACFromGFWList() { - // Make the dir if rulesDirPath is not exesited. - if !FileManager.default.fileExists(atPath: PACRulesDirPath) { - do { - try FileManager.default.createDirectory(atPath: PACRulesDirPath - , withIntermediateDirectories: true, attributes: nil) - } catch { - } - } - - Alamofire.request(GFWListURL).responseString { - response in - if response.result.isSuccess { - if let v = response.result.value { - do { - try v.write(toFile: GFWListFilePath, atomically: true, encoding: String.Encoding.utf8) - - if GeneratePACFile() { - // Popup a user notification - let notification = NSUserNotification() - notification.title = "PAC has been updated by latest GFW List." - NSUserNotificationCenter.default.deliver(notification) - } - } catch { - - } - } - } else { - // Popup a user notification - let notification = NSUserNotification() - notification.title = "Failed to download latest GFW List." - NSUserNotificationCenter.default.deliver(notification) - } - } -} diff --git a/V2rayU/Preference/PreferenceAbout.swift b/V2rayU/Preference/PreferenceAbout.swift index 6f19d46..875bad7 100644 --- a/V2rayU/Preference/PreferenceAbout.swift +++ b/V2rayU/Preference/PreferenceAbout.swift @@ -11,7 +11,7 @@ import Preferences import ServiceManagement import Sparkle -final class PreferenceAboutController: NSViewController, PreferencePane { +final class PreferenceAboutViewController: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier.aboutTab let preferencePaneTitle = "About" let toolbarItemIcon = NSImage(named: NSImage.infoName)! diff --git a/V2rayU/Preference/PreferenceAbout.xib b/V2rayU/Preference/PreferenceAbout.xib index be95052..7b12d54 100755 --- a/V2rayU/Preference/PreferenceAbout.xib +++ b/V2rayU/Preference/PreferenceAbout.xib @@ -6,7 +6,7 @@ - + @@ -112,6 +112,5 @@ - diff --git a/V2rayU/Preference/PreferenceAdvance.xib b/V2rayU/Preference/PreferenceAdvance.xib index 21f7a04..a691af5 100755 --- a/V2rayU/Preference/PreferenceAdvance.xib +++ b/V2rayU/Preference/PreferenceAdvance.xib @@ -6,7 +6,7 @@ - + diff --git a/V2rayU/Preference/PreferenceGeneral.xib b/V2rayU/Preference/PreferenceGeneral.xib index 404e306..bda3c10 100755 --- a/V2rayU/Preference/PreferenceGeneral.xib +++ b/V2rayU/Preference/PreferenceGeneral.xib @@ -52,20 +52,26 @@ diff --git a/V2rayU/Preference/PreferencePac.swift b/V2rayU/Preference/PreferencePac.swift index fecc980..99c928e 100644 --- a/V2rayU/Preference/PreferencePac.swift +++ b/V2rayU/Preference/PreferencePac.swift @@ -6,12 +6,19 @@ // Copyright © 2018 yanue. All rights reserved. // -import Foundation +import Cocoa import Preferences -import ServiceManagement -import Sparkle +import Alamofire -final class PreferencePacController: NSViewController, PreferencePane { +let PACRulesDirPath = AppResourcesPath + "/pac/" +let PACUserRuleFilePath = PACRulesDirPath + "user-rule.txt" +let PACFilePath = PACRulesDirPath + "pac.js" +let PACUrl = "http://127.0.0.1:" + String(httpServerPort) + "/pac/pac.js" +let PACAbpFile = PACRulesDirPath + "abp.js" +let GFWListFilePath = PACRulesDirPath + "gfwlist.txt" +let GFWListURL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt" + +final class PreferencePacViewController: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier.pacTab let preferencePaneTitle = "Pac File" let toolbarItemIcon = NSImage(named: NSImage.bookmarksTemplateName)! @@ -20,9 +27,181 @@ final class PreferencePacController: NSViewController, PreferencePane { return "PreferencePac" } + @IBOutlet weak var gfwPacListUrl: NSTextField! + @IBOutlet var userRulesView: NSTextView! + override func viewDidLoad() { super.viewDidLoad() // fix: https://github.com/sindresorhus/Preferences/issues/31 self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height); + + let gfwUrl = UserDefaults.get(forKey: .gfwPacListUrl) + if gfwUrl != nil { + gfwPacListUrl.stringValue = gfwUrl! + } else { + gfwPacListUrl.stringValue = GFWListURL + } + + // read userRules from UserDefaults + let txt = UserDefaults.get(forKey: .userRules) + var userRuleTxt = """ +! Put user rules line by line in this file. +! See https://adblockplus.org/en/filter-cheatsheet + +""" + if txt != nil { + if txt!.count>0 { + userRuleTxt = txt! + } + } else { + let str = try? String(contentsOfFile: PACUserRuleFilePath, encoding: String.Encoding.utf8) + if str!.count>0 { + userRuleTxt = str! + } + } + userRulesView.string = userRuleTxt + } + + @IBAction func updatePac(_ sender: Any) { + if let str = userRulesView?.string { + do { + // save user rules into UserDefaults + UserDefaults.set(forKey: .userRules, value: str) + print("updatePac str",str) + try str.data(using: String.Encoding.utf8)?.write(to: URL(fileURLWithPath: PACUserRuleFilePath), options: .atomic) + + UpdatePACFromGFWList() + + if GeneratePACFile() { + // Popup a user notification + let notification = NSUserNotification() + notification.title = "PAC has been updated by User Rules." + NSUserNotificationCenter.default.deliver(notification) + } else { + let notification = NSUserNotification() + notification.title = "It's failed to update PAC by User Rules." + NSUserNotificationCenter.default.deliver(notification) + } + } catch { + } + } + } +} + +// Because of LocalSocks5.ListenPort may be changed +func GeneratePACFile() -> Bool { + let socks5Address = "127.0.0.1" + + let v2ray = V2rayServer.loadSelectedItem() + var sockPort = "1080" + if v2ray != nil && v2ray!.isValid { + let cfg = V2rayConfig() + cfg.parseJson(jsonText: v2ray!.json) + sockPort = cfg.socksPort + } + + // permission + _ = shell(launchPath: "/bin/bash", arguments: ["-c", "cd " + AppResourcesPath + " && /bin/chmod -R 755 ./pac"]) + + do { + let gfwlist = try String(contentsOfFile: GFWListFilePath, encoding: String.Encoding.utf8) + if let data = Data(base64Encoded: gfwlist, options: .ignoreUnknownCharacters) { + let str = String(data: data, encoding: String.Encoding.utf8) + var lines = str!.components(separatedBy: CharacterSet.newlines) + + // read userRules from UserDefaults + let userRules = UserDefaults.get(forKey: .userRules) + if userRules != nil { + try userRules!.data(using: String.Encoding.utf8)?.write(to: URL(fileURLWithPath: PACUserRuleFilePath), options: .atomic) + } + + do { + let userRuleStr = try String(contentsOfFile: PACUserRuleFilePath, encoding: String.Encoding.utf8) + let userRuleLines = userRuleStr.components(separatedBy: CharacterSet.newlines) + + lines = userRuleLines + lines + } catch { + NSLog("Not found user-rule.txt") + } + // Filter empty and comment lines + lines = lines.filter({ (s: String) -> Bool in + if s.isEmpty { + return false + } + let c = s[s.startIndex] + if c == "!" || c == "[" { + return false + } + return true + }) + + do { + // rule lines to json array + let rulesJsonData: Data = try JSONSerialization.data(withJSONObject: lines, options: .prettyPrinted) + let rulesJsonStr = String(data: rulesJsonData, encoding: String.Encoding.utf8) + + // Get raw pac js + let jsData = try? Data(contentsOf: URL.init(fileURLWithPath: PACAbpFile)) + var jsStr = String(data: jsData!, encoding: String.Encoding.utf8) + + // Replace rules placeholder in pac js + jsStr = jsStr!.replacingOccurrences(of: "__RULES__", with: rulesJsonStr!) + // Replace __SOCKS5PORT__ palcholder in pac js + jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5PORT__", with: "\(sockPort)") + // Replace __SOCKS5ADDR__ palcholder in pac js + var sin6 = sockaddr_in6() + if socks5Address.withCString({ cstring in inet_pton(AF_INET6, cstring, &sin6.sin6_addr) }) == 1 { + jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5ADDR__", with: "[\(socks5Address)]") + } else { + jsStr = jsStr!.replacingOccurrences(of: "__SOCKS5ADDR__", with: socks5Address) + } + + // Write the pac js to file. + try jsStr!.data(using: String.Encoding.utf8)?.write(to: URL(fileURLWithPath: PACFilePath), options: .atomic) + return true + } catch { + + } + } + + } catch { + NSLog("Not found gfwlist.txt") + } + return false +} + +func UpdatePACFromGFWList() { + // Make the dir if rulesDirPath is not exesited. + if !FileManager.default.fileExists(atPath: PACRulesDirPath) { + do { + try FileManager.default.createDirectory(atPath: PACRulesDirPath + , withIntermediateDirectories: true, attributes: nil) + } catch { + } + } + + Alamofire.request(GFWListURL).responseString { + response in + if response.result.isSuccess { + if let v = response.result.value { + do { + try v.write(toFile: GFWListFilePath, atomically: true, encoding: String.Encoding.utf8) + + if GeneratePACFile() { + // Popup a user notification + let notification = NSUserNotification() + notification.title = "PAC has been updated by latest GFW List." + NSUserNotificationCenter.default.deliver(notification) + } + } catch { + + } + } + } else { + // Popup a user notification + let notification = NSUserNotification() + notification.title = "Failed to download latest GFW List." + NSUserNotificationCenter.default.deliver(notification) + } } } diff --git a/V2rayU/Preference/PreferencePac.xib b/V2rayU/Preference/PreferencePac.xib old mode 100755 new mode 100644 index ccede70..7e0e233 --- a/V2rayU/Preference/PreferencePac.xib +++ b/V2rayU/Preference/PreferencePac.xib @@ -6,8 +6,10 @@ - + + + @@ -17,48 +19,53 @@ - + - - - - - - + + + + - - - - - + + + + + + + %{value1}@ + + + + - + - - - - - - - - - - + @@ -84,20 +91,17 @@ + + + + + + + + + - diff --git a/V2rayU/Preference/PreferenceSubscript.xib b/V2rayU/Preference/PreferenceSubscript.xib index c923d15..1eebb58 100755 --- a/V2rayU/Preference/PreferenceSubscript.xib +++ b/V2rayU/Preference/PreferenceSubscript.xib @@ -17,14 +17,14 @@ - + - + - + @@ -123,9 +123,9 @@