using System; using System.IO; using System.Security.Cryptography; using System.Text; using System.Threading; using UnityEngine; using XUtliPoolLib; namespace XUpdater { public sealed class XCaching : XSingleton { public string VersionServer { get { return this._version_server; } } public string HostUrl { get { return this._host_url; } } public string UpdatePath { get { return this._update_path; } } public XDownloader Downloader { get { return this._down_loader; } } private string _version_server = null; private string _host_url = null; internal static readonly string UPDATE_DIRECTORY = "/update/"; private string _update_path = null; private StringBuilder _log = new StringBuilder(); private XDownloader _down_loader = null; private MD5CryptoServiceProvider _md5Generator = null; private AsyncExtractRequest _aer = null; private AsyncWriteRequest _meta_awr = null; internal string GetLocalPath(XBundleData data) { return string.Format("{0}{1}.assetbundle", this._update_path, data.Name); } internal string GetLocalUrl(XBundleData data) { bool flag = XSingleton.singleton.RunTimePlatform == BuildTarget.Standalone; string arg; if (flag) { arg = "file:///"; } else { arg = "file://"; } string text = string.Format("{0}{1}{2}.assetbundle", arg, this._update_path, data.Name); XSingleton.singleton.AddLog("LocalURL: ", text, null, null, null, null, XDebugColor.XDebug_None); return text; } public string GetLoginServerAddress(string loginType) { IPlatform xplatform = XSingleton.singleton.XPlatform; return xplatform.GetHostWithHttpDns(xplatform.GetLoginServer(loginType)); } internal string GetDownloadUrl(XBundleData data) { return this.MakeToken(string.Format("{0}{1}/{2}.assetbundle", this.HostUrl, XSingleton.singleton.Platform, data.Name)); } internal string MakeToken(string url) { return string.Format("{0}?token={1}", url, DateTime.Now.Ticks); } public override bool Init() { IPlatform xplatform = XSingleton.singleton.XPlatform; this._version_server = xplatform.GetHostWithHttpDns(xplatform.GetVersionServer()); this._host_url = xplatform.GetHostUrl(); this._md5Generator = new MD5CryptoServiceProvider(); this._down_loader = XUpdater.XGameRoot.AddComponent(); this._update_path = Application.persistentDataPath + XCaching.UPDATE_DIRECTORY; return true; } internal bool EnableCache() { bool flag = !Directory.Exists(this._update_path); if (flag) { XSingleton.singleton.AddLog("Create new path " + this._update_path, null, null, null, null, null, XDebugColor.XDebug_None); try { Directory.CreateDirectory(this._update_path); return Directory.Exists(this._update_path); } catch (Exception ex) { XSingleton.singleton.AddErrorLog(string.Format("Error ", ex.Message), null, null, null, null, null); return false; } } XSingleton.singleton.AddLog(string.Format("Path {0} exists.", this._update_path), null, null, null, null, null, XDebugColor.XDebug_None); return true; } internal AsyncCachedRequest IsBundleCached(XBundleData bundle, uint size) { string fullpath = this.GetLocalPath(bundle); AsyncCachedRequest req = new AsyncCachedRequest(); bool flag = bundle.Size < size; if (flag) { new Thread((ThreadStart) delegate { bool flag2 = File.Exists(fullpath); if (flag2) { byte[] bundle2 = this.LoadFile(fullpath); string a = this.CalculateMD5(bundle2); req.Cached = (a == bundle.MD5); req.MaybeCached = true; } req.IsDone = true; }).Start(); } else { req.MaybeCached = File.Exists(fullpath); req.IsDone = true; } return req; } internal bool CleanCache() { string path = ((int)Application.platform == 8) ? ("/private" + this._update_path) : this._update_path; bool result; try { bool flag = Directory.Exists(path); if (flag) { DirectoryInfo directoryInfo = new DirectoryInfo(path); directoryInfo.Delete(true); bool flag2 = !Directory.Exists(path); bool flag3 = flag2; if (flag3) { result = this.EnableCache(); } else { result = false; } } else { result = true; } } catch (Exception ex) { XSingleton.singleton.AddErrorLog("CleanCache error: ", ex.Message, null, null, null, null); result = false; } return result; } internal byte[] LoadFile(string fullpath) { return File.ReadAllBytes(fullpath); } private AsyncReadRequest LoadFileAsync(string fullpath) { AsyncReadRequest arr = new AsyncReadRequest(); new Thread((ThreadStart) delegate { arr.bytes = File.ReadAllBytes(fullpath); arr.IsDone = true; }).Start(); return arr; } internal void Download(XBundleData bundle, HandleFetchBundle callback, float percent) { this._down_loader.GetBundle(bundle, this.GetDownloadUrl(bundle), new HandleBundleDownload(this.OnBundleDownload), callback, percent); } internal AsyncWriteRequest Download(string meta, uint size, float percent) { this._meta_awr = new AsyncWriteRequest(); this._meta_awr.Size = size; this._meta_awr.Location = meta; this._meta_awr.Name = meta.Substring(meta.LastIndexOf('/') + 1); this._meta_awr.HasError = false; string name = meta.Substring(meta.LastIndexOf("/") + 1); meta = this.MakeToken(this.HostUrl + XSingleton.singleton.Platform + meta); this._down_loader.GetMeta(meta, name, new XDownloader.HandleBytesDownload(this.OnMetaDownload), percent); return this._meta_awr; } internal bool Extract(XBundleData bundle, HandleFetchBundle callback, float percent) { bool flag =(int) Application.platform == 8; bool result; if (flag) { bool flag2 = this._aer == null; if (flag2) { this._aer = new AsyncExtractRequest(); new Thread((ThreadStart)delegate { string localPath = this.GetLocalPath(bundle); this._aer.Data = File.ReadAllBytes(localPath); this._aer.IsDone = true; }).Start(); } bool isDone = this._aer.IsDone; if (isDone) { callback(null, this._aer.Data, bundle, false); this._aer.Data = null; this._aer = null; result = true; } else { result = false; } } else { this._down_loader.GetBundle(bundle, this.GetLocalUrl(bundle), null, callback, percent); result = true; } return result; } private void OnMetaDownload(WWW www, string error) { bool flag = string.IsNullOrEmpty(error); if (flag) { byte[] bs = www.bytes; new Thread((ThreadStart)delegate { try { bool needCheckFile = XSingleton.singleton.NeedCheckFile; if (needCheckFile) { bool flag2 = Path.GetExtension(this._meta_awr.Location).Contains("ab"); if (flag2) { bool flag3 = bs[0] != 85 || bs[1] != 110 || bs[2] != 105 || bs[3] != 116 || bs[4] != 121 || bs[5] != 70 || bs[6] != 83; if (flag3) { throw new Exception("Meta head check failed."); } } } string text = Path.Combine(this._update_path, "AssetBundles"); string fileName = Path.GetFileName(this._meta_awr.Location); bool flag4 = !Directory.Exists(text); if (flag4) { Directory.CreateDirectory(text); } string text2 = Path.Combine(text, fileName); File.WriteAllBytes(text2, bs); bool needCheckFile2 = XSingleton.singleton.NeedCheckFile; if (needCheckFile2) { Thread.Sleep(1); bool flag5 = this.CheckFileSize(text2, (long)((ulong)this._meta_awr.Size)); if (!flag5) { throw new Exception("Meta File size " + this._meta_awr.Size + " not match."); } XSingleton.singleton.XPlatform.SetNoBackupFlag(text2); this._meta_awr.IsDone = true; } else { XSingleton.singleton.XPlatform.SetNoBackupFlag(text2); this._meta_awr.IsDone = true; } } catch (Exception ex) { this.OnDownloadFailed(ex.Message, this._meta_awr); } }).Start(); } else { this.OnDownloadFailed(error, this._meta_awr); } } private void OnDownloadFailed(string error, AsyncWriteRequest awr) { XSingleton.singleton.AddErrorLog("Download Meta ", awr.Name, " error: ", error, null, null); awr.HasError = true; } private AsyncWriteRequest OnBundleDownload(WWW www, XBundleData bundle, string error) { AsyncWriteRequest req = new AsyncWriteRequest(); bool flag = string.IsNullOrEmpty(error); if (flag) { byte[] bs = www.bytes; new Thread((ThreadStart)delegate { req.Location = this.GetLocalPath(bundle); try { File.WriteAllBytes(req.Location, bs); req.IsDone = true; } catch (Exception ex) { this.OnDownloadFailed(ex.Message, req); } }).Start(); } else { this.OnDownloadFailed(error, req); } return req; } internal string CalculateMD5(byte[] bundle) { byte[] value = this._md5Generator.ComputeHash(bundle); return BitConverter.ToString(value); } internal string CalculateMD5(byte[] bundle, int offset, int count) { byte[] value = this._md5Generator.ComputeHash(bundle, offset, count); return BitConverter.ToString(value); } public bool CheckFileSize(string filePath, long fileSize) { bool result; try { bool flag = !File.Exists(filePath); if (flag) { result = false; } else { FileInfo fileInfo = new FileInfo(filePath); result = (fileSize == fileInfo.Length); } } catch (Exception ex) { XSingleton.singleton.AddErrorLog("XCaching.CheckFileSize: " + ex.Message, null, null, null, null, null); result = false; } return result; } public override void Uninit() { } } }