Repository navigation
Expand file tree
/
Copy pathMiniZip.cs
More file actions
94 lines (82 loc) · 3.35 KB
/
Copy pathMiniZip.cs
File metadata and controls
94 lines (82 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace ModUpdater
{
public static class MiniZip
{
public struct ZipEntry
{
public string FileName;
public byte[] Data;
}
public static List<ZipEntry> Extract(byte[] zipBytes)
{
var entries = new List<ZipEntry>();
using (var stream = new MemoryStream(zipBytes))
using (var reader = new BinaryReader(stream))
{
while (stream.Position < stream.Length - 4)
{
uint signature = reader.ReadUInt32();
if (signature != 0x04034b50)
break;
reader.ReadUInt16(); // version needed
ushort flags = reader.ReadUInt16();
ushort method = reader.ReadUInt16();
reader.ReadUInt32(); // mod time + date
reader.ReadUInt32(); // crc32
uint compressedSize = reader.ReadUInt32();
uint uncompressedSize = reader.ReadUInt32();
ushort nameLen = reader.ReadUInt16();
ushort extraLen = reader.ReadUInt16();
string fileName = Encoding.UTF8.GetString(reader.ReadBytes(nameLen));
reader.ReadBytes(extraLen);
bool hasDataDescriptor = (flags & 0x08) != 0;
if (fileName.EndsWith("/") || fileName.EndsWith("\\"))
{
if (compressedSize > 0)
reader.ReadBytes((int)compressedSize);
continue;
}
byte[] fileData;
if (method == 0)
{
fileData = reader.ReadBytes((int)compressedSize);
}
else if (method == 8)
{
byte[] compressed = reader.ReadBytes((int)compressedSize);
using (var compStream = new MemoryStream(compressed))
using (var deflate = new DeflateStream(compStream, CompressionMode.Decompress))
using (var output = new MemoryStream())
{
deflate.CopyTo(output);
fileData = output.ToArray();
}
}
else
{
throw new NotSupportedException($"Unsupported compression method {method} for {fileName}");
}
if (hasDataDescriptor)
{
uint maybeSignature = reader.ReadUInt32();
if (maybeSignature == 0x08074b50)
{
reader.ReadBytes(12); // crc32 + compressed + uncompressed
}
else
{
reader.ReadBytes(8); // compressed + uncompressed (maybeSignature was crc32)
}
}
entries.Add(new ZipEntry { FileName = fileName, Data = fileData });
}
}
return entries;
}
}
}