/// <summary> /// Gets the Pk2 folder info /// </summary> /// <param name="FolderPath">Path to the location inside Pk2</param> public Pk2Folder GetFolder(string FolderPath) { if (FolderPath == "") { return(m_RootFolder); } // Normalize key format FolderPath = FolderPath.ToUpper(m_EnglishCulture).Replace("/", "\\"); if (FolderPath.EndsWith("\\")) { FolderPath = FolderPath.Remove(FolderPath.Length - 1); } Pk2Folder folder = null; m_Folders.TryGetValue(FolderPath, out folder); return(folder); }
/// <summary> /// Creates and load all entries from the Pk2 file /// </summary> /// <param name="FullPath">Path to the file</param> /// <param name="BlowfishKey">Key used to decrypt the file</param> public Pk2Reader(string FullPath, string BlowfishKey) { if (!File.Exists(FullPath)) { throw new FileNotFoundException("Pk2 file not found!"); } // Normalize path this.FullPath = Path.GetFullPath(FullPath); // Generate key from string Key = GenerateFinalBlowfishKey(BlowfishKey); ASCIIKey = BlowfishKey; // Open file m_FileStream = new FileStream(this.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read); Size = m_FileStream.Length; // Initialize the reader pointer m_Blowfish.Initialize(Key); BinaryReader reader = new BinaryReader(m_FileStream); Header = (sPk2Header)BufferToStruct(reader.ReadBytes(256), typeof(sPk2Header)); // Initialize root folder m_RootFolder = new Pk2Folder { Name = Path.GetDirectoryName(this.FullPath) }; // Check if the Pk2 file is loaded correctly try { // Reads stream Read(reader.BaseStream.Position, m_RootFolder, string.Empty); } catch (Exception ex) { // The only reason to fail is a wrong blowfish key or differents Pk2 structures throw new FormatException("The Pk2 structure cannot match with the blowfish key.", ex); } }
/// <summary> /// Reads Pk2 block structure from the position specified and save all data into the Folder /// </summary> private void Read(long Position, Pk2Folder CurrentFolder, string ParentPath) { // Set cursor position in the stream BinaryReader reader = new BinaryReader(m_FileStream); reader.BaseStream.Position = Position; // Keep a list with all folders from this block to add it to subfolders List <Pk2Folder> subfolders = new List <Pk2Folder>(); // Read pk2 block sPk2EntryBlock entryBlock = (sPk2EntryBlock)BufferToStruct(m_Blowfish.Decode(reader.ReadBytes(Marshal.SizeOf(typeof(sPk2EntryBlock)))), typeof(sPk2EntryBlock)); for (int i = 0; i < 20; i++) { // Entry sPk2Entry entry = entryBlock.Entries[i]; // Check entry type switch (entry.Type) { // Null Entry case 0: break; // Folder case 1: // Check if is not a parent/root folder if (entry.Name != "." && entry.Name != "..") { Pk2Folder folder = new Pk2Folder() { Name = entry.Name, Position = BitConverter.ToInt64(entry.g_Position, 0) }; // Add subfolder subfolders.Add(folder); // Save dictionary reference m_Folders[ParentPath + entry.Name.ToUpper(m_EnglishCulture)] = folder; } break; // File case 2: Pk2File file = new Pk2File { Position = entry.Position, Name = entry.Name, Size = entry.Size, ParentFolder = CurrentFolder }; // Add files to the current folder CurrentFolder.Files.Add(file); // Save dictionary reference m_Files[ParentPath + entry.Name.ToUpper(m_EnglishCulture)] = file; break; } } // Read the next pk2 block chain if (entryBlock.Entries[19].NextChain != 0) { Read(entryBlock.Entries[19].NextChain, CurrentFolder, ParentPath); } // Add subfolders to the current folder CurrentFolder.SubFolders.AddRange(subfolders); // Continue reading folder by folder foreach (var f in subfolders) { Read(f.Position, f, ParentPath + f.Name.ToUpper(m_EnglishCulture) + "\\"); } }