New option for ss:// URL associationtags/4.2.0.0
@@ -0,0 +1,47 @@ | |||||
using System; | |||||
using System.IO; | |||||
using System.IO.Pipes; | |||||
using System.Net; | |||||
using System.Text; | |||||
namespace Shadowsocks.Controller | |||||
{ | |||||
class RequestAddUrlEventArgs : EventArgs | |||||
{ | |||||
public readonly string Url; | |||||
public RequestAddUrlEventArgs(string url) | |||||
{ | |||||
this.Url = url; | |||||
} | |||||
} | |||||
internal class NamedPipeServer | |||||
{ | |||||
public event EventHandler<RequestAddUrlEventArgs> AddUrlRequested; | |||||
public async void Run(string path) | |||||
{ | |||||
byte[] buf = new byte[4096]; | |||||
while (true) | |||||
{ | |||||
using (NamedPipeServerStream stream = new NamedPipeServerStream(path)) | |||||
{ | |||||
stream.WaitForConnection(); | |||||
await stream.ReadAsync(buf, 0, 4); | |||||
int opcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); | |||||
if (opcode == 1) | |||||
{ | |||||
await stream.ReadAsync(buf, 0, 4); | |||||
int strlen = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); | |||||
await stream.ReadAsync(buf, 0, strlen); | |||||
string url = Encoding.UTF8.GetString(buf, 0, strlen); | |||||
AddUrlRequested?.Invoke(this, new RequestAddUrlEventArgs(url)); | |||||
} | |||||
stream.Close(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -218,6 +218,25 @@ namespace Shadowsocks.Controller | |||||
StatisticsStrategyConfiguration.Save(configuration); | StatisticsStrategyConfiguration.Save(configuration); | ||||
} | } | ||||
public bool AskAddServerBySSURL(string ssURL) | |||||
{ | |||||
var dr = MessageBox.Show(I18N.GetString("Import from URL: {0} ?", ssURL), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo); | |||||
if (dr == DialogResult.Yes) | |||||
{ | |||||
if (AddServerBySSURL(ssURL)) | |||||
{ | |||||
MessageBox.Show(I18N.GetString("Successfully imported from {0}", ssURL)); | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
MessageBox.Show(I18N.GetString("Failed to import. Please check if the link is valid.")); | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
public bool AddServerBySSURL(string ssURL) | public bool AddServerBySSURL(string ssURL) | ||||
{ | { | ||||
try | try | ||||
@@ -0,0 +1,107 @@ | |||||
using Microsoft.Win32; | |||||
using NLog; | |||||
using Shadowsocks.Util; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Reflection; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Shadowsocks.Controller | |||||
{ | |||||
static class ProtocolHandler | |||||
{ | |||||
const string ssURLRegKey = @"SOFTWARE\Classes\ss"; | |||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
// Don't use Application.ExecutablePath | |||||
// see https://stackoverflow.com/questions/12945805/odd-c-sharp-path-issue | |||||
private static readonly string ExecutablePath = Assembly.GetEntryAssembly().Location; | |||||
// TODO: Elevate when necessary | |||||
public static bool Set(bool enabled) | |||||
{ | |||||
RegistryKey ssURLAssociation = null; | |||||
try | |||||
{ | |||||
ssURLAssociation = Registry.CurrentUser.CreateSubKey(ssURLRegKey, RegistryKeyPermissionCheck.ReadWriteSubTree); | |||||
if (ssURLAssociation == null) | |||||
{ | |||||
logger.Error(@"Failed to create HKCU\SOFTWARE\Classes\ss to register ss:// association."); | |||||
return false; | |||||
} | |||||
if (enabled) | |||||
{ | |||||
ssURLAssociation.SetValue("", "URL:Shadowsocks"); | |||||
ssURLAssociation.SetValue("URL Protocol", ""); | |||||
var shellOpen = ssURLAssociation.CreateSubKey("shell").CreateSubKey("open").CreateSubKey("command"); | |||||
shellOpen.SetValue("", $"{ExecutablePath} --open-url %1"); | |||||
logger.Info(@"Successfully added ss:// association."); | |||||
} | |||||
else | |||||
{ | |||||
Registry.CurrentUser.DeleteSubKeyTree(ssURLRegKey); | |||||
logger.Info(@"Successfully removed ss:// association."); | |||||
} | |||||
return true; | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
logger.LogUsefulException(e); | |||||
return false; | |||||
} | |||||
finally | |||||
{ | |||||
if (ssURLAssociation != null) | |||||
{ | |||||
try | |||||
{ | |||||
ssURLAssociation.Close(); | |||||
ssURLAssociation.Dispose(); | |||||
} | |||||
catch (Exception e) | |||||
{ logger.LogUsefulException(e); } | |||||
} | |||||
} | |||||
} | |||||
public static bool Check() | |||||
{ | |||||
RegistryKey ssURLAssociation = null; | |||||
try | |||||
{ | |||||
ssURLAssociation = Registry.CurrentUser.OpenSubKey(ssURLRegKey, true); | |||||
if (ssURLAssociation == null) | |||||
{ | |||||
//logger.Info(@"ss:// links not associated."); | |||||
return false; | |||||
} | |||||
var shellOpen = ssURLAssociation.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command"); | |||||
return (string)shellOpen.GetValue("") == $"{ExecutablePath} --open-url %1"; | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
logger.LogUsefulException(e); | |||||
return false; | |||||
} | |||||
finally | |||||
{ | |||||
if (ssURLAssociation != null) | |||||
{ | |||||
try | |||||
{ | |||||
ssURLAssociation.Close(); | |||||
ssURLAssociation.Dispose(); | |||||
} | |||||
catch (Exception e) | |||||
{ logger.LogUsefulException(e); } | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -18,6 +18,7 @@ Servers,Серверы,服务器,伺服器,サーバー,서버 | |||||
Edit Servers...,Редактировать серверы…,编辑服务器...,編輯伺服器...,サーバーの編集...,서버 수정… | Edit Servers...,Редактировать серверы…,编辑服务器...,編輯伺服器...,サーバーの編集...,서버 수정… | ||||
Statistics Config...,Настройки статистики…,统计配置...,統計設定檔...,統計情報の設定...,통계 설정 | Statistics Config...,Настройки статистики…,统计配置...,統計設定檔...,統計情報の設定...,통계 설정 | ||||
Start on Boot,Автозагрузка,开机启动,開機啟動,システムと同時に起動,시스템 시작 시에 시작하기 | Start on Boot,Автозагрузка,开机启动,開機啟動,システムと同時に起動,시스템 시작 시에 시작하기 | ||||
Associate ss:// Links,Ассоциированный ss:// Ссылки,关联 ss:// 链接,關聯 ss:// 鏈接,, | |||||
Forward Proxy...,Прямой прокси…,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定...,포워드 프록시 | Forward Proxy...,Прямой прокси…,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定...,포워드 프록시 | ||||
Allow other Devices to connect,Общий доступ к подключению,允许其他设备连入,允許其他裝置連入,他のデバイスからの接続を許可する,다른 기기에서 연결 허용 | Allow other Devices to connect,Общий доступ к подключению,允许其他设备连入,允許其他裝置連入,他のデバイスからの接続を許可する,다른 기기에서 연결 허용 | ||||
Local PAC,Локальный PAC,使用本地 PAC,使用本機 PAC,ローカル PAC,로컬 PAC | Local PAC,Локальный PAC,使用本地 PAC,使用本機 PAC,ローカル PAC,로컬 PAC | ||||
@@ -184,6 +185,9 @@ Find Shadowsocks icon in your notify tray.,Значок Shadowsocks можно | |||||
"If you want to start multiple Shadowsocks, make a copy in another directory.","Если вы хотите запустить несколько копий Shadowsocks одновременно, создайте отдельную папку на каждую копию.",如果想同时启动多个,可以另外复制一份到别的目录。,如果想同時啟動多個,可以另外複製一份至別的目錄。,複数起動したい場合は、プログラムファイルを別のフォルダーにコピーしてから、もう一度実行して下さい。,"만약 여러 개의 Shadowsocks를 사용하고 싶으시다면, 파일을 다른 곳에 복사해주세요." | "If you want to start multiple Shadowsocks, make a copy in another directory.","Если вы хотите запустить несколько копий Shadowsocks одновременно, создайте отдельную папку на каждую копию.",如果想同时启动多个,可以另外复制一份到别的目录。,如果想同時啟動多個,可以另外複製一份至別的目錄。,複数起動したい場合は、プログラムファイルを別のフォルダーにコピーしてから、もう一度実行して下さい。,"만약 여러 개의 Shadowsocks를 사용하고 싶으시다면, 파일을 다른 곳에 복사해주세요." | ||||
Failed to decode QRCode,Не удалось распознать QRCode,无法解析二维码,QR 碼解碼失敗,QR コードの読み取りに失敗しました。,QR코드를 해석하는데에 실패했습니다. | Failed to decode QRCode,Не удалось распознать QRCode,无法解析二维码,QR 碼解碼失敗,QR コードの読み取りに失敗しました。,QR코드를 해석하는데에 실패했습니다. | ||||
Failed to update registry,Не удалось обновить запись в реестре,无法修改注册表,無法修改登錄檔,レジストリの更新に失敗しました。,레지스트리를 업데이트하는데에 실패했습니다. | Failed to update registry,Не удалось обновить запись в реестре,无法修改注册表,無法修改登錄檔,レジストリの更新に失敗しました。,레지스트리를 업데이트하는데에 실패했습니다. | ||||
Import from URL: {0} ?,импортировать из адреса: {0} ?,从URL导入: {0} ?,從URL匯入: {0} ?,, | |||||
Successfully imported from {0},Успешно импортировано из {0},导入成功:{0},導入成功:{0},, | |||||
Failed to import. Please check if the link is valid.,,导入失败,请检查链接是否有效。,導入失敗,請檢查鏈接是否有效。,, | |||||
System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: | System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: | ||||
Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번 | Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번 | ||||
"Unexpected error, shadowsocks will exit. Please report to","Непредвиденная ошибка, пожалуйста сообщите на",非预期错误,Shadowsocks将退出。请提交此错误到,非預期錯誤,Shadowsocks 將結束。請報告此錯誤至,予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:,알 수 없는 오류로 Shadowsocks가 종료될 것입니다. 오류를 제보해주세요: | "Unexpected error, shadowsocks will exit. Please report to","Непредвиденная ошибка, пожалуйста сообщите на",非预期错误,Shadowsocks将退出。请提交此错误到,非預期錯誤,Shadowsocks 將結束。請報告此錯誤至,予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:,알 수 없는 오류로 Shadowsocks가 종료될 것입니다. 오류를 제보해주세요: | ||||
@@ -1,21 +1,26 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Threading; | |||||
using System.Windows.Forms; | |||||
using Microsoft.Win32; | |||||
using NLog; | using NLog; | ||||
using Microsoft.Win32; | |||||
using Shadowsocks.Controller; | using Shadowsocks.Controller; | ||||
using Shadowsocks.Controller.Hotkeys; | using Shadowsocks.Controller.Hotkeys; | ||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
using Shadowsocks.View; | using Shadowsocks.View; | ||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.IO.Pipes; | |||||
using System.Linq; | |||||
using System.Net; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using System.Windows.Forms; | |||||
namespace Shadowsocks | namespace Shadowsocks | ||||
{ | { | ||||
static class Program | |||||
internal static class Program | |||||
{ | { | ||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||||
public static ShadowsocksController MainController { get; private set; } | public static ShadowsocksController MainController { get; private set; } | ||||
public static MenuViewController MenuController { get; private set; } | public static MenuViewController MenuController { get; private set; } | ||||
public static string[] Args { get; private set; } | public static string[] Args { get; private set; } | ||||
@@ -24,15 +29,15 @@ namespace Shadowsocks | |||||
/// </summary> | /// </summary> | ||||
/// </summary> | /// </summary> | ||||
[STAThread] | [STAThread] | ||||
static void Main(string[] args) | |||||
private static void Main(string[] args) | |||||
{ | { | ||||
Directory.SetCurrentDirectory(Application.StartupPath); | Directory.SetCurrentDirectory(Application.StartupPath); | ||||
// todo: initialize the NLog configuartion | // todo: initialize the NLog configuartion | ||||
Model.NLogConfig.TouchAndApplyNLogConfig(); | Model.NLogConfig.TouchAndApplyNLogConfig(); | ||||
// .NET Framework 4.7.2 on Win7 compatibility | // .NET Framework 4.7.2 on Win7 compatibility | ||||
System.Net.ServicePointManager.SecurityProtocol |= | |||||
System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12; | |||||
ServicePointManager.SecurityProtocol |= | |||||
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; | |||||
// store args for further use | // store args for further use | ||||
Args = args; | Args = args; | ||||
@@ -50,27 +55,58 @@ namespace Shadowsocks | |||||
if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.7.2"), | if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.7.2"), | ||||
"Shadowsocks Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)) | "Shadowsocks Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)) | ||||
{ | { | ||||
//Process.Start("https://www.microsoft.com/download/details.aspx?id=53344"); // 4.6.2 | |||||
Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net472"); | Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net472"); | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
string pipename = $"Shadowsocks\\{Application.StartupPath.GetHashCode()}"; | |||||
Utils.ReleaseMemory(true); | |||||
using (Mutex mutex = new Mutex(false, $"Global\\Shadowsocks_{Application.StartupPath.GetHashCode()}")) | |||||
string addedUrl = null; | |||||
using (NamedPipeClientStream pipe = new NamedPipeClientStream(pipename)) | |||||
{ | { | ||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); | |||||
// handle UI exceptions | |||||
Application.ThreadException += Application_ThreadException; | |||||
// handle non-UI exceptions | |||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; | |||||
Application.ApplicationExit += Application_ApplicationExit; | |||||
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; | |||||
Application.EnableVisualStyles(); | |||||
Application.SetCompatibleTextRenderingDefault(false); | |||||
AutoStartup.RegisterForRestart(true); | |||||
if (!mutex.WaitOne(0, false)) | |||||
bool pipeExist = false; | |||||
try | |||||
{ | |||||
pipe.Connect(10); | |||||
pipeExist = true; | |||||
} | |||||
catch (TimeoutException) | |||||
{ | |||||
pipeExist = false; | |||||
} | |||||
// TODO: switch to better argv parser when it's getting complicate | |||||
List<string> alist = Args.ToList(); | |||||
// check --open-url param | |||||
int urlidx = alist.IndexOf("--open-url") + 1; | |||||
if (urlidx > 0) | |||||
{ | |||||
if (Args.Length <= urlidx) | |||||
{ | |||||
return; | |||||
} | |||||
// --open-url exist, and no other instance, add it later | |||||
if (!pipeExist) | |||||
{ | |||||
addedUrl = Args[urlidx]; | |||||
} | |||||
// has other instance, send url via pipe then exit | |||||
else | |||||
{ | |||||
byte[] b = Encoding.UTF8.GetBytes(Args[urlidx]); | |||||
byte[] opAddUrl = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)); | |||||
byte[] blen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(b.Length)); | |||||
pipe.Write(opAddUrl, 0, 4); // opcode addurl | |||||
pipe.Write(blen, 0, 4); | |||||
pipe.Write(b, 0, b.Length); | |||||
pipe.Close(); | |||||
return; | |||||
} | |||||
} | |||||
// has another instance, and no need to communicate with it return | |||||
else if (pipeExist) | |||||
{ | { | ||||
Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks"); | Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks"); | ||||
if (oldProcesses.Length > 0) | if (oldProcesses.Length > 0) | ||||
@@ -83,21 +119,44 @@ namespace Shadowsocks | |||||
I18N.GetString("Shadowsocks is already running.")); | I18N.GetString("Shadowsocks is already running.")); | ||||
return; | return; | ||||
} | } | ||||
Directory.SetCurrentDirectory(Application.StartupPath); | |||||
} | |||||
Utils.ReleaseMemory(true); | |||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); | |||||
// handle UI exceptions | |||||
Application.ThreadException += Application_ThreadException; | |||||
// handle non-UI exceptions | |||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; | |||||
Application.ApplicationExit += Application_ApplicationExit; | |||||
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; | |||||
Application.EnableVisualStyles(); | |||||
Application.SetCompatibleTextRenderingDefault(false); | |||||
AutoStartup.RegisterForRestart(true); | |||||
Directory.SetCurrentDirectory(Application.StartupPath); | |||||
#if DEBUG | #if DEBUG | ||||
// truncate privoxy log file while debugging | |||||
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); | |||||
if (File.Exists(privoxyLogFilename)) | |||||
using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { } | |||||
// truncate privoxy log file while debugging | |||||
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); | |||||
if (File.Exists(privoxyLogFilename)) | |||||
using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { } | |||||
#endif | #endif | ||||
MainController = new ShadowsocksController(); | |||||
MenuController = new MenuViewController(MainController); | |||||
MainController = new ShadowsocksController(); | |||||
MenuController = new MenuViewController(MainController); | |||||
HotKeys.Init(MainController); | |||||
MainController.Start(); | |||||
Application.Run(); | |||||
} | |||||
HotKeys.Init(MainController); | |||||
MainController.Start(); | |||||
NamedPipeServer namedPipeServer = new NamedPipeServer(); | |||||
Task.Run(() => namedPipeServer.Run(pipename)); | |||||
namedPipeServer.AddUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); | |||||
if (!addedUrl.IsNullOrEmpty()) | |||||
{ | |||||
MainController.AskAddServerBySSURL(addedUrl); | |||||
} | |||||
Application.Run(); | |||||
} | } | ||||
private static int exited = 0; | private static int exited = 0; | ||||
@@ -135,7 +194,7 @@ namespace Shadowsocks | |||||
logger.Info("os wake up"); | logger.Info("os wake up"); | ||||
if (MainController != null) | if (MainController != null) | ||||
{ | { | ||||
System.Threading.Tasks.Task.Factory.StartNew(() => | |||||
Task.Factory.StartNew(() => | |||||
{ | { | ||||
Thread.Sleep(10 * 1000); | Thread.Sleep(10 * 1000); | ||||
try | try | ||||
@@ -36,6 +36,7 @@ namespace Shadowsocks.View | |||||
private ContextMenu contextMenu1; | private ContextMenu contextMenu1; | ||||
private MenuItem disableItem; | private MenuItem disableItem; | ||||
private MenuItem AutoStartupItem; | private MenuItem AutoStartupItem; | ||||
private MenuItem ProtocolHandlerItem; | |||||
private MenuItem ShareOverLANItem; | private MenuItem ShareOverLANItem; | ||||
private MenuItem SeperatorItem; | private MenuItem SeperatorItem; | ||||
private MenuItem ConfigItem; | private MenuItem ConfigItem; | ||||
@@ -315,6 +316,7 @@ namespace Shadowsocks.View | |||||
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)), | this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)), | ||||
new MenuItem("-"), | new MenuItem("-"), | ||||
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), | this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), | ||||
this.ProtocolHandlerItem = CreateMenuItem("Associate ss:// Links", new EventHandler(this.ProtocolHandlerItem_Click)), | |||||
this.ShareOverLANItem = CreateMenuItem("Allow other Devices to connect", new EventHandler(this.ShareOverLANItem_Click)), | this.ShareOverLANItem = CreateMenuItem("Allow other Devices to connect", new EventHandler(this.ShareOverLANItem_Click)), | ||||
new MenuItem("-"), | new MenuItem("-"), | ||||
this.hotKeyItem = CreateMenuItem("Edit Hotkeys...", new EventHandler(this.hotKeyItem_Click)), | this.hotKeyItem = CreateMenuItem("Edit Hotkeys...", new EventHandler(this.hotKeyItem_Click)), | ||||
@@ -442,6 +444,7 @@ namespace Shadowsocks.View | |||||
VerboseLoggingToggleItem.Checked = config.isVerboseLogging; | VerboseLoggingToggleItem.Checked = config.isVerboseLogging; | ||||
ShowPluginOutputToggleItem.Checked = config.showPluginOutput; | ShowPluginOutputToggleItem.Checked = config.showPluginOutput; | ||||
AutoStartupItem.Checked = AutoStartup.Check(); | AutoStartupItem.Checked = AutoStartup.Check(); | ||||
ProtocolHandlerItem.Checked = ProtocolHandler.Check(); | |||||
onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac; | onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac; | ||||
localPACItem.Checked = !onlinePACItem.Checked; | localPACItem.Checked = !onlinePACItem.Checked; | ||||
secureLocalPacUrlToggleItem.Checked = config.secureLocalPac; | secureLocalPacUrlToggleItem.Checked = config.secureLocalPac; | ||||
@@ -821,8 +824,7 @@ namespace Shadowsocks.View | |||||
private void ImportURLItem_Click(object sender, EventArgs e) | private void ImportURLItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
var success = controller.AddServerBySSURL(Clipboard.GetText(TextDataFormat.Text)); | |||||
if (success) | |||||
if (controller.AskAddServerBySSURL(Clipboard.GetText(TextDataFormat.Text))) | |||||
{ | { | ||||
ShowConfigForm(); | ShowConfigForm(); | ||||
} | } | ||||
@@ -845,6 +847,16 @@ namespace Shadowsocks.View | |||||
{ | { | ||||
MessageBox.Show(I18N.GetString("Failed to update registry")); | MessageBox.Show(I18N.GetString("Failed to update registry")); | ||||
} | } | ||||
LoadCurrentConfiguration(); | |||||
} | |||||
private void ProtocolHandlerItem_Click(object sender, EventArgs e) | |||||
{ | |||||
ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; | |||||
if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) | |||||
{ | |||||
MessageBox.Show(I18N.GetString("Failed to update registry")); | |||||
} | |||||
LoadCurrentConfiguration(); | |||||
} | } | ||||
private void LocalPACItem_Click(object sender, EventArgs e) | private void LocalPACItem_Click(object sender, EventArgs e) | ||||
@@ -113,6 +113,8 @@ | |||||
<Compile Include="Controller\HotkeyReg.cs" /> | <Compile Include="Controller\HotkeyReg.cs" /> | ||||
<Compile Include="Controller\LoggerExtension.cs" /> | <Compile Include="Controller\LoggerExtension.cs" /> | ||||
<Compile Include="Controller\Service\PACDaemon.cs" /> | <Compile Include="Controller\Service\PACDaemon.cs" /> | ||||
<Compile Include="Controller\Service\NamedPipeServer.cs" /> | |||||
<Compile Include="Controller\System\ProtocolHandler.cs" /> | |||||
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" /> | <Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" /> | ||||
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" /> | <Compile Include="Encryption\AEAD\AEADEncryptor.cs" /> | ||||
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" /> | <Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" /> | ||||