diff --git a/OPENSSL-GUIDE b/OPENSSL-GUIDE deleted file mode 100644 index 42eaa8fe..00000000 --- a/OPENSSL-GUIDE +++ /dev/null @@ -1,15 +0,0 @@ -OpenSSL library guide for VS2017 - -# Read NOTES.WIN and NOTES.PERL - -# use Visual Studio native tools command prompt -# use activeperl, install NASM assembler -ppm install dmake - -# Win32 x86 -set PATH=D:\NASM-32;%PATH% -perl Configure VC-WIN32 --release --prefix=C:\Users\home\Downloads\openssl-1.1.0g\x86-build --openssldir=C:\Users\home\Downloads\openssl-1.1.0g\x86-install -nmake -nmake test -# to rebuild -nmake distclean diff --git a/appveyor.yml b/appveyor.yml index 3086bd28..bc8cb60d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,7 @@ after_build: $text += 'SHA-256' + $newLine $text += (Get-FileHash $file -Algorithm SHA256).Hash + $newLine $text += 'SHA-512' + $newLine - $text += (Get-FileHash $file -Algorithm SHA512).Hash + $text += (Get-FileHash $file -Algorithm SHA512).Hash + $newLine return $text } diff --git a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs index 30e29666..1d278249 100644 --- a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs +++ b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs @@ -9,6 +9,9 @@ using System.Text; using Newtonsoft.Json; using Shadowsocks.Model; using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Security.Cryptography; namespace Shadowsocks.Controller { @@ -32,23 +35,37 @@ namespace Shadowsocks.Controller private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); + private static SocketsHttpHandler socketsHttpHandler; + private static HttpClient httpClient; private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat"; + private static readonly string GEOSITE_SHA256SUM_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat.sha256sum"; + private static byte[] geositeDB; public static readonly Dictionary> Geosites = new Dictionary>(); static GeositeUpdater() { - if (!File.Exists(DATABASE_PATH)) + //socketsHttpHandler = new SocketsHttpHandler(); + //httpClient = new HttpClient(socketsHttpHandler); + + if (File.Exists(DATABASE_PATH) && new FileInfo(DATABASE_PATH).Length > 0) { + geositeDB = File.ReadAllBytes(DATABASE_PATH); + } + else + { + geositeDB = Resources.dlc_dat; File.WriteAllBytes(DATABASE_PATH, Resources.dlc_dat); } LoadGeositeList(); } - static void LoadGeositeList(byte[] data = null) + /// + /// load new GeoSite data from geositeDB + /// + static void LoadGeositeList() { - data = data ?? File.ReadAllBytes(DATABASE_PATH); - var list = GeositeList.Parser.ParseFrom(data); + var list = GeositeList.Parser.ParseFrom(geositeDB); foreach (var item in list.Entries) { Geosites[item.GroupName.ToLower()] = item.Domains; @@ -61,9 +78,12 @@ namespace Shadowsocks.Controller Error = null; } - public static void UpdatePACFromGeosite(Configuration config) + public static async Task UpdatePACFromGeosite() { string geositeUrl = GEOSITE_URL; + string geositeSha256sumUrl = GEOSITE_SHA256SUM_URL; + SHA256 mySHA256 = SHA256.Create(); + var config = Program.MainController.GetCurrentConfiguration(); string group = config.geositeGroup; bool blacklist = config.geositeBlacklistMode; @@ -73,31 +93,83 @@ namespace Shadowsocks.Controller geositeUrl = config.geositeUrl; } logger.Info($"Checking Geosite from {geositeUrl}"); - WebClient http = new WebClient(); + + // use System.Net.Http.HttpClient to download GeoSite db. + // NASTY workaround: new HttpClient every update + // because we can't change proxy on existing socketsHttpHandler instance + socketsHttpHandler = new SocketsHttpHandler(); + httpClient = new HttpClient(socketsHttpHandler); if (config.enabled) { - http.Proxy = new WebProxy( + socketsHttpHandler.UseProxy = true; + socketsHttpHandler.Proxy = new WebProxy( config.isIPv6Enabled ? $"[{IPAddress.IPv6Loopback}]" : IPAddress.Loopback.ToString(), config.localPort); } - http.DownloadDataCompleted += (o, e) => + + try { - try + // download checksum first + var geositeSha256sum = await httpClient.GetStringAsync(geositeSha256sumUrl); + geositeSha256sum = geositeSha256sum.Substring(0, 64).ToUpper(); + logger.Info($"Got Sha256sum: {geositeSha256sum}"); + // compare downloaded checksum with local geositeDB + byte[] localDBHashBytes = mySHA256.ComputeHash(geositeDB); + string localDBHash = BitConverter.ToString(localDBHashBytes).Replace("-", String.Empty); + logger.Info($"Local Sha256sum: {localDBHash}"); + // if already latest + if (geositeSha256sum == localDBHash) + { + logger.Info("Local GeoSite DB is up to date."); + return; + } + + // not latest. download new DB + var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl); + + // verify sha256sum + byte[] downloadedDBHashBytes = mySHA256.ComputeHash(downloadedBytes); + string downloadedDBHash = BitConverter.ToString(downloadedDBHashBytes).Replace("-", String.Empty); + logger.Info($"Actual Sha256sum: {downloadedDBHash}"); + if (geositeSha256sum != downloadedDBHash) { - File.WriteAllBytes(DATABASE_PATH, e.Result); - LoadGeositeList(); + logger.Info("Sha256sum Verification: FAILED. Downloaded GeoSite DB is corrupted. Aborting the update."); + throw new Exception("Sha256sum mismatch"); + } + else + { + logger.Info("Sha256sum Verification: PASSED. Applying to local GeoSite DB."); + } - bool pacFileChanged = MergeAndWritePACFile(group, blacklist); - UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); + // write to geosite file + using (FileStream geositeFileStream = File.Create(DATABASE_PATH)) + await geositeFileStream.WriteAsync(downloadedBytes, 0, downloadedBytes.Length); + + // update stuff + geositeDB = downloadedBytes; + LoadGeositeList(); + bool pacFileChanged = MergeAndWritePACFile(group, blacklist); + UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); + } + catch (Exception ex) + { + Error?.Invoke(null, new ErrorEventArgs(ex)); + } + finally + { + if (socketsHttpHandler != null) + { + socketsHttpHandler.Dispose(); + socketsHttpHandler = null; } - catch (Exception ex) + if (httpClient != null) { - Error?.Invoke(null, new ErrorEventArgs(ex)); + httpClient.Dispose(); + httpClient = null; } - }; - http.DownloadDataAsync(new Uri(geositeUrl)); + } } public static bool MergeAndWritePACFile(string group, bool blacklist) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 796c8eb0..1d0ecce5 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -411,11 +411,6 @@ namespace Shadowsocks.Controller return $"ss://{url}{tag}"; } - public void UpdatePACFromGeosite() - { - GeositeUpdater.UpdatePACFromGeosite(_config); - } - public void UpdateStatisticsConfiguration(bool enabled) { if (availabilityStatistics != null) diff --git a/shadowsocks-csharp/Controller/System/ProtocolHandler.cs b/shadowsocks-csharp/Controller/System/ProtocolHandler.cs index 2a0112cb..35bc4757 100644 --- a/shadowsocks-csharp/Controller/System/ProtocolHandler.cs +++ b/shadowsocks-csharp/Controller/System/ProtocolHandler.cs @@ -20,7 +20,6 @@ namespace Shadowsocks.Controller // 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; diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 6674fd72..872e2f2a 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -26,32 +26,17 @@ namespace Shadowsocks public static MenuViewController MenuController { get; private set; } public static string[] Args { get; private set; } - [System.Runtime.InteropServices.DllImport("user32.dll")] - private static extern bool SetProcessDPIAware(); - /// /// 应用程序的主入口点。 /// - /// [STAThread] static void Main(string[] args) { // todo: initialize the NLog configuartion Model.NLogConfig.TouchAndApplyNLogConfig(); - // .NET Framework 4.7.2 on Win7 compatibility - System.Net.ServicePointManager.SecurityProtocol |= - System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12; - // store args for further use Args = args; - // Check OS since we are using dual-mode socket - if (!Utils.IsWinVistaOrHigher()) - { - MessageBox.Show(I18N.GetString("Unsupported operating system, use Windows Vista at least."), - "Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } string pipename = $"Shadowsocks\\{Application.StartupPath.GetHashCode()}"; string addedUrl = null; @@ -125,7 +110,9 @@ namespace Shadowsocks Application.SetCompatibleTextRenderingDefault(false); AutoStartup.RegisterForRestart(true); - Directory.SetCurrentDirectory(Application.StartupPath); + // See https://github.com/dotnet/runtime/issues/13051 + // we have to do this for self-contained executables + Directory.SetCurrentDirectory(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)); #if DEBUG // truncate privoxy log file while debugging diff --git a/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml b/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml new file mode 100644 index 00000000..8975df70 --- /dev/null +++ b/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml @@ -0,0 +1,18 @@ + + + + + Release + Any CPU + bin\Release\netcoreapp3.1\win-x64\publish\ + FileSystem + netcoreapp3.1 + win-x64 + true + True + False + True + + \ No newline at end of file diff --git a/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml.user b/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml.user new file mode 100644 index 00000000..312c6e3b --- /dev/null +++ b/shadowsocks-csharp/Properties/PublishProfiles/win-x64.pubxml.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml b/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml new file mode 100644 index 00000000..b25dd23a --- /dev/null +++ b/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml @@ -0,0 +1,18 @@ + + + + + Release + Any CPU + bin\Release\netcoreapp3.1\win-x86\publish\ + FileSystem + netcoreapp3.1 + win-x86 + true + True + False + True + + \ No newline at end of file diff --git a/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml.user b/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml.user new file mode 100644 index 00000000..312c6e3b --- /dev/null +++ b/shadowsocks-csharp/Properties/PublishProfiles/win-x86.pubxml.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 83eb3384..5083cd1d 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -705,9 +705,9 @@ namespace Shadowsocks.View controller.TouchPACFile(); } - private void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) + private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) { - controller.UpdatePACFromGeosite(); + await GeositeUpdater.UpdatePACFromGeosite(); } private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 122f1c50..05d73e9f 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -71,20 +71,20 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - +