예제 #1
0
        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();
        }
예제 #2
0
        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();
        }
예제 #3
0
        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);
        }
예제 #4
0
 private static CASCHandlerLite Open(LocaleFlags locale, BackgroundWorkerEx worker, CASCConfig config)
 {
     using (var _ = new PerfCounter("new CASCHandlerLite()"))
     {
         return(new CASCHandlerLite(config, locale, worker));
     }
 }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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;
        }
예제 #8
0
        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;
        }
예제 #9
0
파일: CASC.cs 프로젝트: aeo24/WoWMap
        public static void Initialize(string path, LocaleFlags locale)
        {
            Locale = locale;
            Handler = CASCHandler.OpenLocalStorage(path);
            Handler.Root.SetFlags(locale, ContentFlags.None, false);

            Initialized = true;
        }
예제 #10
0
파일: CASC.cs 프로젝트: WowDevs/WoWMap
        public static void Initialize(string path, LocaleFlags locale)
        {
            Locale  = locale;
            Handler = CASCHandler.OpenLocalStorage(path);
            Handler.Root.SetFlags(locale, ContentFlags.None, false);

            Initialized = true;
        }
예제 #11
0
        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);
                }
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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;
            }
        }
예제 #17
0
        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);
        }
예제 #18
0
        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);
            }
        }
예제 #19
0
        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);
            }
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }
예제 #22
0
        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));
        }
예제 #23
0
        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);
                }
            }
        }
예제 #24
0
        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);
            }
        }
예제 #25
0
        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.");
        }
예제 #26
0
        public CASCFolder SetFlags(LocaleFlags locale, ContentFlags content, bool createTree = true)
        {
            Locale = locale;
            Content = content;

            if (createTree)
                Root = CreateStorageTree();

            return Root;
        }
예제 #27
0
        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);
        }
예제 #28
0
        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);
        }
예제 #29
0
        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));
            }
        }
예제 #30
0
        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();
        }
예제 #31
0
 private static CASCHandlerLite Open(LocaleFlags locale, BackgroundWorkerEx worker, CASCConfig config)
 {
     using (var _ = new PerfCounter("new CASCHandlerLite()"))
     {
         return new CASCHandlerLite(config, locale, worker);
     }
 }
예제 #32
0
        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);
        }
예제 #33
0
 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
 {
     locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), comboBox1.SelectedItem as string);
 }
예제 #34
0
파일: Locale.cs 프로젝트: Kruithne/W3DT
 public Locale(string id, string name, LocaleFlags flags)
 {
     ID = id;
     Name = name;
     Flags = flags;
 }
예제 #35
0
 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
 {
     locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), comboBox1.SelectedItem as string);
 }
예제 #36
0
        public static CASCHandlerLite OpenLocalStorage(string basePath, LocaleFlags locale, BackgroundWorkerEx worker = null)
        {
            CASCConfig config = CASCConfig.LoadLocalStorageConfig(basePath);

            return Open(locale, worker, config);
        }
예제 #37
0
        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();
        }
예제 #38
0
        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();
        }
예제 #39
0
 public static CASCHandlerLite OpenStorage(LocaleFlags locale, CASCConfig config, BackgroundWorkerEx worker = null)
 {
     return Open(locale, worker, config);
 }
예제 #40
0
        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));
        }
예제 #41
0
        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();
        }
예제 #42
0
        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());
        }
예제 #43
0
파일: Locale.cs 프로젝트: justMaku/W3DT
 public Locale(string id, string name, LocaleFlags flags)
 {
     ID    = id;
     Name  = name;
     Flags = flags;
 }