public Stream OpenFile(string file, LocaleFlags locale) { var hash = Hasher.ComputeHash(file); var rootInfos = GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.Flags & locale) != 0) { var encInfo = GetEncodingInfo(rootInfo.MD5); if (encInfo == null) { continue; } foreach (var key in encInfo.Keys) { return(OpenFile(key)); } } } throw new NotSupportedException(); }
public void SaveFileTo(string fullName, string extractPath, LocaleFlags locale) { var hash = Hasher.ComputeHash(fullName); var rootInfos = GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.Flags & locale) != 0) { var encInfo = GetEncodingInfo(rootInfo.MD5); if (encInfo == null) { continue; } foreach (var key in encInfo.Keys) { ExtractFile(key, extractPath, fullName); return; } } } throw new NotSupportedException(); }
public MemoryStream SaveFileTo(string fullName, string extractPath, LocaleFlags locale) { var hash = Hasher.ComputeHash(fullName); var rootInfos = GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.Flags & locale) != 0) { var encInfo = GetEncodingInfo(rootInfo.MD5); if (encInfo == null) { continue; } foreach (var key in encInfo.Keys) { return(ExtractFile(key, extractPath, fullName)); } } } return(null); }
private static CASCHandlerLite Open(LocaleFlags locale, BackgroundWorkerEx worker, CASCConfig config) { using (var _ = new PerfCounter("new CASCHandlerLite()")) { return(new CASCHandlerLite(config, locale, worker)); } }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) { throw new Exception("Unsupported game " + config.BuildUID); } Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); WowRootHandler RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, false, false); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.LocaleFlags == locale || (rootEntry.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.ContentFlags & ContentFlags.Alternate) == ContentFlags.None) { if (EncodingHandler.GetEntry(rootEntry.cKey, out EncodingEntry enc)) { if (!HashToEKey.ContainsKey(entry.Key)) { HashToEKey.Add(entry.Key, enc.Keys[0]); FileDataIdToHash.Add(RootHandler.GetFileDataIdByHash(entry.Key), entry.Key); } } } } RootHandler.Clear(); RootHandler = null; EncodingHandler.Clear(); EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToEKey.Count); }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) throw new Exception("Unsupported game " + config.BuildUID); Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); RootHandlerBase RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.Block.LocaleFlags == locale || (rootEntry.Block.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.Block.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { var enc = EncodingHandler.GetEntry(rootEntry.MD5); if (enc != null) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(rootEntry.FileDataId, entry.Key); } } } } RootHandler.Clear(); EncodingHandler.Clear(); RootHandler = null; EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
public static void Initialize(string path, LocaleFlags locale, BackgroundWorkerEx worker = null) { Locale = locale; Handler = CASCHandler.OpenLocalStorage(path, worker); Handler.Root.SetFlags(locale, ContentFlags.None, false); Initialized = true; }
public static void InitializeOnline(LocaleFlags locale, BackgroundWorkerEx worker = null) { Locale = locale; Handler = CASCHandler.OpenOnlineStorage("wow", worker: worker); Handler.Root.SetFlags(locale, ContentFlags.None, false); Initialized = true; }
public static void Initialize(string path, LocaleFlags locale) { Locale = locale; Handler = CASCHandler.OpenLocalStorage(path); Handler.Root.SetFlags(locale, ContentFlags.None, false); Initialized = true; }
public RootHandler(BinaryReader stream) { while (stream.BaseStream.Position < stream.BaseStream.Length) { int count = stream.ReadInt32(); ContentFlags contentFlags = (ContentFlags)stream.ReadUInt32(); LocaleFlags localeFlags = (LocaleFlags)stream.ReadUInt32(); if (localeFlags == LocaleFlags.None) { throw new Exception("localeFlags == LocaleFlags.None"); } if (contentFlags != ContentFlags.None && (contentFlags & (ContentFlags.F00000008 | ContentFlags.F00000010 | ContentFlags.LowViolence | ContentFlags.NoCompression | ContentFlags.F20000000)) == 0) { throw new Exception("contentFlags != ContentFlags.None"); } RootEntry[] entries = new RootEntry[count]; int[] fileDataIDs = new int[count]; int fileDataIndex = 0; for (var i = 0; i < count; ++i) { entries[i].LocaleFlags = localeFlags; entries[i].ContentFlags = contentFlags; fileDataIDs[i] = fileDataIndex + (int)stream.ReadUInt32(); fileDataIndex = fileDataIDs[i] + 1; } for (var i = 0; i < count; ++i) { entries[i].MD5 = stream.Read <MD5Hash>(); ulong hash = stream.ReadUInt64(); RootData.Add(hash, entries[i]); ulong hash2; int fileDataID = fileDataIDs[i]; if (FileDataStore.TryGetValue(fileDataID, out hash2)) { if (hash2 != hash) { Log.Write("CASC: Hash collision for file ID {0}", fileDataID); } continue; } FileDataStore.Add(fileDataID, hash); FileDataStoreReverse.Add(hash, fileDataID); } } }
public Stream OpenFile(ulong hash, string fullName, LocaleFlags locale, ContentFlags content = ContentFlags.None) { EncodingEntry encInfo = GetEncodingEntry(hash, locale, content); if (encInfo != null) { return(OpenFile(encInfo.Keys[0])); } throw new FileNotFoundException(fullName); }
public CASCFolder SetFlags(LocaleFlags locale, ContentFlags content, bool createTree = true) { Locale = locale; Content = content; if (createTree) { Root = CreateStorageTree(); } return(Root); }
public CASCFolder SetFlags(LocaleFlags locale, bool overrideArchive = false, bool createTree = true) { Locale = locale; OverrideArchive = overrideArchive; if (createTree) { Root = CreateStorageTree(); } return(Root); }
public void SaveFileTo(ulong hash, string fullName, string extractPath, LocaleFlags locale, ContentFlags content = ContentFlags.None) { EncodingEntry encInfo = GetEncodingEntry(hash, locale, content); if (encInfo != null) { ExtractFile(encInfo.Keys[0], extractPath, fullName); return; } throw new FileNotFoundException(fullName); }
public CASCFolder SetFlags(LocaleFlags locale, ContentFlags content, bool createTree = true) { using (var _ = new PerfCounter(GetType().Name + "::SetFlags()")) { Locale = locale; Content = content; if (createTree) Root = CreateStorageTree(); return Root; } }
public CASCFolder CreateStorageTree(LocaleFlags locale) { var rootHash = Hasher.ComputeHash("root"); var root = new CASCFolder(rootHash); CASCFolder.FolderNames[rootHash] = "root"; NumRootEntriesSelect = 0; // Cleanup fake names for unknown files NumUnknownFiles = 0; foreach (var unkFile in UnknownFiles) { CASCFile.FileNames.Remove(unkFile.Key); } //Stream sw = new FileStream("unknownHashes.dat", FileMode.Create); //BinaryWriter bw = new BinaryWriter(sw); // Create new tree based on specified locale foreach (var rootEntry in RootHandler.RootData) { if (!rootEntry.Value.Any(re => (re.Block.LocaleFlags & locale) != 0)) { continue; } string file; if (!CASCFile.FileNames.TryGetValue(rootEntry.Key, out file)) { //file = "unknown\\" + rootEntry.Key.ToString("X16"); //NumUnknownFiles++; //UnknownFiles[rootEntry.Key] = true; } else { CreateSubTree(root, rootEntry.Key, file); NumRootEntriesSelect++; } } //bw.Flush(); //bw.Close(); Logger.WriteLine("CASCHandler: {0} file names missing", NumUnknownFiles); return(root); }
public CASCFolder SetFlags(LocaleFlags locale, ContentFlags content, bool createTree = true) { using (var _ = new PerfCounter(GetType().Name + "::SetFlags()")) { Locale = locale; Content = content; if (createTree) { Root = CreateStorageTree(); } return(Root); } }
public CASCFolder SetFlags(LocaleFlags locale, bool overrideArchive = false, bool createTree = true) { using (var _ = new PerfCounter(GetType().Name + "::SetFlags()")) { Locale = locale; OverrideArchive = overrideArchive; if (createTree) { Root = CreateStorageTree(); } return(Root); } }
private EncodingEntry GetEncodingEntryOld(ulong hash, LocaleFlags locale, ContentFlags content) { var rootInfos = RootHandler.GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.LocaleFlags & locale) != 0 && (rootInfo.Block.ContentFlags & content) == 0) { var encInfo = EncodingHandler.GetEncodingInfo(rootInfo.MD5); if (encInfo != null) { return(encInfo); } } } return(null); }
public S1RootHandler(BinaryReader stream, BackgroundWorkerEx worker) { worker?.ReportProgress(0, "Loading \"root\"..."); using (StreamReader sr = new StreamReader(stream.BaseStream)) { string line; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split('|'); string file; LocaleFlags locale = LocaleFlags.All; if (tokens[0].IndexOf(':') != -1) { string[] tokens2 = tokens[0].Split(':'); file = tokens2[0]; locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), tokens2[1]); } else { file = tokens[0]; } ulong fileHash = Hasher.ComputeHash(file); RootData[fileHash] = new RootEntry() { LocaleFlags = locale, ContentFlags = ContentFlags.None, MD5 = tokens[1].ToByteArray().ToMD5() }; CASCFile.Files[fileHash] = new CASCFile(fileHash, file); } } worker?.ReportProgress(100); }
private EncodingEntry GetEncodingEntry(ulong hash, LocaleFlags locale, ContentFlags content) { var rootInfos = RootHandler.GetRootInfo(hash); var rootInfosLocale = rootInfos.Where(re => (re.Block.LocaleFlags & locale) != 0); if (rootInfosLocale.Count() > 1) { if (content != ContentFlags.None) { var rootInfosLocaleAndContent = rootInfosLocale.Where(re => (re.Block.ContentFlags & content) == 0); if (rootInfosLocaleAndContent.Any()) { rootInfosLocale = rootInfosLocaleAndContent; } } } return(EncodingHandler.GetEncodingInfo(rootInfosLocale.First().MD5)); }
private void LoadSettings() { LocaleFlags locale = Enum.TryParse(Startup.Settings.Locale, true, out LocaleFlags tmp) ? tmp : LocaleFlags.enUS; Startup.Logger.LogConsole($"Default Locale set to {locale}."); settings = new CASSettings() { Host = Startup.Settings.HostDomain, BasePath = _env.WebRootPath, OutputPath = Path.Combine("Output", Startup.Settings.Product), SystemFilesPath = Path.Combine("SystemFiles", Startup.Settings.Product), BuildInfoPath = this.buildInfoPath, PatchUrl = Startup.Settings.PatchUrl, Logger = Startup.Logger, Cache = Startup.Cache, Locale = locale, CDNs = new HashSet <string>(), StaticMode = Startup.Settings.StaticMode, Product = Startup.Settings.Product }; if (!settings.StaticMode) { settings.CDNs.Add(settings.Host); } else { Startup.Logger.LogConsole($"CASCHost running in static mode"); } if (Startup.Settings.CDNs != null) { foreach (var cdn in Startup.Settings.CDNs) { settings.CDNs.Add(cdn); } } }
public static void OpenRoot(LocaleFlags locale, uint minimumid = 0, bool onlineListfile = false) { Logger.LogInformation("Loading Root..."); var rootkey = BuildConfig.GetKey("root"); if (!EncodingHandler.CEKeys.TryGetValue(rootkey, out EncodingCEKeyPageTable enc)) { Logger.LogCritical($"Encoding missing Root {rootkey.ToString()}"); return; } LocalIndexEntry idxInfo = LocalIndexHandler?.GetIndexInfo(enc.EKeys[0]); if (idxInfo != null) { var path = Path.Combine(BasePath, "Data", "data", string.Format("data.{0:D3}", idxInfo.Archive)); RootHandler = new RootHandler(DataHandler.Read(path, idxInfo), locale, minimumid, onlineListfile); } else { string key = enc.EKeys[0].ToString(); string path = Path.Combine(Settings.SystemFilesPath, key); path = Helper.FixOutputPath(path, "data"); if (!File.Exists(path)) { string url = "/data/" + key.Substring(0, 2) + "/" + key.Substring(2, 2) + "/" + key; if (!DataHandler.Download(url, path)) { Logger.LogCritical($"Unable to download Root {key}."); } } RootHandler = new RootHandler(DataHandler.ReadDirect(path), locale, minimumid, onlineListfile); } }
static void Main(string[] args) { if (args.Length != 4) { Console.WriteLine("Invalid arguments count!"); Console.WriteLine("Usage: CASCConsole <pattern> <destination> <localeFlags> <contentFlags>"); return; } Console.WriteLine("Settings:"); Console.WriteLine(" WowPath: {0}", Settings.Default.StoragePath); Console.WriteLine(" OnlineMode: {0}", Settings.Default.OnlineMode); Console.WriteLine("Loading..."); BackgroundWorkerEx bgLoader = new BackgroundWorkerEx(); bgLoader.ProgressChanged += BgLoader_ProgressChanged; CASCConfig config = Settings.Default.OnlineMode ? CASCConfig.LoadOnlineStorageConfig(Settings.Default.Product, "us") : CASCConfig.LoadLocalStorageConfig(Settings.Default.StoragePath); CASCHandler cascHandler = CASCHandler.OpenStorage(config, bgLoader); string pattern = args[0]; string dest = args[1]; LocaleFlags locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), args[2]); ContentFlags content = (ContentFlags)Enum.Parse(typeof(ContentFlags), args[3]); cascHandler.Root.LoadListFile(Path.Combine(Environment.CurrentDirectory, "listfile.txt"), bgLoader); CASCFolder root = cascHandler.Root.SetFlags(locale, content); Console.WriteLine("Loaded."); Console.WriteLine("Extract params:", pattern, dest, locale); Console.WriteLine(" Pattern: {0}", pattern); Console.WriteLine(" Destination: {0}", dest); Console.WriteLine(" LocaleFlags: {0}", locale); Console.WriteLine(" ContentFlags: {0}", content); Wildcard wildcard = new Wildcard(pattern, true, RegexOptions.IgnoreCase); foreach (var file in root.GetFiles()) { if (wildcard.IsMatch(file.FullName)) { Console.Write("Extracting '{0}'...", file.FullName); try { cascHandler.SaveFileTo(file.FullName, dest); Console.WriteLine(" Ok!"); } catch (Exception exc) { Console.WriteLine(" Error!"); Logger.WriteLine(exc.Message); } } } Console.WriteLine("Extracted."); }
public CASCFolder SetFlags(LocaleFlags locale, ContentFlags content, bool createTree = true) { Locale = locale; Content = content; if (createTree) Root = CreateStorageTree(); return Root; }
public static CASCHandlerLite OpenOnlineStorage(string product, LocaleFlags locale, string region = "us", BackgroundWorkerEx worker = null) { CASCConfig config = CASCConfig.LoadOnlineStorageConfig(product, region); return Open(locale, worker, config); }
public Wc3RootHandler(BinaryReader stream, BackgroundWorkerEx worker) { worker?.ReportProgress(0, "Loading \"root\"..."); using (StreamReader sr = new StreamReader(stream.BaseStream)) { string line; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split('|'); if (tokens.Length != 3 && tokens.Length != 4) { throw new Exception("tokens.Length != 3 && tokens.Length != 4"); } string file; LocaleFlags locale = LocaleFlags.All; if (tokens[0].IndexOf(':') != -1) { string[] tokens2 = tokens[0].Split(':'); if (tokens2.Length == 2) { file = tokens2[0] + "\\" + tokens2[1]; } else if (tokens2.Length == 3) { file = tokens2[0] + "\\" + tokens2[1] + "\\" + tokens2[2]; } else if (tokens2.Length == 4) { file = tokens2[0] + "\\" + tokens2[1] + "\\" + tokens2[2] + "\\" + tokens2[3]; } else { throw new Exception("tokens2.Length"); } } else { file = tokens[0]; } if (!Enum.TryParse(tokens[2], out locale)) { locale = LocaleFlags.All; } ulong fileHash = Hasher.ComputeHash(file); RootData[fileHash] = new RootEntry() { LocaleFlags = locale, ContentFlags = ContentFlags.None, MD5 = tokens[1].ToByteArray().ToMD5() }; CASCFile.Files[fileHash] = new CASCFile(fileHash, file); } } worker?.ReportProgress(100); }
public WowRootHandler(BinaryReader stream, BackgroundWorkerEx worker) { worker?.ReportProgress(0, "Loading \"root\"..."); while (stream.BaseStream.Position < stream.BaseStream.Length) { int count = stream.ReadInt32(); ContentFlags contentFlags = (ContentFlags)stream.ReadUInt32(); LocaleFlags localeFlags = (LocaleFlags)stream.ReadUInt32(); if (localeFlags == LocaleFlags.None) { throw new Exception("block.LocaleFlags == LocaleFlags.None"); } if (contentFlags != ContentFlags.None && (contentFlags & (ContentFlags.F00000008 | ContentFlags.F00000010 | ContentFlags.LowViolence | ContentFlags.NoCompression | ContentFlags.F20000000)) == 0) { throw new Exception("block.ContentFlags != ContentFlags.None"); } RootEntry[] entries = new RootEntry[count]; int[] filedataIds = new int[count]; int fileDataIndex = 0; for (var i = 0; i < count; ++i) { entries[i].LocaleFlags = localeFlags; entries[i].ContentFlags = contentFlags; filedataIds[i] = fileDataIndex + stream.ReadInt32(); fileDataIndex = filedataIds[i] + 1; } //Console.WriteLine("Block: {0} {1} (size {2})", block.ContentFlags, block.LocaleFlags, count); for (var i = 0; i < count; ++i) { entries[i].MD5 = stream.Read <MD5Hash>(); ulong hash = stream.ReadUInt64(); RootData.Add(hash, entries[i]); //Console.WriteLine("File: {0:X8} {1:X16} {2}", entries[i].FileDataId, hash, entries[i].MD5.ToHexString()); int fileDataId = filedataIds[i]; if (FileDataStore.TryGetValue(fileDataId, out ulong hash2)) { if (hash2 == hash) { // duplicate, skipping continue; } else { Logger.WriteLine("ERROR: got miltiple hashes for filedataid {0}", fileDataId); continue; } } FileDataStore.Add(fileDataId, hash); FileDataStoreReverse.Add(hash, fileDataId); } worker?.ReportProgress((int)(stream.BaseStream.Position / (float)stream.BaseStream.Length * 100)); } }
public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0) { this.minimumId = minimumid; this.locale = locale; BinaryReader stream = new BinaryReader(data); long length = stream.BaseStream.Length; while (stream.BaseStream.Position < length) { RootChunk chunk = new RootChunk() { Count = stream.ReadUInt32(), ContentFlags = (ContentFlags)stream.ReadUInt32(), LocaleFlags = (LocaleFlags)stream.ReadUInt32(), }; // set the global root if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None) { GlobalRoot = chunk; } uint fileDataIndex = 0; for (int i = 0; i < chunk.Count; i++) { uint offset = stream.ReadUInt32(); RootEntry entry = new RootEntry() { FileDataIdOffset = offset, FileDataId = fileDataIndex + offset }; fileDataIndex = entry.FileDataId + 1; chunk.Entries.Add(entry); } foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); entry.NameHash = stream.ReadUInt64(); maxId = Math.Max(maxId, entry.FileDataId); } Chunks.Add(chunk); } if (GlobalRoot == null) { CASContainer.Logger.LogCritical($"No Global root found. Root file is corrupt."); return; } // set maxid from cache maxId = Math.Max(Math.Max(maxId, minimumid), CASContainer.Settings.Cache?.MaxId ?? 0); // store encoding map encodingMap = (data as BLTEStream)?.EncodingMap.FirstOrDefault() ?? new EncodingMap(EncodingType.ZLib, 9); stream?.Dispose(); data?.Dispose(); }
private static CASCHandlerLite Open(LocaleFlags locale, BackgroundWorkerEx worker, CASCConfig config) { using (var _ = new PerfCounter("new CASCHandlerLite()")) { return new CASCHandlerLite(config, locale, worker); } }
private CASCHandlerLite(CASCConfig config, LocaleFlags locale, BackgroundWorkerEx worker) : base(config, worker) { if (config.GameType != CASCGameType.WoW) throw new Exception("Unsupported game " + config.BuildUID); Logger.WriteLine("CASCHandlerLite: loading encoding data..."); EncodingHandler EncodingHandler; using (var _ = new PerfCounter("new EncodingHandler()")) { using (var fs = OpenEncodingFile(this)) EncodingHandler = new EncodingHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} encoding data", EncodingHandler.Count); Logger.WriteLine("CASCHandlerLite: loading root data..."); WowRootHandler RootHandler; using (var _ = new PerfCounter("new RootHandler()")) { using (var fs = OpenRootFile(EncodingHandler, this)) RootHandler = new WowRootHandler(fs, worker); } Logger.WriteLine("CASCHandlerLite: loaded {0} root data", RootHandler.Count); RootHandler.SetFlags(locale, ContentFlags.None, false); CDNIndexData = new Dictionary<MD5Hash, IndexEntry>(comparer); if (LocalIndex != null) LocalIndexData = new Dictionary<MD5Hash, IndexEntry>(comparer); RootEntry rootEntry; foreach (var entry in RootHandler.GetAllEntries()) { rootEntry = entry.Value; if ((rootEntry.LocaleFlags == locale || (rootEntry.LocaleFlags & locale) != LocaleFlags.None) && (rootEntry.ContentFlags & ContentFlags.LowViolence) == ContentFlags.None) { EncodingEntry enc; if (EncodingHandler.GetEntry(rootEntry.MD5, out enc)) { if (!HashToKey.ContainsKey(entry.Key)) { HashToKey.Add(entry.Key, enc.Key); FileDataIdToHash.Add(RootHandler.GetFileDataIdByHash(entry.Key), entry.Key); if (LocalIndex != null) { IndexEntry iLocal = LocalIndex.GetIndexInfo(enc.Key); if (iLocal != null && !LocalIndexData.ContainsKey(enc.Key)) LocalIndexData.Add(enc.Key, iLocal); } IndexEntry iCDN = CDNIndex.GetIndexInfo(enc.Key); if (iCDN != null && !CDNIndexData.ContainsKey(enc.Key)) CDNIndexData.Add(enc.Key, iCDN); } } } } CDNIndex.Clear(); //CDNIndex = null; LocalIndex?.Clear(); LocalIndex = null; RootHandler.Clear(); RootHandler = null; EncodingHandler.Clear(); EncodingHandler = null; GC.Collect(); Logger.WriteLine("CASCHandlerLite: loaded {0} files", HashToKey.Count); }
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), comboBox1.SelectedItem as string); }
public Locale(string id, string name, LocaleFlags flags) { ID = id; Name = name; Flags = flags; }
public static CASCHandlerLite OpenLocalStorage(string basePath, LocaleFlags locale, BackgroundWorkerEx worker = null) { CASCConfig config = CASCConfig.LoadLocalStorageConfig(basePath); return Open(locale, worker, config); }
public void SaveFileTo(string fullName, string extractPath, LocaleFlags locale) { var hash = Hasher.ComputeHash(fullName); var rootInfos = GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.Flags & locale) != 0) { var encInfo = GetEncodingInfo(rootInfo.MD5); if (encInfo == null) continue; foreach (var key in encInfo.Keys) { ExtractFile(key, extractPath, fullName); return; } } } throw new NotSupportedException(); }
public Stream OpenFile(string file, LocaleFlags locale) { var hash = Hasher.ComputeHash(file); var rootInfos = GetRootInfo(hash); foreach (var rootInfo in rootInfos) { if ((rootInfo.Block.Flags & locale) != 0) { var encInfo = GetEncodingInfo(rootInfo.MD5); if (encInfo == null) continue; foreach (var key in encInfo.Keys) return OpenFile(key); } } throw new NotSupportedException(); }
public static CASCHandlerLite OpenStorage(LocaleFlags locale, CASCConfig config, BackgroundWorkerEx worker = null) { return Open(locale, worker, config); }
public async static Task <byte[]> GetFileByFilename(string buildConfig, string cdnConfig, string filename, LocaleFlags locale = LocaleFlags.All_WoW) { var build = await BuildCache.GetOrCreate(buildConfig, cdnConfig); using var hasher = new Jenkins96(); var lookup = hasher.ComputeHash(filename, true); var target = ""; if (build.root.entriesLookup.TryGetValue(lookup, out var entry)) { RootEntry prioritizedEntry; if (locale == LocaleFlags.All_WoW) { prioritizedEntry = entry.FirstOrDefault(subentry => subentry.contentFlags.HasFlag(ContentFlags.LowViolence) == false && (subentry.localeFlags.HasFlag(LocaleFlags.All_WoW) || subentry.localeFlags.HasFlag(LocaleFlags.enUS)) ); } else { prioritizedEntry = entry.FirstOrDefault(subentry => subentry.contentFlags.HasFlag(ContentFlags.LowViolence) == false && subentry.localeFlags.HasFlag(locale) ); } var selectedEntry = (prioritizedEntry.fileDataID != 0) ? prioritizedEntry : entry.First(); target = selectedEntry.md5.ToHexString().ToLower(); } if (string.IsNullOrEmpty(target)) { var filedataid = await Database.GetFileDataIDByFilename(filename); if (filedataid != 0) { if (build.root.entriesFDID.TryGetValue(filedataid, out var fdidentry)) { RootEntry prioritizedEntry; if (locale == LocaleFlags.All_WoW) { prioritizedEntry = fdidentry.FirstOrDefault(subentry => subentry.contentFlags.HasFlag(ContentFlags.LowViolence) == false && (subentry.localeFlags.HasFlag(LocaleFlags.All_WoW) || subentry.localeFlags.HasFlag(LocaleFlags.enUS)) ); } else { prioritizedEntry = fdidentry.FirstOrDefault(subentry => subentry.contentFlags.HasFlag(ContentFlags.LowViolence) == false && subentry.localeFlags.HasFlag(locale) ); } var selectedEntry = (prioritizedEntry.fileDataID != 0) ? prioritizedEntry : fdidentry.First(); target = selectedEntry.md5.ToHexString().ToLower(); } } } if (string.IsNullOrEmpty(target)) { throw new FileNotFoundException("No file found in root for filename " + filename); } return(await GetFile(buildConfig, cdnConfig, target)); }
public RootHandler(Stream data, LocaleFlags locale, uint minimumid = 0, bool onlineListfile = false) { this.minimumId = minimumid; this.locale = locale; string cdnPath = Helper.GetCDNPath("listfile.csv"); if (!(File.Exists(Path.Combine(CASContainer.Settings.OutputPath, cdnPath))) && onlineListfile) { CASContainer.Logger.LogInformation("Downloading listfile from WoW.Tools"); ListFileClient.DownloadFile("https://wow.tools/casc/listfile/download/csv/unverified", cdnPath); } BinaryReader stream = new BinaryReader(data); // 8.2 root change int magic = stream.ReadInt32(); bool newFormat = magic == headerMagic; if (newFormat) { allFiles = stream.ReadInt32(); namedFiles = stream.ReadInt32(); } else { stream.BaseStream.Position = 0; } long length = stream.BaseStream.Length; while (stream.BaseStream.Position < length) { RootChunk chunk = new RootChunk() { Count = stream.ReadUInt32(), ContentFlags = (ContentFlags)stream.ReadUInt32(), LocaleFlags = (LocaleFlags)stream.ReadUInt32(), }; parsedFiles += (int)chunk.Count; // set the global root if (chunk.LocaleFlags == LocaleFlags.All_WoW && chunk.ContentFlags == ContentFlags.None) { GlobalRoot = chunk; } uint fileDataIndex = 0; for (int i = 0; i < chunk.Count; i++) { uint offset = stream.ReadUInt32(); RootEntry entry = new RootEntry() { FileDataIdOffset = offset, FileDataId = fileDataIndex + offset }; fileDataIndex = entry.FileDataId + 1; chunk.Entries.Add(entry); } if (newFormat) { foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); maxId = Math.Max(maxId, entry.FileDataId); } if (parsedFiles > allFiles - namedFiles) { foreach (var entry in chunk.Entries) { entry.NameHash = stream.ReadUInt64(); } } else // no namehash { foreach (var entry in chunk.Entries) { entry.NameHash = 0; } } } else { foreach (var entry in chunk.Entries) { entry.CEKey = new MD5Hash(stream); entry.NameHash = stream.ReadUInt64(); maxId = Math.Max(maxId, entry.FileDataId); } } Chunks.Add(chunk); } if (GlobalRoot == null) { CASContainer.Logger.LogCritical($"No Global root found. Root file is corrupt."); return; } // use listfile to assign names var listFileLines = File.ReadAllLines(cdnPath); foreach (var listFileData in listFileLines) { var splitData = listFileData.Split(';'); if (splitData.Length != 2) { continue; } if (!uint.TryParse(splitData[0], out uint listFileDataID)) { continue; } ListFile[listFileDataID] = new Jenkins96().ComputeHash(splitData[1]); } foreach (var chunk in Chunks) { foreach (var entry in chunk.Entries) { if (entry.NameHash == 0) { if (ListFile.ContainsKey(entry.FileDataId)) { entry.NameHash = ListFile[entry.FileDataId]; } } } } // set maxid from cache maxId = Math.Max(Math.Max(maxId, minimumid), CASContainer.Settings.Cache?.MaxId ?? 0); // store encoding map encodingMap = (data as BLTEStream)?.EncodingMap.FirstOrDefault() ?? new EncodingMap(EncodingType.ZLib, 9); stream?.Dispose(); data?.Dispose(); }
public async Task <ActionResult> GetDB2ByTableName(string tableName, string fullBuild, LocaleFlags locale = LocaleFlags.All_WoW) { var buildConfig = await Database.GetBuildConfigByFullBuild(fullBuild); var cdnConfig = await Database.GetCDNConfigByBuildConfig(buildConfig); if (string.IsNullOrEmpty(buildConfig) || string.IsNullOrEmpty(cdnConfig) || string.IsNullOrEmpty(tableName)) { throw new ArgumentException("Invalid arguments!"); } Logger.WriteLine("Serving DB2 \"" + tableName + "\" for build " + fullBuild + " with locale " + locale); try { return(new FileContentResult(await CASC.GetFileByFilename(buildConfig, cdnConfig, "dbfilesclient/" + tableName.ToLower() + ".db2", locale), "application/octet-stream") { FileDownloadName = Path.GetFileName(tableName.ToLower() + ".db2") }); } catch (FileNotFoundException) { Console.ForegroundColor = ConsoleColor.Yellow; Logger.WriteLine("Table " + tableName + " not found in root of buildconfig " + buildConfig + " cdnconfig " + cdnConfig); Console.ResetColor(); return(NotFound()); } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Logger.WriteLine("Error " + e.Message + " occured when getting file " + tableName + " of buildconfig " + buildConfig + " cdnconfig " + cdnConfig); Console.ResetColor(); } return(NotFound()); }