/// <summary> /// Adds a CASRecord to the EncodingFile generating all required entries. This will overwrite existing entries /// </summary> /// <param name="record"></param> public void AddOrUpdate(CASRecord record) { // CKeyPageTable - overwrite existing var cKeyEntry = new EncodingContentEntry { CKey = record.CKey, DecompressedSize = record.EBlock.DecompressedSize }; cKeyEntry.EKey = record.EKey; _CKeyEntries[record.CKey] = cKeyEntry; // EKeyPageTable - overwrite existing // get or add to the ESpecStringTable int especIndex = ESpecStringTable.IndexOf(record.ESpec); if (especIndex == -1) { especIndex = ESpecStringTable.Count - 2; ESpecStringTable.Insert(especIndex, record.ESpec); } // create the entry var eKeyEntry = new EncodingEncodedEntry() { CompressedSize = record.EBlock.CompressedSize, EKey = record.EKey, ESpecIndex = (uint)especIndex }; _EKeyEntries[record.EKey] = eKeyEntry; }
/// <summary> /// Removes a CASRecord /// </summary> /// <param name="record"></param> public bool Remove(CASRecord record, TACTRepo tactRepo = null) { if (record == null) { return(false); } if (_CKeyEntries.TryGetValue(record.CKey, out var entry)) { _CKeyEntries.Remove(record.CKey); _EKeyEntries.Remove(entry.EKey); // propagate removal if (tactRepo != null) { tactRepo.IndexContainer?.Remove(entry.EKey); tactRepo.DownloadFile?.Remove(entry.EKey); tactRepo.DownloadSizeFile?.Remove(entry.EKey); } return(true); } return(false); }
/// <summary> /// Enqueues a CASRecord to be written to the indicies and archives /// </summary> /// <param name="record"></param> public void Enqueue(CASRecord record) { if (!string.IsNullOrWhiteSpace(record.BLTEPath)) { lock (QueuedEntries) QueuedEntries[record.EKey] = record; } }
/// <summary> /// Adds a CASRecord, this will overwrite existing entries /// </summary> /// <param name="record"></param> /// <param name="tags"></param> public void AddOrUpdate(CASRecord record) { var entry = new DownloadSizeFileEntry() { EKey = record.EKey, CompressedSize = record.EBlock.CompressedSize, }; AddOrUpdate(entry, record.Tags); }
/// <summary> /// Adds a CASRecord, this will overwrite existing entries /// </summary> /// <param name="record"></param> /// <param name="repo"></param> public override void AddOrUpdate(CASRecord record, TACTRepo repo = null) { var entry = new DownloadSizeFileEntry() { EKey = record.EKey, CompressedSize = record.EBlock.CompressedSize, }; AddOrUpdate(entry, record.Tags); }
/// <summary> /// Removes a CASRecord /// </summary> /// <param name="record"></param> public void Remove(CASRecord record) { if (_CKeyEntries.TryGetValue(record.CKey, out var cKeyEntry)) { Remove(cKeyEntry); } if (_EKeyEntries.TryGetValue(record.CKey, out var eKeyEntry)) { Remove(eKeyEntry); } }
/// <summary> /// Adds a CASRecord to the InstallFile, this will overwrite existing entries /// </summary> /// <param name="record"></param> /// <param name="tactRepo">If provided, will add the entry to all relevant system files</param> /// <param name="tags"></param> public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null) { var entry = new InstallFileEntry() { FilePath = record.FileName, CKey = record.CKey, DecompressedSize = record.EBlock.DecompressedSize, }; AddOrUpdate(entry, record.Tags); // add the record to the Encoding File tactRepo?.EncodingFile?.AddOrUpdate(record, tactRepo); }
/// <summary> /// Removes a CASRecord /// </summary> /// <param name="record"></param> public bool Remove(CASRecord record) { if (record == null) { return(false); } if (_CKeyEntries.TryGetValue(record.CKey, out var entry)) { _CKeyEntries.Remove(record.CKey); _EKeyEntries.Remove(record.EKey); return(true); } return(false); }
/// <summary> /// Adds a CASRecord to the archive /// </summary> /// <param name="record"></param> public void Add(CASRecord record) { var entry = new IndexEntry() { Key = IsPatchIndex ? record.CKey : record.EKey, CompressedSize = record.EBlock.CompressedSize, Offset = (uint)_currentOffset }; _currentOffset += record.EBlock.CompressedSize; _indexEntries[entry.Key] = entry; _newEntries[entry.Key] = record; RequiresSave = true; }
/// <summary> /// Adds a CASRecord, this will overwrite existing entries /// </summary> /// <param name="record"></param> /// <param name="priority">0 = highest, 2 = lowest, -1 for Install</param> /// <param name="tags"></param> public void AddOrUpdate(CASRecord record, sbyte priority) { // prevent overflow for old versions if (DownloadHeader.BasePriority + priority < 0) { priority = 0; } var entry = new DownloadFileEntry() { EKey = record.EKey, CompressedSize = record.EBlock.CompressedSize, Flags = new byte[DownloadHeader.FlagSize], Priority = priority, Checksum = 0 // TODO do we know what this is? }; AddOrUpdate(entry, record.Tags); }
/// <summary> /// Adds a CASRecord to the InstallFile, this will overwrite existing entries /// </summary> /// <param name="record"></param> /// <param name="tactRepo">If provided, will add the entry to all relevant system files</param> /// <param name="tags"></param> public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null) { var entry = new InstallFileEntry() { FilePath = record.FileName, CKey = record.CKey, DecompressedSize = record.EBlock.DecompressedSize, }; AddOrUpdate(entry, record.Tags); // add the record to all referenced files if (tactRepo != null) { tactRepo.EncodingFile?.AddOrUpdate(record); tactRepo.IndexContainer?.Enqueue(record); tactRepo.DownloadFile?.AddOrUpdate(record, 2); tactRepo.DownloadSizeFile?.AddOrUpdate(record); } }
/// <summary> /// Adds a CASRecord to the EncodingFile generating all required entries. This will overwrite existing entries /// </summary> /// <param name="record"></param> public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null) { // CKeyPageTable Remove(record, tactRepo); var cKeyEntry = new EncodingContentEntry { CKey = record.CKey, EKeys = new List <MD5Hash>(), DecompressedSize = record.EBlock.DecompressedSize, }; cKeyEntry.EKeys.Add(record.EKey); _CKeyEntries.Add(record.CKey, cKeyEntry); // get or add to the ESpecStringTable int especIndex = ESpecStringTable.IndexOf(record.ESpec); if (especIndex == -1) { especIndex = ESpecStringTable.Count - 2; ESpecStringTable.Insert(especIndex, record.ESpec); } // EKeyPageTable var eKeyEntry = new EncodingEncodedEntry() { CompressedSize = record.EBlock.CompressedSize, EKey = record.EKey, ESpecIndex = (uint)especIndex }; _EKeyEntries[record.EKey] = eKeyEntry; // propogate the new record if (tactRepo != null) { tactRepo.IndexContainer?.Enqueue(record); tactRepo.DownloadFile?.AddOrUpdate(record); tactRepo.DownloadSizeFile?.AddOrUpdate(record); } }
/// <summary> /// Adds a CASRecord to the EncodingFile generating all required entries. This will overwrite existing entries /// </summary> /// <param name="record"></param> public void AddOrUpdate(CASRecord record) { // CKeyPageTable if (_CKeyEntries.TryGetValue(record.CKey, out var cKeyEntry)) { _EKeyEntries.Remove(cKeyEntry.EKey); cKeyEntry.EKey = record.EKey; } else { cKeyEntry = new EncodingContentEntry { CKey = record.CKey, EKey = record.EKey, DecompressedSize = record.EBlock.DecompressedSize, }; _CKeyEntries.Add(record.CKey, cKeyEntry); } // get or add to the ESpecStringTable int especIndex = ESpecStringTable.IndexOf(record.ESpec); if (especIndex == -1) { especIndex = ESpecStringTable.Count - 2; ESpecStringTable.Insert(especIndex, record.ESpec); } // EKeyPageTable var eKeyEntry = new EncodingEncodedEntry() { CompressedSize = record.EBlock.CompressedSize, EKey = record.EKey, ESpecIndex = (uint)especIndex }; _EKeyEntries[record.EKey] = eKeyEntry; }
/// <summary> /// Enqueues a CASRecord to be written to the indicies and archives /// </summary> /// <param name="record"></param> public void Enqueue(CASRecord record) { lock (QueuedEntries) QueuedEntries[record.EKey] = record; }
/// <summary> /// Dequeues a CASRecord from being written to the indicies and archives /// </summary> /// <param name="record"></param> /// <returns></returns> public bool Dequeue(CASRecord record) { lock (QueuedEntries) return(QueuedEntries.Remove(record.EKey)); }
public static string MANIFEST_PATH; // = CdnRootDir + @"\wow"; static void Main(string[] args) { string seetingsDir = Directory.GetCurrentDirectory() + "/AppSettings.json"; AppSettings settings = null; try { FileStream f = new FileStream(seetingsDir, FileMode.Open, FileAccess.Read, FileShare.Read); var streamReader = new StreamReader(f, Encoding.UTF8); settings = JsonConvert.DeserializeObject <AppSettings>(streamReader.ReadToEnd()); } catch (Exception e) { settings = new AppSettings { cdnRootDir = "", mysqlUser = "******", mysqlPassword = "******", dataFolderPath = Directory.GetCurrentDirectory() + "\\Data\\", exportFolderPath = Directory.GetCurrentDirectory() + "\\DataExport\\", databaseName = "tacthost", databaseAdress = "localhost" }; string json = JsonConvert.SerializeObject(settings, Formatting.Indented); File.WriteAllText(seetingsDir, json); } CDN_DATA_DIR = settings.cdnRootDir + @"tpr\wow"; MANIFEST_PATH = settings.cdnRootDir + @"wow"; var tactRepo = new TACTRepo(CDN_DATA_DIR) { ManifestContainer = new ManifestContainer("wow", Locale.EU), ConfigContainer = new ConfigContainer() }; tactRepo.ManifestContainer.OpenLocal(MANIFEST_PATH); tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory, tactRepo.ManifestContainer); tactRepo.IndexContainer = new Net.Indices.IndexContainer(); tactRepo.IndexContainer.Open(tactRepo.BaseDirectory); tactRepo.EncodingFile = new Net.Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey); tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCEntry); tactRepo.RootFile = new Net.Root.RootFile(tactRepo.BaseDirectory, rootCEntry.EKey); tactRepo.InstallFile = new InstallFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.InstallEKey); tactRepo.DownloadFile = new Net.Download.DownloadFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.DownloadEKey); tactRepo.PatchFile = new Net.Patch.PatchFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.PatchEKey); tactRepo.RootFile.FileLookup = new ListFileLookup(); string[] files = Directory.GetFiles(settings.dataFolderPath, "*", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { files[i] = files[i].Replace(settings.dataFolderPath, ""); } Console.WriteLine("Found " + files.Length + " Files to proccess in " + settings.dataFolderPath); foreach (string s in files) { string filename = s.Substring(s.LastIndexOf("\\") + 1); string path = s.Substring(0, s.LastIndexOf("\\") + 1); LocaleFlags locale = LocaleFlags.All_WoW; if (path.ToLower().Contains("dbfilesclient")) { var match = Regex.Match(path, @"(frFR)|(enUS)|(ptBR)|(ruRU)|(esES)|(esMX)|(itIT)|(deDE)|(enGB)|(ptPT)"); var pathSplit = path.Split("\\"); var localeString = ""; foreach (var split in pathSplit) { if (split.Contains(match.Value)) { locale = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), split); localeString = split; path = path.Replace("\\" + localeString, ""); break; } } } CASRecord record = BlockTableEncoder.EncodeAndExport(settings.dataFolderPath + s, settings.exportFolderPath, (path + filename).Replace("\\", "/")); uint fId = tactRepo.RootFile.FileLookup.GetOrCreateFileId(record.FileName); Console.WriteLine("Added " + filename + " with ID: " + fId); tactRepo.RootFile.AddOrUpdate(record, tactRepo, locale); tactRepo.InstallFile.AddOrUpdate(record, tactRepo); } tactRepo.Save(tactRepo.BaseDirectory, settings.cdnRootDir); }
public abstract void AddOrUpdate(CASRecord record, TACTRepo repo = null);
/// <summary> /// Enqueues a CASRecord for storing archiving /// </summary> /// <param name="record"></param> public void Enqueue(CASRecord record) { _fileQueue.TryAdd(record.EKey, record); }
public void AddOrUpdate(CASRecord record, TACTRepo repo = null) { throw new NotImplementedException(); }
/// <summary> /// Finalises and encodes the stream's contents /// </summary> /// <returns></returns> public CASRecord Finalise() { if (Finalised) { return(Result); } // lock the final block _blocks[_blocks.Count - 1].Lock(); MD5Hash EKey, CKey = ComputeCKey(); EMap encoding = _blocks.Count == 1 ? _blocks[0].EncodingMap : new EMap(EType.ZLib, 9); uint decompressedSize = 0; string eSpec; using (var md5 = MD5.Create()) using (var ms = new MemoryStream((int)memStream.Length + 0x100)) using (var bw = new BinaryWriter(ms)) { // replace the stream contents with the BLTE structure uint headerSize = (uint)(_blocks.Count == 1 ? 0 : 0x18 * _blocks.Count + 0xC); // Header bw.Write(BlockTableStreamReader.BLTE_MAGIC); bw.WriteUInt32BE(headerSize); // Frame if (headerSize > 0) { bw.Write((byte)0xF); // flag bw.WriteUInt24BE((uint)_blocks.Count); // chunkCount // EBlock meta foreach (var block in _blocks.Values) { block.Finalise(); // apply encoding byte and any compression block.Position = 0; bw.WriteUInt32BE(block.CompressedSize); bw.WriteUInt32BE(block.DecompressedSize); bw.Write(md5.ComputeHash(block)); decompressedSize += block.DecompressedSize; } } else { var block = _blocks[0]; block.Finalise(); // apply encoding byte and any compression decompressedSize = block.DecompressedSize; } foreach (var block in _blocks.Values) { block.Position = 0; block.CopyTo(ms); } // calculate the EKey if (headerSize == 0) { ms.Position = 0; EKey = new MD5Hash(md5.ComputeHash(ms)); } else { EKey = ms.HashSlice(md5, 0, headerSize); } // set ESpec eSpec = string.Join(",", _blocks.Values); // merge the streams memStream.Position = 0; memStream.SetLength(ms.Length); memStream.Capacity = (int)ms.Length; ms.WriteTo(memStream); // cleanup _blocks.Clear(); Finalised = true; } // store for repeat finalisation return(Result = new CASRecord() { CKey = CKey, EBlock = new EBlock() { DecompressedSize = decompressedSize, CompressedSize = (uint)memStream.Length, EKey = EKey, EncodingMap = encoding }, ESpec = "b:{" + eSpec + "}" }); }