From b7877b093969fabf4e47d93a5b398139612c5460 Mon Sep 17 00:00:00 2001 From: Qiu Yuzhou Date: Wed, 3 Oct 2018 01:17:54 +0800 Subject: [PATCH] Can export diagnosis to file. --- ShadowsocksX-NG.xcodeproj/project.pbxproj | 4 + ShadowsocksX-NG/AppDelegate.swift | 23 ++++++ ShadowsocksX-NG/Base.lproj/MainMenu.xib | 10 ++- ShadowsocksX-NG/Diagnose.swift | 93 +++++++++++++++++++++++ ShadowsocksX-NG/ServerProfile.swift | 11 +++ 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 ShadowsocksX-NG/Diagnose.swift diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index e93ba98..137a5a8 100755 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 9B7297E7214D69C300FD24AA /* libmbedcrypto.2.12.0.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 9B7297E5214D68F800FD24AA /* libmbedcrypto.2.12.0.dylib */; }; 9B7297EA214D7C6B00FD24AA /* ShareServerProfilesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7297E8214D7C6B00FD24AA /* ShareServerProfilesWindowController.swift */; }; 9B7297EC214DA88A00FD24AA /* ShareServerProfilesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B7297EE214DA88A00FD24AA /* ShareServerProfilesWindowController.xib */; }; + 9B84DAED2163A72F00DFF068 /* Diagnose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B84DAEC2163A72F00DFF068 /* Diagnose.swift */; }; 9B86459D1E7C2CAD00A84029 /* ProxyInterfacesViewCtrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B86459C1E7C2CAD00A84029 /* ProxyInterfacesViewCtrl.swift */; }; 9B938D991E864B38005F5636 /* menu_g_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B938D931E864B38005F5636 /* menu_g_icon.png */; }; 9B938D9A1E864B38005F5636 /* menu_g_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B938D941E864B38005F5636 /* menu_g_icon@2x.png */; }; @@ -208,6 +209,7 @@ 9B7297E8214D7C6B00FD24AA /* ShareServerProfilesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareServerProfilesWindowController.swift; sourceTree = ""; }; 9B7297ED214DA88A00FD24AA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ShareServerProfilesWindowController.xib; sourceTree = ""; }; 9B7297F0214DA89000FD24AA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/ShareServerProfilesWindowController.strings"; sourceTree = ""; }; + 9B84DAEC2163A72F00DFF068 /* Diagnose.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Diagnose.swift; sourceTree = ""; }; 9B86459C1E7C2CAD00A84029 /* ProxyInterfacesViewCtrl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxyInterfacesViewCtrl.swift; sourceTree = ""; }; 9B938D931E864B38005F5636 /* menu_g_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_g_icon.png; sourceTree = ""; }; 9B938D941E864B38005F5636 /* menu_g_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu_g_icon@2x.png"; sourceTree = ""; }; @@ -389,6 +391,7 @@ 9BA04B221D23D5A5005AAD7F /* ProxyConfTool.m */, 9B5831F41E7302F8009D5B7D /* ShortcutsController.h */, 9B5831F51E7302F8009D5B7D /* ShortcutsController.m */, + 9B84DAEC2163A72F00DFF068 /* Diagnose.swift */, ); path = "ShadowsocksX-NG"; sourceTree = ""; @@ -847,6 +850,7 @@ 9B3FFF0D1D05FEB30019A709 /* Utils.swift in Sources */, 9BEEF0751D04EF3E00FC52B3 /* PreferencesWindowController.swift in Sources */, 9B0BFFE91D0460A70040E62B /* AppDelegate.swift in Sources */, + 9B84DAED2163A72F00DFF068 /* Diagnose.swift in Sources */, 9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */, 9B5831FF1E741969009D5B7D /* PreferencesWinController.swift in Sources */, 9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */, diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index e0f5f52..1c88cb3 100755 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -386,6 +386,29 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele NSWorkspace.shared.open(URL(string: "https://github.com/shadowsocks/ShadowsocksX-NG/releases")!) } + @IBAction func exportDiagnosis(_ sender: NSMenuItem) { + let savePanel = NSSavePanel() + savePanel.title = "Save All Server URLs To File".localized + savePanel.canCreateDirectories = true + savePanel.allowedFileTypes = ["txt"] + savePanel.isExtensionHidden = false + + let formatter = DateFormatter() + formatter.dateFormat = "yyyyMMdd_HHmmss" + let dateString = formatter.string(from: Date()) + + savePanel.nameFieldStringValue = "ShadowsocksX-NG_diagnose_\(dateString)" + + savePanel.becomeKey() + let result = savePanel.runModal() + if (result.rawValue == NSFileHandlingPanelOKButton) { + if let url = savePanel.url { + let diagnosisText = diagnose() + try! diagnosisText.write(to: url, atomically: false, encoding: String.Encoding.utf8) + } + } + } + @IBAction func showHelp(_ sender: NSMenuItem) { NSWorkspace.shared.open(URL(string: "https://github.com/shadowsocks/ShadowsocksX-NG/wiki")!) } diff --git a/ShadowsocksX-NG/Base.lproj/MainMenu.xib b/ShadowsocksX-NG/Base.lproj/MainMenu.xib index 3bde40b..3daf684 100755 --- a/ShadowsocksX-NG/Base.lproj/MainMenu.xib +++ b/ShadowsocksX-NG/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -123,6 +123,12 @@ + + + + + + diff --git a/ShadowsocksX-NG/Diagnose.swift b/ShadowsocksX-NG/Diagnose.swift new file mode 100644 index 0000000..ac31d51 --- /dev/null +++ b/ShadowsocksX-NG/Diagnose.swift @@ -0,0 +1,93 @@ +// +// diagnose.swift +// ShadowsocksX-NG +// +// Created by 邱宇舟 on 2018/10/2. +// Copyright © 2018 qiuyuzhou. All rights reserved. +// + +import Foundation + +func shell(_ args: String...) -> String { + let task = Process() + task.launchPath = "/usr/bin/env" + task.arguments = args + + let pipe = Pipe() + task.standardOutput = pipe + + task.launch() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: String.Encoding.utf8) + + return output ?? "" +} + +func diagnose() -> String { + var strs = [String]() + + strs.append("\n-----------------------------------\n") + let infoDict = Bundle.main.infoDictionary! + let infoDictJsonData = try! JSONSerialization.data(withJSONObject: infoDict, options: JSONSerialization.WritingOptions.prettyPrinted) + + strs.append(String(data: infoDictJsonData, encoding: String.Encoding.utf8)!) + strs.append("\n-----------------------------------\n") + + let defaults = UserDefaults.standard + let keys = [ + "ShadowsocksOn", + "ShadowsocksRunningMode", + "LocalSocks5.ListenPort", + "LocalSocks5.ListenAddress", + "PacServer.ListenPort", + "LocalSocks5.Timeout", + "LocalSocks5.EnableUDPRelay", + "LocalSocks5.EnableVerboseMode", + "GFWListURL", + "LocalHTTP.ListenAddress", + "LocalHTTP.ListenPort", + "LocalHTTPOn", + "LocalHTTP.FollowGlobal", + "ProxyExceptions", + ] + + strs.append("Preferences:\n") + for key in keys { + if let obj = defaults.object(forKey: key) { + strs.append("\(key)=\(obj)\n") + } + } + strs.append("-----------------------------------\n") + strs.append("Active server profile: \n") + + if let profile = ServerProfileManager.instance.getActiveProfile() { + strs.append(profile.debugString()) + } else { + strs.append("No actived server profile!") + } + + strs.append("-----------------------------------\n") + strs.append("$ ls -l ~/Library/Application Support/ShadowsocksX-NG/\n") + strs.append(shell("ls", "-l", NSHomeDirectory() + "/Library/Application Support/ShadowsocksX-NG/")) + strs.append("-----------------------------------\n") + strs.append("$ ls -l ~/Library/LaunchAgents/\n") + strs.append(shell("ls", "-l", NSHomeDirectory() + "/Library/LaunchAgents/")) + strs.append("-----------------------------------\n") + strs.append("$ ls -l ~/.ShadowsocksX-NG/\n") + strs.append(shell("ls", "-l", NSHomeDirectory() + "/.ShadowsocksX-NG/")) + strs.append("-----------------------------------\n") + strs.append("$ ls -l /Library/Application Support/ShadowsocksX-NG/") + strs.append(shell("ls", "-l", "/Library/Application Support/ShadowsocksX-NG/")) + strs.append("-----------------------------------\n") + strs.append("$ lsof -PiTCP -sTCP:LISTEN") + strs.append(shell("lsof", "-PiTCP", "-sTCP:LISTEN")) + strs.append("-----------------------------------\n") + strs.append("$ ifconfig") + strs.append(shell("ifconfig")) + strs.append("-----------------------------------\n") + + let output = strs.joined() + return output +} diff --git a/ShadowsocksX-NG/ServerProfile.swift b/ShadowsocksX-NG/ServerProfile.swift index b66da16..eef74c6 100644 --- a/ShadowsocksX-NG/ServerProfile.swift +++ b/ShadowsocksX-NG/ServerProfile.swift @@ -194,6 +194,17 @@ class ServerProfile: NSObject, NSCopying { return conf } + + func debugString() -> String { + var buf = "" + print("ServerHost=\(String(repeating: "*", count: serverHost.count))", to: &buf) + print("ServerPort=\(serverPort)", to: &buf) + print("Method=\(method)", to: &buf) + print("Password=\(String(repeating: "*", count: password.count))", to: &buf) + print("Plugin=\(plugin)", to: &buf) + print("PluginOptions=\(pluginOptions)", to: &buf) + return buf + } func isValid() -> Bool { func validateIpAddress(_ ipToValidate: String) -> Bool {