Пример #1
0
        private static RDAFolder NavigateTo(RDAFolder root, string FullPath, string CurrentPos)
        {
            FullPath   = FullPath.Replace("\\", "/");
            CurrentPos = CurrentPos.Replace("\\", "/");
            FullPath   = FullPath.Trim('/');
            CurrentPos = CurrentPos.Trim('/');
            List <string> list  = Enumerable.ToList(FullPath.Split('/'));
            string        str   = list[0];
            RDAFolder     root1 = null;

            foreach (RDAFolder rdaFolder in root.Folders)
            {
                if (rdaFolder.Name == str)
                {
                    root1 = rdaFolder;
                    break;
                }
            }
            if (root1 == null)
            {
                RDAFolder rdaFolder = new RDAFolder(root);
                rdaFolder.Name     = str;
                rdaFolder.FullPath = CurrentPos + "/" + str;
                root.Folders.Add(rdaFolder);
                root1 = rdaFolder;
            }
            if (list.Count == 1)
            {
                return(root1);
            }
            list.RemoveAt(0);
            return(NavigateTo(root1, StringExtension.PutTogether(list, '/'), CurrentPos + "/" + str));
        }
Пример #2
0
 public static RDAFolder GenerateFrom(List<RDAFile> file, FileHeader.Version version)
 {
     RDAFolder root = new RDAFolder(version);
     root.Files.AddRange(file.FindAll(f => !f.FileName.Contains("/")));
     foreach (RDAFile rdaFile in file.FindAll(f => f.FileName.Contains("/")))
         NavigateTo(root, Path.GetDirectoryName(rdaFile.FileName), "").Files.Add(rdaFile);
     return root;
 }
Пример #3
0
 public void Dispose()
 {
     if (read != null)
         read.Close();
     rdaFileEntries.Clear();
     rdaFolder = null;
     foreach (Stream stream in RDAFileStreamCache.Cache.Values)
         stream.Close();
     RDAFileStreamCache.Cache.Clear();
     GC.Collect();
 }
Пример #4
0
        public static RDAFolder GenerateFrom(List <RDAFile> file, FileHeader.Version version)
        {
            RDAFolder root = new RDAFolder(version);

            root.Files.AddRange(file.FindAll(f => !f.FileName.Contains("/")));
            foreach (RDAFile rdaFile in file.FindAll(f => f.FileName.Contains("/")))
            {
                NavigateTo(root, Path.GetDirectoryName(rdaFile.FileName), "").Files.Add(rdaFile);
            }
            return(root);
        }
Пример #5
0
 public void Dispose()
 {
     if (read != null)
     {
         read.Close();
     }
     rdaFileEntries.Clear();
     rdaFolder = null;
     foreach (Stream stream in RDAFileStreamCache.Cache.Values)
     {
         stream.Close();
     }
     RDAFileStreamCache.Cache.Clear();
     GC.Collect();
 }
Пример #6
0
        public static List<RDAFolder> GenerateOf(RDAFolder root)
        {
            Dictionary<string, RDAFolder> dictionary = new Dictionary<string, RDAFolder>();
            foreach (RDAFile rdaFile in root.GetAllFiles())
            {
                string key = Path.GetExtension(rdaFile.FileName).ToLower();
                if (!dictionary.ContainsKey(key))
                    dictionary.Add(key, new RDAFolder(root.Version));
                dictionary[key].Files.Add(rdaFile);
            }

            foreach (KeyValuePair<string, RDAFolder> keyValuePair in dictionary)
                keyValuePair.Value.RDABlockCreator_FileType_IsCompressable = new bool?(FileType_CompressedExtensions.Contains(keyValuePair.Key));

            return Enumerable.ToList(dictionary.Values);
        }
Пример #7
0
        public static List <RDAFolder> GenerateOf(RDAFolder root)
        {
            Dictionary <string, RDAFolder> dictionary = new Dictionary <string, RDAFolder>();

            foreach (RDAFile rdaFile in root.GetAllFiles())
            {
                string key = Path.GetExtension(rdaFile.FileName).ToLower();
                if (!dictionary.ContainsKey(key))
                {
                    dictionary.Add(key, new RDAFolder(root.Version));
                }
                dictionary[key].Files.Add(rdaFile);
            }

            foreach (KeyValuePair <string, RDAFolder> keyValuePair in dictionary)
            {
                keyValuePair.Value.RDABlockCreator_FileType_IsCompressable = new bool?(FileType_CompressedExtensions.Contains(keyValuePair.Key));
            }

            return(Enumerable.ToList(dictionary.Values));
        }
Пример #8
0
        public void ReadRDAFile()
        {
            read = new BinaryReader(new FileStream(FileName, FileMode.Open));

            byte[] firstTwoBytes = read.ReadBytes(2); read.BaseStream.Position = 0;
            if (firstTwoBytes[0] == 'R' && firstTwoBytes[1] == '\0')
            {
                fileHeader = ReadFileHeader(read, FileHeader.Version.Version_2_0);
            }
            else if (firstTwoBytes[0] == 'R' && firstTwoBytes[1] == 'e')
            {
                fileHeader = ReadFileHeader(read, FileHeader.Version.Version_2_2);
            }
            else
            {
                throw new Exception("Invalid or unsupported RDA file!");
            }

            rdaReadBlocks = 0;
            skippedDataSections.Clear();

            ulong beginningOfDataSection = (ulong)read.BaseStream.Position;
            ulong currentBlockOffset     = fileHeader.firstBlockOffset;

            while (currentBlockOffset < (ulong)read.BaseStream.Length)
            {
                ulong nextBlockOffset = ReadBlock(currentBlockOffset, beginningOfDataSection);
                beginningOfDataSection = currentBlockOffset + BlockInfo.GetSize(fileHeader.version);
                currentBlockOffset     = nextBlockOffset;
            }

            // When writing we need to make sure that the section that is latest in the file is the last one in this list.
            skippedDataSections.Sort((a, b) => a.offset.CompareTo(b.offset));

            rdaFolder = RDAFolder.GenerateFrom(rdaFileEntries, fileHeader.version);
            UpdateOutput("Done. " + rdaFileEntries.Count + " files. " + rdaReadBlocks + " blocks read, " + NumSkippedBlocks + " encrypted blocks skipped (" + NumSkippedFiles + " files).");
        }
Пример #9
0
        public void ReadRDAFile()
        {
            read = new BinaryReader(new FileStream(FileName, FileMode.Open));

            byte[] firstTwoBytes = read.ReadBytes(2); read.BaseStream.Position = 0;
            if (firstTwoBytes[0] == 'R' && firstTwoBytes[1] == '\0')
            {
                fileHeader = ReadFileHeader(read, FileHeader.Version.Version_2_0);
            }
            else if (firstTwoBytes[0] == 'R' && firstTwoBytes[1] == 'e')
            {
                fileHeader = ReadFileHeader(read, FileHeader.Version.Version_2_2);
            }
            else
            {
                throw new Exception("Invalid or unsupported RDA file!");
            }

            rdaReadBlocks = 0;
            skippedDataSections.Clear();

            ulong beginningOfDataSection = (ulong)read.BaseStream.Position;
            ulong currentBlockOffset = fileHeader.firstBlockOffset;
            while (currentBlockOffset < (ulong)read.BaseStream.Length)
            {
                ulong nextBlockOffset = ReadBlock(currentBlockOffset, beginningOfDataSection);
                beginningOfDataSection = currentBlockOffset + BlockInfo.GetSize(fileHeader.version);
                currentBlockOffset = nextBlockOffset;
            }

            // When writing we need to make sure that the section that is latest in the file is the last one in this list.
            skippedDataSections.Sort((a, b) => a.offset.CompareTo(b.offset));

            rdaFolder = RDAFolder.GenerateFrom(rdaFileEntries, fileHeader.version);
            UpdateOutput("Done. " + rdaFileEntries.Count + " files. " + rdaReadBlocks + " blocks read, " + NumSkippedBlocks + " encrypted blocks skipped (" + NumSkippedFiles + " files).");
        }
Пример #10
0
 public RDAWriter(RDAFolder folder)
 {
     Folder = folder;
 }
Пример #11
0
 public RDAFolder(RDAFolder parent)
 {
     this.Parent  = parent;
     this.Version = parent.Version;
 }
Пример #12
0
 public RDAFolder(RDAFolder parent)
 {
     this.Parent = parent;
     this.Version = parent.Version;
 }
Пример #13
0
 private static RDAFolder NavigateTo(RDAFolder root, string FullPath, string CurrentPos)
 {
     FullPath = FullPath.Replace("\\", "/");
     CurrentPos = CurrentPos.Replace("\\", "/");
     FullPath = FullPath.Trim('/');
     CurrentPos = CurrentPos.Trim('/');
     List<string> list = Enumerable.ToList(FullPath.Split('/'));
     string str = list[0];
     RDAFolder root1 = null;
     foreach (RDAFolder rdaFolder in root.Folders)
     {
         if (rdaFolder.Name == str)
         {
             root1 = rdaFolder;
             break;
         }
     }
     if (root1 == null)
     {
         RDAFolder rdaFolder = new RDAFolder(root);
         rdaFolder.Name = str;
         rdaFolder.FullPath = CurrentPos + "/" + str;
         root.Folders.Add(rdaFolder);
         root1 = rdaFolder;
     }
     if (list.Count == 1)
         return root1;
     list.RemoveAt(0);
     return NavigateTo(root1, StringExtension.PutTogether(list, '/'), CurrentPos + "/" + str);
 }
Пример #14
0
        public void Write(string Filename, FileHeader.Version version, bool compress, RDAReader originalReader, BackgroundWorker wrk)
        {
            FileStream   fileStream = new FileStream(Filename, FileMode.Create);
            BinaryWriter writer     = new BinaryWriter(fileStream);

            // we'll write the header at the end, when we know the offset to the first block
            writer.BaseStream.Position = FileHeader.GetSize(version);

            // blocks are organized by file type. there is one RDAFolder per block
            List <RDAFolder> blockFolders = RDABlockCreator.GenerateOf(Folder);
            int numBlocks = (int)originalReader.NumSkippedBlocks + blockFolders.Count;

            BlockInfo[] blockInfos       = new BlockInfo[numBlocks];
            ulong[]     blockInfoOffsets = new ulong[numBlocks];
            int         writeBlockIndex  = 0;

            // Write blocks skipped when reading. They have to appear at exactly the place where they came
            // from, because the file data offsets are encrypted and can therefore not be changed.
            for (int skippedBlockIndex = 0; skippedBlockIndex < originalReader.NumSkippedBlocks; ++skippedBlockIndex)
            {
                RDASkippedDataSection skippedBlock = originalReader.SkippedDataSections[skippedBlockIndex];

                if (wrk != null)
                {
                    UI_LastMessage = "Writing  Block " + (writeBlockIndex + 1) + "/" + numBlocks + " => ??? files (encrypted)";
                    wrk.ReportProgress((int)((double)writeBlockIndex / numBlocks * 100.0));
                }

                // Skip ahead to the correct position.
                // This will create "holes" in the file if the skipped sections are not contiguous or
                // don't start at the beginning of the file, but we'll have to live with it to some extent
                // anyway (we won't fit our "own" data in perfectly). And I'm just too afraid to get the
                // bin-packing wrong.
                writer.BaseStream.WriteBytes((skippedBlock.offset - (ulong)writer.BaseStream.Position), 0);

                // write the data
                originalReader.CopySkippedDataSextion(skippedBlock.offset, skippedBlock.size, writer.BaseStream);

                // generate the new block info
                BlockInfo blockInfo = skippedBlock.blockInfo.Clone();
                blockInfos[writeBlockIndex]       = blockInfo;
                blockInfoOffsets[writeBlockIndex] = (ulong)writer.BaseStream.Position;

                if (writeBlockIndex > 0)
                {
                    blockInfos[writeBlockIndex - 1].nextBlock = blockInfoOffsets[writeBlockIndex];
                }

                // we'll write the block info at the end, once we know the next block offset
                writer.BaseStream.Position += BlockInfo.GetSize(version);
                ++writeBlockIndex;
            }

            // write regular blocks
            for (int blockFolderIndex = 0; blockFolderIndex < blockFolders.Count; ++blockFolderIndex)
            {
                RDAFolder blockFolder = blockFolders[blockFolderIndex];

                bool compressBlock = compress && blockFolder.RDABlockCreator_FileType_IsCompressable.GetValueOrDefault(false);

                if (wrk != null)
                {
                    UI_LastMessage = "Writing Block " + (writeBlockIndex + 1) + "/" + numBlocks + " => " + blockFolder.Files.Count + " files";
                    wrk.ReportProgress((int)((double)writeBlockIndex / numBlocks * 100.0));
                }

                Dictionary <RDAFile, ulong> dirEntryOffsets         = new Dictionary <RDAFile, ulong>();
                Dictionary <RDAFile, ulong> dirEntryCompressedSizes = new Dictionary <RDAFile, ulong>();
                foreach (RDAFile file in blockFolder.Files)
                {
                    byte[] dataToWrite = file.GetData();
                    if (compressBlock)
                    {
                        dataToWrite = ZLib.ZLib.Compress(dataToWrite);
                    }
                    dirEntryOffsets.Add(file, (ulong)writer.BaseStream.Position);
                    dirEntryCompressedSizes.Add(file, (ulong)dataToWrite.Length);
                    writer.Write(dataToWrite);
                }

                int    dirEntrySize = (int)DirEntry.GetSize(version);
                int    decompressedDirEntriesSize = blockFolder.Files.Count * dirEntrySize;
                byte[] decompressedDirEntries     = new byte[decompressedDirEntriesSize];
                for (int dirEntryIndex = 0; dirEntryIndex < blockFolder.Files.Count; ++dirEntryIndex)
                {
                    RDAFile  file     = blockFolder.Files[dirEntryIndex];
                    DirEntry dirEntry = new DirEntry()
                    {
                        compressed = dirEntryCompressedSizes[file],
                        filesize   = file.UncompressedSize,
                        filename   = file.FileName,
                        timestamp  = file.TimeStamp.ToTimeStamp(),
                        unknown    = 0,
                        offset     = dirEntryOffsets[file],
                    };
                    byte[] dirEntryBytes = CreateDirEntryBytes(dirEntry, version);
                    Buffer.BlockCopy(dirEntryBytes, 0, decompressedDirEntries, dirEntryIndex * dirEntrySize, dirEntrySize);
                }
                byte[] compressedDirEntries = compressBlock ? ZLib.ZLib.Compress(decompressedDirEntries) : decompressedDirEntries;
                writer.Write(compressedDirEntries);

                BlockInfo blockInfo = new BlockInfo()
                {
                    flags            = compressBlock ? 1u : 0u,
                    fileCount        = (uint)blockFolder.Files.Count,
                    directorySize    = (ulong)compressedDirEntries.Length,
                    decompressedSize = (ulong)decompressedDirEntriesSize,
                    nextBlock        = 0, // will set this at the end of the next block
                };
                blockInfos[writeBlockIndex]       = blockInfo;
                blockInfoOffsets[writeBlockIndex] = (ulong)writer.BaseStream.Position;

                if (writeBlockIndex > 0)
                {
                    blockInfos[writeBlockIndex - 1].nextBlock = blockInfoOffsets[writeBlockIndex];
                }

                // we'll write the block info at the end, once we know the next block offset
                writer.BaseStream.Position += BlockInfo.GetSize(version);
                ++writeBlockIndex;
            }
            // the last block gets nextBlockOffset after end of file
            blockInfos[blockInfos.Length - 1].nextBlock = blockInfoOffsets[blockInfos.Length - 1] + BlockInfo.GetSize(version);

            // now write all block infos
            for (int index = 0; index < blockInfos.Length; ++index)
            {
                WriteBlockInfo(writer, blockInfoOffsets[index], blockInfos[index], version);
            }

            // now write the header
            FileHeader fileHeader = FileHeader.Create(version);

            fileHeader.firstBlockOffset = blockInfoOffsets[0];
            WriteHeader(writer, 0, fileHeader, version);

            fileStream.Close();
        }
Пример #15
0
 public RDAWriter(RDAFolder folder)
 {
     Folder = folder;
 }