Inheritance: ICASCEntry
Beispiel #1
0
        protected void CreateSubTree(CASCFolder root, ulong filehash, string file)
        {
            string[] parts = file.Split(PathDelimiters);

            CASCFolder folder = root;

            for (int i = 0; i < parts.Length; ++i)
            {
                bool isFile = (i == parts.Length - 1);

                string entryName = parts[i];

                ICASCEntry entry = folder.GetEntry(entryName);

                if (entry == null)
                {
                    if (isFile)
                    {
                        entry = new CASCFile(filehash);
                        CASCFile.FileNames[filehash] = file;
                    }
                    else
                    {
                        entry = new CASCFolder(entryName);
                    }

                    folder.Entries[entryName] = entry;
                    folder.EntriesMirror[entryName] = entry;
                }

                folder = entry as CASCFolder;
            }
        }
Beispiel #2
0
        public string GetFileExtension(CASCFile file)
        {
            try
            {
                using (Stream stream = CASC.OpenFile(file.Hash))
                {
                    byte[] magic = new byte[15];

                    stream.Read(magic, 0, magic.Length);

                    foreach (var number in MagicNumbers)
                    {
                        if (number.Key.EqualsToIgnoreLength(magic))
                        {
                            return(number.Value);
                        }
                    }

                    foreach (var number in LargeMagicNumbers)
                    {
                        if (number.Key.EqualsToIgnoreLength(magic))
                        {
                            return(number.Value);
                        }
                    }
                }
            }
            catch
            { }
            return(string.Empty);
        }
Beispiel #3
0
        private void ScanFile(CASCFile file)
        {
            if (scanBackgroundWorker.CancellationPending)
            {
                throw new OperationCanceledException();
            }

            NumScanned++;

            var fileNames = scanner.ScanFile(file);

            if (fileNames.Any())
            {
                // only report progress when not skipping a file, it's faster that way
                int progress            = (int)(NumScanned / (float)NumFiles * 100);
                ScanProgressState state = new ScanProgressState();
                state.NumFilesScanned = NumScanned;
                state.NumFilesTotal   = NumFiles;
                state.CurrentFileName = file.FullName;
                scanBackgroundWorker.ReportProgress(progress, state);

                foreach (var fileName in fileNames)
                {
                    ulong hash = Hasher.ComputeHash(fileName);

                    if ((CASC.Root as WowRootHandler).IsUnknownFile(hash))
                    {
                        BeginInvoke((MethodInvoker)(() => UpdateFileNames(fileName, file.FullName)));
                    }
                }
            }
        }
Beispiel #4
0
        protected void CreateSubTree(CASCFolder root, ulong filehash, string file)
        {
            string[] parts = file.Split(PathDelimiters);

            CASCFolder folder = root;

            for (int i = 0; i < parts.Length; ++i)
            {
                bool isFile = (i == parts.Length - 1);

                string entryName = parts[i];

                ICASCEntry entry = folder.GetEntry(entryName);

                if (entry == null)
                {
                    if (isFile)
                    {
                        entry = new CASCFile(filehash);
                        CASCFile.FileNames[filehash] = file;
                    }
                    else
                    {
                        entry = new CASCFolder(entryName);
                    }

                    folder.Entries[entryName] = entry;
                }

                folder = entry as CASCFolder;
            }
        }
Beispiel #5
0
        private void ExtractFile(CASCFile file)
        {
            if (backgroundWorker1.CancellationPending)
                throw new OperationCanceledException();

            backgroundWorker1.ReportProgress((int)((float)++NumExtracted / (float)NumFiles * 100));

            cascHandler.SaveFileTo(file.FullName, ExtractPath, locale);
        }
Beispiel #6
0
 private void PreviewBlp(CASCFile file)
 {
     using (var stream = _casc.OpenFile(file.Hash))
     {
         var blp    = new BlpFile(stream);
         var bitmap = blp.GetBitmap(0);
         var form   = new ImagePreviewForm(bitmap);
         form.Show();
     }
 }
Beispiel #7
0
        private void ExtractFile(CASCFile file)
        {
            if (backgroundWorker1.CancellationPending)
            {
                throw new OperationCanceledException();
            }

            backgroundWorker1.ReportProgress((int)((float)++NumExtracted / (float)NumFiles * 100));

            cascHandler.SaveFileTo(file.FullName, ExtractPath, locale);
        }
Beispiel #8
0
 private void PreviewText(CASCFile file)
 {
     using (var stream = _casc.OpenFile(file.Hash))
     {
         var text = new StreamReader(stream).ReadToEnd();
         var form = new Form {
             FormBorderStyle = FormBorderStyle.SizableToolWindow, StartPosition = FormStartPosition.CenterParent
         };
         form.Controls.Add(new TextBox
         {
             Multiline  = true,
             ReadOnly   = true,
             Dock       = DockStyle.Fill,
             Text       = text,
             ScrollBars = ScrollBars.Both
         });
         form.Show();
     }
 }
Beispiel #9
0
        private void ExtractFile(CASCFile file)
        {
            if (backgroundWorker1.CancellationPending)
            {
                throw new OperationCanceledException();
            }

            backgroundWorker1.ReportProgress((int)((float)++NumExtracted / (float)NumFiles * 100));

            var rootInfos = cascHandler.GetRootInfo(file.Hash);

            if (rootInfos == null)
            {
                return;
            }

            foreach (var rootInfo in rootInfos)
            {
                // only enUS atm
                if ((rootInfo.Block.Flags & locale) == 0)
                {
                    continue;
                }

                var encInfo = cascHandler.GetEncodingInfo(rootInfo.MD5);

                if (encInfo == null)
                {
                    continue;
                }

                foreach (var key in encInfo.Keys)
                {
                    cascHandler.ExtractFile(key, ExtractPath, file.FullName);
                    return;
                }
            }
        }
Beispiel #10
0
        public string GetFileExtension(CASCFile file)
        {
            try
            {
                using (Stream stream = CASC.OpenFile(file.Hash))
                {
                    byte[] magic = new byte[4];

                    stream.Read(magic, 0, 4);

                    foreach (var number in MagicNumbers)
                    {
                        if (number.Key.EqualsToIgnoreLength(magic))
                        {
                            return number.Value;
                        }
                    }
                }
            }
            catch
            { }
            return string.Empty;
        }
        public async Task AnalyzeUnknownFiles(Action <int> progressCallback)
        {
            if (_casc == null)
            {
                return;
            }

            IProgress <int> progress = new Progress <int>(progressCallback);

            await Task.Run(() =>
            {
                FileScanner scanner = new FileScanner(_casc, _root);

                Dictionary <int, string> idToName = new Dictionary <int, string>();

                if (_casc.Config.GameType == CASCGameType.WoW)
                {
                    if (_casc.FileExists("DBFilesClient\\SoundEntries.db2"))
                    {
                        using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2"))
                        {
                            DB2Reader se = new DB2Reader(stream);

                            foreach (var row in se)
                            {
                                string name = row.Value.GetField <string>(2);

                                int type = row.Value.GetField <int>(1);

                                bool many = row.Value.GetField <int>(4) > 0;

                                for (int i = 3; i < 23; i++)
                                {
                                    idToName[row.Value.GetField <int>(i)] = "unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg");
                                }
                            }
                        }
                    }

                    if (_casc.FileExists("DBFilesClient\\SoundKit.db2") && _casc.FileExists("DBFilesClient\\SoundKitEntry.db2"))
                    {
                        using (Stream skStream = _casc.OpenFile("DBFilesClient\\SoundKit.db2"))
                            using (Stream skeStream = _casc.OpenFile("DBFilesClient\\SoundKitEntry.db2"))
                            {
                                DB5Reader sk  = new DB5Reader(skStream);
                                DB5Reader ske = new DB5Reader(skeStream);

                                Dictionary <int, List <int> > lookup = new Dictionary <int, List <int> >();

                                foreach (var row in ske)
                                {
                                    int soundKitId = row.Value.GetField <int>(3);

                                    if (!lookup.ContainsKey(soundKitId))
                                    {
                                        lookup[soundKitId] = new List <int>();
                                    }

                                    lookup[soundKitId].Add(row.Value.GetField <int>(0));
                                }

                                foreach (var row in sk)
                                {
                                    string name = row.Value.GetField <string>(0).Replace(':', '_');

                                    int type = row.Value.GetField <byte>(12);

                                    List <int> ske_entries;

                                    if (!lookup.TryGetValue(row.Key, out ske_entries))
                                    {
                                        continue;
                                    }

                                    bool many = ske_entries.Count > 1;

                                    int i = 0;

                                    foreach (var fid in ske_entries)
                                    {
                                        idToName[fid] = "unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg");
                                        i++;
                                    }
                                }
                            }
                    }
                }

                CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder;

                if (unknownFolder == null)
                {
                    return;
                }

                IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true);
                int numTotal = files.Count();
                int numDone  = 0;

                WowRootHandler wowRoot = _casc.Root as WowRootHandler;

                foreach (var unknownEntry in files)
                {
                    CASCFile unknownFile = unknownEntry as CASCFile;

                    string name;
                    if (idToName.TryGetValue(wowRoot.GetFileDataIdByHash(unknownFile.Hash), out name))
                    {
                        unknownFile.FullName = name;
                    }
                    else
                    {
                        string ext            = scanner.GetFileExtension(unknownFile);
                        unknownFile.FullName += ext;

                        if (ext == ".m2")
                        {
                            using (var m2file = _casc.OpenFile(unknownFile.Hash))
                                using (var br = new BinaryReader(m2file))
                                {
                                    m2file.Position = 0x138;
                                    string m2name   = br.ReadCString();

                                    unknownFile.FullName = "unknown\\" + m2name + ".m2";
                                }
                        }
                    }

                    progress.Report((int)(++numDone / (float)numTotal * 100.0f));
                }

                _casc.Root.Dump();
            });
        }
Beispiel #12
0
        private static CASCFolder LoadListFile(CASCHandler cascHandler, string path, BackgroundWorker worker)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException("list file missing!");
            }

            var rootHash = CASCHandler.Hasher.ComputeHash("root");

            var root = new CASCFolder(rootHash);

            CASCHandler.FolderNames[rootHash] = "root";

            using (var sr = new StreamReader(path))
            {
                string file;
                int    filesCount = 0;

                CASCFolder folder = root;

                while ((file = sr.ReadLine()) != null)
                {
                    filesCount++;

                    string[] parts = file.Split('\\');

                    for (int i = 0; i < parts.Length; ++i)
                    {
                        bool isFile = (i == parts.Length - 1);

                        ulong hash = isFile ? CASCHandler.Hasher.ComputeHash(file) : CASCHandler.Hasher.ComputeHash(parts[i]);

                        // skip invalid names
                        if (isFile && !cascHandler.RootData.ContainsKey(hash))
                        {
                            break;
                        }

                        ICASCEntry entry = folder.GetEntry(hash);

                        if (entry == null)
                        {
                            if (isFile)
                            {
                                entry = new CASCFile(hash);
                                CASCHandler.FileNames[hash] = file;
                            }
                            else
                            {
                                entry = new CASCFolder(hash);
                                CASCHandler.FolderNames[hash] = parts[i];
                            }

                            folder.SubEntries[hash] = entry;

                            if (isFile)
                            {
                                folder = root;
                                break;
                            }
                        }

                        folder = entry as CASCFolder;
                    }
                }
                Logger.WriteLine("CASCHandler: loaded {0} file names", CASCHandler.FileNames.Count);
            }
            return(root);
        }
Beispiel #13
0
        private static CASCFolder LoadListFile(CASCHandler cascHandler, string path, BackgroundWorker worker)
        {
            if (!File.Exists(path))
                throw new FileNotFoundException("list file missing!");

            var rootHash = CASCHandler.Hasher.ComputeHash("root");

            var root = new CASCFolder(rootHash);

            CASCHandler.FolderNames[rootHash] = "root";

            using (var sr = new StreamReader(path))
            {
                string file;
                int filesCount = 0;

                CASCFolder folder = root;

                while ((file = sr.ReadLine()) != null)
                {
                    filesCount++;

                    string[] parts = file.Split('\\');

                    for (int i = 0; i < parts.Length; ++i)
                    {
                        bool isFile = (i == parts.Length - 1);

                        ulong hash = isFile ? CASCHandler.Hasher.ComputeHash(file) : CASCHandler.Hasher.ComputeHash(parts[i]);

                        // skip invalid names
                        if (isFile && !cascHandler.RootData.ContainsKey(hash))
                            break;

                        ICASCEntry entry = folder.GetEntry(hash);

                        if (entry == null)
                        {
                            if (isFile)
                            {
                                entry = new CASCFile(hash);
                                CASCHandler.FileNames[hash] = file;
                            }
                            else
                            {
                                entry = new CASCFolder(hash);
                                CASCHandler.FolderNames[hash] = parts[i];
                            }

                            folder.SubEntries[hash] = entry;

                            if (isFile)
                            {
                                folder = root;
                                break;
                            }
                        }

                        folder = entry as CASCFolder;
                    }
                }
                Logger.WriteLine("CASCHandler: loaded {0} file names", CASCHandler.FileNames.Count);
            }
            return root;
        }
Beispiel #14
0
        private void ScanFile(CASCFile file)
        {
            if (scanBackgroundWorker.CancellationPending)
                throw new OperationCanceledException();

            NumScanned++;

            var fileNames = scanner.ScanFile(file);

            if (fileNames.Any())
            {
                // only report progress when not skipping a file, it's faster that way
                int progress = (int)(NumScanned / (float)NumFiles * 100);
                ScanProgressState state = new ScanProgressState();
                state.NumFilesScanned = NumScanned;
                state.NumFilesTotal = NumFiles;
                state.CurrentFileName = file.FullName;
                scanBackgroundWorker.ReportProgress(progress, state);

                foreach (var fileName in fileNames)
                {
                    ulong hash = Hasher.ComputeHash(fileName);

                    if ((CASC.Root as WowRootHandler).IsUnknownFile(hash))
                    {
                        BeginInvoke((MethodInvoker)(() => UpdateFileNames(fileName, file.FullName)));
                    }
                }
            }
        }
Beispiel #15
0
        public async Task AnalyzeUnknownFiles(Action <int> progressCallback)
        {
            if (_casc == null)
            {
                return;
            }

            IProgress <int> progress = new Progress <int>(progressCallback);

            await Task.Run(() =>
            {
                FileScanner scanner = new FileScanner(_casc, _root);

                Dictionary <int, List <string> > idToName = new Dictionary <int, List <string> >();

                if (_casc.Config.GameType == CASCGameType.WoW && AnalyzeSoundFiles)
                {
                    if (_casc.FileExists("DBFilesClient\\SoundEntries.db2"))
                    {
                        using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2"))
                        {
                            WDB2Reader se = new WDB2Reader(stream);

                            foreach (var row in se)
                            {
                                string name = row.Value.GetField <string>(2);

                                int type = row.Value.GetField <int>(1);

                                bool many = row.Value.GetField <int>(4) > 0;

                                for (int i = 3; i < 23; i++)
                                {
                                    int id = row.Value.GetField <int>(i);

                                    if (!idToName.ContainsKey(id))
                                    {
                                        idToName[id] = new List <string>();
                                    }

                                    idToName[id].Add("unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg"));
                                }
                            }
                        }
                    }

                    if (_casc.FileExists(1237434 /*"DBFilesClient\\SoundKit.db2"*/) && _casc.FileExists(1237435 /*"DBFilesClient\\SoundKitEntry.db2"*/) && _casc.FileExists(1665033 /*"DBFilesClient\\SoundKitName.db2"*/))
                    {
                        using (Stream skStream = _casc.OpenFile(1237434))
                            using (Stream skeStream = _casc.OpenFile(1237435))
                                using (Stream sknStream = _casc.OpenFile(1665033))
                                {
                                    Func <ulong, bool> keyCheckFunc = x => KeyService.GetKey(x) != null;
                                    WDC3Reader sk  = new WDC3Reader(skStream, keyCheckFunc);
                                    WDC3Reader ske = new WDC3Reader(skeStream, keyCheckFunc);
                                    WDC3Reader skn = new WDC3Reader(sknStream, keyCheckFunc);

                                    Dictionary <int, List <int> > lookup = new Dictionary <int, List <int> >();

                                    foreach (var row in ske)
                                    {
                                        int soundKitId = row.Value.GetField <int>(0);

                                        if (!lookup.ContainsKey(soundKitId))
                                        {
                                            lookup[soundKitId] = new List <int>();
                                        }

                                        lookup[soundKitId].Add(row.Value.GetField <int>(1));
                                    }

                                    foreach (var row in sk)
                                    {
                                        WDC3Row sknRow = skn.GetRow(row.Key);

                                        if (sknRow != null)
                                        {
                                            string name = sknRow.GetField <string>(0).Replace(':', '_').Replace("\"", "");

                                            int type = row.Value.GetField <byte>(6);

                                            if (!lookup.TryGetValue(row.Key, out List <int> ske_entries))
                                            {
                                                continue;
                                            }

                                            bool many = ske_entries.Count > 1;

                                            int i = 0;

                                            foreach (var fid in ske_entries)
                                            {
                                                if (!idToName.ContainsKey(fid))
                                                {
                                                    idToName[fid] = new List <string>();
                                                }

                                                if (AddFileDataIdToSoundFiles)
                                                {
                                                    idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg"));
                                                }
                                                else
                                                {
                                                    idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg"));
                                                }

                                                i++;
                                            }
                                        }
                                    }
                                }
                    }
                }

                CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder;

                if (unknownFolder == null)
                {
                    return;
                }

                foreach (var kv in idToName)
                {
                    foreach (var fn in kv.Value)
                    {
                        Logger.WriteLine($"{kv.Key};{fn}");
                    }
                }

                IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true).ToList();
                int numTotal = files.Count();
                int numDone  = 0;

                WowRootHandler wowRoot = _casc.Root as WowRootHandler;

                Jenkins96 Hasher      = new Jenkins96();
                char[] PathDelimiters = new char[] { '/', '\\' };

                foreach (var unknownEntry in files)
                {
                    CASCFile unknownFile = unknownEntry as CASCFile;

                    if (idToName.TryGetValue(wowRoot.GetFileDataIdByHash(unknownFile.Hash), out List <string> name))
                    {
                        if (name.Count == 1)
                        {
                            unknownFile.FullName = name[0];
                        }
                        else
                        {
                            unknownFolder.Entries.Remove(unknownFile.Name);

                            foreach (var file in name)
                            {
                                //Logger.WriteLine(file);

                                string[] parts = file.Split(PathDelimiters);

                                string entryName = parts[parts.Length - 1];

                                ulong filehash = unknownFile.Hash;

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

                                unknownFolder.Entries[entryName] = entry;
                            }
                        }
                    }
                    else
                    {
                        string ext            = scanner.GetFileExtension(unknownFile);
                        unknownFile.FullName += ext;

                        if (ext == ".m2")
                        {
                            using (var m2file = _casc.OpenFile(unknownFile.Hash))
                                using (var br = new BinaryReader(m2file))
                                {
                                    m2file.Position = 0x14;
                                    int nameOffs    = br.ReadInt32();

                                    m2file.Position = nameOffs + 8; // + sizeof(MD21)
                                    string m2name   = br.ReadCString();

                                    unknownFile.FullName = "unknown\\" + m2name + ".m2";

                                    Logger.WriteLine($"{wowRoot.GetFileDataIdByHash(unknownFile.Hash)};{unknownFile.FullName}");

                                    //m2file.Position = 0;

                                    //while (m2file.Position != m2file.Length)
                                    //{
                                    //    int chunkType = br.ReadInt32();
                                    //    int chunkSize = br.ReadInt32();

                                    //    if (chunkType == 0x44494641) // AFID
                                    //    {
                                    //        int count = chunkSize / 8;

                                    //        for (int i = 0; i < count; i++)
                                    //        {
                                    //            ushort animId = br.ReadUInt16();
                                    //            ushort subAnimId = br.ReadUInt16();
                                    //            int FileDataId = br.ReadInt32();

                                    //            if (FileDataId != 0)
                                    //                Logger.WriteLine($"{FileDataId};{wowRoot.GetFileDataIdByHash(unknownFile.Hash)}\\{name}\\{name}{animId:D4}-{subAnimId:D2}.anim");
                                    //        }

                                    //        break;
                                    //    }
                                    //    else
                                    //    {
                                    //        m2file.Position += chunkSize;
                                    //    }
                                    //}
                                }
                        }
                    }

                    progress.Report((int)(++numDone / (float)numTotal * 100));
                }

                _casc.Root.Dump();
            });
        }
Beispiel #16
0
        public IEnumerable<string> ScanFile(CASCFile file)
        {
            if (excludeFileTypes.Contains(Path.GetExtension(file.FullName).ToLower()))
                yield break;

            Stream fileStream = null;

            try
            {
                fileStream = CASC.OpenFile(file.Hash, file.FullName);
            }
            catch
            {
                Logger.WriteLine("Skipped {0} because of both local and CDN indices are missing.", file.FullName);
                yield break;
            }

            using (fileStream)
            {
                int b;
                int state = 1;
                StringBuilder sb = new StringBuilder();

                // look for regex a+(da+)*\.a+ where a = IsAlphaNum() and d = IsFileDelim()
                // using a simple state machine
                while ((b = fileStream.ReadByte()) > -1)
                {
                    if (state == 1 && IsAlphaNum(b) || state == 2 && IsAlphaNum(b) || state == 3 && IsAlphaNum(b)) // alpha
                    {
                        state = 2;
                        sb.Append((char)b);

                        if (sb.Length > 10)
                        {
                            int nextByte = fileStream.ReadByte();

                            if (nextByte == 0)
                            {
                                string foundStr = sb.ToString();

                                foreach (var ext in extensions)
                                    yield return foundStr + ext;
                            }

                            if (nextByte > -1)
                                fileStream.Position -= 1;
                        }
                    }
                    else if (state == 2 && IsFileDelim(b)) // delimiter
                    {
                        state = 3;
                        sb.Append((char)b);
                    }
                    else if (state == 2 && b == 46) // dot
                    {
                        state = 4;
                        sb.Append((char)b);
                    }
                    else if (state == 4 && IsAlphaNum(b)) // extension
                    {
                        state = 5;
                        sb.Append((char)b);
                    }
                    else if (state == 5 && IsAlphaNum(b)) // extension
                    {
                        sb.Append((char)b);
                    }
                    else if (state == 5 && !IsFileChar(b)) // accept
                    {
                        state = 1;
                        if (sb.Length >= 10)
                            yield return sb.ToString();
                        sb.Clear();
                    }
                    else
                    {
                        state = 1;
                        sb.Clear();
                    }
                }
            }
        }
Beispiel #17
0
        public async Task AnalyzeUnknownFiles(Action <int> progressCallback)
        {
            if (_casc == null)
            {
                return;
            }

            IProgress <int> progress = new Progress <int>(progressCallback);

            await Task.Run(() =>
            {
                FileScanner scanner = new FileScanner(_casc, _root);

                Dictionary <uint, List <string> > idToName = new Dictionary <uint, List <string> >();

                if (_casc.Config.GameType == CASCGameType.WoW)
                {
                    if (_casc.FileExists("DBFilesClient\\SoundEntries.db2"))
                    {
                        using (Stream stream = _casc.OpenFile("DBFilesClient\\SoundEntries.db2"))
                        {
                            DB2Reader se = new DB2Reader(stream);

                            foreach (var row in se)
                            {
                                string name = row.Value.GetField <string>(2);

                                int type = row.Value.GetField <int>(1);

                                bool many = row.Value.GetField <int>(4) > 0;

                                for (int i = 3; i < 23; i++)
                                {
                                    uint id = row.Value.GetField <uint>(i);

                                    if (!idToName.ContainsKey(id))
                                    {
                                        idToName[id] = new List <string>();
                                    }

                                    idToName[id].Add("unknown\\sound\\" + name + (many ? "_" + (i - 2).ToString("D2") : "") + (type == 28 ? ".mp3" : ".ogg"));
                                }
                            }
                        }
                    }

                    if (_casc.FileExists("DBFilesClient\\SoundKit.db2") && _casc.FileExists("DBFilesClient\\SoundKitEntry.db2") && _casc.FileExists("DBFilesClient\\SoundKitName.db2"))
                    {
                        using (Stream skStream = _casc.OpenFile("DBFilesClient\\SoundKit.db2"))
                            using (Stream skeStream = _casc.OpenFile("DBFilesClient\\SoundKitEntry.db2"))
                                using (Stream sknStream = _casc.OpenFile("DBFilesClient\\SoundKitName.db2"))
                                {
                                    WDC1Reader sk  = new WDC1Reader(skStream);
                                    WDC1Reader ske = new WDC1Reader(skeStream);
                                    WDC1Reader skn = new WDC1Reader(sknStream);

                                    Dictionary <uint, List <uint> > lookup = new Dictionary <uint, List <uint> >();

                                    foreach (var row in ske)
                                    {
                                        uint soundKitId = row.Value.GetField <uint>(0);

                                        if (!lookup.ContainsKey(soundKitId))
                                        {
                                            lookup[soundKitId] = new List <uint>();
                                        }

                                        lookup[soundKitId].Add(row.Value.GetField <uint>(1));
                                    }

                                    foreach (var row in sk)
                                    {
                                        string name = skn.GetRow(row.Key).GetField <string>(0).Replace(':', '_');

                                        int type = row.Value.GetField <byte>(6);

                                        if (!lookup.TryGetValue(row.Key, out List <uint> ske_entries))
                                        {
                                            continue;
                                        }

                                        bool many = ske_entries.Count > 1;

                                        int i = 0;

                                        foreach (var fid in ske_entries)
                                        {
                                            if (!idToName.ContainsKey(fid))
                                            {
                                                idToName[fid] = new List <string>();
                                            }

                                            idToName[fid].Add("unknown\\sound\\" + name + (many ? "_" + (i + 1).ToString("D2") : "") + "_" + fid + (type == 28 ? ".mp3" : ".ogg"));
                                            i++;
                                        }
                                    }
                                }
                    }
                }

                CASCFolder unknownFolder = _root.GetEntry("unknown") as CASCFolder;

                if (unknownFolder == null)
                {
                    return;
                }

                IEnumerable <CASCFile> files = CASCFolder.GetFiles(unknownFolder.Entries.Select(kv => kv.Value), null, true).ToList();
                int numTotal = files.Count();
                int numDone  = 0;

                WowRootHandler wowRoot = _casc.Root as WowRootHandler;

                Jenkins96 Hasher      = new Jenkins96();
                char[] PathDelimiters = new char[] { '/', '\\' };

                foreach (var unknownEntry in files)
                {
                    CASCFile unknownFile = unknownEntry as CASCFile;

                    if (idToName.TryGetValue((uint)wowRoot.GetFileDataIdByHash(unknownFile.Hash), out List <string> name))
                    {
                        if (name.Count == 1)
                        {
                            unknownFile.FullName = name[0];
                        }
                        else
                        {
                            unknownFolder.Entries.Remove(unknownFile.Name);

                            foreach (var file in name)
                            {
                                Logger.WriteLine(file);

                                string[] parts = file.Split(PathDelimiters);

                                string entryName = parts[parts.Length - 1];

                                ulong filehash = unknownFile.Hash;

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

                                unknownFolder.Entries[entryName] = entry;
                            }
                        }
                    }
                    else
                    {
                        string ext            = scanner.GetFileExtension(unknownFile);
                        unknownFile.FullName += ext;

                        if (ext == ".m2")
                        {
                            using (var m2file = _casc.OpenFile(unknownFile.Hash))
                                using (var br = new BinaryReader(m2file))
                                {
                                    m2file.Position = 0x14;
                                    int nameOffs    = br.ReadInt32();

                                    m2file.Position = nameOffs + 8; // + sizeof(MD21)
                                    string m2name   = br.ReadCString();

                                    unknownFile.FullName = "unknown\\" + m2name + ".m2";
                                }
                        }
                    }

                    progress.Report((int)(++numDone / (float)numTotal * 100));
                }

                _casc.Root.Dump();
            });
        }
Beispiel #18
0
        private void ExtractFile(CASCFile file)
        {
            if (backgroundWorker1.CancellationPending)
                throw new OperationCanceledException();

            backgroundWorker1.ReportProgress((int)((float)++NumExtracted / (float)NumFiles * 100));

            var rootInfos = cascHandler.GetRootInfo(file.Hash);

            if (rootInfos == null)
                return;

            foreach (var rootInfo in rootInfos)
            {
                // only enUS atm
                if ((rootInfo.Block.Flags & locale) == 0)
                    continue;

                var encInfo = cascHandler.GetEncodingInfo(rootInfo.MD5);

                if (encInfo == null)
                    continue;

                foreach (var key in encInfo.Keys)
                {
                    cascHandler.ExtractFile(key, ExtractPath, file.FullName);
                    return;
                }
            }
        }
 private void PreviewBlp(CASCFile file)
 {
     using (var stream = _casc.OpenFile(file.Hash))
     {
         var blp = new BlpFile(stream);
         var bitmap = blp.GetBitmap(0);
         var form = new ImagePreviewForm(bitmap);
         form.Show();
     }
 }
 private void PreviewText(CASCFile file)
 {
     using (var stream = _casc.OpenFile(file.Hash))
     {
         var text = new StreamReader(stream).ReadToEnd();
         var form = new Form { FormBorderStyle = FormBorderStyle.SizableToolWindow, StartPosition = FormStartPosition.CenterParent };
         form.Controls.Add(new TextBox
         {
             Multiline = true,
             ReadOnly = true,
             Dock = DockStyle.Fill,
             Text = text,
             ScrollBars = ScrollBars.Both
         });
         form.Show();
     }
 }
Beispiel #21
0
        public CASCHandler(CASCFolder root, BackgroundWorker worker)
        {
            if (!OnlineMode)
            {
                var idxFiles = GetIdxFiles(Properties.Settings.Default.WowPath);

                if (idxFiles.Count == 0)
                {
                    throw new FileNotFoundException("idx files missing!");
                }

                worker.ReportProgress(0);

                int idxIndex = 0;

                foreach (var idx in idxFiles)
                {
                    using (var fs = new FileStream(idx, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        using (var br = new BinaryReader(fs))
                        {
                            int    h2Len   = br.ReadInt32();
                            int    h2Check = br.ReadInt32();
                            byte[] h2      = br.ReadBytes(h2Len);

                            long padPos = (8 + h2Len + 0x0F) & 0xFFFFFFF0;
                            fs.Position = padPos;

                            int dataLen   = br.ReadInt32();
                            int dataCheck = br.ReadInt32();

                            int numBlocks = dataLen / 18;

                            for (int i = 0; i < numBlocks; i++)
                            {
                                IndexEntry info      = new IndexEntry();
                                byte[]     key       = br.ReadBytes(9);
                                int        indexHigh = br.ReadByte();
                                int        indexLow  = br.ReadInt32BE();

                                info.Index  = (int)((byte)(indexHigh << 2) | ((indexLow & 0xC0000000) >> 30));
                                info.Offset = (indexLow & 0x3FFFFFFF);
                                info.Size   = br.ReadInt32();

                                // duplicate keys wtf...
                                //IndexData[key] = info; // use last key
                                if (!LocalIndexData.ContainsKey(key)) // use first key
                                {
                                    LocalIndexData.Add(key, info);
                                }
                            }

                            padPos      = (dataLen + 0x0FFF) & 0xFFFFF000;
                            fs.Position = padPos;

                            fs.Position += numBlocks * 18;
                            //for (int i = 0; i < numBlocks; i++)
                            //{
                            //    var bytes = br.ReadBytes(18); // unknown data
                            //}

                            if (fs.Position != fs.Position)
                            {
                                throw new Exception("idx file under read");
                            }
                        }

                    worker.ReportProgress((int)((float)++idxIndex / (float)idxFiles.Count * 100));
                }

                Logger.WriteLine("CASCHandler: loaded {0} indexes", LocalIndexData.Count);
            }

            worker.ReportProgress(0);

            using (var fs = OpenEncodingFile())
                using (var br = new BinaryReader(fs))
                {
                    br.ReadBytes(2); // EN
                    byte   b1         = br.ReadByte();
                    byte   b2         = br.ReadByte();
                    byte   b3         = br.ReadByte();
                    ushort s1         = br.ReadUInt16();
                    ushort s2         = br.ReadUInt16();
                    int    numEntries = br.ReadInt32BE();
                    int    i1         = br.ReadInt32BE();
                    byte   b4         = br.ReadByte();
                    int    entriesOfs = br.ReadInt32BE();

                    fs.Position += entriesOfs; // skip strings

                    fs.Position += numEntries * 32;
                    //for (int i = 0; i < numEntries; ++i)
                    //{
                    //    br.ReadBytes(16);
                    //    br.ReadBytes(16);
                    //}

                    for (int i = 0; i < numEntries; ++i)
                    {
                        ushort keysCount;

                        while ((keysCount = br.ReadUInt16()) != 0)
                        {
                            int    fileSize = br.ReadInt32BE();
                            byte[] md5      = br.ReadBytes(16);

                            var entry = new EncodingEntry();
                            entry.Size = fileSize;

                            for (int ki = 0; ki < keysCount; ++ki)
                            {
                                byte[] key = br.ReadBytes(16);

                                entry.Keys.Add(key);
                            }

                            //Encodings[md5] = entry;
                            EncodingData.Add(md5, entry);
                        }

                        //br.ReadBytes(28);
                        while (br.PeekChar() == 0)
                        {
                            fs.Position++;
                        }

                        worker.ReportProgress((int)((float)fs.Position / (float)fs.Length * 100));
                    }
                    //var pos = br.BaseStream.Position;
                    //for (int i = 0; i < i1; ++i)
                    //{
                    //    br.ReadBytes(16);
                    //    br.ReadBytes(16);
                    //}
                    Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingData.Count);
                }

            worker.ReportProgress(0);

            using (var fs = OpenRootFile())
                using (var br = new BinaryReader(fs))
                {
                    while (fs.Position < fs.Length)
                    {
                        int count = br.ReadInt32();

                        RootBlock block = new RootBlock();
                        block.Unk1  = br.ReadUInt32();
                        block.Flags = (LocaleFlags)br.ReadUInt32();

                        if (block.Flags == LocaleFlags.None)
                        {
                            throw new Exception("block.Flags == LocaleFlags.None");
                        }

                        RootEntry[] entries = new RootEntry[count];

                        for (var i = 0; i < count; ++i)
                        {
                            entries[i]       = new RootEntry();
                            entries[i].Block = block;
                            entries[i].Unk1  = br.ReadInt32();
                        }

                        for (var i = 0; i < count; ++i)
                        {
                            entries[i].MD5 = br.ReadBytes(16);

                            ulong hash = br.ReadUInt64();
                            entries[i].Hash = hash;

                            // don't load other locales
                            //if (block.Flags != LocaleFlags.All && (block.Flags & LocaleFlags.enUS) == 0)
                            //    continue;

                            if (!RootData.ContainsKey(hash))
                            {
                                RootData[hash] = new List <RootEntry>();
                                RootData[hash].Add(entries[i]);
                            }
                            else
                            {
                                RootData[hash].Add(entries[i]);
                            }
                        }

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

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

            worker.ReportProgress(0);

            if (File.Exists(listFile))
            {
                FolderNames[Hasher.ComputeHash("root")] = "root";

                using (StreamReader sr = new StreamReader(listFile))
                {
                    string file;
                    int    filesCount = 0;

                    CASCFolder folder = root;

                    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;
                        }

                        filesCount++;

                        string[] parts = file.Split('\\');

                        for (int i = 0; i < parts.Length; ++i)
                        {
                            bool isFile = (i == parts.Length - 1);

                            ulong hash = isFile ? fileHash : Hasher.ComputeHash(parts[i]);

                            ICASCEntry entry = folder.GetEntry(hash);

                            if (entry == null)
                            {
                                if (isFile)
                                {
                                    entry           = new CASCFile(hash);
                                    FileNames[hash] = file;
                                }
                                else
                                {
                                    entry             = new CASCFolder(hash);
                                    FolderNames[hash] = parts[i];
                                }

                                folder.SubEntries[hash] = entry;

                                if (isFile)
                                {
                                    folder = root;
                                    break;
                                }
                            }

                            folder = entry as CASCFolder;
                        }

                        if ((filesCount % 1000) == 0)
                        {
                            worker.ReportProgress((int)((float)sr.BaseStream.Position / (float)sr.BaseStream.Length * 100));
                        }
                    }

                    Logger.WriteLine("CASCHandler: loaded {0} file names", FileNames.Count);
                }
            }
            else
            {
                throw new FileNotFoundException("list file missing!");
            }
        }
Beispiel #22
0
        public IEnumerable <string> ScanFile(CASCFile file)
        {
            if (excludeFileTypes.Contains(Path.GetExtension(file.FullName).ToLower()))
            {
                yield break;
            }

            Stream fileStream = null;

            try
            {
                fileStream = CASC.OpenFile(file.Hash);
            }
            catch
            {
                Logger.WriteLine("Skipped {0} because of both local and CDN indices are missing.", file.FullName);
                yield break;
            }

            using (fileStream)
            {
                int           b;
                int           state = 1;
                StringBuilder sb    = new StringBuilder();

                // look for regex a+(da+)*\.a+ where a = IsAlphaNum() and d = IsFileDelim()
                // using a simple state machine
                while ((b = fileStream.ReadByte()) > -1)
                {
                    if (state == 1 && IsAlphaNum(b) || state == 2 && IsAlphaNum(b) || state == 3 && IsAlphaNum(b)) // alpha
                    {
                        state = 2;
                        sb.Append((char)b);

                        if (sb.Length > 10)
                        {
                            int nextByte = fileStream.ReadByte();

                            if (nextByte == 0)
                            {
                                string foundStr = sb.ToString();

                                foreach (var ext in extensions)
                                {
                                    yield return(foundStr + ext);
                                }
                            }

                            if (nextByte > -1)
                            {
                                fileStream.Position -= 1;
                            }
                        }
                    }
                    else if (state == 2 && IsFileDelim(b)) // delimiter
                    {
                        state = 3;
                        sb.Append((char)b);
                    }
                    else if (state == 2 && b == 46) // dot
                    {
                        state = 4;
                        sb.Append((char)b);
                    }
                    else if (state == 4 && IsAlphaNum(b)) // extension
                    {
                        state = 5;
                        sb.Append((char)b);
                    }
                    else if (state == 5 && IsAlphaNum(b)) // extension
                    {
                        sb.Append((char)b);
                    }
                    else if (state == 5 && !IsFileChar(b)) // accept
                    {
                        state = 1;
                        if (sb.Length >= 10)
                        {
                            yield return(sb.ToString());
                        }
                        sb.Clear();
                    }
                    else
                    {
                        state = 1;
                        sb.Clear();
                    }
                }
            }
        }
Beispiel #23
0
        public CASCHandler(CASCFolder root, BackgroundWorker worker)
        {
            if (!OnlineMode)
            {
                var idxFiles = GetIdxFiles(Properties.Settings.Default.WowPath);

                if (idxFiles.Count == 0)
                    throw new FileNotFoundException("idx files missing!");

                worker.ReportProgress(0);

                int idxIndex = 0;

                foreach (var idx in idxFiles)
                {
                    using (var fs = new FileStream(idx, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    using (var br = new BinaryReader(fs))
                    {
                        int h2Len = br.ReadInt32();
                        int h2Check = br.ReadInt32();
                        byte[] h2 = br.ReadBytes(h2Len);

                        long padPos = (8 + h2Len + 0x0F) & 0xFFFFFFF0;
                        fs.Position = padPos;

                        int dataLen = br.ReadInt32();
                        int dataCheck = br.ReadInt32();

                        int numBlocks = dataLen / 18;

                        for (int i = 0; i < numBlocks; i++)
                        {
                            IndexEntry info = new IndexEntry();
                            byte[] key = br.ReadBytes(9);
                            int indexHigh = br.ReadByte();
                            int indexLow = br.ReadInt32BE();

                            info.Index = (int)((byte)(indexHigh << 2) | ((indexLow & 0xC0000000) >> 30));
                            info.Offset = (indexLow & 0x3FFFFFFF);
                            info.Size = br.ReadInt32();

                            // duplicate keys wtf...
                            //IndexData[key] = info; // use last key
                            if (!LocalIndexData.ContainsKey(key)) // use first key
                                LocalIndexData.Add(key, info);
                        }

                        padPos = (dataLen + 0x0FFF) & 0xFFFFF000;
                        fs.Position = padPos;

                        fs.Position += numBlocks * 18;
                        //for (int i = 0; i < numBlocks; i++)
                        //{
                        //    var bytes = br.ReadBytes(18); // unknown data
                        //}

                        if (fs.Position != fs.Position)
                            throw new Exception("idx file under read");
                    }

                    worker.ReportProgress((int)((float)++idxIndex / (float)idxFiles.Count * 100));
                }

                Logger.WriteLine("CASCHandler: loaded {0} indexes", LocalIndexData.Count);
            }

            worker.ReportProgress(0);

            using (var fs = OpenEncodingFile())
            using (var br = new BinaryReader(fs))
            {
                br.ReadBytes(2); // EN
                byte b1 = br.ReadByte();
                byte b2 = br.ReadByte();
                byte b3 = br.ReadByte();
                ushort s1 = br.ReadUInt16();
                ushort s2 = br.ReadUInt16();
                int numEntries = br.ReadInt32BE();
                int i1 = br.ReadInt32BE();
                byte b4 = br.ReadByte();
                int entriesOfs = br.ReadInt32BE();

                fs.Position += entriesOfs; // skip strings

                fs.Position += numEntries * 32;
                //for (int i = 0; i < numEntries; ++i)
                //{
                //    br.ReadBytes(16);
                //    br.ReadBytes(16);
                //}

                for (int i = 0; i < numEntries; ++i)
                {
                    ushort keysCount;

                    while ((keysCount = br.ReadUInt16()) != 0)
                    {
                        int fileSize = br.ReadInt32BE();
                        byte[] md5 = br.ReadBytes(16);

                        var entry = new EncodingEntry();
                        entry.Size = fileSize;

                        for (int ki = 0; ki < keysCount; ++ki)
                        {
                            byte[] key = br.ReadBytes(16);

                            entry.Keys.Add(key);
                        }

                        //Encodings[md5] = entry;
                        EncodingData.Add(md5, entry);
                    }

                    //br.ReadBytes(28);
                    while (br.PeekChar() == 0)
                        fs.Position++;

                    worker.ReportProgress((int)((float)fs.Position / (float)fs.Length * 100));
                }
                //var pos = br.BaseStream.Position;
                //for (int i = 0; i < i1; ++i)
                //{
                //    br.ReadBytes(16);
                //    br.ReadBytes(16);
                //}
                Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingData.Count);
            }

            worker.ReportProgress(0);

            using (var fs = OpenRootFile())
            using (var br = new BinaryReader(fs))
            {
                while (fs.Position < fs.Length)
                {
                    int count = br.ReadInt32();

                    RootBlock block = new RootBlock();
                    block.Unk1 = br.ReadUInt32();
                    block.Flags = (LocaleFlags)br.ReadUInt32();

                    if (block.Flags == LocaleFlags.None)
                        throw new Exception("block.Flags == LocaleFlags.None");

                    RootEntry[] entries = new RootEntry[count];

                    for (var i = 0; i < count; ++i)
                    {
                        entries[i] = new RootEntry();
                        entries[i].Block = block;
                        entries[i].Unk1 = br.ReadInt32();
                    }

                    for (var i = 0; i < count; ++i)
                    {
                        entries[i].MD5 = br.ReadBytes(16);

                        ulong hash = br.ReadUInt64();
                        entries[i].Hash = hash;

                        // don't load other locales
                        //if (block.Flags != LocaleFlags.All && (block.Flags & LocaleFlags.enUS) == 0)
                        //    continue;

                        if (!RootData.ContainsKey(hash))
                        {
                            RootData[hash] = new List<RootEntry>();
                            RootData[hash].Add(entries[i]);
                        }
                        else
                            RootData[hash].Add(entries[i]);
                    }

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

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

            worker.ReportProgress(0);

            if (File.Exists(listFile))
            {
                FolderNames[Hasher.ComputeHash("root")] = "root";

                using (StreamReader sr = new StreamReader(listFile))
                {
                    string file;
                    int filesCount = 0;

                    CASCFolder folder = root;

                    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;
                        }

                        filesCount++;

                        string[] parts = file.Split('\\');

                        for (int i = 0; i < parts.Length; ++i)
                        {
                            bool isFile = (i == parts.Length - 1);

                            ulong hash = isFile ? fileHash : Hasher.ComputeHash(parts[i]);

                            ICASCEntry entry = folder.GetEntry(hash);

                            if (entry == null)
                            {
                                if (isFile)
                                {
                                    entry = new CASCFile(hash);
                                    FileNames[hash] = file;
                                }
                                else
                                {
                                    entry = new CASCFolder(hash);
                                    FolderNames[hash] = parts[i];
                                }

                                folder.SubEntries[hash] = entry;

                                if (isFile)
                                {
                                    folder = root;
                                    break;
                                }
                            }

                            folder = entry as CASCFolder;
                        }

                        if ((filesCount % 1000) == 0)
                            worker.ReportProgress((int)((float)sr.BaseStream.Position / (float)sr.BaseStream.Length * 100));
                    }

                    Logger.WriteLine("CASCHandler: loaded {0} file names", FileNames.Count);
                }
            }
            else
            {
                throw new FileNotFoundException("list file missing!");
            }
        }