WingCloudHexExplorer/HexExplorer/UpdateLib.cs

520 lines
20 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace HexExplorer
{
/// <summary>
/// 由于本人网络知识欠缺,不想自费弄个服务器(如果该软件捐助达到一定程度我会考虑),
/// 也不会搭网站,目前也没找到合适快速的固定下载链接方式,
/// 看到蓝奏云比较合适,它的验证机制还是挺简单的,就是挺麻烦的,可以过验证,故采用此方式。
/// 本方式不能保证一定会有效,得看蓝奏云运营商了
///
///【虽然代码500来行但这个类本人花费了大量的时间进行实现请不得用于除学习和本软件更新之外的用途使用】
/// </summary>
class UpdateLib
{
private static UpdateLib updateLib;
public static UpdateLib Instance
{
get
{
if (updateLib==null)
{
updateLib = new UpdateLib();
}
return updateLib;
}
}
private readonly string uri = "https://wws.lanzoui.com/b020fwpwh";
private const string useragent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131";
private const string accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9";
private const string sec_ch_ua = "\"Chromium\";v=\"92\", \" Not A; Brand\";v=\"99\"";
private const string cookie = "codelen=1; pc_ad1=1";
private const string AcceptLanguage = "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6";
private const string lanzou_header = "https://wws.lanzoui.com/";
private const string AcceptEncoding = "gzip, deflate, br";
public const int DefaultBufferSize = 1024;
public readonly RequestCachePolicy cachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
#pragma warning disable IDE1006, CS0649 //禁用命名样式提示和未使用为null警告
[DataContract]
public class DownLoadLinkData
{
[DataMember]
public int zt;
[DataMember]
public string dom;
[DataMember]
public string url;
[DataMember]
public int inf;
}
[DataContract]
public class ResultJson
{
[DataMember]
public int tz { get; set; }
[DataMember]
public string info { get; set; }
[DataMember]
public ResultCotent[] text { get; set; }
}
[DataContract]
public struct ResultCotent
{
[DataMember]
public string icon { get; set; }
[DataMember]
public int t { get; set; }
[DataMember]
public string id { get; set; }
[DataMember]
public string name_all { get; set; }
[DataMember]
public string size { get; set; }
[DataMember]
public string time { get; set; }
[DataMember]
public string duan { get; set; }
[DataMember]
public int p_ico { get; set; }
}
public class UpdateInfo
{
public string url;
public float ver;
public string size;
}
#pragma warning restore IDE1006, CS0649
private UpdateLib()
{
}
private string RegexMatch(string pattern, string input, out int index, int start = 0)
{
Regex regex = new Regex(pattern);
var match = regex.Match(input, start);
if (match.Success)
{
index = match.Index;
return match.Value;
}
index = -1;
return null;
}
public HttpWebRequest HttpGet(string url, RequestCachePolicy cachePolicy, string refer = null)
{
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "GET";
request.UseDefaultCredentials = true;
request.UserAgent = useragent;
request.CachePolicy = cachePolicy;
request.Timeout = 5000;
request.Accept = accept;
request.Headers.Add(HttpRequestHeader.Authorization, "wws.lanzoui.com");
request.Headers.Add(HttpRequestHeader.Cookie, "down_ip=1");
request.Headers.Add(HttpRequestHeader.AcceptEncoding, AcceptEncoding);
request.Headers.Add(HttpRequestHeader.AcceptLanguage, AcceptLanguage);
request.Headers.Add(HttpRequestHeader.CacheControl, "max-age=0");
request.Headers.Add("dnt", "1");
request.Headers.Add("sec-ch-ua", sec_ch_ua);
request.Headers.Add("sec-ch-ua-mobile", "?0");
request.Headers.Add("sec-fetch-dest", "document");
request.Headers.Add("sec-fetch-mode", "navigate");
request.Headers.Add("sec-fetch-site", "orign");
request.Headers.Add("sec-fetch-user", "?1");
request.Headers.Add("sec-gpc", "1");
request.Headers.Add("upgrade-insecure-requests", "1");
if (refer != null)
request.Referer = refer;
return request;
}
public Stream HttpPost(string url, RequestCachePolicy cachePolicy, string submit, string refer = null)
{
byte[] buffer = Encoding.ASCII.GetBytes(submit);
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "POST";
request.CachePolicy = cachePolicy;
request.Accept = "application/json, text/javascript, */*";
request.Headers.Add(HttpRequestHeader.AcceptEncoding, AcceptEncoding);
request.Headers.Add(HttpRequestHeader.AcceptLanguage, AcceptLanguage);
request.ContentLength = buffer.Length;
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add(HttpRequestHeader.Cookie, cookie);
request.Headers.Add("dnt", "1");
request.Headers.Add("origin", "https://wws.lanzoui.com");
if (refer != null)
request.Referer = refer;
request.Headers.Add("sec-ch-ua", sec_ch_ua);
request.Headers.Add("sec-ch-ua-mobile", "?0");
request.Headers.Add("sec-fetch-dest", "empty");
request.Headers.Add("sec-fetch-mode", "cors");
request.Headers.Add("sec-fetch-site", "same-origin");
request.Headers.Add("sec-gpc", "1");
request.UserAgent = useragent;
request.Headers.Add("x-requested-with", "XMLHttpRequest");
try
{
using (var rstream = request.GetRequestStream())
{
rstream.Write(buffer, 0, buffer.Length);
}
return request.GetResponse().GetResponseStream();
}
catch
{
return null;
}
}
public string GetResponseCotent(HttpWebRequest request)
{
try
{
using (var res = request.GetResponse())
{
using (var stream = res.GetResponseStream())
{
StreamReader streamReader;
using (streamReader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress),
Encoding.UTF8, false, DefaultBufferSize, false))
{
return streamReader.ReadToEnd();
}
}
}
}
catch
{
return null;
}
}
private void InfoNewest(Action<string> Log)
{
Log?.Invoke("当前为最新版本!!!");
MessageBox.Show("您已经拥有最新版本的HexExplorer", Program.AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
public UpdateInfo GetUpdateInfo(Action<string> Log = null)
{
string content = null;
ResultJson result = null;
string tmp = null;
Stream stream = null;
Log?.Invoke("正在初始化请求……");
try
{
//第一步访问页面获取动态的t和k的值
HttpWebRequest request = HttpGet(uri, cachePolicy);
Log?.Invoke("正在请求服务器……");
string t = null, k = null;
content = GetResponseCotent(request);
Log?.Invoke("开始解析服务器返回信息……");
tmp = RegexMatch(@"'t'\s?:\s?\w+", content, out _);
t = tmp.Substring(tmp.IndexOf(":") + 1);
tmp = RegexMatch(@"'k'\s?:\s?\w+", content, out _);
k = tmp.Substring(tmp.IndexOf(":") + 1);
string tv = null, kv = null;
if (t != null && k != null)
{
tmp = RegexMatch($@"var\s?{t}\s?=\s?'\w+'", content, out _);
tv = tmp.Substring(tmp.IndexOf("\'")).Trim('\'');
tmp = RegexMatch($@"var\s?{k}\s?=\s?'\w+'", content, out _);
kv = tmp.Substring(tmp.IndexOf("\'")).Trim('\'');
}
//第二步:校验结果,若成功获取目录信息
if (tv == null || kv == null)
{
throw new InvalidDataException("tv|kv");
}
Log?.Invoke("正在获取版本信息……");
using (stream = HttpPost("https://wws.lanzoui.com/filemoreajax.php", cachePolicy,
$"lx=2&fid=3868377&uid=1846046&pg=1&rep=0&t={tv}&k={kv}&up=1&ls=1&pwd=fw9s",
"https://wws.lanzoui.com/b020fwpwh"))
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(ResultJson));
result = jsonSerializer.ReadObject(stream) as ResultJson;
}
if (result == null)
{
throw new NullReferenceException("result");
}
if (result.tz == 1)
{
throw new InvalidDataException("result");
}
//第三步:若获取成功,解析正确的信息
/*
* 发行版更新命名规则Ver_[版本号].exe例子Ver_1.0.exe
* 但如果以后发布与发行可执行程序包不相关的东西,不会符合下面的判断条件
* 版本号必为float类型否则无效包因为需要判断该程序的版本为了简化操作
*/
Log?.Invoke("获取更新中……");
var items = result.text.Where(item =>
{
if (item.id != "-1" && item.t != 1)
{
Regex regex = new Regex(@"^Ver_(\d+\.\d+).exe$", RegexOptions.IgnoreCase);
var match = regex.Match(item.name_all);
return match.Success;
}
return false;
}).ToList();
if (items.Count == 0)
{
InfoNewest(Log);
return null;
}
float newestVer = 0;
string url = null;
string size = null;
foreach (var item in items)
{
string value = RegexMatch(@"\d+\.\d+", item.name_all, out _);
float v = float.Parse(value);
if (v > newestVer)
{
newestVer = v;
url = item.id;
size = item.size;
}
}
Log?.Invoke($"获取最新版本成功,版本号为{newestVer}");
if (newestVer == Program.Version)
{
InfoNewest(Log);
return null;
}
if (newestVer < Program.Version)
{
Log?.Invoke("当前版本号异常!!!");
MessageBox.Show("您的程序版本号异常,建议从官方进行下载!!!", Program.AppName,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return null;
}
return new UpdateInfo { url = url, ver = newestVer, size = size };
}
catch (Exception ex)
{
Log?.Invoke(ex.Message);
MessageBox.Show($"{ex.InnerException.Message}。故升级失败!", "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
public string GetUpdateURL(Action<string> Log = null)
{
string content = null;
string tmp = null;
Stream stream = null;
DownLoadLinkData linkData = null;
UpdateInfo updateInfo = GetUpdateInfo();
var url = updateInfo.url;
try
{
//第四步:访问下载界面
Log?.Invoke("正在请求更新……");
HttpWebRequest request = HttpGet(lanzou_header + url, cachePolicy, url);
using (var res = request.GetResponse())
{
using (stream = res.GetResponseStream())
{
StreamReader streamReader;
using (streamReader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress),
Encoding.UTF8, false, DefaultBufferSize, false))
{
content = streamReader.ReadToEnd();
RegexMatch(@"e\>\-\-\>", content, out int start);
content = RegexMatch(@"<iframe.+?>", content, out _, start);
tmp = RegexMatch("src=\".+?\"", content, out _);
content = url;
url = tmp.Substring(6).Trim('\"');
}
}
}
//第五步:获取下载链接
Log?.Invoke("正在获取下载链接……");
request = HttpGet(lanzou_header + url, cachePolicy, lanzou_header + content);
using (var res = request.GetResponse())
{
using (stream = res.GetResponseStream())
{
StreamReader streamReader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress),
Encoding.UTF8, false, DefaultBufferSize, false);
content = streamReader.ReadToEnd();
}
}
var tem = content;
content = RegexMatch(@"(\s)data\s?:\s?{.+}", content, out _);
string signs = null, sign = null;
tmp = RegexMatch(@"'signs'\s?:\s?\w+", content, out _);
signs = tmp.Substring(tmp.IndexOf(":") + 1).Trim();
tmp = RegexMatch(@"'sign'\s?:\s?\w+", content, out _);
sign = tmp.Substring(tmp.IndexOf(":") + 1).Trim();
string signsv = null, signv = null;
tmp = RegexMatch($@"var\s?{signs}\s?=\s?'\S+'", tem, out _);
signsv = tmp.Substring(tmp.IndexOf("\'")).Trim('\'');
tmp = RegexMatch($@"var\s?{sign}\s?=\s?'\S+'", tem, out _);
signv = tmp.Substring(tmp.IndexOf("\'")).Trim('\'');
tmp = $"action=downprocess&signs={signsv}&sign={signv}&ves=1&websign=2&websignkey=BSBU";
Log?.Invoke("获取下载链接成功,即将开始下载……");
using (stream = HttpPost("https://wws.lanzoui.com/ajaxm.php", cachePolicy, tmp, lanzou_header + url))
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(DownLoadLinkData));
linkData = jsonSerializer.ReadObject(stream) as DownLoadLinkData;
}
url = $"{linkData.dom}/file/{linkData.url}";
return url;
}
catch (Exception ex)
{
Log?.Invoke(ex.Message);
MessageBox.Show($"{ex.InnerException.Message}。故升级失败!", "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
public void UpdateProgramNewest(Action<string> Log = null, Action<long, long> UpdateProgressBarValue = null)
{
var dlink = GetUpdateURL();
if (dlink != null)
{
Directory.CreateDirectory(Program.AppUpDate);
HttpWebRequest request = WebRequest.CreateHttp(dlink);
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "GET";
request.UserAgent = useragent;
request.Headers.Add(HttpRequestHeader.AcceptLanguage, AcceptLanguage);
request.Headers.Add(HttpRequestHeader.AcceptEncoding, AcceptEncoding);
request.Accept = accept;
request.KeepAlive = true;
request.Host = "vip.d0.baidupan.com";
request.Headers.Add(HttpRequestHeader.Cookie, "down_ip=1");
request.Headers.Add("dnt", "1");
request.Headers.Add("sec-ch-ua", sec_ch_ua);
request.Headers.Add("sec-ch-ua-mobile", "?0");
request.Headers.Add("sec-fetch-dest", "document");
request.Headers.Add("sec-fetch-mode", "cors");
request.Headers.Add("sec-fetch-site", "cross-origin");
request.Headers.Add("sec-fetch-user", "?1");
request.Headers.Add("sec-gpc", "1");
request.Headers.Add("upgrade-insecure-requests", "1");
request.AllowAutoRedirect = true;
Log?.Invoke("开始下载中……");
using (var res = request.GetResponse())
{
var total = res.ContentLength;
using (var stream = res.GetResponseStream())
{
using (BinaryReader reader = new BinaryReader(stream))
{
using (var fs = File.Create(Program.AppUpDateBin))
{
byte[] buffer;
using (BinaryWriter writer = new BinaryWriter(fs))
{
while ((buffer = reader.ReadBytes(DefaultBufferSize)).Length > 0)
{
writer.Write(buffer);
UpdateProgressBarValue?.Invoke(fs.Length, total);
}
}
}
}
}
}
}
}
}
}