Ejemplo n.º 1
0
        static void LoadXp3Enc(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return;
            }

            if (File.Exists(filePath))
            {
                Xp3Enc.Load(filePath);
            }
        }
Ejemplo n.º 2
0
        static void CreateArchive(CommandLineOptions options, LinkedList <TFileSource> sourceFiles, string outpuFile)
        {
            // Load encryption module
            LoadXp3Enc(options.Xp3EncPath);

            using (FileStream arcStream = File.Create(outpuFile))
                using (BinaryWriter arcWriter = new BinaryWriter(arcStream))
                {
                    // Write header

                    arcWriter.WriteBytes(new byte[] { 0x58, 0x50, 0x33, 0x0D, 0x0A, 0x20, 0x0A, 0x1A });
                    arcWriter.WriteBytes(new byte[] { 0x8B, 0x67, 0x01 });
                    arcWriter.WriteInt64(8 + 3 + 8 + 4);
                    arcWriter.WriteUInt32(1);

                    arcWriter.WriteByte(0x80);
                    arcWriter.WriteInt64(0);

                    long indexOffsetPos = arcStream.Position;
                    arcWriter.WriteInt64(0);

                    LinkedList <TFileInfo> files = new LinkedList <TFileInfo>();

                    long fileDataStart = arcStream.Position;

                    // Add protection warning file

                    arcWriter.WriteBytes(ProtectionWarningPng);
                    {
                        TFileSegment segm = new TFileSegment();
                        segm.Offset    = fileDataStart + 0x30;
                        segm.Size      = 0x9D; // ProtectionWarningPng.Length;
                        segm.StoreSize = 0x9D; // ProtectionWarningPng.Length;
                        segm.Flags     = 0;

                        TFileInfo info = new TFileInfo();
                        info.Name      = "$$$ This is a protected archive. $$$ 著作者はこのアーカイブが正規の利用方法以外の方法で展開されることを望んでいません。 $$$ This is a protected archive. $$$ 著作者はこのアーカイブが正規の利用方法以外の方法で展開されることを望んでいません。 $$$ This is a protected archive. $$$ 著作者はこのアーカイブが正規の利用方法以外の方法で展開されることを望んでいません。 $$$ Warning! Extracting this archive may infringe on author's rights. 警告 このアーカイブを展開することにより、あなたは著作者の権利を侵害するおそれがあります。.txt";
                        info.NameMd5   = Util.StringMd5(info.Name.ToLower());
                        info.Size      = segm.Size;
                        info.StoreSize = segm.StoreSize;
                        info.Adler32   = Util.Adler32(ProtectionWarningPng);
                        info.Flags     = 0;
                        info.Segments.Add(segm);

                        files.AddLast(info);
                    }

                    // Store file

                    foreach (var item in sourceFiles)
                    {
                        byte[] data = File.ReadAllBytes(item.LocalPath);

                        TFileSegment segm = new TFileSegment();
                        segm.Offset    = arcStream.Position;
                        segm.Size      = data.Length;
                        segm.StoreSize = data.Length;
                        segm.Flags     = 0;

                        TFileInfo info = new TFileInfo();
                        info.Name      = item.Path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                        info.NameMd5   = Util.StringMd5(info.Name.ToLower());
                        info.Timestamp = new DateTimeOffset(new FileInfo(item.LocalPath).LastWriteTime).ToUnixTimeMilliseconds();
                        info.Size      = segm.Size;
                        info.StoreSize = segm.StoreSize;
                        info.Adler32   = Util.Adler32(data); // This algorithm maybe wrong.
                        info.Flags     = (1u << 31);         // protected
                        info.Segments.Add(segm);

                        files.AddLast(info);

                        Console.WriteLine("Storing file: {0}", info.Name);

                        // Encrypt file data
                        if (Xp3Enc.Loaded)
                        {
                            Xp3Enc.Encrypt(info.Adler32, 0, data);
                        }
                        else if (options.XorKey != null)
                        {
                            XorEncrypt(data, (byte)options.XorKey);
                        }

                        // Store to archive
                        arcWriter.WriteBytes(data);
                    }

                    // Build index
                    Console.WriteLine("Building index...");

                    MemoryStream indexStream = new MemoryStream();
                    BinaryWriter indexWriter = new BinaryWriter(indexStream);

                    foreach (var item in files)
                    {
                        new ChunkWriter(indexWriter, "hnfn").Write(hnfnWriter => {
                            hnfnWriter.WriteUInt32(item.Adler32);
                            hnfnWriter.WriteUnicodeString(item.Name);
                        });
                    }

                    foreach (var item in files)
                    {
                        new ChunkWriter(indexWriter, "File").Write(fileWriter => {
                            if (item.Timestamp != 0)
                            {
                                new ChunkWriter(indexWriter, "time").Write(timeWriter => {
                                    timeWriter.WriteInt64(item.Timestamp);
                                });
                            }

                            new ChunkWriter(indexWriter, "adlr").Write(adlrWriter => {
                                adlrWriter.WriteUInt32(item.Adler32);
                            });

                            new ChunkWriter(indexWriter, "segm").Write(segmWriter => {
                                foreach (var segm in item.Segments)
                                {
                                    segmWriter.WriteUInt32(segm.Flags);
                                    segmWriter.WriteInt64(segm.Offset);
                                    segmWriter.WriteInt64(segm.Size);
                                    segmWriter.WriteInt64(segm.StoreSize);
                                }
                            });

                            new ChunkWriter(indexWriter, "info").Write(infoWriter => {
                                infoWriter.WriteUInt32(item.Flags);
                                infoWriter.WriteInt64(item.Size);
                                infoWriter.WriteInt64(item.StoreSize);
                                infoWriter.WriteUnicodeString(item.NameMd5);
                            });
                        });
                    }

                    // Compress index

                    byte[] indexData           = indexStream.ToArray();
                    byte[] compressedIndexData = Util.Deflate(indexData);

                    // Write index

                    long indexOffset = arcStream.Position;

                    arcWriter.WriteByte(1); // compressed
                    arcWriter.WriteInt64(compressedIndexData.Length);
                    arcWriter.WriteInt64(indexData.Length);
                    arcWriter.WriteBytes(compressedIndexData);

                    arcStream.Position = indexOffsetPos;
                    arcWriter.WriteInt64(indexOffset);

                    // Done

                    arcWriter.Flush();
                    arcWriter.Close();

                    Console.WriteLine("Done.");
                }
        }