public override Stream OpenEntry(ArcFile arc, Entry entry) { Stream input; if (arc is NpaArchive && entry is NpaEntry) { input = new EncryptedStream(arc as NpaArchive, entry as NpaEntry); } else { input = arc.File.CreateStream(entry.Offset, entry.Size); } return(UnpackEntry(input, entry as PackedEntry)); }
public override void Create(Stream output, IEnumerable <Entry> list, ResourceOptions options, EntryCallback callback) { var npa_options = GetOptions <NpaOptions> (options); int callback_count = 0; // build file index var index = new Indexer(list, npa_options); output.Position = 41 + index.Size; long data_offset = 0; // write files foreach (var entry in index.Entries.Where(e => e.Type != "directory")) { if (data_offset > uint.MaxValue) { throw new FileSizeException(); } if (null != callback) { callback(callback_count++, entry, arcStrings.MsgAddingFile); } using (var file = File.OpenRead(entry.Name)) { var size = file.Length; if (size > uint.MaxValue) { throw new FileSizeException(); } entry.Offset = data_offset; entry.UnpackedSize = (uint)size; Stream destination = output; if (null != npa_options.Scheme) { destination = new EncryptedStream(output, entry, npa_options.Scheme, index.Key); } try { if (entry.IsPacked) { var start = destination.Position; using (var zstream = new ZLibStream(destination, CompressionMode.Compress, CompressionLevel.Level9, true)) { file.CopyTo(zstream); } entry.Size = (uint)(destination.Position - start); } else { file.CopyTo(destination); entry.Size = entry.UnpackedSize; } } finally { if (destination is EncryptedStream) { destination.Dispose(); } } data_offset += entry.Size; } } if (null != callback) { callback(callback_count++, null, arcStrings.MsgWritingIndex); } output.Position = 0; using (var header = new BinaryWriter(output, Encoding.ASCII, true)) { header.Write(Signature); header.Write((short)0); header.Write((byte)0); header.Write(npa_options.Key1); header.Write(npa_options.Key2); header.Write(npa_options.CompressContents); header.Write(npa_options.Scheme != null); header.Write(index.TotalCount); header.Write(index.FolderCount); header.Write(index.FileCount); header.Write((long)0); header.Write(index.Size); int entry_number = 0; foreach (var entry in index.Entries) { header.Write(entry.RawName.Length); for (int i = 0; i < entry.RawName.Length; ++i) { header.Write((byte)(entry.RawName[i] - DecryptName(i, entry_number, index.Key))); } header.Write((byte)("directory" == entry.Type ? 1 : 2)); header.Write(entry.FolderId); header.Write((uint)entry.Offset); header.Write(entry.Size); header.Write(entry.UnpackedSize); ++entry_number; } } }