Exemplo n.º 1
0
 public NpkWriter(NpkStoredEntry entry, Stream archive, Aes aes)
 {
     m_input   = File.OpenRead(entry.Name);
     m_archive = archive;
     m_entry   = entry;
     m_aes     = aes;
     m_buffer  = null;
 }
Exemplo n.º 2
0
        public override void Create(Stream output, IEnumerable <Entry> list, ResourceOptions options,
                                    EntryCallback callback)
        {
            var npk_options = GetOptions <Npk2Options> (options);

            if (null == npk_options.Key)
            {
                throw new InvalidEncryptionScheme();
            }

            var enc          = DefaultEncoding.WithFatalFallback();
            int index_length = 0;
            var dir          = new List <NpkStoredEntry>();

            foreach (var entry in list)
            {
                var ext       = Path.GetExtension(entry.Name).ToLowerInvariant();
                var npk_entry = new NpkStoredEntry
                {
                    Name     = entry.Name,
                    RawName  = enc.GetBytes(entry.Name.Replace('\\', '/')),
                    IsSolid  = SolidFiles.Contains(ext),
                    IsPacked = !DisableCompression.Contains(ext),
                };
                int segment_count = 1;
                if (!npk_entry.IsSolid)
                {
                    segment_count = (int)(((long)entry.Size + DefaultSegmentSize - 1) / DefaultSegmentSize);
                }
                index_length += 3 + npk_entry.RawName.Length + 0x28 + segment_count * 0x14;
                dir.Add(npk_entry);
            }
            index_length = (index_length + 0xF) & ~0xF;

            int callback_count = 0;

            using (var aes = Aes.Create())
            {
                aes.Mode        = CipherMode.CBC;
                aes.Padding     = PaddingMode.PKCS7;
                aes.Key         = npk_options.Key;
                aes.IV          = GenerateAesIV();
                output.Position = 0x20 + index_length;
                foreach (var entry in dir)
                {
                    if (null != callback)
                    {
                        callback(callback_count++, entry, arcStrings.MsgAddingFile);
                    }

                    using (var writer = new NpkWriter(entry, output, aes))
                        writer.Write(DefaultSegmentSize);
                }
                output.Position = 0;
                var buffer = new byte[] { (byte)'N', (byte)'P', (byte)'K', (byte)'2', 1, 0, 0, 0 };
                output.Write(buffer, 0, 8);
                output.Write(aes.IV, 0, 0x10);
                LittleEndian.Pack(dir.Count, buffer, 0);
                LittleEndian.Pack(index_length, buffer, 4);
                output.Write(buffer, 0, 8);

                using (var encryptor = aes.CreateEncryptor())
                    using (var proxy = new ProxyStream(output, true))
                        using (var index_stream = new CryptoStream(proxy, encryptor, CryptoStreamMode.Write))
                            using (var index = new BinaryWriter(index_stream))
                            {
                                if (null != callback)
                                {
                                    callback(callback_count++, null, arcStrings.MsgWritingIndex);
                                }
                                foreach (var entry in dir)
                                {
                                    index.Write(entry.IsSolid); // 0 -> segmentation enabled, 1 -> no segmentation
                                    index.Write((short)entry.RawName.Length);
                                    index.Write(entry.RawName);
                                    index.Write(entry.UnpackedSize);
                                    index.Write(entry.CheckSum);
                                    index.Write(entry.Segments.Count);
                                    foreach (var segment in entry.Segments)
                                    {
                                        index.Write(segment.Offset);
                                        index.Write(segment.AlignedSize);
                                        index.Write(segment.Size);
                                        index.Write(segment.UnpackedSize);
                                    }
                                }
                            }
            }
        }