using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Cache; using System.Text; using System.Windows.Forms; using VictusLauncher.Properties; using Ionic.Zip; using Extentions; namespace VictusLauncher { public class VersionInfo { public VersionInfo(Int32 version, String executableHash) { Version = version; ExecutableHash = executableHash; } public VersionInfo() { Version = 100; ExecutableHash = "0"; } public Int32 Version; public String ExecutableHash; } public class FileHash { public String FullPath { get { return String.Format("{0}{1}", Program.BaseDirectory, FileName); } } public FileHash(String fileName, String hash) { FileName = fileName; Hash = hash; } public String FileName; public String Hash; } public static class Patch { public static WebClientEx Web; public static VersionInfo Local; public static VersionInfo Server; static Patch() { Web = new WebClientEx { CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore), Proxy = new WebProxy(), Encoding = Encoding.Default, }; Web.DownloadProgressChanged += OnWebDownloadProgressChanged; Local = GetLocalVersion(); Server = GetServerVersion(); } public static void OnWebDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { Program.MainForm.FileProgress.Max = e.TotalBytesToReceive; Program.MainForm.FileProgress.Value = e.BytesReceived; Program.MainForm.FileProgress.Refresh(); } public static VersionInfo GetLocalVersion() { VersionInfo localVersion = new VersionInfo(); FileInfo eFileInfo = new FileInfo(String.Format("{0}{1}", Program.BaseDirectory, "Victus.exe")); if (eFileInfo.Exists) { using (FileStream eFile = File.Open(eFileInfo.FullName, FileMode.Open)) { eFile.Seek(0x4E, SeekOrigin.Begin); Byte[] buffer = new byte[4]; eFile.Read(buffer, 0, 4); localVersion.Version = BitConverter.ToInt32(buffer, 0); } localVersion.ExecutableHash = eFileInfo.GetMD5Hash(); } return localVersion; } public static VersionInfo GetServerVersion() { try { Uri fUri = new Uri(String.Format(Resources.URL_Patch, "version.dat")); String result = Web.DownloadDataAsyncTimeout(fUri).Decrypt(); String[] buffer = result.Split(new [] { Environment.NewLine }, StringSplitOptions.None); return new VersionInfo(Convert.ToInt32(buffer[0]), buffer[1]); } catch (Exception) { return null; } } public static List GetHashData() { try { List fHashList = new List(); Uri fUri = new Uri(String.Format(Resources.URL_Patch, "hash.dat")); String result = Web.DownloadDataAsyncTimeout(fUri).Decrypt(); String[] buffer = result.Split(new[] { Environment.NewLine }, StringSplitOptions.None); for (int i = 0; i < buffer.Length; i+=2) { FileHash fHash = new FileHash(buffer[i], buffer[i+1]); fHashList.Add(fHash); } return fHashList; } catch (Exception) { return null; } } public static Boolean PatchFile(String fileName) { try { FileInfo pFile = new FileInfo(String.Format("{0}{1}", Program.BaseDirectory, fileName)); Uri fUri = new Uri(String.Format(Resources.URL_Patch, fileName)); if (pFile.Directory != null && !pFile.Directory.Exists) { pFile.Directory.Create(); } Web.DownloadFileAsyncTimeout(fUri, pFile.FullName); } catch (Exception) { return false; } return true; } public static Boolean PatchZip(Int32 version) { try { FileInfo pFile = new FileInfo(String.Format("{0}\\{1}.zip", Path.GetTempPath(), version)); Uri fUri = new Uri(String.Format(Resources.URL_Patch_Zip, version)); if (pFile.Directory != null && !pFile.Directory.Exists) { pFile.Directory.Create(); } Web.DownloadFileAsyncTimeout(fUri, pFile.FullName); using (ZipFile zFile = new ZipFile(pFile.FullName)) { zFile.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; zFile.Encryption = EncryptionAlgorithm.None; zFile.ExtractAll(Program.BaseDirectory); } File.Delete(pFile.FullName); } catch (Exception) { return false; } return true; } public static Boolean PatchHashes() { try { List fHashList = GetHashData(); foreach (FileHash fileHash in fHashList) { FileInfo hFileInfo = new FileInfo(fileHash.FullPath); if (!hFileInfo.Exists || hFileInfo.GetMD5Hash() != fileHash.Hash) { if (!PatchFile(fileHash.FileName)) { return false; } } Application.DoEvents(); } if (GetLocalVersion().ExecutableHash != Server.ExecutableHash) { if (!PatchFile(".\\Victus.exe")) { return false; } } } catch (Exception) { return false; } return true; } public static Boolean Start() { if (Server != null) { Program.MainForm.FileProgress.Visible = true; Program.MainForm.ProgressBar.Max = (Server.Version - Local.Version) + 1; while (Local.Version < Server.Version) { if (PatchZip(Local.Version+1)) { Program.MainForm.ProgressBar.DoStep(); Local = GetLocalVersion(); } else break; } if (Local.Version < Server.Version || !PatchHashes()) { MessageBox.Show(Resources.MessageBox_Message_Patch_Error, Resources.MessageBox_Title_Patch_Error, MessageBoxButtons.OK, MessageBoxIcon.Asterisk); Program.MainForm.ProgressBar.Reset(); return false; } Program.MainForm.ProgressBar.DoFullStep(); Program.MainForm.FileProgress.Visible = false; Program.MainForm.StartButton.Enabled = true; return true; } return false; } } }