Example #1
0
        public CASCHandlerBase(CASCConfig config, BackgroundWorkerEx worker)
        {
            Config = config;

            Logger.WriteLine("CASCHandlerBase: loading CDN indices...");

            using (var _ = new PerfCounter("CDNIndexHandler.Initialize()"))
            {
                CDNIndex = CDNIndexHandler.Initialize(config, worker);
            }

            Logger.WriteLine("CASCHandlerBase: loaded {0} CDN indexes", CDNIndex.Count);

            if (!config.OnlineMode)
            {
                CDNCache.Enabled = false;

                Logger.WriteLine("CASCHandlerBase: loading local indices...");

                using (var _ = new PerfCounter("LocalIndexHandler.Initialize()"))
                {
                    LocalIndex = LocalIndexHandler.Initialize(config, worker);
                }

                Logger.WriteLine("CASCHandlerBase: loaded {0} local indexes", LocalIndex.Count);
            }
        }
Example #2
0
 private static CASCHandler Open(BackgroundWorkerEx worker, CASCConfig config)
 {
     using (var _ = new PerfCounter("new CASCHandler()"))
     {
         return(new CASCHandler(config, worker));
     }
 }
Example #3
0
        private bool LoadPreHashedListFile(string pathbin, string pathtext, BackgroundWorkerEx worker = null)
        {
            using (var _ = new PerfCounter("WowRootHandler::LoadPreHashedListFile()"))
            {
                worker?.ReportProgress(0, "Loading \"listfile\"...");

                if (!File.Exists(pathbin))
                {
                    return(false);
                }

                var timebin  = File.GetLastWriteTime(pathbin);
                var timetext = File.GetLastWriteTime(pathtext);

                if (timebin != timetext) // text has been modified, recreate crehashed file
                {
                    return(false);
                }

                Logger.WriteLine("WowRootHandler: loading file names...");

                using (var fs = new FileStream(pathbin, FileMode.Open))
                    using (var br = new BinaryReader(fs))
                    {
                        int numFolders = br.ReadInt32();

                        for (int i = 0; i < numFolders; i++)
                        {
                            string dirName = br.ReadString();

                            Logger.WriteLine(dirName);

                            int numFiles = br.ReadInt32();

                            for (int j = 0; j < numFiles; j++)
                            {
                                ulong  fileHash = br.ReadUInt64();
                                string fileName = br.ReadString();

                                string fileNameFull = dirName != String.Empty ? dirName + "\\" + fileName : fileName;

                                // skip invalid names
                                if (!RootData.ContainsKey(fileHash))
                                {
                                    Logger.WriteLine("Invalid file name: {0}", fileNameFull);
                                    continue;
                                }

                                CASCFile.Files[fileHash] = new CASCFile(fileHash, fileNameFull);
                            }

                            worker?.ReportProgress((int)(fs.Position / (float)fs.Length * 100));
                        }

                        Logger.WriteLine("WowRootHandler: loaded {0} valid file names", CASCFile.Files.Count);
                    }
            }

            return(true);
        }
Example #4
0
 private static CASCHandlerLite Open(LocaleFlags locale, BackgroundWorkerEx worker, CASCConfig config)
 {
     using (var _ = new PerfCounter("new CASCHandlerLite()"))
     {
         return(new CASCHandlerLite(config, locale, worker));
     }
 }
Example #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);
        }
Example #6
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);
            }
        }
Example #7
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);
            }
        }
Example #8
0
        private CASCHandler(CASCConfig config, BackgroundWorkerEx worker) : base(config, worker)
        {
            Logger.WriteLine("CASCHandler: loading encoding data...");

            using (var _ = new PerfCounter("new EncodingHandler()"))
            {
                using (var fs = OpenEncodingFile(this))
                    EncodingHandler = new EncodingHandler(fs, worker);
            }

            Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Download) != 0)
            {
                Logger.WriteLine("CASCHandler: loading download data...");

                using (var _ = new PerfCounter("new DownloadHandler()"))
                {
                    using (var fs = OpenDownloadFile(EncodingHandler, this))
                        DownloadHandler = new DownloadHandler(fs, worker);
                }

                Logger.WriteLine("CASCHandler: loaded {0} download data", EncodingHandler.Count);
            }

            Logger.WriteLine("CASCHandler: loading root data...");

            using (var _ = new PerfCounter("new RootHandler()"))
            {
                using (var fs = OpenRootFile(EncodingHandler, this))
                {
                    if (config.GameType == CASCGameType.S2 || config.GameType == CASCGameType.HotS)
                    {
                        RootHandler = new MNDXRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.D3)
                    {
                        RootHandler = new D3RootHandler(fs, worker, this);
                    }
                    else if (config.GameType == CASCGameType.WoW)
                    {
                        RootHandler = new WowRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Agent || config.GameType == CASCGameType.Bna || config.GameType == CASCGameType.Client)
                    {
                        RootHandler = new AgentRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.S1)
                    {
                        RootHandler = new S1RootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.WC3)
                    {
                        RootHandler = new WC3RootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Hearthstone)
                    {
                        RootHandler = new HSRootHandler(fs, worker);
                    }
                    else if (config.GameType == CASCGameType.Overwatch)
                    {
                        RootHandler = new OwRootHandler(fs, worker, this);
                    }
                    else if (config.GameType == CASCGameType.Destiny2)
                    {
                        RootHandler = new Destiny2RootHandler(fs, worker);
                    }
                    else
                    {
                        using (var ufs = new FileStream("unk_root", FileMode.Create))
                            fs.BaseStream.CopyTo(ufs);
                        throw new Exception("Unsupported game " + config.BuildUID);
                    }
                }
            }

            Logger.WriteLine("CASCHandler: loaded {0} root data", RootHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Install) != 0)
            {
                Logger.WriteLine("CASCHandler: loading install data...");

                using (var _ = new PerfCounter("new InstallHandler()"))
                {
                    using (var fs = OpenInstallFile(EncodingHandler, this))
                        InstallHandler = new InstallHandler(fs, worker);

                    InstallHandler.Print();
                }

                Logger.WriteLine("CASCHandler: loaded {0} install data", InstallHandler.Count);
            }
        }
Example #9
0
        public override void LoadListFile(string path, BackgroundWorkerEx worker = null)
        {
            //CASCFile.Files.Clear();

            using (var _ = new PerfCounter("WowRootHandler::LoadListFile()"))
            {
                worker?.ReportProgress(0, "Loading \"listfile\"...");

                if (!File.Exists(path))
                {
                    Logger.WriteLine("WowRootHandler: list file missing!");
                    return;
                }

                bool isCsv = Path.GetExtension(path) == ".csv";

                Logger.WriteLine($"WowRootHandler: loading listfile {path}...");

                using (var fs2 = File.Open(path, FileMode.Open))
                    using (var sr = new StreamReader(fs2))
                    {
                        string line;

                        char[] splitChar = isCsv ? new char[] { ';' } : new char[] { ' ' };

                        while ((line = sr.ReadLine()) != null)
                        {
                            string[] tokens = line.Split(splitChar, 2);

                            if (tokens.Length != 2)
                            {
                                Logger.WriteLine($"Invalid line in listfile: {line}");
                                continue;
                            }

                            if (!int.TryParse(tokens[0], out int fileDataId))
                            {
                                Logger.WriteLine($"Invalid line in listfile: {line}");
                                continue;
                            }

                            // skip invalid names
                            if (!RootData.ContainsKey(fileDataId))
                            {
                                Logger.WriteLine($"Invalid fileDataId in listfile: {line}");
                                continue;
                            }

                            string file = tokens[1];

                            ulong fileHash = FileDataStore[fileDataId];

                            if (!CASCFile.Files.ContainsKey(fileHash))
                            {
                                CASCFile.Files.Add(fileHash, new CASCFile(fileHash, file));
                            }
                            else
                            {
                                Logger.WriteLine($"Duplicate fileDataId {fileDataId} detected: {line}");
                            }

                            worker?.ReportProgress((int)(sr.BaseStream.Position / (float)sr.BaseStream.Length * 100));
                        }
                    }

                Logger.WriteLine($"WowRootHandler: loaded {CASCFile.Files.Count} valid file names");
            }
        }
Example #10
0
        public override void LoadListFile(string path, BackgroundWorkerEx worker = null)
        {
            CASCFile.Files.Clear();

            if (LoadPreHashedListFile("listfile.bin", path, worker))
            {
                return;
            }

            using (var _ = new PerfCounter("WowRootHandler::LoadListFile()"))
            {
                worker?.ReportProgress(0, "Loading \"listfile\"...");

                if (!File.Exists(path))
                {
                    Logger.WriteLine("WowRootHandler: list file missing!");
                    return;
                }

                Logger.WriteLine("WowRootHandler: loading file names...");

                Dictionary <string, Dictionary <ulong, string> > dirData = new Dictionary <string, Dictionary <ulong, string> >(StringComparer.OrdinalIgnoreCase)
                {
                    [""] = new Dictionary <ulong, string>()
                };
                using (var fs = new FileStream("listfile.bin", FileMode.Create))
                    using (var bw = new BinaryWriter(fs))
                        using (var fs2 = File.Open(path, FileMode.Open))
                            using (var sr = new StreamReader(fs2))
                            {
                                string file;

                                while ((file = sr.ReadLine()) != null)
                                {
                                    ulong fileHash = Hasher.ComputeHash(file);

                                    // skip invalid names
                                    if (!RootData.ContainsKey(fileHash))
                                    {
                                        Logger.WriteLine("Invalid file name: {0}", file);
                                        continue;
                                    }

                                    CASCFile.Files[fileHash] = new CASCFile(fileHash, file);

                                    int dirSepIndex = file.LastIndexOf('\\');

                                    if (dirSepIndex >= 0)
                                    {
                                        string key = file.Substring(0, dirSepIndex);

                                        if (!dirData.ContainsKey(key))
                                        {
                                            dirData[key] = new Dictionary <ulong, string>();
                                        }

                                        dirData[key][fileHash] = file.Substring(dirSepIndex + 1);
                                    }
                                    else
                                    {
                                        dirData[""][fileHash] = file;
                                    }

                                    worker?.ReportProgress((int)(sr.BaseStream.Position / (float)sr.BaseStream.Length * 100));
                                }

                                bw.Write(dirData.Count); // count of dirs

                                foreach (var dir in dirData)
                                {
                                    bw.Write(dir.Key); // dir name

                                    Logger.WriteLine(dir.Key);

                                    bw.Write(dirData[dir.Key].Count); // count of files in dir

                                    foreach (var fh in dirData[dir.Key])
                                    {
                                        bw.Write(fh.Key);   // file name hash
                                        bw.Write(fh.Value); // file name (without dir name)
                                    }
                                }

                                Logger.WriteLine("WowRootHandler: loaded {0} valid file names", CASCFile.Files.Count);
                            }

                File.SetLastWriteTime("listfile.bin", File.GetLastWriteTime(path));
            }
        }
Example #11
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)
                {
                    if (EncodingHandler.GetEntry(rootEntry.MD5, out EncodingEntry 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);
        }
Example #12
0
        private CASCHandler(CASCConfig config, BackgroundWorkerEx worker) : base(config, worker)
        {
            Logger.WriteLine("CASCHandler: loading encoding data...");

            using (var _ = new PerfCounter("new EncodingHandler()"))
            {
                using (var fs = OpenEncodingFile(this))
                    EncodingHandler = new EncodingHandler(fs, worker);
            }

            Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Download) != 0)
            {
                Logger.WriteLine("CASCHandler: loading download data...");

                using (var _ = new PerfCounter("new DownloadHandler()"))
                {
                    using (var fs = OpenDownloadFile(EncodingHandler, this))
                        DownloadHandler = new DownloadHandler(fs, worker);
                }

                Logger.WriteLine("CASCHandler: loaded {0} download data", EncodingHandler.Count);
            }

            KeyService.LoadKeys();

            Logger.WriteLine("CASCHandler: loading root data...");

            using (var _ = new PerfCounter("new RootHandler()"))
            {
                if (config.IsVfsRoot)
                {
                    RootHandler = new TVFSRootHandler(worker, this);
                }
                else
                {
                    using (var fs = OpenRootFile(EncodingHandler, this))
                    {
                        RootHandlerBase UnknownRootHandler()
                        {
                            using (var ufs = new FileStream("unk_root", FileMode.Create))
                                fs.BaseStream.CopyTo(ufs);
                            throw new Exception("Unsupported game " + config.BuildProduct);
                        }

                        RootHandler = config.GameType switch
                        {
                            CASCGameType.S2 => new MNDXRootHandler(fs, worker),
                            CASCGameType.HotS => new MNDXRootHandler(fs, worker),
                            CASCGameType.D3 => new D3RootHandler(fs, worker, this),
                            CASCGameType.WoW => new WowRootHandler(fs, worker),
                            CASCGameType.S1 => new S1RootHandler(fs, worker),
                            CASCGameType.Agent => new DummyRootHandler(fs, worker),
                            CASCGameType.Bna => new DummyRootHandler(fs, worker),
                            CASCGameType.Client => new DummyRootHandler(fs, worker),
                            CASCGameType.Hearthstone => new DummyRootHandler(fs, worker),
                            CASCGameType.Destiny2 => new DummyRootHandler(fs, worker),
                            CASCGameType.Wlby => new DummyRootHandler(fs, worker),
                            CASCGameType.Rtro => new DummyRootHandler(fs, worker),
                            _ => UnknownRootHandler()
                        };
                    }
                }
            }

            Logger.WriteLine("CASCHandler: loaded {0} root data", RootHandler.Count);

            if ((CASCConfig.LoadFlags & LoadFlags.Install) != 0)
            {
                Logger.WriteLine("CASCHandler: loading install data...");

                using (var _ = new PerfCounter("new InstallHandler()"))
                {
                    using (var fs = OpenInstallFile(EncodingHandler, this))
                        InstallHandler = new InstallHandler(fs, worker);

                    //InstallHandler.Print();
                }

                Logger.WriteLine("CASCHandler: loaded {0} install data", InstallHandler.Count);
            }
        }