This commit is contained in:
1415ddfer 2024-03-09 18:29:16 +08:00
parent dc4233d645
commit d09249272c
19 changed files with 472 additions and 190 deletions

View File

@ -10,7 +10,7 @@
<DockPanel> <DockPanel>
<TextBlock Text="关&#13;于" Margin="20" FontSize="50" Foreground="OrangeRed"/> <TextBlock Text="关&#13;于" Margin="20" FontSize="50" Foreground="OrangeRed"/>
<StackPanel> <StackPanel>
<TextBlock x:Name="info" Text=" 铃依登陆器&#13;&#13;The best luancher&#13; Power by DDF" Margin="30,150,30,30" HorizontalAlignment="Center" Foreground="#2e4e7e" FontSize="16"/> <TextBlock x:Name="info" Text=" 灵依游戏大厅&#13;&#13;The best luancher&#13; Power by DDF" Margin="30,150,30,30" HorizontalAlignment="Center" Foreground="#2e4e7e" FontSize="16"/>
<TextBlock Text="Contact me" HorizontalAlignment="Center" Foreground="#FF81EB78"/> <TextBlock Text="Contact me" HorizontalAlignment="Center" Foreground="#FF81EB78"/>
<TextBlock HorizontalAlignment="Center"> <TextBlock HorizontalAlignment="Center">
<Hyperlink NavigateUri="https://github.com/1415ddfer/ZeroHelper" Click="Hyperlink_Click"> <Hyperlink NavigateUri="https://github.com/1415ddfer/ZeroHelper" Click="Hyperlink_Click">

View File

@ -1,7 +1,6 @@
<Application x:Class="Zerolauncher.App" <Application x:Class="Zerolauncher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Zerolauncher"
StartupUri="MainWindow.xaml"> StartupUri="MainWindow.xaml">
<Application.Resources> <Application.Resources>

View File

@ -11,10 +11,25 @@ namespace Zerolauncher
protected override void OnStartup(StartupEventArgs e) protected override void OnStartup(StartupEventArgs e)
{ {
base.OnStartup(e); base.OnStartup(e);
_ = UpDateManager.TakeQMessage();
DataStream.Load(); var a = CloundMananger.TakeQMessage();
_ = WebApiManager.StartListener(); a.Wait();
AccountManager.initLoadData(); UpDateManager.DoCheckUpdate();
if (DownloadTask.state)
{
}else
{
DataStream.Load();
_ = WebApiManager.StartListener();
AccountManager.initLoadData();
}
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
WebApiManager.StopListener();
} }
} }

View File

@ -3,33 +3,57 @@ using System.Text;
namespace Zerolauncher.Defender namespace Zerolauncher.Defender
{ {
class EngineCacheSha class CacheSha
{ {
const string key = "mysecretkey"; const string key = "mysecretkey";
static string? sha; static string? sha_engine;
static string? sha_main;
public static int errorCode = 0; public static int errorCode = 0;
public static void Put(string eSha) public static void PutE(string eSha)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < eSha.Length; i++) for (int i = 0; i < eSha.Length; i++)
{ {
sb.Append((char)(eSha[i] ^ key[i % key.Length])); sb.Append((char)(eSha[i] ^ key[i % key.Length]));
} }
sha = sb.ToString(); sha_engine = sb.ToString();
} }
public static string? Get() public static string? GetE()
{ {
if (sha == null) { return null; } if (sha_engine == null) { return null; }
var sb = new StringBuilder(); var sb = new StringBuilder();
for (int i = 0; i < sha.Length; i++) for (int i = 0; i < sha_engine.Length; i++)
{ {
sb.Append((char)(sha[i] ^ key[i % key.Length])); sb.Append((char)(sha_engine[i] ^ key[i % key.Length]));
}
return sb.ToString();
}
public static void PutM(string eSha)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < eSha.Length; i++)
{
sb.Append((char)(eSha[i] ^ key[i % key.Length]));
}
sha_main = sb.ToString();
}
public static string? GetM()
{
if (sha_main == null) { return null; }
var sb = new StringBuilder();
for (int i = 0; i < sha_main.Length; i++)
{
sb.Append((char)(sha_main[i] ^ key[i % key.Length]));
} }
return sb.ToString(); return sb.ToString();
} }
} }
} }

View File

@ -145,7 +145,6 @@ namespace Zerolauncher
private void Button_Click_3(object sender, RoutedEventArgs e) private void Button_Click_3(object sender, RoutedEventArgs e)
{ {
WebApiManager.StopListener();
Close(); Close();
} }

82
Manager/CloundMananger.cs Normal file
View File

@ -0,0 +1,82 @@
using System.Net.Http;
using System.Net;
using Zerolauncher.Defender;
using Zerolauncher.util;
namespace Zerolauncher.Manager
{
class StaticUrl
{
public const string QMessageMain = "https://sharechain.qq.com/";
public const string MasterMessage = "54aeb77c47b967d22c2c1396d00d91f0";
public const string SummerMessage = "037846c482eddc948612b0d0f8ed98d5";
public const string LoveMessage = "";
}
class UpDateData
{
public static bool state = false;
public static string version = "";
public static string tis = "";
public static string mini_packet_url = "";
public static string full_packet_url = "";
}
class CloundMananger
{
public static async Task TakeQMessage()
{
var client = new HttpClient();
client.DefaultRequestVersion = HttpVersion.Version20;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (iPad; U; CPU OS 6_0 like Mac OS X; zh-CN; iPad2)");
HttpResponseMessage response;
try
{
client.Timeout = TimeSpan.FromMinutes(3);
response = await client.GetAsync($"{StaticUrl.QMessageMain}{StaticUrl.MasterMessage}");
}
catch (Exception _ex)
{
CacheSha.errorCode = 1;
return;
}
var responseString = await response.Content.ReadAsStringAsync();
if(!FormatMessage(responseString))
{
CacheSha.errorCode = 2;
}
}
static bool FormatMessage(string message)
{
message = message.Split("<div class=\"note-content\">")[1].Split("</article>")[0].Replace("</div>", "").Replace("\n", "").Replace("\t", "").Replace("\r", "").Replace("'", "");
var arr = message.Split("<div>");
if (arr.Length >= 7 && FormatSha(arr[6], false) && FormatSha(arr[5], true))
{
UpDateData.version = arr[1];
UpDateData.tis = arr[2];
UpDateData.mini_packet_url = arr[3];
UpDateData.full_packet_url = arr[4];
UpDateData.state = true;
return true;
}
return false;
}
static bool FormatSha(string sha0, bool e)
{
if (sha0.Length < 90) return false;
int count;
var sha = SpaceEncoder.Decode(sha0[..86], out count);
if (sha == null)
{
//Console.WriteLine($"faile: {count}");
return false;
}
if (e) CacheSha.PutE(sha);
else CacheSha.PutM(sha);
return true;
}
}
}

View File

@ -20,7 +20,7 @@ namespace Zerolauncher.Manager
else else
{ {
dataStream = JsonConvert.DeserializeObject<Data>( dataStream = JsonConvert.DeserializeObject<Data>(
"{\"teamIndex\":0,\"Groups\":[{\"Name\":\"队伍1\", \"Accounts\": [{\"providerId\":0,\"userName\":\"test\",\"userPWD\":\"test\",\"nickName\":\"测试账号\",\"serverId\":\"1\"}]}]}"); "{\"teamIndex\":0,\"Groups\":[{\"Name\":\"队伍1\", \"Accounts\": [{\"providerId\":0,\"userName\":\"test\",\"userPWD\":\"test\",\"nickName\":\"测试账号\",\"serverId\":\"1\"}]}], \"engine_cache_ver\": 0}");
} }
} }
@ -85,5 +85,6 @@ namespace Zerolauncher.Manager
{ {
public int teamIndex; public int teamIndex;
public List<Group> Groups; public List<Group> Groups;
public int engine_cache_ver;
} }
} }

View File

@ -19,10 +19,11 @@ namespace Zerolauncher.Manager
public static bool CreateGame(Account account) public static bool CreateGame(Account account)
{ {
var key = AccToKey(account); var key = AccToKey(account);
if (mGame.ContainsKey(key)) { return false; } if (mGame.ContainsKey(key)) { return false; }
if (EngineCacheSha.errorCode != 0) { if (CacheSha.errorCode != 0) {
switch (EngineCacheSha.errorCode) switch (CacheSha.errorCode)
{ {
case 1: case 1:
MessageBox.Show("发生网络错误==EMS。\n 请检查网络", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error); MessageBox.Show("发生网络错误==EMS。\n 请检查网络", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error);
@ -118,23 +119,36 @@ namespace Zerolauncher.Manager
public int mHandle; public int mHandle;
public Account account; public Account? account;
string gameMode;
public SingleGame(Account acc) public SingleGame(Account? acc, string mod = StaticHandleA.GameMode)
{ {
restartUrl = null; restartUrl = null;
this.account = acc; account = acc;
gameMode = mod;
mHandle = 0; mHandle = 0;
process = EngineShell.CheckEngineSafe(); process = EngineShell.CheckEngineSafe(gameMode);
process.OutputDataReceived += Handle; if (gameMode != StaticHandleA.UpdateMode)
process.Exited += Process_Exited; {
process.OutputDataReceived += Handle;
process.Exited += Process_Exited;
}
process.Start(); process.Start();
process.BeginOutputReadLine(); // 开始异步读取 if (gameMode != StaticHandleA.UpdateMode)
{
process.BeginOutputReadLine(); // 开始异步读取
if (gameMode == StaticHandleA.Version)
{
process.WaitForExit();
}
}
} }
private void CreateProcess() private void CreateProcess()
{ {
process = EngineShell.CheckEngineSafe(); process = EngineShell.CheckEngineSafe(gameMode);
process.OutputDataReceived += Handle; process.OutputDataReceived += Handle;
process.Exited += Process_Exited; process.Exited += Process_Exited;
process.Start(); process.Start();
@ -143,12 +157,13 @@ namespace Zerolauncher.Manager
private void Process_Exited(object? sender, EventArgs e) private void Process_Exited(object? sender, EventArgs e)
{ {
Trace.WriteLine( //Trace.WriteLine(
$"Exit time : {process.ExitTime}\n" + // $"Exit time : {process.ExitTime}\n" +
$"Exit code : {process.ExitCode}\n" + // $"Exit code : {process.ExitCode}\n" +
$"Elapsed time : {Math.Round((process.ExitTime - process.StartTime).TotalMilliseconds)}"); // $"Elapsed time : {Math.Round((process.ExitTime - process.StartTime).TotalMilliseconds)}");
Trace.WriteLine($"进程已退出:{account.nickName}"); //Trace.WriteLine($"进程已退出:{account.nickName}");
if ( restartUrl == null ) if (gameMode != StaticHandleA.GameMode) return;
if ( restartUrl == null)
{ {
EngineManager.OnGameExit(account); EngineManager.OnGameExit(account);
return; return;
@ -165,7 +180,11 @@ namespace Zerolauncher.Manager
if(restartUrl == null) if(restartUrl == null)
{ {
Send($"{StaticHandleS.ShowWindow} {ServicesStaticInfo.ServicesName[account.providerId]}-{account.nickName}"); Send($"{StaticHandleS.ShowWindow} {ServicesStaticInfo.ServicesName[account.providerId]}-{account.nickName}");
_ = LoginManager.DoLogin(this); Task.Run(async delegate
{
if (lines[1] == "True") await Task.Delay(5000);
_ =LoginManager.DoLogin(this);
});
} }
else else
{ {
@ -181,6 +200,9 @@ namespace Zerolauncher.Manager
restartUrl = lines[1]; restartUrl = lines[1];
Send(StaticHandleS.CloseGame); Send(StaticHandleS.CloseGame);
break; break;
case StaticHandleC.Version:
mHandle = int.Parse(lines[1]);
break;
} }
} }
@ -204,31 +226,33 @@ namespace Zerolauncher.Manager
{ {
static bool is_check = false; static bool is_check = false;
const string engine_file = @"ZeroEngine.exe"; const string engine_file = @"ZeroEngine.exe";
public static Process CheckEngineSafe() public static Process CheckEngineSafe(string mod)
{ {
if (!is_check && EngineManager.CheckEmpy()) bool is_first_luancher = EngineManager.CheckEmpy();
{ //if (!is_check && is_first_luancher)
string? now_bit; //{
using (SHA256 sha256 = SHA256.Create()) // string? now_bit;
{ // using (SHA256 sha256 = SHA256.Create())
using (FileStream fileStream = File.OpenRead(engine_file)) // {
{ // using (FileStream fileStream = File.OpenRead(engine_file))
byte[] hashBytes = sha256.ComputeHash(fileStream); // {
now_bit = BitConverter.ToString(hashBytes).Replace("-", string.Empty); // byte[] hashBytes = sha256.ComputeHash(fileStream);
} // now_bit = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
} // }
if (EngineCacheSha.Get() != now_bit) // }
{ // if (EngineCacheSha.Get() != now_bit)
throw new FileReadException("无法读取文件内容"); // {
} // throw new FileReadException("无法读取文件内容");
} // }
is_check = true; // is_check = true;
//}
var process = new Process var process = new Process
{ {
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
{ {
FileName = engine_file, FileName = engine_file,
Arguments = StaticHandleA.GameMode, Arguments = $"{mod} {is_first_luancher}",
UseShellExecute = false, UseShellExecute = false,
CreateNoWindow = true, CreateNoWindow = true,
RedirectStandardInput = true, RedirectStandardInput = true,

View File

@ -57,7 +57,7 @@ namespace Zerolauncher.Manager
{ {
var client = new HttpClient(); var client = new HttpClient();
string? need_web = null; string? need_web = null;
client.Timeout = TimeSpan.FromSeconds(10); client.Timeout = TimeSpan.FromSeconds(3);
switch (game.account.providerId) switch (game.account.providerId)
{ {
case 0: case 0:
@ -122,7 +122,16 @@ namespace Zerolauncher.Manager
break; break;
} }
responseString = responseString.Split("name=\"game_box\"")[1].Split("src=\"")[1].Split("\"")[0]; responseString = responseString.Split("name=\"game_box\"")[1].Split("src=\"")[1].Split("\"")[0];
response = await client.PostAsync(responseString, null); try
{
response = await client.PostAsync(responseString, null);
}
catch (Exception ex)
{
game.Send($"{StaticHandleS.HintText} 网络发生错误,类型:{ex.GetType().Name.Replace(" ", "_")},消息:{ex.Message.Replace(" ", "_")}");
need_web = $"http://web.4399.com/stat/togame.php?target=ddt&server_id=S{game.account.serverId}";
break;
}
responseString = await response.Content.ReadAsStringAsync(); responseString = await response.Content.ReadAsStringAsync();
responseString = "http://" + response.RequestMessage.RequestUri.ToString().Split("/")[2] + "/" + responseString.Split("movie\" value='")[1].Split("'")[0]; responseString = "http://" + response.RequestMessage.RequestUri.ToString().Split("/")[2] + "/" + responseString.Split("movie\" value='")[1].Split("'")[0];
Trace.WriteLine(responseString); Trace.WriteLine(responseString);

View File

@ -1,73 +1,62 @@
using System.IO; using System.Diagnostics;
using System.IO;
using System.Net; using System.Net;
using System.Net.Http; using System.Security.Cryptography;
using Zerolauncher.Defender; using Zerolauncher.Defender;
namespace Zerolauncher.Manager namespace Zerolauncher.Manager
{ {
class DownloadTask
{
public static bool state = false;
public static string url = "";
}
class UpDateManager class UpDateManager
{ {
public static bool isCheeking = false;
public static async Task TakeQMessage() public static void DoCheckUpdate(bool checkMain=true, bool needEngine = false)
{ {
var client = new HttpClient(); if (isCheeking) return;
client.DefaultRequestVersion = HttpVersion.Version20; isCheeking=true;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower; bool needMian= false;
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (iPad; U; CPU OS 6_0 like Mac OS X; zh-CN; iPad2)"); if(checkMain)
HttpResponseMessage response;
try
{ {
client.Timeout = TimeSpan.FromMinutes(3); string filePath = Process.GetCurrentProcess().MainModule.FileName;
response = await client.GetAsync("https://sharechain.qq.com/037846c482eddc948612b0d0f8ed98d5"); // 初夏 string? now_bit;
}catch (Exception _ex) using (SHA256 sha256 = SHA256.Create())
{
EngineCacheSha.errorCode = 1;
return;
}
var responseString = await response.Content.ReadAsStringAsync();
responseString = responseString.Split("<div class=\"note-content\">")[1].Split("</article>")[0].Replace("</div>", "").Replace("\n", "").Replace("\t", "").Replace("\r", "").Replace("'", "");
var arr = responseString.Split("<div>").Last();
if (arr.Length < 90)
{
EngineCacheSha.errorCode = 2;
return;
}
int count;
var sha = SpaceEncoder.Decode(arr[..86], out count);
if (sha == null)
{
//Console.WriteLine($"faile: {count}");
EngineCacheSha.errorCode = 2;
return;
}
EngineCacheSha.Put(sha);
}
public async Task GetTask()
{
var client = new HttpClient();
client.DefaultRequestVersion = HttpVersion.Version20;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (iPad; U; CPU OS 6_0 like Mac OS X; zh-CN; iPad2)");
var response = await client.GetAsync("https://sharechain.qq.com/13111bbd6ffbffa3057878431bef103e");
var responseString = await response.Content.ReadAsStringAsync();
if (responseString.Contains("<div class=\"note-content\">"))
{
responseString = responseString.Split("<div class=\"note-content\">")[1].Split("</article>")[0].Replace("</div>", "").Replace("\n", "").Replace(" ", "").Replace("\t", "").Replace("\r", "").Replace("'", "");
Console.WriteLine(responseString.Replace("<div>", "\n"));
var arr = responseString.Split("<div>");
int main_version, engine_version, sa_version;
if (int.TryParse(arr[0], out main_version) && int.TryParse(arr[1], out engine_version))
{ {
using (FileStream fileStream = File.OpenRead(filePath))
{
byte[] hashBytes = sha256.ComputeHash(fileStream);
now_bit = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
}
} }
needMian = now_bit == CacheSha.GetM() && now_bit != null;
} }
// todo open faile update dialog if(!needEngine)
{
string? now_bit;
using (SHA256 sha256 = SHA256.Create())
{
using (FileStream fileStream = File.OpenRead(@"ZeroEngine.exe"))
{
byte[] hashBytes = sha256.ComputeHash(fileStream);
now_bit = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
}
}
needEngine = now_bit == CacheSha.GetE() && now_bit != null;
}
if(needEngine && needMian) { isCheeking = false; return; }
DownloadTask.state = true;
if(needEngine == needMian) DownloadTask.url = UpDateData.full_packet_url;
else DownloadTask.url = UpDateData.mini_packet_url;
isCheeking = false;
} }
public static void DownLoad(string Url, string FileName) public static void DownLoad(string Url, string FileName, bool has)
{ {
bool Value = false; bool Value = false;
WebResponse response = null; WebResponse response = null;

View File

@ -4,6 +4,5 @@
{ {
public static string[] ServicesName = ["4399大区", "7k7k大区", "第七大道"]; public static string[] ServicesName = ["4399大区", "7k7k大区", "第七大道"];
public static string[] ServicesShortName = ["43", "7k", "7d"]; public static string[] ServicesShortName = ["43", "7k", "7d"];
} }
} }

View File

@ -17,11 +17,13 @@
public const string BrowserDone = "0b"; public const string BrowserDone = "0b";
public const string StartGame = "0c"; public const string StartGame = "0c";
public const string GameDone = "0d"; public const string GameDone = "0d";
public const string Version = "0e";
} }
class StaticHandleA class StaticHandleA
{ {
public const string GameMode = "0a"; public const string GameMode = "0a";
public const string UpdateMode = "0b"; public const string UpdateMode = "0b";
public const string Version = "0c";
} }
} }

View File

@ -37,6 +37,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Downloader" Version="3.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>

View File

@ -97,12 +97,14 @@ namespace Zerolauncher.dialog
baseDialog.Close(); baseDialog.Close();
} }
} }
} }
class UpdateDialog class UpdateDialog
{ {
static BaseDialog? baseDialog; static BaseDialog? baseDialog;
static DownloadControl? editControl; public static DownloadControl1? editControl;
public static bool ui_enale = false;
public static void CreateDailog(Window p) public static void CreateDailog(Window p)
{ {
@ -110,9 +112,11 @@ namespace Zerolauncher.dialog
{ {
return; return;
} }
editControl = new DownloadControl(); editControl = new DownloadControl1();
baseDialog = new BaseDialog(editControl); baseDialog = new BaseDialog(editControl);
ui_enale = true;
baseDialog.ShowDialog(); baseDialog.ShowDialog();
ui_enale = false;
baseDialog = null; baseDialog = null;
editControl = null; editControl = null;
} }

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Zerolauncher.dialog.DownloadControl" <UserControl x:Class="Zerolauncher.dialog.DownloadControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -7,8 +7,8 @@
d:DesignHeight="169" d:DesignWidth="290"> d:DesignHeight="169" d:DesignWidth="290">
<StackPanel Margin="5"> <StackPanel Margin="5">
<Image Source="/res/39376.jpg" Height="100"/> <Image Source="/res/39376.jpg" Height="100"/>
<TextBlock Text="零蛋正在更新装备..." Foreground="PaleGoldenrod" HorizontalAlignment="Center" Margin="5"/> <TextBlock Name="text1" Text="零蛋正在更新装备..." Foreground="PaleGoldenrod" HorizontalAlignment="Center" Margin="5"/>
<ProgressBar Name="pbDown" HorizontalAlignment="Center" Height="10" Width="200" Value="50"/> <ProgressBar Name="pbDown" HorizontalAlignment="Center" Height="10" Width="200" Value="50"/>
<Label Name="label1" Content="0 kb/s--50%" Foreground="BurlyWood" HorizontalAlignment="Center"/> <TextBlock Name="text2" Text="0 kb/s" Foreground="BurlyWood" HorizontalAlignment="Center"/>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@ -1,5 +1,5 @@
using System.IO; using Downloader;
using System.Net.Http; using System.ComponentModel;
using System.Windows.Controls; using System.Windows.Controls;
namespace Zerolauncher.dialog namespace Zerolauncher.dialog
@ -7,97 +7,60 @@ namespace Zerolauncher.dialog
/// <summary> /// <summary>
/// DownloadControl.xaml 的交互逻辑 /// DownloadControl.xaml 的交互逻辑
/// </summary> /// </summary>
public partial class DownloadControl : UserControl public partial class DownloadControl1 : UserControl
{ {
const string cache_dir = "./.cache/auto.cache"; const string cache_dir = "./.cache/auto.cache";
static bool is_strat = false;
public DownloadControl() public DownloadControl1()
{ {
InitializeComponent(); InitializeComponent();
if (!is_strat) text2.Text = "正在连接服务器";
} }
private void OnError(Exception ex)
{
// UnityEngine.Debug.Log("捕获异常 >>> " + ex);
}
public async Task Download(string fileUrl) public static void DoDownload(string fileUrl)
{ {
using (HttpClient client = new HttpClient()) var downloadOpt = new DownloadConfiguration()
{ {
// 获取文件大小 ChunkCount = 8, // file parts to download, the default value is 1
HttpResponseMessage responseHead = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, fileUrl)); ParallelDownload = true // download parts of the file as parallel or not. The default value is false
long? contentLength = responseHead.Content.Headers.ContentLength; };
Console.WriteLine($"文件大小:{contentLength} 字节"); var downloader = new DownloadService(downloadOpt);
// Provide `FileName` and `TotalBytesToReceive` at the start of each download
downloader.DownloadStarted += OnDownloadStarted;
// 计算块大小 // Provide any information about download progress,
int blockSize = 1024 * 1024; // 1MB // like progress percentage of sum of chunks, total speed,
int blockCount = (int)Math.Ceiling((double)contentLength / blockSize); // average speed, total received bytes and received bytes array
// to live streaming.
downloader.DownloadProgressChanged += OnDownloadProgressChanged;
// 创建SemaphoreSlim以限制同时进行的下载任务的数量 // Download completed event that can include errors or
SemaphoreSlim semaphore = new SemaphoreSlim(4); // 最多允许4个并发下载任务 // canceled or download completed successfully.
downloader.DownloadFileCompleted += OnDownloadFileCompleted;
}
using (FileStream fileStream = new FileStream(cache_dir, FileMode.Create, FileAccess.Write, FileShare.None, blockSize, true)) private static void OnDownloadFileCompleted(object? sender, AsyncCompletedEventArgs e)
{ {
// 创建任务列表
Task[] tasks = new Task[blockCount];
for (int i = 0; i < blockCount; i++) }
{
int blockNumber = i;
tasks[i] = Task.Run(async () =>
{
await semaphore.WaitAsync(); // 等待获取许可
try private static void OnDownloadProgressChanged(object? sender, DownloadProgressChangedEventArgs e)
{ {
// 计算当前块的范围 if (UpdateDialog.ui_enale)
var start = blockNumber * blockSize; {
var end = (blockNumber == blockCount - 1) ? contentLength - 1 : start + blockSize - 1; UpdateDialog.editControl.pbDown.Value = e.ProgressPercentage;
UpdateDialog.editControl.text2.Text = $"{e.AverageBytesPerSecondSpeed}";
// 设置请求头,请求指定范围的数据
var request = new HttpRequestMessage { RequestUri = new Uri(fileUrl), Method = HttpMethod.Get };
request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(start, end);
// 下载当前块
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
byte[] buffer = await response.Content.ReadAsByteArrayAsync();
await fileStream.WriteAsync(buffer, 0, buffer.Length);
}
// 显示下载进度
double percent = (double)(blockNumber + 1) / blockCount * 100;
Console.WriteLine($"已下载:{percent:F2}%");
}
finally
{
semaphore.Release(); // 释放许可
}
});
}
// 等待所有任务完成
await Task.WhenAll(tasks);
}
} }
throw new NotImplementedException();
Console.WriteLine("下载完成!");
} }
private void OnUpdate(long size, long count) private static void OnDownloadStarted(object? sender, DownloadStartedEventArgs e)
{
}
private void OnDone(byte[] data)
{
}
private void OnDestroy()
{ {
is_strat = true;
if (UpdateDialog.ui_enale) UpdateDialog.editControl.text1.Text = "零蛋正在更新装备...";
} }
} }

9
util/Download.cs Normal file
View File

@ -0,0 +1,9 @@

namespace Zerolauncher.util
{
class Download
{
}
}

162
util/MyEncrypt.cs Normal file
View File

@ -0,0 +1,162 @@
using System.Security.Cryptography;
using System.IO;
namespace Zerolauncher.util
{
// MyEncrypt.SHA_Encrypt("test.txt", "test1.txt", "123456"); //文件加密
// MyEncrypt.SHA_Dencrypt("test1.txt", "test2.txt", "123456"); //文件解密
public class MyEncrypt
{
private const ulong FC_TAG = 0xFC010203040506CF;
private const int BUFFER_SIZE = 128 * 1024;
//检验两个Byte数组是否相同
private static bool CheckByteArrays(byte[] b1, byte[] b2)
{
if (b1.Length == b2.Length)
{
for (int i = 0; i < b1.Length; ++i)
{
if (b1[i] != b2[i])
return false;
}
return true;
}
return false;
}
/// <param name="password">密码</param>
/// <param name="salt"></param>
/// <returns>加密对象</returns>
private static SymmetricAlgorithm CreateRijndael(string password, byte[] salt)
{
PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, salt, "SHA256", 1000);
SymmetricAlgorithm sma = Rijndael.Create();
sma.KeySize = 256;
sma.Key = pdb.GetBytes(32);
sma.Padding = PaddingMode.PKCS7;
return sma;
}
// 加密文件随机数生成
private static RandomNumberGenerator rand = new RNGCryptoServiceProvider();
// 生成指定长度的随机Byte数组
private static byte[] GenerateRandomBytes(int count)
{
byte[] bytes = new byte[count];
rand.GetBytes(bytes);
return bytes;
}
// 加密文件
public static void SHA_Encrypt(string inFile, string outFile, string password)
{
using (FileStream fin = File.OpenRead(inFile),
fout = File.OpenWrite(outFile))
{
long lSize = fin.Length; // 输入文件长度
int size = (int)lSize;
byte[] bytes = new byte[BUFFER_SIZE]; // 缓存
int read = -1; // 输入文件读取数量
int value = 0;
// 获取IV和salt
byte[] IV = GenerateRandomBytes(16);
byte[] salt = GenerateRandomBytes(16);
// 创建加密对象
SymmetricAlgorithm sma = CreateRijndael(password, salt);
sma.IV = IV;
// 在输出文件开始部分写入IV和salt
fout.Write(IV, 0, IV.Length);
fout.Write(salt, 0, salt.Length);
// 创建散列加密
HashAlgorithm hasher = SHA256.Create();
using (CryptoStream cout = new CryptoStream(fout, sma.CreateEncryptor(), CryptoStreamMode.Write),
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
BinaryWriter bw = new BinaryWriter(cout);
bw.Write(lSize);
bw.Write(FC_TAG);
// 读写字节块到加密流缓冲区
while ((read = fin.Read(bytes, 0, bytes.Length)) != 0)
{
cout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
}
// 关闭加密流
chash.Flush();
chash.Close();
// 读取散列
byte[] hash = hasher.Hash;
// 输入文件写入散列
cout.Write(hash, 0, hash.Length);
// 关闭文件流
cout.Flush();
cout.Close();
}
}
}
// 解密文件
public static void SHA_Dencrypt(string inFile, string outFile, string password)
{
// 创建打开文件流
using (FileStream fin = File.OpenRead(inFile),
fout = File.OpenWrite(outFile))
{
int size = (int)fin.Length;
byte[] bytes = new byte[BUFFER_SIZE];
int read = -1;
int value = 0;
int outValue = 0;
byte[] IV = new byte[16];
fin.Read(IV, 0, 16);
byte[] salt = new byte[16];
fin.Read(salt, 0, 16);
SymmetricAlgorithm sma = CreateRijndael(password, salt);
sma.IV = IV;
value = 32;
long lSize = -1;
// 创建散列对象, 校验文件
HashAlgorithm hasher = SHA256.Create();
using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read),
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
// 读取文件长度
BinaryReader br = new BinaryReader(cin);
lSize = br.ReadInt64();
ulong tag = br.ReadUInt64();
if (FC_TAG != tag)
throw new Exception("文件被破坏");
long numReads = lSize / BUFFER_SIZE;
long slack = (long)lSize % BUFFER_SIZE;
for (int i = 0; i < numReads; ++i)
{
read = cin.Read(bytes, 0, bytes.Length);
fout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
outValue += read;
}
if (slack > 0)
{
read = cin.Read(bytes, 0, (int)slack);
fout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
outValue += read;
}
chash.Flush();
chash.Close();
fout.Flush();
fout.Close();
byte[] curHash = hasher.Hash;
// 获取比较和旧的散列对象
byte[] oldHash = new byte[hasher.HashSize / 8];
read = cin.Read(oldHash, 0, oldHash.Length);
if ((oldHash.Length != read) || (!CheckByteArrays(oldHash, curHash)))
throw new Exception("文件被破坏");
}
if (outValue != lSize)
throw new Exception("文件大小不匹配");
}
}
}
}

View File

@ -1,6 +1,6 @@
using System.Text; using System.Text;
namespace Zerolauncher.Manager namespace Zerolauncher.util
{ {
class SpaceEncoder class SpaceEncoder
{ {