Exemplo n.º 1
0
        public static void Merge(Dictionary <string, FPakEntry> tempFiles, out Dictionary <string, FPakEntry> files, string mount)
        {
            files = new Dictionary <string, FPakEntry>();
            foreach (FPakEntry entry in tempFiles.Values)
            {
                if (files.ContainsKey(mount + entry.GetPathWithoutExtension()) ||
                    entry.GetExtension().Equals(".uptnl") ||
                    entry.GetExtension().Equals(".uexp") ||
                    entry.GetExtension().Equals(".ubulk"))
                {
                    continue;
                }

                if (entry.IsUE4Package())                                                  // if .uasset
                {
                    if (!tempFiles.ContainsKey(Path.ChangeExtension(entry.Name, ".umap"))) // but not including a .umap
                    {
                        string    e    = Path.ChangeExtension(entry.Name, ".uexp");
                        FPakEntry uexp = tempFiles.ContainsKey(e) ? tempFiles[e] : null; // add its uexp
                        if (uexp != null)
                        {
                            entry.Uexp = uexp;
                        }

                        string    u     = Path.ChangeExtension(entry.Name, ".ubulk");
                        FPakEntry ubulk = tempFiles.ContainsKey(u) ? tempFiles[u] : null; // add its ubulk
                        if (ubulk != null)
                        {
                            entry.Ubulk = ubulk;
                        }
                        else
                        {
                            string    f     = Path.ChangeExtension(entry.Name, ".ufont");
                            FPakEntry ufont = tempFiles.ContainsKey(f) ? tempFiles[f] : null; // add its ufont
                            if (ufont != null)
                            {
                                entry.Ubulk = ufont;
                            }
                        }
                    }
                }
                else if (entry.IsUE4Map()) // if .umap
                {
                    string    e    = Path.ChangeExtension(entry.Name, ".uexp");
                    string    u    = Path.ChangeExtension(entry.Name, ".ubulk");
                    FPakEntry uexp = tempFiles.ContainsKey(e) ? tempFiles[e] : null; // add its uexp
                    if (uexp != null)
                    {
                        entry.Uexp = uexp;
                    }
                    FPakEntry ubulk = tempFiles.ContainsKey(u) ? tempFiles[u] : null; // add its ubulk
                    if (ubulk != null)
                    {
                        entry.Ubulk = ubulk;
                    }
                }

                files[mount + entry.GetPathWithoutExtension()] = entry;
            }
        }
Exemplo n.º 2
0
        private IReadOnlyDictionary <string, GameFile> ReadIndexLegacy(bool caseInsensitive)
        {
            Ar.Position = Info.IndexOffset;
            var index = new FByteArchive($"{Name} - Index", ReadAndDecrypt((int)Info.IndexSize));

            string mountPoint;

            try
            {
                mountPoint = index.ReadFString();
            }
            catch (Exception e)
            {
                throw new InvalidAesKeyException($"Given aes key '{AesKey?.KeyString}'is not working with '{Name}'", e);
            }

            ValidateMountPoint(ref mountPoint);
            MountPoint = mountPoint;
            var fileCount = index.Read <int>();
            var files     = new Dictionary <string, GameFile>(fileCount);

            for (var i = 0; i < fileCount; i++)
            {
                var path  = string.Concat(mountPoint, index.ReadFString());
                var entry = new FPakEntry(this, path, index);
                if (entry.IsDeleted && entry.Size == 0)
                {
                    continue;
                }
                if (entry.IsEncrypted)
                {
                    EncryptedFileCount++;
                }
                if (caseInsensitive)
                {
                    files[path.ToLowerInvariant()] = entry;
                }
                else
                {
                    files[path] = entry;
                }
            }

            return(Files = files);
        }
Exemplo n.º 3
0
        public static void Set(this AssetPropertiesViewModel vm, FPakEntry entry)
        {
            Application.Current.Dispatcher.Invoke(delegate
            {
                string ext     = string.Join("   ", entry.GetExtension(), entry.Uexp?.GetExtension(), entry.Ubulk?.GetExtension());
                string offsets = string.Join("   ", "0x" + (entry.Offset + entry.StructSize).ToString("X2"),
                                             entry.Uexp != null ? "0x" + (entry.Uexp.Offset + entry.StructSize).ToString("X2") : string.Empty,
                                             entry.Ubulk != null ? "0x" + (entry.Ubulk.Offset + entry.StructSize).ToString("X2") : string.Empty);
                string tSize = Strings.GetReadableSize(entry.Size + (entry.Uexp?.Size ?? 0) + (entry.Ubulk?.Size ?? 0));

                vm.AssetName          = entry.GetNameWithExtension();
                vm.PartOf             = entry.PakFileName;
                vm.IncludedExtensions = ext.TrimEnd();
                vm.Offsets            = offsets.TrimEnd();
                vm.TotalSize          = tSize;
                vm.IsEncrypted        = entry.Encrypted ? Properties.Resources.Yes : Properties.Resources.No;
                vm.CompMethod         = ((ECompressionFlags)entry.CompressionMethodIndex).ToString();
            });
        }
Exemplo n.º 4
0
        private void Populate(dynamic nodeList, string pathWithoutFile, string seqPath, FPakEntry entry)
        {
            string folder;
            int    p = seqPath.IndexOf('/');

            if (p == -1)
            {
                folder  = seqPath;
                seqPath = string.Empty;
            }
            else
            {
                folder = seqPath.Substring(0, p);
                int p1 = p + 1;
                seqPath = seqPath[p1..];
Exemplo n.º 5
0
        private Dictionary <string, FPakEntry> GetOldFiles(EPakLoader mode)
        {
            var diff = new Dictionary <string, FPakEntry>();
            var ofd  = new OpenFileDialog()
            {
                Title            = Properties.Resources.SelectFile,
                InitialDirectory = Properties.Settings.Default.OutputPath + "\\Backups\\",
                Filter           = Properties.Resources.FbkpFilter,
                Multiselect      = false
            };

            if ((bool)ofd.ShowDialog())
            {
                string n = Path.GetFileName(ofd.FileName);
                StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.Analyzing, n), Properties.Resources.Processing);
                DebugHelper.WriteLine("{0} {1} {2} {3}", "[FModel]", "[PakMenuItemViewModel]", "[Loader]", $"Backup file is {n}");

                var oldFilesTemp = new Dictionary <string, FPakEntry>();
                using FileStream fileStream = new FileStream(ofd.FileName, FileMode.Open);
                BinaryReader checkReader = new BinaryReader(fileStream);
                bool         isLz4       = checkReader.ReadUInt32() == 0x184D2204u;
                fileStream.Seek(0, SeekOrigin.Begin);
                var target = new MemoryStream();
                if (isLz4)
                {
                    using LZ4DecoderStream compressionStream = LZ4Stream.Decode(fileStream);
                    compressionStream.CopyTo(target);
                }
                else
                {
                    fileStream.CopyTo(target);
                }
                using (target)
                {
                    target.Position           = 0;
                    using BinaryReader reader = new BinaryReader(target);
                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        // we must follow this order
                        long   offset                 = reader.ReadInt64();
                        long   size                   = reader.ReadInt64();
                        long   uncompressedSize       = reader.ReadInt64();
                        bool   encrypted              = reader.ReadBoolean();
                        long   structSize             = reader.ReadInt32();
                        string name                   = reader.ReadString();
                        int    compressionMethodIndex = reader.ReadInt32();

                        // we only need name and uncompressedSize to compare
                        FPakEntry entry = new FPakEntry("CatsWillDominateTheWorld.pak", name, offset, size, uncompressedSize, new byte[20], null, 0, (uint)compressionMethodIndex, 0);
                        oldFilesTemp[entry.Name] = entry;
                    }
                }

                var newFiles = new Dictionary <string, FPakEntry>();
                foreach (var fileReader in Globals.CachedPakFiles)
                {
                    foreach (var files in fileReader.Value)
                    {
                        newFiles.Add(files.Key, files.Value);
                    }
                }

                Paks.Merge(oldFilesTemp, out var oldFiles, string.Empty);

                switch (mode)
                {
                case EPakLoader.New:
                    foreach (var kvp in newFiles)
                    {
                        if (!oldFiles.TryGetValue(kvp.Key, out var entry))
                        {
                            diff.Add(kvp.Key, kvp.Value);
                        }
                    }
                    break;

                case EPakLoader.Modified:
                    foreach (var kvp in newFiles)
                    {
                        if (oldFiles.TryGetValue(kvp.Key, out var entry))
                        {
                            if (entry.UncompressedSize != kvp.Value.UncompressedSize)
                            {
                                diff.Add(kvp.Key, kvp.Value);
                            }
                        }
                    }
                    break;

                case EPakLoader.NewModified:
                    foreach (var kvp in newFiles)
                    {
                        if (oldFiles.TryGetValue(kvp.Key, out var entry))
                        {
                            if (entry.UncompressedSize != kvp.Value.UncompressedSize)
                            {
                                diff.Add(kvp.Key, kvp.Value);
                            }
                        }
                        else
                        {
                            diff.Add(kvp.Key, kvp.Value);
                        }
                    }
                    break;
                }

                var deleted = oldFiles.Where(kvp => !newFiles.TryGetValue(kvp.Key, out var _) && kvp.Key.StartsWith("/FortniteGame/Content/Athena/Items/Cosmetics/")).ToDictionary(x => x.Key, x => x.Value);
                if (deleted.Count > 0)
                {
                    FConsole.AppendText(Properties.Resources.RemovedRenamedCosmetics, FColors.Red, true);
                    foreach (var kvp in deleted)
                    {
                        FConsole.AppendText($"    - {kvp.Value.Name.Substring(1)}", FColors.LightGray, true);
                    }
                }
            }
            return(diff);
        }
Exemplo n.º 6
0
        public static string GetJsonProperties(FPakEntry entry, string mount, bool loadContent)
        {
            PakPackage p = GetPakPackage(entry, mount, loadContent);

            if (!p.Equals(default))
Exemplo n.º 7
0
 public static string GetJsonProperties(FPakEntry entry, string mount) => GetJsonProperties(entry, mount, false);
Exemplo n.º 8
0
        private static async Task LoadBackupFile(bool updateMode = false)
        {
            OpenFileDialog openFiledialog = new OpenFileDialog();

            openFiledialog.Title            = "Choose your Backup File";
            openFiledialog.InitialDirectory = FProp.Default.FOutput_Path + "\\Backups\\";
            openFiledialog.Multiselect      = false;
            openFiledialog.Filter           = "FBKP Files (*.fbkp)|*.fbkp|All Files (*.*)|*.*";
            if (openFiledialog.ShowDialog() == true)
            {
                DebugHelper.WriteLine($".PAKs: Loading {openFiledialog.FileName} as the backup file");
                new UpdateMyProcessEvents("Comparing Files", "Waiting").Update();

                FPakEntry[] BackupEntries;
                using (FileStream fileStream = new FileStream(openFiledialog.FileName, FileMode.Open))
                    using (BinaryReader reader = new BinaryReader(fileStream))
                    {
                        DebugHelper.WriteLine(".PAKs: Populating FPakEntry[] for the backup file");

                        List <FPakEntry> entries = new List <FPakEntry>();
                        while (reader.BaseStream.Position < reader.BaseStream.Length)
                        {
                            // we must follow this order
                            long   offset                 = reader.ReadInt64();
                            long   size                   = reader.ReadInt64();
                            long   uncompressedSize       = reader.ReadInt64();
                            bool   encrypted              = reader.ReadBoolean();
                            long   structSize             = reader.ReadInt32();
                            string name                   = reader.ReadString();
                            long   compressionMethodIndex = reader.ReadInt32();

                            // we actually only need name and uncompressedSize to compare
                            FPakEntry entry = new FPakEntry(name, offset, size, uncompressedSize, new byte[20], null, 0, 0, 0);
                            entries.Add(entry);
                        }
                        BackupEntries = entries.ToArray();
                    }

                if (BackupEntries.Any())
                {
                    DebugHelper.WriteLine(".PAKs: FPakEntry[] for the backup file is populated");

                    List <FPakEntry> LocalEntries = new List <FPakEntry>();
                    foreach (FPakEntry[] PAKsFileInfos in PAKEntries.PAKToDisplay.Values)
                    {
                        PAKsFileInfos.ToList().ForEach(x => LocalEntries.Add(x));
                    }
                    PAKEntries.PAKToDisplay.Clear();
                    DebugHelper.WriteLine(".PAKs: FPakEntry[] for the local .PAKs is populated");

                    //FILTER WITH THE OVERRIDED EQUALS METHOD (CHECKING FILE NAME AND FILE UNCOMPRESSED SIZE)
                    DebugHelper.WriteLine($".PAKs: Comparing...\t File Size Check: {FProp.Default.FDiffFileSize}");
                    IEnumerable <FPakEntry> newAssets = LocalEntries.Except(BackupEntries);
                    DebugHelper.WriteLine(".PAKs: Compared");

                    //ADD TO TREE
                    DebugHelper.WriteLine(".PAKs: Filling Treeview with differentiated assets");
                    foreach (FPakEntry entry in newAssets)
                    {
                        string onlyFolders = entry.Name.Substring(0, entry.Name.LastIndexOf('/'));
                        await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                        {
                            TreeViewUtility.PopulateTreeView(srt, onlyFolders.Substring(1));
                        });
                    }

                    //ONLY LOAD THE DIFFERENCE WHEN WE CLICK ON A FOLDER
                    FWindow.FCurrentPAK = "ComparedPAK-WindowsClient.pak";
                    PAKEntries.PAKToDisplay.Add("ComparedPAK-WindowsClient.pak", newAssets.ToArray());
                    await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                    {
                        FWindow.FMain.ViewModel = srt;
                    });

                    DebugHelper.WriteLine(".PAKs: Treeview filled");

                    await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                    {
                        FWindow.FMain.TreeView_Main.IsEnabled     = true;
                        FWindow.FMain.MI_LoadAllPAKs.IsEnabled    = true;
                        FWindow.FMain.MI_BackupPAKs.IsEnabled     = true;
                        FWindow.FMain.MI_DifferenceMode.IsEnabled = true;
                        if (updateMode)
                        {
                            FWindow.FMain.MI_UpdateMode.IsEnabled = true;
                        }
                    });

                    //PRINT REMOVED IF NO FILE SIZE CHECK
                    if (!FProp.Default.FDiffFileSize)
                    {
                        DebugHelper.WriteLine(".PAKs: Checking deleted items");
                        new UpdateMyProcessEvents("Checking deleted items", "Waiting").Update();
                        IEnumerable <FPakEntry> removedAssets = BackupEntries.Except(LocalEntries.ToArray());

                        List <string> removedItems = new List <string>();
                        foreach (FPakEntry entry in removedAssets)
                        {
                            if (entry.Name.StartsWith("/FortniteGame/Content/Athena/Items/Cosmetics/"))
                            {
                                removedItems.Add(entry.Name.Substring(0, entry.Name.LastIndexOf(".")));
                            }
                        }

                        if (removedItems.Count > 0)
                        {
                            DebugHelper.WriteLine(".PAKs: Items Removed/Renamed:");
                            new UpdateMyConsole("Items Removed/Renamed:", CColors.Red, true).Append();
                            removedItems.Distinct().ToList().ForEach(e => {
                                new UpdateMyConsole($"    - {e.Substring(1)}", CColors.White, true).Append();
                                DebugHelper.WriteLine($"    - {e.Substring(1)}");
                            });
                        }
                    }

                    DebugHelper.WriteLine(".PAKs: PAK files have been compared successfully");
                    new UpdateMyProcessEvents("All PAK files have been compared successfully", "Success").Update();
                    umIsOk = true;
                }
                else
                {
                    DebugHelper.WriteLine(".PAKs: FPakEntry[] for the backup file is empty");
                }
            }
            else
            {
                DebugHelper.WriteLine(".PAKs: User canceled when he got asked to select a backup file");

                new UpdateMyConsole("You change your mind pretty fast but it's fine ", CColors.White).Append();
                new UpdateMyConsole("all paks have been loaded instead", CColors.Blue, true).Append();
                FillTreeView(true);

                await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                {
                    FWindow.FMain.TreeView_Main.IsEnabled     = true;
                    FWindow.FMain.MI_LoadAllPAKs.IsEnabled    = true;
                    FWindow.FMain.MI_BackupPAKs.IsEnabled     = true;
                    FWindow.FMain.MI_DifferenceMode.IsEnabled = true;
                    FWindow.FMain.MI_DifferenceMode.IsChecked = false;
                    if (updateMode)
                    {
                        FWindow.FMain.MI_UpdateMode.IsEnabled = true;
                        FWindow.FMain.MI_UpdateMode.IsChecked = false;
                    }
                });
            }
        }
Exemplo n.º 9
0
        private static async Task LoadBackupFile()
        {
            OpenFileDialog openFiledialog = new OpenFileDialog();

            openFiledialog.Title            = "Choose your Backup File";
            openFiledialog.InitialDirectory = FProp.Default.FOutput_Path + "\\Backups\\";
            openFiledialog.Multiselect      = false;
            openFiledialog.Filter           = "FBKP Files (*.fbkp)|*.fbkp|All Files (*.*)|*.*";
            if (openFiledialog.ShowDialog() == true)
            {
                new UpdateMyProcessEvents("Comparing Files", "Waiting").Update();

                FPakEntry[] BackupEntries;
                using (FileStream fileStream = new FileStream(openFiledialog.FileName, FileMode.Open))
                    using (BinaryReader reader = new BinaryReader(fileStream))
                    {
                        List <FPakEntry> entries = new List <FPakEntry>();
                        while (reader.BaseStream.Position < reader.BaseStream.Length)
                        {
                            FPakEntry entry = new FPakEntry();
                            entry.Pos               = reader.ReadInt64();
                            entry.Size              = reader.ReadInt64();
                            entry.UncompressedSize  = reader.ReadInt64();
                            entry.Encrypted         = reader.ReadBoolean();
                            entry.StructSize        = reader.ReadInt32();
                            entry.Name              = reader.ReadString();
                            entry.CompressionMethod = reader.ReadInt32();
                            entries.Add(entry);
                        }
                        BackupEntries = entries.ToArray();
                    }

                if (BackupEntries.Any())
                {
                    List <FPakEntry> LocalEntries = new List <FPakEntry>();
                    foreach (FPakEntry[] PAKsFileInfos in PAKEntries.PAKToDisplay.Values)
                    {
                        PAKsFileInfos.ToList().ForEach(x => LocalEntries.Add(x));
                    }
                    PAKEntries.PAKToDisplay.Clear();

                    //FILTER WITH THE OVERRIDED EQUALS METHOD (CHECKING FILE NAME AND FILE UNCOMPRESSED SIZE)
                    IEnumerable <FPakEntry> newAssets = LocalEntries.ToArray().Except(BackupEntries);

                    //ADD TO TREE
                    foreach (FPakEntry entry in newAssets)
                    {
                        string onlyFolders = entry.Name.Substring(0, entry.Name.LastIndexOf('/'));
                        await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                        {
                            TreeViewUtility.PopulateTreeView(srt, onlyFolders.Substring(1));
                        });
                    }

                    //ONLY LOAD THE DIFFERENCE WHEN WE CLICK ON A FOLDER
                    FWindow.FCurrentPAK = "ComparedPAK-WindowsClient.pak";
                    PAKEntries.PAKToDisplay.Add("ComparedPAK-WindowsClient.pak", newAssets.ToArray());
                    await FWindow.FMain.Dispatcher.InvokeAsync(() =>
                    {
                        FWindow.FMain.ViewModel = srt;
                    });

                    new UpdateMyProcessEvents("All PAK files have been compared successfully", "Success").Update();
                }
            }
            else
            {
                new UpdateMyConsole("You change your mind pretty fast but it's fine ", CColors.White).Append();
                new UpdateMyConsole("all paks have been loaded instead", CColors.Blue, true).Append();
                FillTreeView(true);
            }
        }
Exemplo n.º 10
0
        private IReadOnlyDictionary <string, GameFile> ReadIndexUpdated(bool caseInsensitive)
        {
            // Prepare primary index and decrypt if necessary
            Ar.Position = Info.IndexOffset;
            FArchive primaryIndex = new FByteArchive($"{Name} - Primary Index", ReadAndDecrypt((int)Info.IndexSize));

            string mountPoint;

            try
            {
                mountPoint = primaryIndex.ReadFString();
            }
            catch (Exception e)
            {
                throw new InvalidAesKeyException($"Given aes key '{AesKey?.KeyString}'is not working with '{Name}'", e);
            }

            ValidateMountPoint(ref mountPoint);
            MountPoint = mountPoint;

            var fileCount = primaryIndex.Read <int>();

            EncryptedFileCount = 0;

            primaryIndex.Position += 8; // PathHashSeed

            if (!primaryIndex.ReadBoolean())
            {
                throw new ParserException(primaryIndex, "No path hash index");
            }

            primaryIndex.Position += 36; // PathHashIndexOffset (long) + PathHashIndexSize (long) + PathHashIndexHash (20 bytes)

            if (!primaryIndex.ReadBoolean())
            {
                throw new ParserException(primaryIndex, "No directory index");
            }

            var directoryIndexOffset = primaryIndex.Read <long>();
            var directoryIndexSize   = primaryIndex.Read <long>();

            primaryIndex.Position += 20; // Directory Index hash
            var encodedPakEntriesSize = primaryIndex.Read <int>();
            var encodedPakEntries     = primaryIndex.ReadBytes(encodedPakEntriesSize);

            if (primaryIndex.Read <int>() < 0)
            {
                throw new ParserException("Corrupt pak PrimaryIndex detected");
            }

            // Read FDirectoryIndex
            Ar.Position = directoryIndexOffset;
            var directoryIndex = new FByteArchive($"{Name} - Directory Index", ReadAndDecrypt((int)directoryIndexSize));

            unsafe
            {
                fixed(byte *ptr = encodedPakEntries)
                {
                    var directoryIndexLength = directoryIndex.Read <int>();

                    var files = new Dictionary <string, GameFile>(fileCount);

                    for (var i = 0; i < directoryIndexLength; i++)
                    {
                        var dir           = directoryIndex.ReadFString();
                        var dirDictLength = directoryIndex.Read <int>();

                        for (var j = 0; j < dirDictLength; j++)
                        {
                            var name  = directoryIndex.ReadFString();
                            var path  = string.Concat(mountPoint, dir, name);
                            var entry = new FPakEntry(this, path, ptr + directoryIndex.Read <int>());
                            if (entry.IsEncrypted)
                            {
                                EncryptedFileCount++;
                            }
                            if (caseInsensitive)
                            {
                                files[path.ToLowerInvariant()] = entry;
                            }
                            else
                            {
                                files[path] = entry;
                            }
                        }
                    }

                    Files = files;

                    return(files);
                }
            }
        }