mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
Compare commits
1768 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a7bdd39e8 | ||
|
|
484bc740d7 | ||
|
|
8a67d501a8 | ||
|
|
3c87242bd0 | ||
|
|
999124e68e | ||
|
|
db2f5c9cb9 | ||
|
|
af08a7cd54 | ||
|
|
72eaf66f05 | ||
|
|
8a3be35d67 | ||
|
|
d59e4c2a0d | ||
|
|
71655e04c4 | ||
|
|
a706a9d725 | ||
|
|
970934a40b | ||
|
|
a9c28a7b62 | ||
|
|
4d31436740 | ||
|
|
c82744c51c | ||
|
|
f0eaddc6a6 | ||
|
|
d6156f0f1e | ||
|
|
3c88c7fdd5 | ||
|
|
d11f6aefb0 | ||
|
|
010a38bb73 | ||
|
|
53f12d75db | ||
|
|
6c866324b2 | ||
|
|
a114155189 | ||
|
|
014bbc3ea4 | ||
|
|
d52facd4ab | ||
|
|
0a50386ada | ||
|
|
b9fc680548 | ||
|
|
7dcc13c1f0 | ||
|
|
56d3091688 | ||
|
|
a0af0604d1 | ||
|
|
875c2d7694 | ||
|
|
8c95f863cb | ||
|
|
ddf37e82c2 | ||
|
|
a82fda98d7 | ||
|
|
44e4b1804e | ||
|
|
4ca1a7713e | ||
|
|
9caf7be928 | ||
|
|
bf4217fde6 | ||
|
|
d5a8c37113 | ||
|
|
21ce9a38e6 | ||
|
|
7732fbb698 | ||
|
|
97879f18b6 | ||
|
|
d74454f7e9 | ||
|
|
5c947bccc7 | ||
|
|
fbdefc17c1 | ||
|
|
1425c6ff0d | ||
|
|
e038aea694 | ||
|
|
87ccbf329d | ||
|
|
9dcf384263 | ||
|
|
be045c4f15 | ||
|
|
fd968b3f78 | ||
|
|
833dd7b3a2 | ||
|
|
b9258ad496 | ||
|
|
0678318dde | ||
|
|
7116c0d098 | ||
|
|
2fde8436fb | ||
|
|
61ecd6475f | ||
|
|
64b209a772 | ||
|
|
48dbdbfed5 | ||
|
|
cf50311b9c | ||
|
|
e4d8582a2a | ||
|
|
b8e5ee45eb | ||
|
|
9f20a9e7d2 | ||
|
|
201521d814 | ||
|
|
18bb3cba11 | ||
|
|
af951d6f6a | ||
|
|
e5fe92bf90 | ||
|
|
b1aca7c305 | ||
|
|
c0a0cc4a44 | ||
|
|
7a49eb9e93 | ||
|
|
5aa0610882 | ||
|
|
41ed4c8186 | ||
|
|
90a33ce6b0 | ||
|
|
12574798e1 | ||
|
|
83b11254db | ||
|
|
b25493fd29 | ||
|
|
bb66100486 | ||
|
|
3ebf97dd49 | ||
|
|
bfcdeb3784 | ||
|
|
feece3d788 | ||
|
|
94adb77e9e | ||
|
|
909d36c237 | ||
|
|
e1c8aa226d | ||
|
|
2327679f23 | ||
|
|
574d9f970c | ||
|
|
235096a2eb | ||
|
|
a739fdc544 | ||
|
|
6196e26044 | ||
|
|
46a4064989 | ||
|
|
72b3948f43 | ||
|
|
5d47bfaeb6 | ||
|
|
b2f2ea65ba | ||
|
|
7afa468e15 | ||
|
|
29cb1fed12 | ||
|
|
29f8b512c4 | ||
|
|
9794c8ba72 | ||
|
|
f1b305f682 | ||
|
|
091a800c9d | ||
|
|
975f5f4b4c | ||
|
|
9d6cd930ea | ||
|
|
d5913e8371 | ||
|
|
7f71f76f6e | ||
|
|
caa82a6146 | ||
|
|
bcf7137073 | ||
|
|
9238cf1128 | ||
|
|
2f874ace51 | ||
|
|
2feabed297 | ||
|
|
9001e28b36 | ||
|
|
24d651d7ae | ||
|
|
5667595587 | ||
|
|
32d5b61c4a | ||
|
|
128c9e639f | ||
|
|
5e3f01dc03 | ||
|
|
c97c05a3a7 | ||
|
|
b2beea9c4e | ||
|
|
41fbaa1c28 | ||
|
|
d9274cf794 | ||
|
|
583b048046 | ||
|
|
ead5916eae | ||
|
|
d15ab92da3 | ||
|
|
1ab30f2af5 | ||
|
|
4dbe0b91f1 | ||
|
|
a972d3784e | ||
|
|
6991900eb0 | ||
|
|
d614beb9eb | ||
|
|
253a46d458 | ||
|
|
32b1ec32c6 | ||
|
|
eb2cba09b2 | ||
|
|
e79dceb67e | ||
|
|
87c38d6dab | ||
|
|
9e98d9c45c | ||
|
|
0e9a4b0511 | ||
|
|
eae25aff64 | ||
|
|
b8c06ff36e | ||
|
|
6cf2e054bf | ||
|
|
95749234f5 | ||
|
|
b976961434 | ||
|
|
e1aa727513 | ||
|
|
1f71ce1be2 | ||
|
|
cf13de6ac1 | ||
|
|
c2e01798f8 | ||
|
|
8fc8295a89 | ||
|
|
d392991764 | ||
|
|
e57e87090f | ||
|
|
c701bbbee3 | ||
|
|
2f0eb0bd4b | ||
|
|
17bde8da8a | ||
|
|
99d355e6ca | ||
|
|
c790fd21a4 | ||
|
|
bee51af48b | ||
|
|
ca743eae22 | ||
|
|
93504cf82f | ||
|
|
6d3e4e842b | ||
|
|
54b64a8c3b | ||
|
|
0e59bf39f4 | ||
|
|
8b95e0a76d | ||
|
|
48a2ad7b57 | ||
|
|
cfc6651fff | ||
|
|
b23827a8db | ||
|
|
3f9986c13c | ||
|
|
224989f19b | ||
|
|
c7010b75c1 | ||
|
|
00cfeee56e | ||
|
|
aaa97e2ce2 | ||
|
|
1d52618137 | ||
|
|
34309f17f4 | ||
|
|
220ba67faa | ||
|
|
230f96e8e8 | ||
|
|
930c8899d2 | ||
|
|
7c0cef7dd8 | ||
|
|
951ebb3fa2 | ||
|
|
2a4d098b41 | ||
|
|
5839b87f98 | ||
|
|
425a2bd680 | ||
|
|
939c2497c8 | ||
|
|
8995ba56b8 | ||
|
|
e941ab60ca | ||
|
|
48860f1349 | ||
|
|
94b2c5c593 | ||
|
|
f1d8ae5a22 | ||
|
|
e44d2093e5 | ||
|
|
9fa1201a4c | ||
|
|
7800808648 | ||
|
|
2789e86d21 | ||
|
|
afd1e39b88 | ||
|
|
aec4c738ef | ||
|
|
63ecc8c842 | ||
|
|
5f6d583521 | ||
|
|
0341984f10 | ||
|
|
fe757486ae | ||
|
|
46d480c9a1 | ||
|
|
8fe3cba7a8 | ||
|
|
aa19f4da8b | ||
|
|
a08f95326c | ||
|
|
b4c5437c92 | ||
|
|
8680e3b39e | ||
|
|
1b3002c8df | ||
|
|
394fd2e7db | ||
|
|
d83af56d28 | ||
|
|
28c93d6841 | ||
|
|
5f52fc2176 | ||
|
|
8fba579e3a | ||
|
|
40b1aadeb2 | ||
|
|
40e72ad199 | ||
|
|
618b4bbb83 | ||
|
|
1eaf3e6294 | ||
|
|
fd453e946d | ||
|
|
c294071015 | ||
|
|
c2f6055e33 | ||
|
|
5161f4df33 | ||
|
|
3396f8fe00 | ||
|
|
9291f58091 | ||
|
|
85f3b17c42 | ||
|
|
2a3086a0d7 | ||
|
|
41c3cc1a18 | ||
|
|
1b1df86a11 | ||
|
|
e0660e7775 | ||
|
|
99a6c4de88 | ||
|
|
ffa765bd97 | ||
|
|
b1696524b3 | ||
|
|
14d432e22d | ||
|
|
6a37c55085 | ||
|
|
9c1c6fff9f | ||
|
|
db8c6f4bcb | ||
|
|
ff17ecda7d | ||
|
|
692058677c | ||
|
|
1e90d69912 | ||
|
|
64a1cc68e1 | ||
|
|
0fdf9c74a8 | ||
|
|
20353f35ff | ||
|
|
e2df7894f9 | ||
|
|
7af029b5de | ||
|
|
8fc5ca5a71 | ||
|
|
aa0356de9f | ||
|
|
e44a43d2b1 | ||
|
|
8997f00b9b | ||
|
|
c5da416764 | ||
|
|
840e58fc03 | ||
|
|
7f911c5219 | ||
|
|
a887390c23 | ||
|
|
f4dddcec8e | ||
|
|
0d9d82d7e6 | ||
|
|
3a6d24b1d9 | ||
|
|
b9b159be4c | ||
|
|
40212083a5 | ||
|
|
d3428b066e | ||
|
|
94c64b2a45 | ||
|
|
0d671a0bb2 | ||
|
|
d34a47c148 | ||
|
|
5aa216bd21 | ||
|
|
8af47548fe | ||
|
|
131bd2b7b8 | ||
|
|
1993673a22 | ||
|
|
30e036f9ec | ||
|
|
0f374b27cf | ||
|
|
0d487df61b | ||
|
|
c082d4203b | ||
|
|
d4380b6bb6 | ||
|
|
095c871174 | ||
|
|
6d73c5b295 | ||
|
|
cc4d28193c | ||
|
|
9433e06b93 | ||
|
|
a92aaa51d5 | ||
|
|
d41908adeb | ||
|
|
81ca15b567 | ||
|
|
b81d0fd730 | ||
|
|
3a1bb187e8 | ||
|
|
3fee14a070 | ||
|
|
5bf789ac65 | ||
|
|
be06049db3 | ||
|
|
a0435f6a60 | ||
|
|
2321e2c90b | ||
|
|
97e98d8629 | ||
|
|
d96e7362d2 | ||
|
|
7dd46fe5ed | ||
|
|
04c044cb2b | ||
|
|
cc10a12fbc | ||
|
|
8b0a1c699f | ||
|
|
15ca7c9807 | ||
|
|
2b4da7e39b | ||
|
|
31f81f38af | ||
|
|
72cf77b7c7 | ||
|
|
0fe48c647e | ||
|
|
7b06652bff | ||
|
|
434ce05416 | ||
|
|
0698031ed4 | ||
|
|
51237a34eb | ||
|
|
b8264a8131 | ||
|
|
cad923018e | ||
|
|
db94b49941 | ||
|
|
72d15d9cbf | ||
|
|
e0186eadc0 | ||
|
|
4cfa5b04af | ||
|
|
f2c54b1f8b | ||
|
|
d7d0bc6582 | ||
|
|
dd9dc2500b | ||
|
|
4efb109da8 | ||
|
|
bcf9a6bdf1 | ||
|
|
e3a25ecdc0 | ||
|
|
783521928d | ||
|
|
9a876abd31 | ||
|
|
97f58b412e | ||
|
|
4c61628078 | ||
|
|
99a8b0f750 | ||
|
|
a9017d7c25 | ||
|
|
d9e4b26648 | ||
|
|
0d03bafe49 | ||
|
|
fee15a31f9 | ||
|
|
997d3910d4 | ||
|
|
a3918cc0d7 | ||
|
|
f056986b07 | ||
|
|
59c1f02f98 | ||
|
|
3a71a2b1f8 | ||
|
|
2ef1215b49 | ||
|
|
130ac83076 | ||
|
|
dd606a0702 | ||
|
|
84cd772f50 | ||
|
|
fa1d7af22f | ||
|
|
a771ba3bc0 | ||
|
|
8b612c658d | ||
|
|
7dd0da5fd7 | ||
|
|
f7b3525c4e | ||
|
|
de83bdae48 | ||
|
|
d90b610767 | ||
|
|
2d41de6b72 | ||
|
|
f391c3caf3 | ||
|
|
9bdf150676 | ||
|
|
0c199609eb | ||
|
|
6eff9d3753 | ||
|
|
7ab16457c7 | ||
|
|
e7ad8132b5 | ||
|
|
da87e45534 | ||
|
|
2ffaef5563 | ||
|
|
55cb350d2c | ||
|
|
7fa271a1b4 | ||
|
|
c53ca372f2 | ||
|
|
75bc8501f4 | ||
|
|
1e22b47fe1 | ||
|
|
74e2dca207 | ||
|
|
a669de24b7 | ||
|
|
e1e9c449e9 | ||
|
|
60e1dc0239 | ||
|
|
10eb94fd82 | ||
|
|
ccc8587e5f | ||
|
|
53c96193c1 | ||
|
|
d4f11e00b1 | ||
|
|
321233b82c | ||
|
|
eb188051d4 | ||
|
|
a136084e11 | ||
|
|
bc06f3179d | ||
|
|
ee84d971b2 | ||
|
|
264d80ef4c | ||
|
|
dba68187ac | ||
|
|
ca4a1936b3 | ||
|
|
77c8d31a90 | ||
|
|
ab7196f86c | ||
|
|
88b3a66bf9 | ||
|
|
ea77666b4a | ||
|
|
db98e5f39b | ||
|
|
df59c5cb9d | ||
|
|
e786e95358 | ||
|
|
75ada5623c | ||
|
|
ad5c655c45 | ||
|
|
65e607454e | ||
|
|
f238be6003 | ||
|
|
dc31e4c5fa | ||
|
|
665d8cd266 | ||
|
|
8324114e84 | ||
|
|
b83e6ee4ce | ||
|
|
58bab0d310 | ||
|
|
1af51aaaba | ||
|
|
a09327b831 | ||
|
|
16543bf74c | ||
|
|
aa4cd373ac | ||
|
|
351e294362 | ||
|
|
a0c5b1cd9d | ||
|
|
df2ed1e584 | ||
|
|
b354f7a3a5 | ||
|
|
bb53d1e1c6 | ||
|
|
2aabd8d0e1 | ||
|
|
aca97c2c6c | ||
|
|
8e7d959cf4 | ||
|
|
b23f031db9 | ||
|
|
1ba529a9d5 | ||
|
|
3d29c183ef | ||
|
|
8a108b590d | ||
|
|
bca0f67344 | ||
|
|
f3dad51134 | ||
|
|
f51840829c | ||
|
|
aa1c0d0870 | ||
|
|
dee5ee6589 | ||
|
|
b799f479c4 | ||
|
|
b4352fefa5 | ||
|
|
77d06fb60e | ||
|
|
00b647457c | ||
|
|
153d10a35c | ||
|
|
06713c641e | ||
|
|
210978ec2d | ||
|
|
42f7d43139 | ||
|
|
19967f5ad7 | ||
|
|
a1de3eb47d | ||
|
|
e88841bdec | ||
|
|
c8e4915f8e | ||
|
|
a93a3f0598 | ||
|
|
084f81fc8d | ||
|
|
d148f36e87 | ||
|
|
150d9c35b7 | ||
|
|
e11198616e | ||
|
|
2f27f1e6f9 | ||
|
|
5392ca9794 | ||
|
|
46672eb583 | ||
|
|
79653eee80 | ||
|
|
16ad86c52a | ||
|
|
6b7c6be5f5 | ||
|
|
fda1c2cc79 | ||
|
|
ef2fee0ee3 | ||
|
|
e287d0811d | ||
|
|
a7164f3c9f | ||
|
|
c55060039a | ||
|
|
c68d8deddd | ||
|
|
f6eabc5db1 | ||
|
|
72d5884db6 | ||
|
|
3595c89c79 | ||
|
|
9ebbc718c5 | ||
|
|
e862480b86 | ||
|
|
1f3d8fe6f1 | ||
|
|
41ae036ab4 | ||
|
|
588d176b96 | ||
|
|
f8697120a0 | ||
|
|
1a767105e6 | ||
|
|
4067b6ed2c | ||
|
|
b272dbfd1f | ||
|
|
48be7bbf86 | ||
|
|
51e22cea71 | ||
|
|
2241e27e68 | ||
|
|
11c90ae879 | ||
|
|
cf55125202 | ||
|
|
9cefb85905 | ||
|
|
fc672da0e0 | ||
|
|
25b297b142 | ||
|
|
ab03c12fa8 | ||
|
|
3095c805ad | ||
|
|
9c18daafb8 | ||
|
|
16182417fb | ||
|
|
9af35201e4 | ||
|
|
f21b982955 | ||
|
|
b3a20d05c5 | ||
|
|
4cd024a2b2 | ||
|
|
63d08ebfd2 | ||
|
|
c696197b03 | ||
|
|
738a72228b | ||
|
|
90641f4488 | ||
|
|
a4cc7eaf9b | ||
|
|
fdca728fdc | ||
|
|
d2c4ae8cdf | ||
|
|
f3d3ac30a6 | ||
|
|
f8cc4ade8a | ||
|
|
b3975b7bbd | ||
|
|
4f1b61f5bc | ||
|
|
beeb37b4fd | ||
|
|
43aa2bad22 | ||
|
|
1b2ba921bb | ||
|
|
f543da0ea8 | ||
|
|
e60c9efa84 | ||
|
|
c52fc6f240 | ||
|
|
ee136b024a | ||
|
|
699bc5f34b | ||
|
|
9eed8e842c | ||
|
|
6d652a12ee | ||
|
|
e043e06656 | ||
|
|
14b52599f4 | ||
|
|
e3e2c0c567 | ||
|
|
4fc5d60f03 | ||
|
|
c37a9e0f82 | ||
|
|
fed17ebb96 | ||
|
|
eeac678872 | ||
|
|
f9ed0f2df9 | ||
|
|
0ddbacac85 | ||
|
|
f0d28aa5cf | ||
|
|
cc84f6fee4 | ||
|
|
00e6eef369 | ||
|
|
1ae71907bc | ||
|
|
3ff688fba2 | ||
|
|
bb59b3d456 | ||
|
|
186ea74ada | ||
|
|
c108f2dcf3 | ||
|
|
4cca232d83 | ||
|
|
1db511e9cb | ||
|
|
76afa7d3bf | ||
|
|
3513f7b1cd | ||
|
|
4531fe39e6 | ||
|
|
8d276a85bc | ||
|
|
5f0d042bc3 | ||
|
|
408f07e3c4 | ||
|
|
d1a540c90c | ||
|
|
00df8e930e | ||
|
|
3b768b1b77 | ||
|
|
42a7ececa0 | ||
|
|
e8867de049 | ||
|
|
a1dfa3dfa3 | ||
|
|
83917d4f79 | ||
|
|
513cd4f905 | ||
|
|
eda0309df3 | ||
|
|
74e27c028e | ||
|
|
36c06c4089 | ||
|
|
249b8a9cdd | ||
|
|
62bee15f00 | ||
|
|
d8797b69e4 | ||
|
|
084fe72b02 | ||
|
|
c823acaa3f | ||
|
|
e0d6cd9cb7 | ||
|
|
01021e102b | ||
|
|
6de738ff17 | ||
|
|
c0612547eb | ||
|
|
e960907698 | ||
|
|
84e03b1b27 | ||
|
|
f1a80da34b | ||
|
|
5a5a55e556 | ||
|
|
e1f132b45b | ||
|
|
087011aede | ||
|
|
1430bf9b31 | ||
|
|
4e5de817ef | ||
|
|
5d6b94f8c3 | ||
|
|
8dfbe56f42 | ||
|
|
df79d983d7 | ||
|
|
6c23a28826 | ||
|
|
f72289570a | ||
|
|
51bc9dc20e | ||
|
|
e45ac6bfa9 | ||
|
|
44d1cbdb0c | ||
|
|
3fa7e854d3 | ||
|
|
0f5c080be6 | ||
|
|
871009ef8d | ||
|
|
89a565c6c4 | ||
|
|
6ed60e4d5f | ||
|
|
4dab1df3ae | ||
|
|
7b7aa2cdf0 | ||
|
|
d1e1a65f32 | ||
|
|
9d332b4ac5 | ||
|
|
fc2462e281 | ||
|
|
fb2cddabf0 | ||
|
|
33481a9465 | ||
|
|
45de87cb97 | ||
|
|
553c533ada | ||
|
|
634e562b93 | ||
|
|
c789ead590 | ||
|
|
d23560a441 | ||
|
|
9f306966db | ||
|
|
8eea2cef97 | ||
|
|
3abbb89c2e | ||
|
|
76de7d54c7 | ||
|
|
35aee6e066 | ||
|
|
8a0152fe7c | ||
|
|
7769435fc8 | ||
|
|
ae311ea66e | ||
|
|
d15816f162 | ||
|
|
5cbb31c559 | ||
|
|
b7f5b36f2b | ||
|
|
e9dd413de6 | ||
|
|
c5de3d8cc1 | ||
|
|
624c385e27 | ||
|
|
893890c985 | ||
|
|
e12efc8b52 | ||
|
|
015dfa41b1 | ||
|
|
5e72ce5fbe | ||
|
|
236e653176 | ||
|
|
3946c3ba03 | ||
|
|
5bdd39e6eb | ||
|
|
46267c0531 | ||
|
|
7b96eb7704 | ||
|
|
60d5955101 | ||
|
|
587675e488 | ||
|
|
c0ae319c63 | ||
|
|
d810f8d8db | ||
|
|
a88390a546 | ||
|
|
8575e5615d | ||
|
|
5fe9516c09 | ||
|
|
938775789d | ||
|
|
f37bebe51f | ||
|
|
21f14cd3f2 | ||
|
|
4e7baeb2c9 | ||
|
|
d78a682dd8 | ||
|
|
44021b7abc | ||
|
|
7f9e543213 | ||
|
|
c489e5a59b | ||
|
|
8de30db7f9 | ||
|
|
415f0c6774 | ||
|
|
aa9cf195a5 | ||
|
|
6412fc8135 | ||
|
|
8b1ba9a00c | ||
|
|
b02584ef9e | ||
|
|
88cd6bfd1a | ||
|
|
89a3da14c9 | ||
|
|
619d987492 | ||
|
|
744e410a1a | ||
|
|
6e51967993 | ||
|
|
7989ab2e28 | ||
|
|
a3570a568d | ||
|
|
c0cd998836 | ||
|
|
1a452acd1c | ||
|
|
6c54083b08 | ||
|
|
76105ebdaf | ||
|
|
2c452201fa | ||
|
|
9fc7fc73f9 | ||
|
|
e7417e35ba | ||
|
|
19eb4c7cba | ||
|
|
1f39a0c9da | ||
|
|
a480a8893c | ||
|
|
d3a9e341a5 | ||
|
|
95caffe607 | ||
|
|
fdeca61284 | ||
|
|
45dc653191 | ||
|
|
6e48302b7b | ||
|
|
a7918d7b11 | ||
|
|
ec21253af9 | ||
|
|
97cdda8663 | ||
|
|
35ac2b9d71 | ||
|
|
14affd8ffa | ||
|
|
c48409c903 | ||
|
|
227f66f299 | ||
|
|
c2d9bf94d1 | ||
|
|
8f03841161 | ||
|
|
344a1ed912 | ||
|
|
ff71993b31 | ||
|
|
18bb773b2c | ||
|
|
7f905c7940 | ||
|
|
8a4ba6fc56 | ||
|
|
e0b275c01c | ||
|
|
5926db85df | ||
|
|
a4715a10e7 | ||
|
|
de0f5c0fcb | ||
|
|
88d85ce6ac | ||
|
|
131c171d3e | ||
|
|
c5ddef6ef7 | ||
|
|
f36486d006 | ||
|
|
eaf466c5c3 | ||
|
|
b41bcc349e | ||
|
|
825c61bdcd | ||
|
|
f13f49bd71 | ||
|
|
88f5d4544b | ||
|
|
b7432a20f0 | ||
|
|
ab57c85e66 | ||
|
|
c7c41bc0d8 | ||
|
|
c66f9b06a4 | ||
|
|
a3ac7e7ca7 | ||
|
|
187b762f8a | ||
|
|
3a7fbdfa52 | ||
|
|
bbeb46b37f | ||
|
|
5450b9a700 | ||
|
|
353b28647c | ||
|
|
2411f4f870 | ||
|
|
34cd059423 | ||
|
|
4b4ec12c87 | ||
|
|
441147c0dc | ||
|
|
08ceac9f46 | ||
|
|
6bc690b50b | ||
|
|
c41888b338 | ||
|
|
6d3c980b39 | ||
|
|
eb5db176fa | ||
|
|
a77c03fcaf | ||
|
|
04b25011e9 | ||
|
|
96b34aec10 | ||
|
|
d560b46c85 | ||
|
|
94789ce455 | ||
|
|
55797e5873 | ||
|
|
675cab3074 | ||
|
|
8d63ab646e | ||
|
|
37a2fa1cdc | ||
|
|
79ed9650b3 | ||
|
|
b6dc58164e | ||
|
|
f9a974c1fe | ||
|
|
91e672befb | ||
|
|
c14d18b9df | ||
|
|
d2cfc1844c | ||
|
|
2fb3243a1a | ||
|
|
6f3124a84f | ||
|
|
59eb5bd9c4 | ||
|
|
ad2b6bb4f7 | ||
|
|
51d64ee10e | ||
|
|
1159efc6cc | ||
|
|
3cfb76a56f | ||
|
|
7a1ad6688a | ||
|
|
4f4af6e3fd | ||
|
|
2736b79097 | ||
|
|
8da2ffa433 | ||
|
|
5bf3d6dc32 | ||
|
|
30d4380afe | ||
|
|
c8b5aad482 | ||
|
|
fa1d440947 | ||
|
|
a89fc3a276 | ||
|
|
3875f62453 | ||
|
|
23e1447ab6 | ||
|
|
91364c6a7c | ||
|
|
a070493fba | ||
|
|
ca0a6ab72c | ||
|
|
10e0562a82 | ||
|
|
44998a2a2b | ||
|
|
f8e033e560 | ||
|
|
5842da84af | ||
|
|
10cc270170 | ||
|
|
f51bdd56aa | ||
|
|
7f79c49f93 | ||
|
|
e4920255f0 | ||
|
|
f8e8273d39 | ||
|
|
ceddab98d1 | ||
|
|
0faa176791 | ||
|
|
9b0e0ee536 | ||
|
|
881d2756db | ||
|
|
ab5af40999 | ||
|
|
6aeef8dcf9 | ||
|
|
5d62196dde | ||
|
|
7fe27ac310 | ||
|
|
1e300349ce | ||
|
|
6b01a7b08e | ||
|
|
34d948df18 | ||
|
|
27091c4f1d | ||
|
|
970a3d7f2a | ||
|
|
2bedbbfc54 | ||
|
|
8de33f0db3 | ||
|
|
df4eab67dc | ||
|
|
2d13bc0046 | ||
|
|
704a0cb35d | ||
|
|
06a983e445 | ||
|
|
2d10df8b87 | ||
|
|
baf66db9dc | ||
|
|
3545693999 | ||
|
|
84fb99c2c8 | ||
|
|
21e2983ae1 | ||
|
|
004e0941d5 | ||
|
|
188a426dde | ||
|
|
6fcfae8bfe | ||
|
|
9515350f52 | ||
|
|
6b88f82656 | ||
|
|
e42d953f47 | ||
|
|
471a3f63fe | ||
|
|
9c257faf26 | ||
|
|
d18cad6d76 | ||
|
|
061273be22 | ||
|
|
b89de6caad | ||
|
|
9bc0a1d7c7 | ||
|
|
eee518b7fa | ||
|
|
b7b78edaa3 | ||
|
|
3eaac68ab4 | ||
|
|
a7672190e9 | ||
|
|
4e4e89b6eb | ||
|
|
33dd519f56 | ||
|
|
5c1149aa8b | ||
|
|
9061e92af6 | ||
|
|
49f5ceaa9b | ||
|
|
525b309d37 | ||
|
|
bdb3a787fc | ||
|
|
a9601ef848 | ||
|
|
6fc4b045fd | ||
|
|
446852c7d0 | ||
|
|
c635f00899 | ||
|
|
1393629bc5 | ||
|
|
49ce17b759 | ||
|
|
74888021c8 | ||
|
|
9483856439 | ||
|
|
dbbc7c8132 | ||
|
|
5d9c99508d | ||
|
|
e4d5b56951 | ||
|
|
e31238d121 | ||
|
|
a283d99e1b | ||
|
|
8cb621ebed | ||
|
|
b203d165f5 | ||
|
|
c695e1136d | ||
|
|
d847202308 | ||
|
|
9d24e0a4b8 | ||
|
|
745fe1eb9f | ||
|
|
3e52b85e9d | ||
|
|
d26f020b50 | ||
|
|
095b5f702c | ||
|
|
9622853b8d | ||
|
|
b94e75fabe | ||
|
|
23dd041e2e | ||
|
|
c73ca21b4d | ||
|
|
7ebdc85ad2 | ||
|
|
99e2c8c90d | ||
|
|
f24bfdf945 | ||
|
|
7963233702 | ||
|
|
b550df2038 | ||
|
|
fb55624f5f | ||
|
|
e96366f489 | ||
|
|
900190cf54 | ||
|
|
2af744b474 | ||
|
|
11153084e2 | ||
|
|
4b9c814bfc | ||
|
|
1b5d3a3b6e | ||
|
|
373637e6a7 | ||
|
|
cb223217c1 | ||
|
|
eab97a3f8b | ||
|
|
fdfaa8ab45 | ||
|
|
2321d9dbee | ||
|
|
bf74dd887a | ||
|
|
3612035894 | ||
|
|
6553e9b0cd | ||
|
|
09f2410170 | ||
|
|
fb73d8c0a7 | ||
|
|
f2b0368078 | ||
|
|
02301ecf6d | ||
|
|
bcb61ee3e4 | ||
|
|
6a824429d0 | ||
|
|
6a52f9097f | ||
|
|
3fa85fc516 | ||
|
|
498d132d8a | ||
|
|
b6340f1458 | ||
|
|
4afc7ae2e4 | ||
|
|
95975a4c33 | ||
|
|
198a0673a2 | ||
|
|
94d1503c64 | ||
|
|
5f13e245f0 | ||
|
|
2715ae645d | ||
|
|
0299232cb5 | ||
|
|
93e181cfd9 | ||
|
|
8072eb1212 | ||
|
|
226ce340f2 | ||
|
|
ab5535eba3 | ||
|
|
8da2499495 | ||
|
|
c057ffb153 | ||
|
|
fe13d29549 | ||
|
|
225aaab4f4 | ||
|
|
14c973558b | ||
|
|
f515ff36b6 | ||
|
|
ed57cfd2f9 | ||
|
|
d69559e9c7 | ||
|
|
396717efd1 | ||
|
|
284fa24464 | ||
|
|
0a20b9179a | ||
|
|
a0d5037885 | ||
|
|
4477833b1d | ||
|
|
e0a5ed4bdb | ||
|
|
46d4b26eba | ||
|
|
f7c6edf849 | ||
|
|
6c157def4b | ||
|
|
741712f89f | ||
|
|
4f749da628 | ||
|
|
8b02795d69 | ||
|
|
f8a0069a5d | ||
|
|
388bbe047e | ||
|
|
2d4ce30e58 | ||
|
|
d4fb17cf66 | ||
|
|
372a2c8375 | ||
|
|
8f27121f21 | ||
|
|
b986bf675f | ||
|
|
80718a461b | ||
|
|
2d14ecf58b | ||
|
|
32aa9877c0 | ||
|
|
cee3a9c11d | ||
|
|
b78643f2d8 | ||
|
|
30a31de45b | ||
|
|
e4c4db534c | ||
|
|
4f7a0d3ad0 | ||
|
|
ea3a96eead | ||
|
|
c0e01ac132 | ||
|
|
28ea50bca4 | ||
|
|
619e44b30f | ||
|
|
d678275dee | ||
|
|
08eed53595 | ||
|
|
ff40f7d262 | ||
|
|
3c1ae51dae | ||
|
|
8a59fc9aaf | ||
|
|
b7ea9dd841 | ||
|
|
0320db6b4a | ||
|
|
18c7f58093 | ||
|
|
7f6f7b1436 | ||
|
|
ca49176b97 | ||
|
|
67be0cd9d7 | ||
|
|
902fadef83 | ||
|
|
2777b6411f | ||
|
|
e3235d7f04 | ||
|
|
dc89c8858e | ||
|
|
d28a278d63 | ||
|
|
7080c2abd0 | ||
|
|
43f86bcab8 | ||
|
|
7d9c875c4d | ||
|
|
ed4099eb12 | ||
|
|
632b83f75d | ||
|
|
66c92637f9 | ||
|
|
6bcaebc471 | ||
|
|
7feee1027c | ||
|
|
4fd8c77fa9 | ||
|
|
bc3bb2d323 | ||
|
|
7764684c68 | ||
|
|
feb2c38572 | ||
|
|
6a97e82a2e | ||
|
|
57c0d19cde | ||
|
|
e14ed89f3d | ||
|
|
6a14893a23 | ||
|
|
0f19735d33 | ||
|
|
6a859ac65d | ||
|
|
4d9c24244c | ||
|
|
cdeb288c4f | ||
|
|
7f8016497b | ||
|
|
ec01225225 | ||
|
|
4e23b84999 | ||
|
|
c7c143fed9 | ||
|
|
4932171834 | ||
|
|
00fc6c8e2f | ||
|
|
1b73dab341 | ||
|
|
99e99c1ccd | ||
|
|
14ce479ab7 | ||
|
|
e7e873a1b2 | ||
|
|
5a57428ec0 | ||
|
|
18e8e6ee98 | ||
|
|
6bf6e51740 | ||
|
|
b52a899a18 | ||
|
|
cf722a7120 | ||
|
|
33cd1f3db8 | ||
|
|
b7d2715ffd | ||
|
|
fe63466d67 | ||
|
|
0fb63eea99 | ||
|
|
59552804f6 | ||
|
|
579d6d73f8 | ||
|
|
f83e3022ba | ||
|
|
bf93bbf5f8 | ||
|
|
fa2a52ff41 | ||
|
|
813d9eace3 | ||
|
|
16e8dd447b | ||
|
|
0129b31dec | ||
|
|
9544960314 | ||
|
|
23a9ca3140 | ||
|
|
dfa4bb6ca4 | ||
|
|
8aac3320be | ||
|
|
42ddb0d5ed | ||
|
|
f60728b537 | ||
|
|
9e6f9d50ef | ||
|
|
d76a473324 | ||
|
|
5a2d2b86d5 | ||
|
|
42e8f481d6 | ||
|
|
9ecf652745 | ||
|
|
8748314b5b | ||
|
|
606923b374 | ||
|
|
3ae830a637 | ||
|
|
92df1ecd5f | ||
|
|
b9d019561f | ||
|
|
48a341b79c | ||
|
|
d1ea8517d2 | ||
|
|
cd23844e35 | ||
|
|
3f24af3a99 | ||
|
|
78421683fe | ||
|
|
61bfbdb26e | ||
|
|
a7a5c41370 | ||
|
|
f0b4c13200 | ||
|
|
b01e97b168 | ||
|
|
7da10795a1 | ||
|
|
959bbdcf1b | ||
|
|
970e31a1b1 | ||
|
|
2dae2b7984 | ||
|
|
d6ac9a0363 | ||
|
|
18336c2b8e | ||
|
|
fc02d32ac3 | ||
|
|
891d5d3c35 | ||
|
|
17dab3df34 | ||
|
|
37c7251ec9 | ||
|
|
a22393075f | ||
|
|
ca3d088785 | ||
|
|
8775b65f58 | ||
|
|
c1204a5efb | ||
|
|
941db572c7 | ||
|
|
addb7ca95d | ||
|
|
5a930930da | ||
|
|
df877e87bf | ||
|
|
adb200d885 | ||
|
|
4f0840b8b8 | ||
|
|
c37ea5c890 | ||
|
|
cac9366c86 | ||
|
|
1fc28f8cd1 | ||
|
|
2109643ec0 | ||
|
|
3caf5a5a6d | ||
|
|
418c1256a8 | ||
|
|
3ae7ba89e8 | ||
|
|
191bb9d916 | ||
|
|
f1d8fadabf | ||
|
|
c898732739 | ||
|
|
6e4f54eaf6 | ||
|
|
4ba2963cfe | ||
|
|
20e6209036 | ||
|
|
44a5433af3 | ||
|
|
0f6f13ed3e | ||
|
|
0ae75634b1 | ||
|
|
9458ea81da | ||
|
|
9f539c1d08 | ||
|
|
37b03c7d5a | ||
|
|
3009e6dcfd | ||
|
|
70343b17bc | ||
|
|
3f6027ec2c | ||
|
|
5706732c55 | ||
|
|
ad633a9dd0 | ||
|
|
7c56df1237 | ||
|
|
c1110f2897 | ||
|
|
647642578b | ||
|
|
5ca4efac31 | ||
|
|
deddf12b70 | ||
|
|
109a7c12ea | ||
|
|
f955031e27 | ||
|
|
6a69c6cd02 | ||
|
|
c1d4ac45ab | ||
|
|
2946a35b0e | ||
|
|
c73a8cb18f | ||
|
|
574a093038 | ||
|
|
4eb1fe0b80 | ||
|
|
4c46cd725b | ||
|
|
fdbd0e1fba | ||
|
|
5801168ce0 | ||
|
|
d4c7551087 | ||
|
|
c9daf0c9f5 | ||
|
|
8cb566b031 | ||
|
|
089b16326e | ||
|
|
c0e43cc0e5 | ||
|
|
514c3539e6 | ||
|
|
62c94a178c | ||
|
|
9fee38b18d | ||
|
|
cd3114d39e | ||
|
|
12b4e15812 | ||
|
|
35336a0827 | ||
|
|
ece7cbfec3 | ||
|
|
a00075ee0d | ||
|
|
b6c4e28b4d | ||
|
|
8b55cce39a | ||
|
|
1db216e6ec | ||
|
|
20142f91fd | ||
|
|
b34be141b7 | ||
|
|
6e99446ce5 | ||
|
|
20a09b4866 | ||
|
|
8ea8dcde19 | ||
|
|
b205e2a84f | ||
|
|
7f7db5eabd | ||
|
|
0651d064fc | ||
|
|
73ca7759d3 | ||
|
|
0f112d0685 | ||
|
|
fa5c91ecf6 | ||
|
|
3b2fd1b9fa | ||
|
|
e424094fdf | ||
|
|
bad9ab2c9d | ||
|
|
61c01ce9b0 | ||
|
|
3de5df9f38 | ||
|
|
910aa1c22e | ||
|
|
71c8f3129f | ||
|
|
224614312f | ||
|
|
f717133947 | ||
|
|
fcbfcfed03 | ||
|
|
e6601c91ca | ||
|
|
0379903689 | ||
|
|
6950eebf9f | ||
|
|
c15f1327c9 | ||
|
|
ec1999f73d | ||
|
|
3d0a18b05d | ||
|
|
156a02c5a8 | ||
|
|
eba1a443e3 | ||
|
|
eb44cdc903 | ||
|
|
196df63de2 | ||
|
|
ed3c11f44c | ||
|
|
7f6c877fdc | ||
|
|
eee8309db8 | ||
|
|
155cfab792 | ||
|
|
e1c36afdec | ||
|
|
6b0d6a41ca | ||
|
|
dab157bb71 | ||
|
|
8d17d09455 | ||
|
|
05208ccd9b | ||
|
|
a1e7c0068d | ||
|
|
e6bec19946 | ||
|
|
ec2be2869f | ||
|
|
ce5432ed73 | ||
|
|
b6e0ad89ce | ||
|
|
2745bfa19b | ||
|
|
3cdc4b38a6 | ||
|
|
fc1ca808d7 | ||
|
|
6983e66037 | ||
|
|
01f7336d09 | ||
|
|
1561bba538 | ||
|
|
3ecf8a5e0c | ||
|
|
e2095fc416 | ||
|
|
8398d40106 | ||
|
|
134fa8892f | ||
|
|
ea5c8dc063 | ||
|
|
0209d00164 | ||
|
|
a8d065dc9e | ||
|
|
7bd9711ade | ||
|
|
61802eadb4 | ||
|
|
b425659058 | ||
|
|
3e32e3d7b1 | ||
|
|
1b661c9df1 | ||
|
|
54fc26b93d | ||
|
|
161f99bbad | ||
|
|
c012db0776 | ||
|
|
8ee257d299 | ||
|
|
f9522107c3 | ||
|
|
e07046a37a | ||
|
|
ad6d0d9ae8 | ||
|
|
fdc33e91bd | ||
|
|
a34f5a855c | ||
|
|
6474741af1 | ||
|
|
c10bd840c5 | ||
|
|
e6dded826b | ||
|
|
8a022c4b18 | ||
|
|
cfef228afc | ||
|
|
237ff9f055 | ||
|
|
020f862814 | ||
|
|
fa6107200d | ||
|
|
eb81f972c4 | ||
|
|
93c1ff396e | ||
|
|
403baf05a6 | ||
|
|
a51b56339a | ||
|
|
f48a6d47dc | ||
|
|
5b52463e4c | ||
|
|
6f08bb72d8 | ||
|
|
045093f453 | ||
|
|
566c49ce53 | ||
|
|
d1d2758ee0 | ||
|
|
5b86c40d5b | ||
|
|
53393e744e | ||
|
|
2dd17e3882 | ||
|
|
c4f7433584 | ||
|
|
9405a7cf4b | ||
|
|
cd677440ce | ||
|
|
c06f4bc5a8 | ||
|
|
4a7337b223 | ||
|
|
1d8afb817e | ||
|
|
0f06c3d934 | ||
|
|
9d5cb8d119 | ||
|
|
a28d686eb9 | ||
|
|
ac525a8ec2 | ||
|
|
52c44befa2 | ||
|
|
c64251c341 | ||
|
|
bdc57d3c33 | ||
|
|
7edc437df2 | ||
|
|
57e4395e7d | ||
|
|
ee17dca9e5 | ||
|
|
e9f3add5b9 | ||
|
|
faf1a9f7e4 | ||
|
|
5357bd07c7 | ||
|
|
8c0e2cbd25 | ||
|
|
674f3b4f28 | ||
|
|
6e42e00974 | ||
|
|
8598885258 | ||
|
|
669e40d53c | ||
|
|
1adcce6c62 | ||
|
|
147be6e6e1 | ||
|
|
5879999094 | ||
|
|
477a30cf5b | ||
|
|
2fec03e1ac | ||
|
|
9a17449a02 | ||
|
|
087a6aad8c | ||
|
|
e243a8e88f | ||
|
|
b57df8026a | ||
|
|
a1d45b44cd | ||
|
|
e47e1d220a | ||
|
|
0129a933df | ||
|
|
fa241bb0d7 | ||
|
|
d8804ae108 | ||
|
|
8090d269e7 | ||
|
|
b0101f20c5 | ||
|
|
dd48e4299a | ||
|
|
c61ee0c24f | ||
|
|
9576867c34 | ||
|
|
4426a24298 | ||
|
|
3b43c1e413 | ||
|
|
aa6575c8f9 | ||
|
|
0268713960 | ||
|
|
f36167d425 | ||
|
|
33ffcb9308 | ||
|
|
a649c25a91 | ||
|
|
fa1e773960 | ||
|
|
62f7238796 | ||
|
|
d4ccf73340 | ||
|
|
5ddb0f96bc | ||
|
|
75a6db8f4c | ||
|
|
ae5635319b | ||
|
|
98ed3080d0 | ||
|
|
c618eacad4 | ||
|
|
3b11e6ef97 | ||
|
|
40af9359db | ||
|
|
d6bf9dae42 | ||
|
|
13917941ff | ||
|
|
28f04329ae | ||
|
|
404a6b231d | ||
|
|
184596da3c | ||
|
|
f00f393687 | ||
|
|
cbbfb89619 | ||
|
|
6a5cf11dd0 | ||
|
|
fc1d0a0464 | ||
|
|
74af1759eb | ||
|
|
ee3162ad71 | ||
|
|
4357165163 | ||
|
|
6973436b94 | ||
|
|
7750ed7106 | ||
|
|
773158e9d8 | ||
|
|
4db615597d | ||
|
|
6bdf2365fc | ||
|
|
a7944f28c5 | ||
|
|
426d459284 | ||
|
|
b00b461ada | ||
|
|
84834b6348 | ||
|
|
f521fd35ff | ||
|
|
2979fceecf | ||
|
|
b12e8e793f | ||
|
|
c77ec59a28 | ||
|
|
42ba8cf828 | ||
|
|
c7618fc895 | ||
|
|
d055b34efe | ||
|
|
b7f635f540 | ||
|
|
5e95a54260 | ||
|
|
4354e82bb5 | ||
|
|
ab7bdc24dc | ||
|
|
81997fe1ba | ||
|
|
de6759a83f | ||
|
|
233dc33130 | ||
|
|
39b07f45f1 | ||
|
|
802662a165 | ||
|
|
2859848fc4 | ||
|
|
b734d00062 | ||
|
|
02a17d22f6 | ||
|
|
7bfff472c6 | ||
|
|
5aa146be17 | ||
|
|
a0bfc22a29 | ||
|
|
6ed46b5fcc | ||
|
|
904e40ef57 | ||
|
|
00ff119ec4 | ||
|
|
60d2511e80 | ||
|
|
ed56a4aa4a | ||
|
|
5b6a1c97e3 | ||
|
|
8bfc9ef4de | ||
|
|
fa949e089e | ||
|
|
c296ca7660 | ||
|
|
538b38869f | ||
|
|
ce328ed90b | ||
|
|
632bae725d | ||
|
|
4f824b1d9a | ||
|
|
120aee8039 | ||
|
|
3b2b341c4d | ||
|
|
4cad40f637 | ||
|
|
2c64380019 | ||
|
|
ccb9593de2 | ||
|
|
921a99fc32 | ||
|
|
400d2c1774 | ||
|
|
762497b1c1 | ||
|
|
be9edc7512 | ||
|
|
9bf9d34d94 | ||
|
|
df8405006c | ||
|
|
d135fdce58 | ||
|
|
ba570b93bb | ||
|
|
6dfe0c7a96 | ||
|
|
73d4430a65 | ||
|
|
ce6fd9b976 | ||
|
|
ae7e8c03f2 | ||
|
|
22e2526f4c | ||
|
|
50283d9411 | ||
|
|
d2c2b58f3b | ||
|
|
50d4b39ca0 | ||
|
|
1ed675e960 | ||
|
|
80b0671844 | ||
|
|
6f387336c0 | ||
|
|
3b2e273832 | ||
|
|
9540b01bcc | ||
|
|
43c839eb89 | ||
|
|
446d6914c1 | ||
|
|
637223aa53 | ||
|
|
17d5565120 | ||
|
|
4b54187b4c | ||
|
|
cfb1421367 | ||
|
|
5072a0f6f5 | ||
|
|
357dff1403 | ||
|
|
a2bd66ded8 | ||
|
|
6bfa3c25a4 | ||
|
|
1ea9ab72c1 | ||
|
|
07c42b8725 | ||
|
|
70392c32e2 | ||
|
|
9b4b2a9f7c | ||
|
|
d3dd708b58 | ||
|
|
af264cdc58 | ||
|
|
cfd6df976f | ||
|
|
b2bd20b47e | ||
|
|
ffea093e95 | ||
|
|
78eb8fcf92 | ||
|
|
a052956881 | ||
|
|
9319ea6992 | ||
|
|
4e5b70dbfa | ||
|
|
c68eaa8397 | ||
|
|
bbb7c85ba7 | ||
|
|
8174359228 | ||
|
|
acf66c5195 | ||
|
|
880c9fa97a | ||
|
|
e5c111f2be | ||
|
|
4e9cd064dd | ||
|
|
12a6d3977e | ||
|
|
a95bbaf820 | ||
|
|
70bafa653b | ||
|
|
3f4338489c | ||
|
|
d91e58f2cc | ||
|
|
192b9c1e8b | ||
|
|
0941239454 | ||
|
|
53ad00cdc4 | ||
|
|
6dd5da48f7 | ||
|
|
efae8328a9 | ||
|
|
f1facc51de | ||
|
|
a471ca6a76 | ||
|
|
83f6690576 | ||
|
|
1850ea67f6 | ||
|
|
2fd6178aa9 | ||
|
|
ec044e6f42 | ||
|
|
bd96279649 | ||
|
|
f7ad595945 | ||
|
|
93c0b91de9 | ||
|
|
138038b08f | ||
|
|
e9a6fed607 | ||
|
|
87a1440382 | ||
|
|
3c2f4ebe9b | ||
|
|
933ffe7828 | ||
|
|
7d20ba5243 | ||
|
|
44dc36af48 | ||
|
|
98558c5ba9 | ||
|
|
6c25322465 | ||
|
|
6d1d62fd32 | ||
|
|
ee4ae661d7 | ||
|
|
0473ec1626 | ||
|
|
c6cf0d40ee | ||
|
|
4cd80e96f3 | ||
|
|
16524717ba | ||
|
|
cab1ce3d0c | ||
|
|
6c2e5e1164 | ||
|
|
c2bf540057 | ||
|
|
a35c66e166 | ||
|
|
084c5e2686 | ||
|
|
6ae715b153 | ||
|
|
9c8692806a | ||
|
|
2d87351d2a | ||
|
|
3114afde0e | ||
|
|
7b338511cc | ||
|
|
09c27681e1 | ||
|
|
4ebc1f82b7 | ||
|
|
4640ca497a | ||
|
|
bebccaae28 | ||
|
|
7ee53373c6 | ||
|
|
d577fe1ac6 | ||
|
|
9f976aaf78 | ||
|
|
8a7d7e366f | ||
|
|
540ab1c6fa | ||
|
|
6792afbdb1 | ||
|
|
e5a7185671 | ||
|
|
cdaf453b2d | ||
|
|
f9cc80e1de | ||
|
|
7beff9e83c | ||
|
|
8f49f1b6f8 | ||
|
|
7e336a0247 | ||
|
|
e37e8bdadc | ||
|
|
40bd61b16b | ||
|
|
87fbb45099 | ||
|
|
e822f9a95c | ||
|
|
8a5a9159e1 | ||
|
|
73b3c6b419 | ||
|
|
f9bd7ebdb0 | ||
|
|
540618c062 | ||
|
|
9e96dec8c9 | ||
|
|
7b7af612ba | ||
|
|
3a747ba87e | ||
|
|
87e57e3a9a | ||
|
|
785d0dcebf | ||
|
|
2314776f55 | ||
|
|
473f5d8189 | ||
|
|
be971cb6f7 | ||
|
|
3f94c1a50d | ||
|
|
2919ec293a | ||
|
|
19d25152e5 | ||
|
|
747180203c | ||
|
|
9f89a0844d | ||
|
|
c64282e915 | ||
|
|
c44a80bab2 | ||
|
|
8dfc4a2ffb | ||
|
|
c341c626a5 | ||
|
|
173a0fe659 | ||
|
|
5fdae1cf82 | ||
|
|
9e892ab397 | ||
|
|
e95559b4fc | ||
|
|
18475cc86d | ||
|
|
88b59600cd | ||
|
|
9a9d64bcbe | ||
|
|
4f3408ec25 | ||
|
|
e9d0fb85ac | ||
|
|
1ce37ef7a8 | ||
|
|
ecad356e30 | ||
|
|
fafd8da91d | ||
|
|
2fb31d4b84 | ||
|
|
8b478451ac | ||
|
|
42b1205fb4 | ||
|
|
80ceb1c375 | ||
|
|
501407c3fe | ||
|
|
abddabf18e | ||
|
|
91d753cbdb | ||
|
|
259acd0694 | ||
|
|
33f7258ea2 | ||
|
|
1ea7bb57e5 | ||
|
|
3e60e796fb | ||
|
|
d9c178cbee | ||
|
|
031b3c55f6 | ||
|
|
b43d2c3d95 | ||
|
|
d865120480 | ||
|
|
15534f466a | ||
|
|
9d63dcb8d6 | ||
|
|
6efe30bd6e | ||
|
|
52dd9f0609 | ||
|
|
bee7f43880 | ||
|
|
d38276e8cf | ||
|
|
f3daaeb200 | ||
|
|
9b152a40a9 | ||
|
|
89ae8ca526 | ||
|
|
68a5e474a6 | ||
|
|
bf58742ddf | ||
|
|
f18e5b75bb | ||
|
|
e919c99b14 | ||
|
|
b960f2e5ba | ||
|
|
5d8728d592 | ||
|
|
04ba6c2d73 | ||
|
|
0cab9bd4b4 | ||
|
|
279d305013 | ||
|
|
750c1fb069 | ||
|
|
359a6042cd | ||
|
|
e27d2ec660 | ||
|
|
da56bfc01f | ||
|
|
6e2c7d2857 | ||
|
|
5481609554 | ||
|
|
a62f4df0b1 | ||
|
|
f893c1272c | ||
|
|
e701f5277e | ||
|
|
f85fd1f6a4 | ||
|
|
8f7ea420b3 | ||
|
|
b39f389a67 | ||
|
|
d8c8dabb52 | ||
|
|
9092ecf331 | ||
|
|
2fd9fe96ad | ||
|
|
554153e6a0 | ||
|
|
3c29122dfe | ||
|
|
c42dc646ae | ||
|
|
edd6206a03 | ||
|
|
a1e7f55b95 | ||
|
|
218823e9b2 | ||
|
|
3e8f52689e | ||
|
|
0219fc3ea9 | ||
|
|
66cb2ab662 | ||
|
|
91c85f0aa6 | ||
|
|
fd9790cc36 | ||
|
|
0d40883176 | ||
|
|
2d0319f779 | ||
|
|
aaeaa44c0b | ||
|
|
9fc77db073 | ||
|
|
bdaa060003 | ||
|
|
b5cb9901b1 | ||
|
|
fb4d503c9a | ||
|
|
c3c2fcf4d0 | ||
|
|
f2d2d94d1b | ||
|
|
11c1b45335 | ||
|
|
b8a308012f | ||
|
|
122a732206 | ||
|
|
59e4383209 | ||
|
|
22b008f723 | ||
|
|
c770094425 | ||
|
|
093a5fdf31 | ||
|
|
f811835f02 | ||
|
|
5dda13b800 | ||
|
|
a20306afe0 | ||
|
|
476b1df323 | ||
|
|
aec5a913da | ||
|
|
e13795651d | ||
|
|
cc175da0d8 | ||
|
|
a2369fb531 | ||
|
|
c5b8a444f2 | ||
|
|
f450608073 | ||
|
|
0e57537167 | ||
|
|
1445b0a48b | ||
|
|
d268cc7685 | ||
|
|
7969bbaac4 | ||
|
|
b9e89ca64b | ||
|
|
f802b41665 | ||
|
|
f0eac57bb9 | ||
|
|
c9d3563f31 | ||
|
|
8563179592 | ||
|
|
1c49ff63e2 | ||
|
|
5f121c5da4 | ||
|
|
72f52359e6 | ||
|
|
9f549b98da | ||
|
|
c346a4ca94 | ||
|
|
d334b54846 | ||
|
|
02f68b793c | ||
|
|
57b9133a0f | ||
|
|
815f5e09e8 | ||
|
|
5bdf01ee59 | ||
|
|
bd9417e74c | ||
|
|
694e869162 | ||
|
|
45845f8963 | ||
|
|
a8b6def76a | ||
|
|
a4ebd5fb3d | ||
|
|
3da3b212fa | ||
|
|
c2528cf93e | ||
|
|
550fecd4d3 | ||
|
|
50b01428b4 | ||
|
|
bb59f28b22 | ||
|
|
7064cda6de | ||
|
|
525c1873e8 | ||
|
|
3d91b4eb5e | ||
|
|
f20c03180e | ||
|
|
08fee76b4e | ||
|
|
149f5e4fb5 | ||
|
|
0f511c4b2a | ||
|
|
42d9dfd117 | ||
|
|
1793fc949d | ||
|
|
3983db08ff | ||
|
|
72114bceea | ||
|
|
c303f96682 | ||
|
|
0e785968c4 | ||
|
|
15110e18e2 | ||
|
|
5465af041b | ||
|
|
310d56fc16 | ||
|
|
231258ef69 | ||
|
|
16b7e3ffc8 | ||
|
|
513e59f830 | ||
|
|
b10a1cf2bd | ||
|
|
1656edaa29 | ||
|
|
cff49aacba | ||
|
|
19c32aff6c | ||
|
|
db3ec8337f | ||
|
|
e7bfc40461 | ||
|
|
3d3ca254ba | ||
|
|
b45bc859a4 | ||
|
|
912d7a8775 | ||
|
|
16885da1b5 | ||
|
|
26714052eb | ||
|
|
3df763a783 | ||
|
|
925842bc4b | ||
|
|
cead62704e | ||
|
|
3f24a744c0 | ||
|
|
cce97548a2 | ||
|
|
9270d7cabf | ||
|
|
264aa6d366 | ||
|
|
69fc74e376 | ||
|
|
a361d41e68 | ||
|
|
38766dac99 | ||
|
|
c30bc65281 | ||
|
|
296ebd942a | ||
|
|
afa19f7ad8 | ||
|
|
a193b2d3b1 | ||
|
|
be4a65e572 | ||
|
|
6832918e71 | ||
|
|
fd9a3ffbcc | ||
|
|
41added690 | ||
|
|
18641d4f9b | ||
|
|
4d0c5099d4 | ||
|
|
9d9d491245 | ||
|
|
7b81d18071 | ||
|
|
7d0acbc988 | ||
|
|
313c044c41 | ||
|
|
f6f8adf97e | ||
|
|
bc97d325ca | ||
|
|
0f2d325f20 | ||
|
|
63d5503e12 | ||
|
|
e53f2cac4a | ||
|
|
3b73464233 | ||
|
|
575f10f766 | ||
|
|
8d3fc3533b | ||
|
|
60370b8539 | ||
|
|
f6db114865 | ||
|
|
1c6c344b6b | ||
|
|
d0302898e0 | ||
|
|
057ac9b001 | ||
|
|
8be931bbcb | ||
|
|
3197ef289c | ||
|
|
631578c175 | ||
|
|
f1809163c7 | ||
|
|
60e1fe86f2 | ||
|
|
59d7de5bfc | ||
|
|
6e95c1d84a | ||
|
|
ee64670755 | ||
|
|
3f7d0f5b68 | ||
|
|
e3514c5c4b | ||
|
|
cc3a9cff88 | ||
|
|
15e821aa39 | ||
|
|
8dd1dbab5f | ||
|
|
65ce91ddf6 | ||
|
|
bf55595d6f | ||
|
|
2aa123ccd7 | ||
|
|
0990b06cc9 | ||
|
|
e05f9843ba | ||
|
|
683d2714d0 | ||
|
|
b8ef1ecafc | ||
|
|
467fc2d03d | ||
|
|
58b4fe4f28 | ||
|
|
97d5e0aac4 | ||
|
|
356c977cff | ||
|
|
99d6062376 | ||
|
|
f8538403e4 | ||
|
|
ba12019bc7 | ||
|
|
726b9c80f6 | ||
|
|
2894711c51 | ||
|
|
85280f6f4f | ||
|
|
d7f4c0ee32 | ||
|
|
1263c0d976 | ||
|
|
cd3cbd2b32 | ||
|
|
b3a4fed8be | ||
|
|
d0b4af6666 | ||
|
|
81ab5c189d | ||
|
|
6ef3be4b5c | ||
|
|
9f90a1d651 | ||
|
|
ce9a3fd1ef | ||
|
|
7c6f05058e | ||
|
|
a8c3a7439e | ||
|
|
839b3ab0cf | ||
|
|
44d54db80e | ||
|
|
a67d7bc429 | ||
|
|
079a818c6c | ||
|
|
6be6ef0b5c | ||
|
|
8e51d9d646 | ||
|
|
ea206f4f02 | ||
|
|
f175a2a252 | ||
|
|
3f7e559b86 | ||
|
|
2959b4d701 | ||
|
|
031286c5eb | ||
|
|
e181fa8c4a | ||
|
|
7b035bec5d | ||
|
|
f39d2bf53a | ||
|
|
7c8e407182 | ||
|
|
a09136d46b | ||
|
|
5fe1363ee1 | ||
|
|
b41823fc10 | ||
|
|
0a64fe28b0 | ||
|
|
e320ccfa9a | ||
|
|
9628ff9456 | ||
|
|
d540f78cfc | ||
|
|
66420cd299 | ||
|
|
dd0594471f | ||
|
|
844ba228ee | ||
|
|
7efc701b32 | ||
|
|
d7e29f7c4d | ||
|
|
f26ba91386 | ||
|
|
c73ac2039c | ||
|
|
671f9cd0cb | ||
|
|
131b5b9714 | ||
|
|
74af0889b9 | ||
|
|
e5ee399045 | ||
| deeb7a0f64 | |||
|
|
5af3bab1dc | ||
|
|
28be84d315 | ||
|
|
a0528c737d | ||
|
|
b506e488e8 | ||
|
|
58eb0e08d6 | ||
|
|
562701894f | ||
|
|
54a562273b | ||
|
|
3f8c9c4cb0 | ||
|
|
3e7d28b043 | ||
|
|
40b10d4a26 | ||
|
|
f367630a2a | ||
|
|
b9e4f00862 | ||
|
|
d6e74d6163 | ||
|
|
4a4522b842 | ||
|
|
710ba4423d | ||
|
|
2a5494a804 | ||
|
|
568909800c | ||
|
|
7513a608b1 | ||
|
|
911e9878bd | ||
|
|
899d7d6e61 | ||
|
|
260c0ee776 | ||
|
|
d71520808d | ||
|
|
177fc2a12c | ||
|
|
5dafcb02d4 | ||
|
|
c4fde80c5e | ||
|
|
06e3486ec4 | ||
|
|
bd7c783aaf | ||
|
|
d732e3cfa4 | ||
|
|
c24cdc66ed | ||
|
|
efa6f7a82e | ||
| ddbbc3b847 | |||
|
|
7037161c07 | ||
|
|
b0b62fcf91 | ||
|
|
bd8ba7b854 | ||
|
|
3a52c68270 | ||
|
|
89fd778bd8 | ||
|
|
6e3e8343a8 | ||
|
|
9224237a99 | ||
|
|
8d16925662 | ||
|
|
ef0bf2758e | ||
|
|
351a7552b9 | ||
|
|
9dcc127454 | ||
|
|
81ff334aae | ||
|
|
e76ed60483 | ||
|
|
04d04576bf | ||
|
|
dbd713756f | ||
|
|
6d821dffa6 | ||
|
|
40e559e608 | ||
|
|
b3fe26fc56 | ||
|
|
bb930da2f1 | ||
|
|
732e352261 | ||
|
|
8f2ada3f20 | ||
|
|
762381fac6 | ||
|
|
c440fdf88d | ||
|
|
7f3f6bb135 | ||
|
|
cb7853174d | ||
|
|
ef8575a107 | ||
|
|
6f3f82e0ad | ||
|
|
7b1609abe2 | ||
|
|
691c44a3b5 | ||
|
|
98c629c789 | ||
|
|
8367bff9fe | ||
|
|
ff22cd774e | ||
|
|
ee5e3fbc1d | ||
|
|
d13b2ad073 | ||
|
|
e9a7efc371 | ||
|
|
9b8ddda191 | ||
|
|
1fc14e1075 | ||
|
|
b3a5204e74 | ||
|
|
0fab1ff976 | ||
|
|
a05b692fc3 | ||
|
|
ed7f140364 | ||
|
|
a4b594121e | ||
|
|
fe8da55c95 | ||
|
|
42c4eab4be | ||
|
|
2e8844c896 | ||
|
|
aed7ff003d | ||
|
|
681b28f654 | ||
|
|
0de64b1551 | ||
|
|
526df2404e | ||
|
|
f20274aac7 | ||
|
|
08b899fdac | ||
|
|
7b91b6e7c8 | ||
|
|
1661b7ec36 | ||
|
|
e5ab9dc883 | ||
|
|
25d22e33a7 | ||
|
|
8ceac9000c | ||
|
|
ecceec8e1a | ||
|
|
d5c88ebab3 | ||
|
|
0a2adbc205 | ||
|
|
3be7f9da37 | ||
|
|
3f2ca67416 | ||
|
|
21087323af | ||
|
|
505838a32a | ||
|
|
fd3f9eb382 | ||
|
|
05f92018c3 | ||
|
|
b8fc4a2415 | ||
|
|
ccd2fc6568 | ||
|
|
a30872809d | ||
|
|
7abf2ed58b | ||
|
|
4822f571c3 | ||
|
|
b0fdac3e6f | ||
|
|
df62c1d3b2 | ||
|
|
56912ade7a | ||
|
|
43698b41a7 | ||
|
|
fd2beeab48 | ||
|
|
5647a424e7 | ||
|
|
a0a418e90b | ||
|
|
75e09b24c0 | ||
|
|
0b06023b82 | ||
|
|
49707498a5 | ||
|
|
a4c2d27985 | ||
|
|
9fac34fb21 | ||
|
|
d4b22936af | ||
|
|
f0d0143be0 | ||
|
|
7d1593e887 | ||
|
|
2588444948 | ||
|
|
69abb8446f | ||
|
|
6fee1f6dc3 | ||
|
|
6e0f4ecbc9 | ||
|
|
e5d10e3dba | ||
|
|
0ba87b6c62 | ||
|
|
da47306f04 | ||
|
|
1930126a59 | ||
|
|
baf9f391f1 | ||
|
|
979703dd1f | ||
|
|
ab9e8063dc | ||
|
|
68c09d7221 |
13
.config/dotnet-tools.json
Normal file
13
.config/dotnet-tools.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"csharpier": {
|
||||
"version": "1.2.5",
|
||||
"commands": [
|
||||
"csharpier"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
}
|
||||
}
|
||||
7
.copilot-agent.yml
Normal file
7
.copilot-agent.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
enabled: true
|
||||
agent:
|
||||
name: copilot-coding-agent
|
||||
allow:
|
||||
- paths: ["src/**/*", "tests/**/*", "README.md", "AGENTS.md"]
|
||||
actions: ["create", "modify"]
|
||||
require_review_before_merge: true
|
||||
568
.editorconfig
Normal file
568
.editorconfig
Normal file
@@ -0,0 +1,568 @@
|
||||
# Version: 2.0.1 (Using https://semver.org/)
|
||||
# Updated: 2020-12-11
|
||||
# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
|
||||
# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
|
||||
# See http://EditorConfig.org for more information about .editorconfig files.
|
||||
|
||||
##########################################
|
||||
# Common Settings
|
||||
##########################################
|
||||
|
||||
# This file is the top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# All Files
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
##########################################
|
||||
# File Extension Settings
|
||||
##########################################
|
||||
|
||||
# Visual Studio Solution Files
|
||||
[*.sln]
|
||||
indent_style = tab
|
||||
|
||||
# Visual Studio XML Project Files
|
||||
[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
|
||||
indent_size = 2
|
||||
|
||||
# XML Configuration Files
|
||||
[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
# JSON Files
|
||||
[*.{json,json5,webmanifest}]
|
||||
indent_size = 2
|
||||
|
||||
# YAML Files
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
# Markdown Files
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Web Files
|
||||
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
|
||||
indent_size = 2
|
||||
|
||||
# Batch Files
|
||||
[*.{cmd,bat}]
|
||||
end_of_line = crlf
|
||||
|
||||
# Bash Files
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
# Makefiles
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
##########################################
|
||||
# Default .NET Code Style Severities
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
|
||||
##########################################
|
||||
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# Default Severity for all .NET Code Style rules below
|
||||
dotnet_analyzer_diagnostic.severity = silent
|
||||
|
||||
##########################################
|
||||
# File Header (Uncomment to support file headers)
|
||||
# https://docs.microsoft.com/visualstudio/ide/reference/add-file-header
|
||||
##########################################
|
||||
|
||||
# [*.{cs,csx,cake,vb,vbx}]
|
||||
# file_header_template = <copyright file="{fileName}" company="PROJECT-AUTHOR">\n© PROJECT-AUTHOR\n</copyright>
|
||||
|
||||
# SA1636: File header copyright text should match
|
||||
# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project.
|
||||
# dotnet_diagnostic.SA1636.severity = none
|
||||
|
||||
##########################################
|
||||
# .NET Language Conventions
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions
|
||||
##########################################
|
||||
|
||||
# .NET Code Style Settings
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# "this." and "Me." qualifiers
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me
|
||||
#dotnet_style_qualification_for_field = true:warning
|
||||
#dotnet_style_qualification_for_property = true:warning
|
||||
#dotnet_style_qualification_for_method = true:warning
|
||||
#dotnet_style_qualification_for_event = true:warning
|
||||
# Language keywords instead of framework type names for type references
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
|
||||
dotnet_style_predefined_type_for_member_access = true:warning
|
||||
# Modifier preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers
|
||||
dotnet_style_require_accessibility_modifiers = always:warning
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
|
||||
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning
|
||||
dotnet_style_readonly_field = true:warning
|
||||
# Parentheses preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
|
||||
# Expression-level preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
|
||||
dotnet_style_object_initializer = true:warning
|
||||
dotnet_style_collection_initializer = true:warning
|
||||
dotnet_style_explicit_tuple_names = true:warning
|
||||
dotnet_style_prefer_inferred_tuple_names = true:warning
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
|
||||
dotnet_style_prefer_auto_properties = true:warning
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
|
||||
dotnet_diagnostic.IDE0045.severity = suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_return = false:suggestion
|
||||
dotnet_diagnostic.IDE0046.severity = suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:warning
|
||||
# Null-checking preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences
|
||||
dotnet_style_coalesce_expression = true:warning
|
||||
dotnet_style_null_propagation = true:warning
|
||||
# Parameter preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences
|
||||
dotnet_code_quality_unused_parameters = all:warning
|
||||
# More style options (Undocumented)
|
||||
# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641
|
||||
dotnet_style_operator_placement_when_wrapping = end_of_line
|
||||
# https://github.com/dotnet/roslyn/pull/40070
|
||||
dotnet_style_prefer_simplified_interpolation = true:warning
|
||||
|
||||
# C# Code Style Settings
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings
|
||||
[*.{cs,csx,cake}]
|
||||
# Implicit and explicit types
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types
|
||||
csharp_style_var_for_built_in_types = true:warning
|
||||
csharp_style_var_when_type_is_apparent = true:warning
|
||||
csharp_style_var_elsewhere = true:warning
|
||||
# Expression-bodied members
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members
|
||||
csharp_style_expression_bodied_methods = true:warning
|
||||
csharp_style_expression_bodied_constructors = true:warning
|
||||
csharp_style_expression_bodied_operators = true:warning
|
||||
csharp_style_expression_bodied_properties = true:warning
|
||||
csharp_style_expression_bodied_indexers = true:warning
|
||||
csharp_style_expression_bodied_accessors = true:warning
|
||||
csharp_style_expression_bodied_lambdas = true:warning
|
||||
csharp_style_expression_bodied_local_functions = true:warning
|
||||
# Pattern matching
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:warning
|
||||
# Inlined variable declarations
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations
|
||||
csharp_style_inlined_variable_declaration = true:warning
|
||||
# Expression-level preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
|
||||
csharp_prefer_simple_default_expression = true:warning
|
||||
# "Null" checking preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences
|
||||
csharp_style_throw_expression = true:warning
|
||||
csharp_style_conditional_delegate_call = true:warning
|
||||
# Code block preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences
|
||||
csharp_prefer_braces = true:warning
|
||||
# Unused value preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
|
||||
dotnet_diagnostic.IDE0058.severity = suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
dotnet_diagnostic.IDE0059.severity = suggestion
|
||||
# Index and range preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences
|
||||
csharp_style_prefer_index_operator = true:warning
|
||||
csharp_style_prefer_range_operator = true:warning
|
||||
# Miscellaneous preferences
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences
|
||||
csharp_style_deconstructed_variable_declaration = true:warning
|
||||
csharp_style_pattern_local_over_anonymous_function = true:warning
|
||||
csharp_using_directive_placement = outside_namespace:warning
|
||||
csharp_prefer_static_local_function = true:warning
|
||||
csharp_prefer_simple_using_statement = true:suggestion
|
||||
dotnet_diagnostic.IDE0063.severity = suggestion
|
||||
|
||||
##########################################
|
||||
# .NET Formatting Conventions
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
|
||||
##########################################
|
||||
|
||||
# Organize usings
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives
|
||||
dotnet_sort_system_directives_first = true
|
||||
# Newline options
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
# Indentation options
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = no_change
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents_when_block = false
|
||||
# Spacing options
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_square_brackets = false
|
||||
# Wrapping options
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
|
||||
csharp_preserve_single_line_statements = false
|
||||
csharp_preserve_single_line_blocks = true
|
||||
|
||||
csharp_style_namespace_declarations = file_scoped
|
||||
|
||||
##########################################
|
||||
# .NET Naming Conventions
|
||||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions
|
||||
##########################################
|
||||
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
dotnet_diagnostic.CA1000.severity = suggestion
|
||||
dotnet_diagnostic.CA1001.severity = error
|
||||
dotnet_diagnostic.CA1018.severity = error
|
||||
dotnet_diagnostic.CA1036.severity = silent
|
||||
dotnet_diagnostic.CA1051.severity = suggestion
|
||||
dotnet_diagnostic.CA1068.severity = error
|
||||
dotnet_diagnostic.CA1069.severity = error
|
||||
dotnet_diagnostic.CA1304.severity = error
|
||||
dotnet_diagnostic.CA1305.severity = suggestion
|
||||
dotnet_diagnostic.CA1307.severity = suggestion
|
||||
dotnet_diagnostic.CA1309.severity = suggestion
|
||||
dotnet_diagnostic.CA1310.severity = error
|
||||
dotnet_diagnostic.CA1507.severity = suggestion
|
||||
dotnet_diagnostic.CA1513.severity = suggestion
|
||||
dotnet_diagnostic.CA1707.severity = suggestion
|
||||
dotnet_diagnostic.CA1708.severity = suggestion
|
||||
dotnet_diagnostic.CA1711.severity = suggestion
|
||||
dotnet_diagnostic.CA1716.severity = suggestion
|
||||
dotnet_diagnostic.CA1720.severity = suggestion
|
||||
dotnet_diagnostic.CA1725.severity = suggestion
|
||||
dotnet_diagnostic.CA1805.severity = suggestion
|
||||
dotnet_diagnostic.CA1816.severity = suggestion
|
||||
dotnet_diagnostic.CA1822.severity = suggestion
|
||||
dotnet_diagnostic.CA1825.severity = error
|
||||
dotnet_diagnostic.CA1826.severity = silent
|
||||
dotnet_diagnostic.CA1827.severity = error
|
||||
dotnet_diagnostic.CA1829.severity = suggestion
|
||||
dotnet_diagnostic.CA1834.severity = error
|
||||
dotnet_diagnostic.CA1845.severity = suggestion
|
||||
dotnet_diagnostic.CA1848.severity = suggestion
|
||||
dotnet_diagnostic.CA1852.severity = suggestion
|
||||
dotnet_diagnostic.CA1860.severity = silent
|
||||
dotnet_diagnostic.CA2016.severity = suggestion
|
||||
dotnet_diagnostic.CA2201.severity = error
|
||||
dotnet_diagnostic.CA2206.severity = error
|
||||
dotnet_diagnostic.CA2208.severity = error
|
||||
dotnet_diagnostic.CA2211.severity = error
|
||||
dotnet_diagnostic.CA2249.severity = error
|
||||
dotnet_diagnostic.CA2251.severity = error
|
||||
dotnet_diagnostic.CA2252.severity = none
|
||||
dotnet_diagnostic.CA2254.severity = suggestion
|
||||
|
||||
dotnet_diagnostic.CS0169.severity = error
|
||||
dotnet_diagnostic.CS0219.severity = error
|
||||
dotnet_diagnostic.CS0649.severity = suggestion
|
||||
dotnet_diagnostic.CS1998.severity = error
|
||||
dotnet_diagnostic.CS8602.severity = error
|
||||
dotnet_diagnostic.CS8604.severity = error
|
||||
dotnet_diagnostic.CS8618.severity = error
|
||||
dotnet_diagnostic.CS0618.severity = suggestion
|
||||
dotnet_diagnostic.CS1998.severity = error
|
||||
dotnet_diagnostic.CS4014.severity = error
|
||||
dotnet_diagnostic.CS8600.severity = error
|
||||
dotnet_diagnostic.CS8603.severity = error
|
||||
dotnet_diagnostic.CS8625.severity = error
|
||||
|
||||
dotnet_diagnostic.BL0005.severity = suggestion
|
||||
|
||||
dotnet_diagnostic.MVC1000.severity = suggestion
|
||||
|
||||
dotnet_diagnostic.RZ10012.severity = error
|
||||
|
||||
dotnet_diagnostic.IDE0004.severity = error # redundant cast
|
||||
dotnet_diagnostic.IDE0005.severity = suggestion
|
||||
dotnet_diagnostic.IDE0007.severity = error # Use var
|
||||
dotnet_diagnostic.IDE0011.severity = error # Use braces on if statements
|
||||
dotnet_diagnostic.IDE0010.severity = silent # populate switch
|
||||
dotnet_diagnostic.IDE0017.severity = suggestion # initialization can be simplified
|
||||
dotnet_diagnostic.IDE0021.severity = silent # expression body for constructors
|
||||
dotnet_diagnostic.IDE0022.severity = silent # expression body for methods
|
||||
dotnet_diagnostic.IDE0023.severity = suggestion # use expression body for operators
|
||||
dotnet_diagnostic.IDE0024.severity = silent # expression body for operators
|
||||
dotnet_diagnostic.IDE0025.severity = suggestion # use expression body for properties
|
||||
dotnet_diagnostic.IDE0027.severity = suggestion # Use expression body for accessors
|
||||
dotnet_diagnostic.IDE0028.severity = silent # expression body for accessors
|
||||
dotnet_diagnostic.IDE0032.severity = suggestion # Use auto property
|
||||
dotnet_diagnostic.IDE0033.severity = error # prefer tuple name
|
||||
dotnet_diagnostic.IDE0037.severity = suggestion # simplify anonymous type
|
||||
dotnet_diagnostic.IDE0040.severity = error # modifiers required
|
||||
dotnet_diagnostic.IDE0041.severity = error # simplify null
|
||||
dotnet_diagnostic.IDE0042.severity = error # deconstruct variable
|
||||
dotnet_diagnostic.IDE0044.severity = suggestion # make field only when possible
|
||||
dotnet_diagnostic.IDE0047.severity = suggestion # parameter name
|
||||
dotnet_diagnostic.IDE0051.severity = error # unused field
|
||||
dotnet_diagnostic.IDE0052.severity = error # unused member
|
||||
dotnet_diagnostic.IDE0053.severity = suggestion # lambda not needed
|
||||
dotnet_diagnostic.IDE0055.severity = suggestion # Fix formatting
|
||||
dotnet_diagnostic.IDE0057.severity = suggestion # substring can be simplified
|
||||
dotnet_diagnostic.IDE0060.severity = suggestion # unused parameters
|
||||
dotnet_diagnostic.IDE0061.severity = suggestion # local expression body
|
||||
dotnet_diagnostic.IDE0062.severity = suggestion # local to static
|
||||
dotnet_diagnostic.IDE0063.severity = error # simplify using
|
||||
dotnet_diagnostic.IDE0066.severity = suggestion # switch expression
|
||||
dotnet_diagnostic.IDE0072.severity = suggestion # Populate switch - forces population of all cases even when default specified
|
||||
dotnet_diagnostic.IDE0078.severity = suggestion # use pattern matching
|
||||
dotnet_diagnostic.IDE0090.severity = suggestion # new can be simplified
|
||||
dotnet_diagnostic.IDE0130.severity = suggestion # namespace folder structure
|
||||
dotnet_diagnostic.IDE0160.severity = silent # Use block namespaces ARE NOT required
|
||||
dotnet_diagnostic.IDE0161.severity = error # Please use file namespaces
|
||||
dotnet_diagnostic.IDE0200.severity = suggestion # lambda not needed
|
||||
dotnet_diagnostic.IDE1006.severity = suggestion # Naming rule violation: These words cannot contain lower case characters
|
||||
dotnet_diagnostic.IDE0260.severity = suggestion # Use pattern matching
|
||||
dotnet_diagnostic.IDE0270.severity = suggestion # Null check simplifcation
|
||||
dotnet_diagnostic.IDE0290.severity = error # Primary Constructor
|
||||
dotnet_diagnostic.IDE0300.severity = suggestion # Collection
|
||||
dotnet_diagnostic.IDE0305.severity = suggestion # Collection ToList
|
||||
|
||||
dotnet_diagnostic.NX0001.severity = error
|
||||
dotnet_diagnostic.NX0002.severity = silent
|
||||
dotnet_diagnostic.NX0003.severity = silent
|
||||
|
||||
##########################################
|
||||
# Styles
|
||||
##########################################
|
||||
|
||||
# camel_case_style - Define the camelCase style
|
||||
dotnet_naming_style.camel_case_style.capitalization = camel_case
|
||||
# pascal_case_style - Define the PascalCase style
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
# constant_case - Define the CONSTANT_CASE style
|
||||
dotnet_naming_style.constant_case.capitalization = all_upper
|
||||
dotnet_naming_style.constant_case.word_separator = _
|
||||
# first_upper_style - The first character must start with an upper-case character
|
||||
dotnet_naming_style.first_upper_style.capitalization = first_word_upper
|
||||
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
|
||||
dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
|
||||
dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
|
||||
# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
|
||||
dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
|
||||
dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
|
||||
# disallowed_style - Anything that has this style applied is marked as disallowed
|
||||
dotnet_naming_style.disallowed_style.capitalization = pascal_case
|
||||
dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
|
||||
dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
|
||||
# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
|
||||
dotnet_naming_style.internal_error_style.capitalization = pascal_case
|
||||
dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
|
||||
dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
|
||||
|
||||
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
|
||||
dotnet_naming_style.underscore_camel_case_style.capitalization = camel_case
|
||||
dotnet_naming_style.underscore_camel_case_style.required_prefix = _
|
||||
|
||||
##########################################
|
||||
# .NET Design Guideline Field Naming Rules
|
||||
# Naming rules for fields follow the .NET Framework design guidelines
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
|
||||
##########################################
|
||||
|
||||
# All public/protected/protected_internal constant fields must be constant_case
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = constant_case
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# All public/protected/protected_internal static readonly fields must be constant_case
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# No other public/protected/protected_internal fields are allowed
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
|
||||
|
||||
##########################################
|
||||
# StyleCop Field Naming Rules
|
||||
# Naming rules for fields follow the StyleCop analyzers
|
||||
# This does not override any rules using disallowed_style above
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
|
||||
##########################################
|
||||
|
||||
# All constant fields must be constant_case
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = constant_case
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# All static readonly fields must be constant_case
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# No non-private instance fields are allowed
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
|
||||
|
||||
# Private fields must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
|
||||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = underscore_camel_case_style
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
|
||||
|
||||
# Local variables must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = warning
|
||||
|
||||
# This rule should never fire. However, it's included for at least two purposes:
|
||||
# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
|
||||
# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
|
||||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
|
||||
|
||||
|
||||
##########################################
|
||||
# Other Naming Rules
|
||||
##########################################
|
||||
|
||||
# All of the following must be PascalCase:
|
||||
# - Namespaces
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
|
||||
# - Classes and Enumerations
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
|
||||
# - Delegates
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
|
||||
# - Constructors, Properties, Events, Methods
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
|
||||
dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
|
||||
dotnet_naming_rule.element_rule.symbols = element_group
|
||||
dotnet_naming_rule.element_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.element_rule.severity = warning
|
||||
|
||||
# Interfaces use PascalCase and are prefixed with uppercase 'I'
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
dotnet_naming_symbols.interface_group.applicable_kinds = interface
|
||||
dotnet_naming_rule.interface_rule.symbols = interface_group
|
||||
dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
|
||||
dotnet_naming_rule.interface_rule.severity = warning
|
||||
|
||||
# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
|
||||
dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
|
||||
dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
|
||||
dotnet_naming_rule.type_parameter_rule.severity = warning
|
||||
|
||||
# Function parameters use camelCase
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
|
||||
dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
|
||||
dotnet_naming_rule.parameters_rule.symbols = parameters_group
|
||||
dotnet_naming_rule.parameters_rule.style = camel_case_style
|
||||
dotnet_naming_rule.parameters_rule.severity = warning
|
||||
|
||||
##########################################
|
||||
# License
|
||||
##########################################
|
||||
# The following applies as to the .editorconfig file ONLY, and is
|
||||
# included below for reference, per the requirements of the license
|
||||
# corresponding to this .editorconfig file.
|
||||
# See: https://github.com/RehanSaeed/EditorConfig
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2017-2019 Muhammad Rehan Saeed
|
||||
# Copyright (c) 2019 Henry Gabryjelski
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any
|
||||
# person obtaining a copy of this software and associated
|
||||
# documentation files (the "Software"), to deal in the
|
||||
# Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute,
|
||||
# sublicense, and/or sell copies of the Software, and to permit
|
||||
# persons to whom the Software is furnished to do so, subject
|
||||
# to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
##########################################
|
||||
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# need original files to be windows
|
||||
*.txt text eol=crlf
|
||||
17
.github/agents/copilot-agent.yml
vendored
Normal file
17
.github/agents/copilot-agent.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
enabled: true
|
||||
agent:
|
||||
name: copilot-coding-agent
|
||||
allow:
|
||||
- paths: ["src/**/*", "tests/**/*", "README.md", "AGENTS.md"]
|
||||
actions: ["create", "modify", "delete"]
|
||||
require_review_before_merge: true
|
||||
required_approvals: 1
|
||||
allowed_merge_strategies:
|
||||
- squash
|
||||
- merge
|
||||
auto_merge_on_green: false
|
||||
run_workflows: true
|
||||
notes: |
|
||||
- This manifest expresses the policy for the Copilot coding agent in this repository.
|
||||
- It does NOT install or authorize the agent; a repository admin must install the Copilot coding agent app and grant the repository the necessary permissions (contents: write, pull_requests: write, checks: write, actions: write/read, issues: write) to allow the agent to act.
|
||||
- Keep allow paths narrow and prefer require_review_before_merge during initial rollout.
|
||||
13
.github/dependabot.yml
vendored
Normal file
13
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "nuget"
|
||||
directory: "/" # change to "/src/YourProject" if .csproj files are in subfolders
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
# optional: target-branch: "master"
|
||||
25
.github/prompts/plan-async.prompt.md
vendored
Normal file
25
.github/prompts/plan-async.prompt.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Plan: Implement Missing Async Functionality in SharpCompress
|
||||
|
||||
SharpCompress has async support for low-level stream operations and Reader/Writer APIs, but critical entry points (Archive.Open, factory methods, initialization) remain synchronous. This plan adds async overloads for all user-facing I/O operations and fixes existing async bugs, enabling full end-to-end async workflows.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add async factory methods** to [ArchiveFactory.cs](src/SharpCompress/Factories/ArchiveFactory.cs), [ReaderFactory.cs](src/SharpCompress/Factories/ReaderFactory.cs), and [WriterFactory.cs](src/SharpCompress/Factories/WriterFactory.cs) with `OpenAsync` and `CreateAsync` overloads accepting `CancellationToken`
|
||||
|
||||
2. **Implement async Open methods** on concrete archive types ([ZipArchive.cs](src/SharpCompress/Archives/Zip/ZipArchive.cs), [TarArchive.cs](src/SharpCompress/Archives/Tar/TarArchive.cs), [RarArchive.cs](src/SharpCompress/Archives/Rar/RarArchive.cs), [GZipArchive.cs](src/SharpCompress/Archives/GZip/GZipArchive.cs), [SevenZipArchive.cs](src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs)) and reader types ([ZipReader.cs](src/SharpCompress/Readers/Zip/ZipReader.cs), [TarReader.cs](src/SharpCompress/Readers/Tar/TarReader.cs), etc.)
|
||||
|
||||
3. **Convert archive initialization logic to async** including header reading, volume loading, and format signature detection across archive constructors and internal initialization methods
|
||||
|
||||
4. **Fix LZMA decoder async bugs** in [LzmaStream.cs](src/SharpCompress/Compressors/LZMA/LzmaStream.cs), [Decoder.cs](src/SharpCompress/Compressors/LZMA/Decoder.cs), and [OutWindow.cs](src/SharpCompress/Compressors/LZMA/OutWindow.cs) to enable true async 7Zip support and remove `NonDisposingStream` workaround
|
||||
|
||||
5. **Complete Rar async implementation** by converting `UnpackV2017` methods to async in [UnpackV2017.cs](src/SharpCompress/Compressors/Rar/UnpackV2017.cs) and updating Rar20 decompression
|
||||
|
||||
6. **Add comprehensive async tests** covering all new async entry points, cancellation scenarios, and concurrent operations across all archive formats in test files
|
||||
|
||||
## Further Considerations
|
||||
|
||||
1. **Breaking changes** - Should new async methods be added alongside existing sync methods (non-breaking), or should sync methods eventually be deprecated? Recommend additive approach for backward compatibility.
|
||||
|
||||
2. **Performance impact** - Header parsing for formats like Zip/Tar is often small; consider whether truly async parsing adds value vs sync parsing wrapped in Task, or make it conditional based on stream type (network vs file).
|
||||
|
||||
3. **7Zip complexity** - The LZMA async bug fix (Step 4) may be challenging due to state management in the decoder; consider whether to scope it separately or implement a simpler workaround that maintains correctness.
|
||||
123
.github/prompts/plan-for-next.prompt.md
vendored
Normal file
123
.github/prompts/plan-for-next.prompt.md
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
# Plan: Modernize SharpCompress Public API
|
||||
|
||||
Based on comprehensive analysis, the API has several inconsistencies around factory patterns, async support, format capabilities, and options classes. Most improvements can be done incrementally without breaking changes.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Standardize factory patterns** by deprecating format-specific static `Open` methods in [Archives/Zip/ZipArchive.cs](src/SharpCompress/Archives/Zip/ZipArchive.cs), [Archives/Tar/TarArchive.cs](src/SharpCompress/Archives/Tar/TarArchive.cs), etc. in favor of centralized [Factories/ArchiveFactory.cs](src/SharpCompress/Factories/ArchiveFactory.cs)
|
||||
|
||||
2. **Complete async implementation** in [Writers/Zip/ZipWriter.cs](src/SharpCompress/Writers/Zip/ZipWriter.cs) and other writers that currently use sync-over-async, implementing true async I/O throughout the writer hierarchy
|
||||
|
||||
3. **Unify options classes** by making [Common/ExtractionOptions.cs](src/SharpCompress/Common/ExtractionOptions.cs) inherit from `OptionsBase` and adding progress reporting to extraction methods consistently
|
||||
|
||||
4. **Clarify GZip semantics** in [Archives/GZip/GZipArchive.cs](src/SharpCompress/Archives/GZip/GZipArchive.cs) by adding XML documentation explaining single-entry limitation and relationship to GZip compression used in Tar.gz
|
||||
|
||||
## Further Considerations
|
||||
|
||||
1. **Breaking changes roadmap** - Should we plan a major version (2.0) to remove deprecated factory methods, clean up `ArchiveType` enum (remove Arc/Arj or add full support), and consolidate naming patterns?
|
||||
|
||||
2. **Progress reporting consistency** - Should `IProgress<ArchiveExtractionProgress<IEntry>>` be added to all extraction extension methods or consolidated into options classes?
|
||||
|
||||
## Detailed Analysis
|
||||
|
||||
### Factory Pattern Issues
|
||||
|
||||
Three different factory patterns exist with overlapping functionality:
|
||||
|
||||
1. **Static Factories**: ArchiveFactory, ReaderFactory, WriterFactory
|
||||
2. **Instance Factories**: IArchiveFactory, IReaderFactory, IWriterFactory
|
||||
3. **Format-specific static methods**: Each archive class has static `Open` methods
|
||||
|
||||
**Example confusion:**
|
||||
```csharp
|
||||
// Three ways to open a Zip archive - which is recommended?
|
||||
var archive1 = ArchiveFactory.Open("file.zip");
|
||||
var archive2 = ZipArchive.Open("file.zip");
|
||||
var archive3 = ArchiveFactory.AutoFactory.Open(fileInfo, options);
|
||||
```
|
||||
|
||||
### Async Support Gaps
|
||||
|
||||
Base `IWriter` interface has async methods, but writer implementations provide minimal async support. Most writers just call synchronous methods:
|
||||
|
||||
```csharp
|
||||
public virtual async Task WriteAsync(...)
|
||||
{
|
||||
// Default implementation calls synchronous version
|
||||
Write(filename, source, modificationTime);
|
||||
await Task.CompletedTask.ConfigureAwait(false);
|
||||
}
|
||||
```
|
||||
|
||||
Real async implementations only in:
|
||||
- `TarWriter` - Proper async implementation
|
||||
- Most other writers use sync-over-async
|
||||
|
||||
### GZip Archive Special Case
|
||||
|
||||
GZip is treated as both a compression format and an archive format, but only supports single-entry archives:
|
||||
|
||||
```csharp
|
||||
protected override GZipArchiveEntry CreateEntryInternal(...)
|
||||
{
|
||||
if (Entries.Any())
|
||||
{
|
||||
throw new InvalidFormatException("Only one entry is allowed in a GZip Archive");
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Options Class Hierarchy
|
||||
|
||||
```
|
||||
OptionsBase (LeaveStreamOpen, ArchiveEncoding)
|
||||
├─ ReaderOptions (LookForHeader, Password, DisableCheckIncomplete, BufferSize, ExtensionHint, Progress)
|
||||
├─ WriterOptions (CompressionType, CompressionLevel, Progress)
|
||||
│ ├─ ZipWriterOptions (ArchiveComment, UseZip64)
|
||||
│ ├─ TarWriterOptions (FinalizeArchiveOnClose, HeaderFormat)
|
||||
│ └─ GZipWriterOptions (no additional properties)
|
||||
└─ ExtractionOptions (standalone - Overwrite, ExtractFullPath, PreserveFileTime, PreserveAttributes)
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
- `ExtractionOptions` doesn't inherit from `OptionsBase` - no encoding support during extraction
|
||||
- Progress reporting inconsistency between readers and extraction
|
||||
- Obsolete properties (`ChecksumIsValid`, `Version`) with unclear migration path
|
||||
|
||||
### Implementation Priorities
|
||||
|
||||
**High Priority (Non-Breaking):**
|
||||
1. Add API usage guide (Archive vs Reader, factory recommendations, async best practices)
|
||||
2. Fix progress reporting consistency
|
||||
3. Complete async implementation in writers
|
||||
|
||||
**Medium Priority (Next Major Version):**
|
||||
1. Unify factory pattern - deprecate format-specific static `Open` methods
|
||||
2. Clean up options classes - make `ExtractionOptions` inherit from `OptionsBase`
|
||||
3. Clarify archive types - remove Arc/Arj from `ArchiveType` enum or add full support
|
||||
4. Standardize naming across archive types
|
||||
|
||||
**Low Priority:**
|
||||
1. Add BZip2 archive support similar to GZipArchive
|
||||
2. Complete obsolete property cleanup with migration guide
|
||||
|
||||
### Backward Compatibility Strategy
|
||||
|
||||
**Safe (Non-Breaking) Changes:**
|
||||
- Add new methods to interfaces (use default implementations)
|
||||
- Add new options properties (with defaults)
|
||||
- Add new factory methods
|
||||
- Improve async implementations
|
||||
- Add progress reporting support
|
||||
|
||||
**Breaking Changes to Avoid:**
|
||||
- ❌ Removing format-specific `Open` methods (deprecate instead)
|
||||
- ❌ Changing `LeaveStreamOpen` default (currently `true`)
|
||||
- ❌ Removing obsolete properties before major version bump
|
||||
- ❌ Changing return types or signatures of existing methods
|
||||
|
||||
**Deprecation Pattern:**
|
||||
- Use `[Obsolete]` for one major version
|
||||
- Use `[EditorBrowsable(EditorBrowsableState.Never)]` in next major version
|
||||
- Remove in following major version
|
||||
155
.github/workflows/NUGET_RELEASE.md
vendored
Normal file
155
.github/workflows/NUGET_RELEASE.md
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
# NuGet Release Workflow
|
||||
|
||||
This document describes the automated NuGet release workflow for SharpCompress.
|
||||
|
||||
## Overview
|
||||
|
||||
The `nuget-release.yml` workflow automatically builds, tests, and publishes SharpCompress packages to NuGet.org when:
|
||||
- Changes are pushed to the `master` or `release` branch
|
||||
- A version tag (format: `MAJOR.MINOR.PATCH`) is pushed
|
||||
|
||||
The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Version Determination
|
||||
|
||||
The workflow automatically determines the version based on whether the commit is tagged using C# code in the build project:
|
||||
|
||||
1. **Tagged Release (Stable)**:
|
||||
- If the current commit has a version tag (e.g., `0.42.1`)
|
||||
- Uses the tag as the version number
|
||||
- Published as a stable release
|
||||
|
||||
2. **Untagged Release (Prerelease)**:
|
||||
- If the current commit is NOT tagged
|
||||
- Creates a prerelease version based on the next minor version
|
||||
- Format: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`
|
||||
- Example: `0.43.0-beta.123` (if last tag is 0.42.x)
|
||||
- Published as a prerelease to NuGet.org (Windows build only)
|
||||
|
||||
### Workflow Steps
|
||||
|
||||
The workflow runs on a matrix of operating systems (Windows and Ubuntu):
|
||||
|
||||
1. **Checkout**: Fetches the repository with full history for version detection
|
||||
2. **Setup .NET**: Installs .NET 10.0
|
||||
3. **Determine Version**: Runs `determine-version` build target to check for tags and determine version
|
||||
4. **Update Version**: Runs `update-version` build target to update the version in the project file
|
||||
5. **Build and Test**: Runs the full build and test suite on both platforms
|
||||
6. **Upload Artifacts**: Uploads the generated `.nupkg` files as workflow artifacts (separate for each OS)
|
||||
7. **Push to NuGet**: (Windows only) Runs `push-to-nuget` build target to publish the package to NuGet.org using the API key
|
||||
|
||||
All version detection, file updates, and publishing logic is implemented in C# in the `build/Program.cs` file using build targets.
|
||||
|
||||
## Setup Requirements
|
||||
|
||||
### 1. NuGet API Key Secret
|
||||
|
||||
The workflow requires a `NUGET_API_KEY` secret to be configured in the repository settings:
|
||||
|
||||
1. Go to https://www.nuget.org/account/apikeys
|
||||
2. Create a new API key with "Push" permission for the SharpCompress package
|
||||
3. In GitHub, go to: **Settings** → **Secrets and variables** → **Actions**
|
||||
4. Create a new secret named `NUGET_API_KEY` with the API key value
|
||||
|
||||
### 2. Branch Protection (Recommended)
|
||||
|
||||
Consider enabling branch protection rules for the `release` branch to ensure:
|
||||
- Code reviews are required before merging
|
||||
- Status checks pass before merging
|
||||
- Only authorized users can push to the branch
|
||||
|
||||
## Usage
|
||||
|
||||
### Creating a Stable Release
|
||||
|
||||
There are two ways to trigger a stable release:
|
||||
|
||||
**Method 1: Push tag to trigger workflow**
|
||||
1. Ensure all changes are committed on the `master` or `release` branch
|
||||
2. Create and push a version tag:
|
||||
```bash
|
||||
git checkout master # or release
|
||||
git tag 0.43.0
|
||||
git push origin 0.43.0
|
||||
```
|
||||
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)
|
||||
|
||||
**Method 2: Tag after pushing to branch**
|
||||
1. Ensure all changes are merged and pushed to the `master` or `release` branch
|
||||
2. Create and push a version tag on the already-pushed commit:
|
||||
```bash
|
||||
git checkout master # or release
|
||||
git tag 0.43.0
|
||||
git push origin 0.43.0
|
||||
```
|
||||
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)
|
||||
|
||||
### Creating a Prerelease
|
||||
|
||||
1. Push changes to the `master` or `release` branch without tagging:
|
||||
```bash
|
||||
git checkout master # or release
|
||||
git push origin master # or release
|
||||
```
|
||||
2. The workflow will automatically:
|
||||
- Build and test the project on both Windows and Ubuntu
|
||||
- Publish a prerelease version like `0.43.0-beta.456` to NuGet.org (Windows build)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Workflow Fails to Push to NuGet
|
||||
|
||||
- **Check the API Key**: Ensure `NUGET_API_KEY` is set correctly in repository secrets
|
||||
- **Check API Key Permissions**: Verify the API key has "Push" permission for SharpCompress
|
||||
- **Check API Key Expiration**: NuGet API keys may expire; create a new one if needed
|
||||
|
||||
### Version Conflict
|
||||
|
||||
If you see "Package already exists" errors:
|
||||
- The workflow uses `--skip-duplicate` flag to handle this gracefully
|
||||
- If you need to republish the same version, delete it from NuGet.org first (if allowed)
|
||||
|
||||
### Build or Test Failures
|
||||
|
||||
- The workflow will not push to NuGet if build or tests fail
|
||||
- Check the workflow logs in GitHub Actions for details
|
||||
- Fix the issues and push again
|
||||
|
||||
## Manual Package Creation
|
||||
|
||||
If you need to create a package manually without publishing:
|
||||
|
||||
```bash
|
||||
dotnet run --project build/build.csproj -- publish
|
||||
```
|
||||
|
||||
The package will be created in the `artifacts/` directory.
|
||||
|
||||
## Build Targets
|
||||
|
||||
The workflow uses the following C# build targets defined in `build/Program.cs`:
|
||||
|
||||
- **determine-version**: Detects version from git tags and outputs VERSION and PRERELEASE variables
|
||||
- **update-version**: Updates VersionPrefix, AssemblyVersion, and FileVersion in the project file
|
||||
- **push-to-nuget**: Pushes the generated NuGet packages to NuGet.org (requires NUGET_API_KEY)
|
||||
|
||||
These targets can be run manually for testing:
|
||||
|
||||
```bash
|
||||
# Determine the version
|
||||
dotnet run --project build/build.csproj -- determine-version
|
||||
|
||||
# Update version in project file
|
||||
VERSION=0.43.0 dotnet run --project build/build.csproj -- update-version
|
||||
|
||||
# Push to NuGet (requires NUGET_API_KEY environment variable)
|
||||
NUGET_API_KEY=your-key dotnet run --project build/build.csproj -- push-to-nuget
|
||||
```
|
||||
|
||||
## Related Files
|
||||
|
||||
- `.github/workflows/nuget-release.yml` - The workflow definition
|
||||
- `build/Program.cs` - Build script with version detection and publishing logic
|
||||
- `src/SharpCompress/SharpCompress.csproj` - Project file with version information
|
||||
120
.github/workflows/TESTING.md
vendored
Normal file
120
.github/workflows/TESTING.md
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
# Testing Guide for NuGet Release Workflow
|
||||
|
||||
This document describes how to test the NuGet release workflow.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
Since this workflow publishes to NuGet.org and requires repository secrets, testing should be done carefully. The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.
|
||||
|
||||
## Pre-Testing Checklist
|
||||
|
||||
- [x] Workflow YAML syntax validated
|
||||
- [x] Version determination logic tested locally
|
||||
- [x] Version update logic tested locally
|
||||
- [x] Build script works (`dotnet run --project build/build.csproj`)
|
||||
|
||||
## Manual Testing Steps
|
||||
|
||||
### 1. Test Prerelease Publishing (Recommended First Test)
|
||||
|
||||
This tests the workflow on untagged commits to the master or release branch.
|
||||
|
||||
**Steps:**
|
||||
1. Ensure `NUGET_API_KEY` secret is configured in repository settings
|
||||
2. Create a test commit on the `master` or `release` branch (e.g., update a comment or README)
|
||||
3. Push to the `master` or `release` branch
|
||||
4. Monitor the GitHub Actions workflow at: https://github.com/adamhathcock/sharpcompress/actions
|
||||
5. Verify:
|
||||
- Workflow triggers and runs successfully on both Windows and Ubuntu
|
||||
- Version is determined correctly (e.g., `0.43.0-beta.XXX` if last tag is 0.42.x)
|
||||
- Build and tests pass on both platforms
|
||||
- Package artifacts are uploaded for both platforms
|
||||
- Package is pushed to NuGet.org as prerelease (Windows build only)
|
||||
|
||||
**Expected Outcome:**
|
||||
- A new prerelease package appears on NuGet.org: https://www.nuget.org/packages/SharpCompress/
|
||||
- Package version follows pattern: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`
|
||||
|
||||
### 2. Test Tagged Release Publishing
|
||||
|
||||
This tests the workflow when a version tag is pushed.
|
||||
|
||||
**Steps:**
|
||||
1. Prepare the `master` or `release` branch with all desired changes
|
||||
2. Create a version tag (must be a pure semantic version like `MAJOR.MINOR.PATCH`):
|
||||
```bash
|
||||
git checkout master # or release
|
||||
git tag 0.42.2
|
||||
git push origin 0.42.2
|
||||
```
|
||||
3. Monitor the GitHub Actions workflow
|
||||
4. Verify:
|
||||
- Workflow triggers and runs successfully on both Windows and Ubuntu
|
||||
- Version is determined as the tag (e.g., `0.42.2`)
|
||||
- Build and tests pass on both platforms
|
||||
- Package artifacts are uploaded for both platforms
|
||||
- Package is pushed to NuGet.org as stable release (Windows build only)
|
||||
|
||||
**Expected Outcome:**
|
||||
- A new stable release package appears on NuGet.org
|
||||
- Package version matches the tag
|
||||
|
||||
### 3. Test Duplicate Package Handling
|
||||
|
||||
This tests the `--skip-duplicate` flag behavior.
|
||||
|
||||
**Steps:**
|
||||
1. Push to the `release` branch without making changes
|
||||
2. Monitor the workflow
|
||||
3. Verify:
|
||||
- Workflow runs but NuGet push is skipped with "duplicate" message
|
||||
- No errors occur
|
||||
|
||||
### 4. Test Build Failure Handling
|
||||
|
||||
This tests that failed builds don't publish packages.
|
||||
|
||||
**Steps:**
|
||||
1. Introduce a breaking change in a test or code
|
||||
2. Push to the `release` branch
|
||||
3. Verify:
|
||||
- Workflow runs and detects the failure
|
||||
- Build or test step fails
|
||||
- NuGet push step is skipped
|
||||
- No package is published
|
||||
|
||||
## Verification
|
||||
|
||||
After each test, verify:
|
||||
|
||||
1. **GitHub Actions Logs**: Check the workflow logs for any errors or warnings
|
||||
2. **NuGet.org**: Verify the package appears with correct version and metadata
|
||||
3. **Artifacts**: Download and inspect the uploaded artifacts
|
||||
|
||||
## Rollback/Cleanup
|
||||
|
||||
If testing produces unwanted packages:
|
||||
|
||||
1. **Prerelease packages**: Can be unlisted on NuGet.org (Settings → Unlist)
|
||||
2. **Stable packages**: Cannot be deleted, only unlisted (use test versions)
|
||||
3. **Tags**: Can be deleted with:
|
||||
```bash
|
||||
git tag -d 0.42.2
|
||||
git push origin :refs/tags/0.42.2
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- NuGet.org does not allow re-uploading the same version
|
||||
- Deleted packages on NuGet.org reserve the version number
|
||||
- The workflow requires the `NUGET_API_KEY` secret to be set
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The workflow is considered successful if:
|
||||
|
||||
- ✅ Prerelease versions are published correctly with beta suffix
|
||||
- ✅ Tagged versions are published as stable releases
|
||||
- ✅ Build and test failures prevent publishing
|
||||
- ✅ Duplicate packages are handled gracefully
|
||||
- ✅ Workflow logs are clear and informative
|
||||
61
.github/workflows/nuget-release.yml
vendored
Normal file
61
.github/workflows/nuget-release.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: NuGet Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release'
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for versioning
|
||||
|
||||
- uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
# Determine version using C# build target
|
||||
- name: Determine Version
|
||||
id: version
|
||||
run: dotnet run --project build/build.csproj -- determine-version
|
||||
|
||||
# Update version in project file using C# build target
|
||||
- name: Update Version in Project
|
||||
run: dotnet run --project build/build.csproj -- update-version
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
|
||||
# Build and test
|
||||
- name: Build and Test
|
||||
run: dotnet run --project build/build.csproj
|
||||
|
||||
# Upload artifacts for verification
|
||||
- name: Upload NuGet Package
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: ${{ matrix.os }}-nuget-package
|
||||
path: artifacts/*.nupkg
|
||||
|
||||
# Push to NuGet.org using C# build target (Windows only, not on PRs)
|
||||
- name: Push to NuGet
|
||||
if: success() && matrix.os == 'windows-latest' && github.event_name != 'pull_request'
|
||||
run: dotnet run --project build/build.csproj -- push-to-nuget
|
||||
env:
|
||||
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||
33
.gitignore
vendored
33
.gitignore
vendored
@@ -1,11 +1,22 @@
|
||||
**/bin/*
|
||||
**/obj/*
|
||||
_ReSharper.SharpCompress/
|
||||
bin/
|
||||
*.suo
|
||||
*.user
|
||||
TestArchives/Scratch/
|
||||
TestArchives/Scratch2/
|
||||
TestResults/
|
||||
*.nupkg
|
||||
packages/*/
|
||||
**/bin/*
|
||||
**/obj/*
|
||||
_ReSharper.SharpCompress/
|
||||
bin/
|
||||
*.suo
|
||||
*.user
|
||||
TestArchives/Scratch/
|
||||
TestArchives/Scratch2/
|
||||
TestResults/
|
||||
*.nupkg
|
||||
packages/*/
|
||||
project.lock.json
|
||||
tests/TestArchives/Scratch
|
||||
tests/TestArchives/*/Scratch
|
||||
tests/TestArchives/*/Scratch2
|
||||
.vs
|
||||
tools
|
||||
.idea/
|
||||
artifacts/
|
||||
|
||||
.DS_Store
|
||||
*.snupkg
|
||||
|
||||
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-dotnettools.csdevkit",
|
||||
"ms-dotnettools.csharp",
|
||||
"ms-dotnettools.vscode-dotnet-runtime",
|
||||
"csharpier.csharpier-vscode",
|
||||
"formulahendry.dotnet-test-explorer"
|
||||
]
|
||||
}
|
||||
97
.vscode/launch.json
vendored
Normal file
97
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug Tests (net10.0)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"test",
|
||||
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
|
||||
"-f",
|
||||
"net10.0",
|
||||
"--no-build",
|
||||
"--verbosity=normal"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Debug Specific Test (net10.0)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"test",
|
||||
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
|
||||
"-f",
|
||||
"net10.0",
|
||||
"--no-build",
|
||||
"--filter",
|
||||
"FullyQualifiedName~${input:testName}"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Debug Performance Tests",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"run",
|
||||
"--project",
|
||||
"${workspaceFolder}/tests/SharpCompress.Performance/SharpCompress.Performance.csproj",
|
||||
"--no-build"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Debug Build Script",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"run",
|
||||
"--project",
|
||||
"${workspaceFolder}/build/build.csproj",
|
||||
"--",
|
||||
"${input:buildTarget}"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "testName",
|
||||
"type": "promptString",
|
||||
"description": "Enter test name or pattern (e.g., TestMethodName or ClassName)",
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"id": "buildTarget",
|
||||
"type": "pickString",
|
||||
"description": "Select build target",
|
||||
"options": [
|
||||
"clean",
|
||||
"restore",
|
||||
"build",
|
||||
"test",
|
||||
"format",
|
||||
"publish",
|
||||
"default"
|
||||
],
|
||||
"default": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
29
.vscode/settings.json
vendored
Normal file
29
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"dotnet.defaultSolution": "SharpCompress.sln",
|
||||
"files.exclude": {
|
||||
"**/bin": true,
|
||||
"**/obj": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/bin/**": true,
|
||||
"**/obj/**": true,
|
||||
"**/artifacts/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/bin": true,
|
||||
"**/obj": true,
|
||||
"**/artifacts": true
|
||||
},
|
||||
"editor.formatOnSave": false,
|
||||
"[csharp]": {
|
||||
"editor.defaultFormatter": "csharpier.csharpier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit"
|
||||
}
|
||||
},
|
||||
"csharpier.enableDebugLogs": false,
|
||||
"omnisharp.enableRoslynAnalyzers": true,
|
||||
"omnisharp.enableEditorConfigSupport": true,
|
||||
"dotnet-test-explorer.testProjectPath": "tests/**/*.csproj"
|
||||
}
|
||||
178
.vscode/tasks.json
vendored
Normal file
178
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/SharpCompress.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "build-release",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/SharpCompress.sln",
|
||||
"-c",
|
||||
"Release",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "build-library",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/src/SharpCompress/SharpCompress.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "restore",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"restore",
|
||||
"${workspaceFolder}/SharpCompress.sln"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "clean",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"clean",
|
||||
"${workspaceFolder}/SharpCompress.sln"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "test",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"test",
|
||||
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
|
||||
"--no-build",
|
||||
"--verbosity=normal"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"dependsOn": "build"
|
||||
},
|
||||
{
|
||||
"label": "test-net10",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"test",
|
||||
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
|
||||
"-f",
|
||||
"net10.0",
|
||||
"--no-build",
|
||||
"--verbosity=normal"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": "test",
|
||||
"dependsOn": "build"
|
||||
},
|
||||
{
|
||||
"label": "test-net48",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"test",
|
||||
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
|
||||
"-f",
|
||||
"net48",
|
||||
"--no-build",
|
||||
"--verbosity=normal"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"group": "test",
|
||||
"dependsOn": "build"
|
||||
},
|
||||
{
|
||||
"label": "format",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"csharpier",
|
||||
"."
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "format-check",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"csharpier",
|
||||
"check",
|
||||
"."
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "run-build-script",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"run",
|
||||
"--project",
|
||||
"${workspaceFolder}/build/build.csproj"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "pack",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"pack",
|
||||
"${workspaceFolder}/src/SharpCompress/SharpCompress.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"-o",
|
||||
"${workspaceFolder}/artifacts/"
|
||||
],
|
||||
"problemMatcher": "$msCompile",
|
||||
"dependsOn": "build-release"
|
||||
},
|
||||
{
|
||||
"label": "performance-tests",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"run",
|
||||
"--project",
|
||||
"${workspaceFolder}/tests/SharpCompress.Performance/SharpCompress.Performance.csproj",
|
||||
"-c",
|
||||
"Release"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
181
AGENTS.md
Normal file
181
AGENTS.md
Normal file
@@ -0,0 +1,181 @@
|
||||
---
|
||||
description: 'Guidelines for building SharpCompress - A C# compression library'
|
||||
applyTo: '**/*.cs'
|
||||
---
|
||||
|
||||
# SharpCompress Development
|
||||
|
||||
## About SharpCompress
|
||||
SharpCompress is a pure C# compression library supporting multiple archive formats (Zip, Tar, GZip, BZip2, 7Zip, Rar, LZip, XZ, ZStandard) for .NET Framework 4.62, .NET Standard 2.1, .NET 6.0, and .NET 8.0. The library provides both seekable Archive APIs and forward-only Reader/Writer APIs for streaming scenarios.
|
||||
|
||||
## C# Instructions
|
||||
- Always use the latest version C#, currently C# 13 features.
|
||||
- Write clear and concise comments for each function.
|
||||
- Follow the existing code style and patterns in the codebase.
|
||||
|
||||
## General Instructions
|
||||
- Make only high confidence suggestions when reviewing code changes.
|
||||
- Write code with good maintainability practices, including comments on why certain design decisions were made.
|
||||
- Handle edge cases and write clear exception handling.
|
||||
- For libraries or external dependencies, mention their usage and purpose in comments.
|
||||
- Preserve backward compatibility when making changes to public APIs.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
- Follow PascalCase for component names, method names, and public members.
|
||||
- Use camelCase for private fields and local variables.
|
||||
- Prefix interface names with "I" (e.g., IUserService).
|
||||
|
||||
## Code Formatting
|
||||
|
||||
**Copilot agents: You MUST run the `format` task after making code changes to ensure consistency.**
|
||||
|
||||
- Use CSharpier for code formatting to ensure consistent style across the project
|
||||
- CSharpier is configured as a local tool in `.config/dotnet-tools.json`
|
||||
|
||||
### Commands
|
||||
|
||||
1. **Restore tools** (first time only):
|
||||
```bash
|
||||
dotnet tool restore
|
||||
```
|
||||
|
||||
2. **Check if files are formatted correctly** (doesn't modify files):
|
||||
```bash
|
||||
dotnet csharpier check .
|
||||
```
|
||||
- Exit code 0: All files are properly formatted
|
||||
- Exit code 1: Some files need formatting (will show which files and differences)
|
||||
|
||||
3. **Format files** (modifies files):
|
||||
```bash
|
||||
dotnet csharpier format .
|
||||
```
|
||||
- Formats all files in the project to match CSharpier style
|
||||
- Run from project root directory
|
||||
|
||||
4. **Configure your IDE** to format on save using CSharpier for the best experience
|
||||
|
||||
### Additional Notes
|
||||
- The project also uses `.editorconfig` for editor settings (indentation, encoding, etc.)
|
||||
- Let CSharpier handle code style while `.editorconfig` handles editor behavior
|
||||
- Always run `dotnet csharpier check .` before committing to verify formatting
|
||||
|
||||
## Project Setup and Structure
|
||||
|
||||
- The project targets multiple frameworks: .NET Framework 4.62, .NET Standard 2.1, .NET 6.0, and .NET 8.0
|
||||
- Main library is in `src/SharpCompress/`
|
||||
- Tests are in `tests/SharpCompress.Test/`
|
||||
- Performance tests are in `tests/SharpCompress.Performance/`
|
||||
- Test archives are in `tests/TestArchives/`
|
||||
- Build project is in `build/`
|
||||
- Use `dotnet build` to build the solution
|
||||
- Use `dotnet test` to run tests
|
||||
- Solution file: `SharpCompress.sln`
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
src/SharpCompress/
|
||||
├── Archives/ # IArchive implementations (Zip, Tar, Rar, 7Zip, GZip)
|
||||
├── Readers/ # IReader implementations (forward-only)
|
||||
├── Writers/ # IWriter implementations (forward-only)
|
||||
├── Compressors/ # Low-level compression streams (BZip2, Deflate, LZMA, etc.)
|
||||
├── Factories/ # Format detection and factory pattern
|
||||
├── Common/ # Shared types (ArchiveType, Entry, Options)
|
||||
├── Crypto/ # Encryption implementations
|
||||
└── IO/ # Stream utilities and wrappers
|
||||
|
||||
tests/SharpCompress.Test/
|
||||
├── Zip/, Tar/, Rar/, SevenZip/, GZip/, BZip2/ # Format-specific tests
|
||||
├── TestBase.cs # Base test class with helper methods
|
||||
└── TestArchives/ # Test data (not checked into main test project)
|
||||
```
|
||||
|
||||
### Factory Pattern
|
||||
All format types implement factory interfaces (`IArchiveFactory`, `IReaderFactory`, `IWriterFactory`) for auto-detection:
|
||||
- `ReaderFactory.Open()` - Auto-detects format by probing stream
|
||||
- `WriterFactory.Open()` - Creates writer for specified `ArchiveType`
|
||||
- Factories located in: `src/SharpCompress/Factories/`
|
||||
|
||||
## Nullable Reference Types
|
||||
|
||||
- Declare variables non-nullable, and check for `null` at entry points.
|
||||
- Always use `is null` or `is not null` instead of `== null` or `!= null`.
|
||||
- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
|
||||
|
||||
## SharpCompress-Specific Guidelines
|
||||
|
||||
### Supported Formats
|
||||
SharpCompress supports multiple archive and compression formats:
|
||||
- **Archive Formats**: Zip, Tar, 7Zip, Rar (read-only)
|
||||
- **Compression**: DEFLATE, BZip2, LZMA/LZMA2, PPMd, ZStandard (decompress only), Deflate64 (decompress only)
|
||||
- **Combined Formats**: Tar.GZip, Tar.BZip2, Tar.LZip, Tar.XZ, Tar.ZStandard
|
||||
- See FORMATS.md for complete format support matrix
|
||||
|
||||
### Stream Handling Rules
|
||||
- **Disposal**: As of version 0.21, SharpCompress closes wrapped streams by default
|
||||
- Use `ReaderOptions` or `WriterOptions` with `LeaveStreamOpen = true` to control stream disposal
|
||||
- Use `NonDisposingStream` wrapper when working with compression streams directly to prevent disposal
|
||||
- Always dispose of readers, writers, and archives in `using` blocks
|
||||
- For forward-only operations, use Reader/Writer APIs; for random access, use Archive APIs
|
||||
|
||||
### Async/Await Patterns
|
||||
- All I/O operations support async/await with `CancellationToken`
|
||||
- Async methods follow the naming convention: `MethodNameAsync`
|
||||
- Key async methods:
|
||||
- `WriteEntryToAsync` - Extract entry asynchronously
|
||||
- `WriteAllToDirectoryAsync` - Extract all entries asynchronously
|
||||
- `WriteAsync` - Write entry asynchronously
|
||||
- `WriteAllAsync` - Write directory asynchronously
|
||||
- `OpenEntryStreamAsync` - Open entry stream asynchronously
|
||||
- Always provide `CancellationToken` parameter in async methods
|
||||
|
||||
### Archive APIs vs Reader/Writer APIs
|
||||
- **Archive API**: Use for random access with seekable streams (e.g., `ZipArchive`, `TarArchive`)
|
||||
- **Reader API**: Use for forward-only reading on non-seekable streams (e.g., `ZipReader`, `TarReader`)
|
||||
- **Writer API**: Use for forward-only writing on streams (e.g., `ZipWriter`, `TarWriter`)
|
||||
- 7Zip only supports Archive API due to format limitations
|
||||
|
||||
### Tar-Specific Considerations
|
||||
- Tar format requires file size in the header
|
||||
- If no size is specified to TarWriter and the stream is not seekable, an exception will be thrown
|
||||
- Tar combined with compression (GZip, BZip2, LZip, XZ) is supported
|
||||
|
||||
### Zip-Specific Considerations
|
||||
- Supports Zip64 for large files (seekable streams only)
|
||||
- Supports PKWare and WinZip AES encryption
|
||||
- Multiple compression methods: None, Shrink, Reduce, Implode, DEFLATE, Deflate64, BZip2, LZMA, PPMd
|
||||
- Encrypted LZMA is not supported
|
||||
|
||||
### Performance Considerations
|
||||
- For large files, use Reader/Writer APIs with non-seekable streams to avoid loading entire file in memory
|
||||
- Leverage async I/O for better scalability
|
||||
- Consider compression level trade-offs (speed vs. size)
|
||||
- Use appropriate buffer sizes for stream operations
|
||||
|
||||
## Testing
|
||||
|
||||
- Always include test cases for critical paths of the application.
|
||||
- Test with multiple archive formats when making changes to core functionality.
|
||||
- Include tests for both Archive and Reader/Writer APIs when applicable.
|
||||
- Test async operations with cancellation tokens.
|
||||
- Do not emit "Act", "Arrange" or "Assert" comments.
|
||||
- Copy existing style in nearby files for test method names and capitalization.
|
||||
- Use test archives from `tests/TestArchives` directory for consistency.
|
||||
- Test stream disposal and `LeaveStreamOpen` behavior.
|
||||
- Test edge cases: empty archives, large files, corrupted archives, encrypted archives.
|
||||
|
||||
### Test Organization
|
||||
- Base class: `TestBase` - Provides `TEST_ARCHIVES_PATH`, `SCRATCH_FILES_PATH`, temp directory management
|
||||
- Framework: xUnit with AwesomeAssertions
|
||||
- Test archives: `tests/TestArchives/` - Use existing archives, don't create new ones unnecessarily
|
||||
- Match naming style of nearby test files
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Don't mix Archive and Reader APIs** - Archive needs seekable stream, Reader doesn't
|
||||
2. **Solid archives (Rar, 7Zip)** - Use `ExtractAllEntries()` for best performance, not individual entry extraction
|
||||
3. **Stream disposal** - Always set `LeaveStreamOpen` explicitly when needed (default is to close)
|
||||
4. **Tar + non-seekable stream** - Must provide file size or it will throw
|
||||
5. **Multi-framework differences** - Some features differ between .NET Framework and modern .NET (e.g., Mono.Posix)
|
||||
6. **Format detection** - Use `ReaderFactory.Open()` for auto-detection, test with actual archive files
|
||||
16
Directory.Build.props
Normal file
16
Directory.Build.props
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AnalysisMode>Recommended</AnalysisMode>
|
||||
<WarningsAsErrors>true</WarningsAsErrors>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RunAnalyzersDuringLiveAnalysis>False</RunAnalyzersDuringLiveAnalysis>
|
||||
<RunAnalyzersDuringBuild>False</RunAnalyzersDuringBuild>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
20
Directory.Packages.props
Normal file
20
Directory.Packages.props
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Bullseye" Version="6.1.0" />
|
||||
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
|
||||
<PackageVersion Include="Glob" Version="1.1.9" />
|
||||
<PackageVersion Include="JetBrains.Profiler.SelfApi" Version="2.5.15" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageVersion Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||
<PackageVersion Include="SimpleExec" Version="13.0.0" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.0" />
|
||||
<PackageVersion Include="System.Buffers" Version="4.6.1" />
|
||||
<PackageVersion Include="System.Memory" Version="4.6.3" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="Microsoft.NET.ILLink.Tasks" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
81
FORMATS.md
Normal file
81
FORMATS.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Formats
|
||||
|
||||
## Accessing Archives
|
||||
|
||||
* Archive classes allow random access to a seekable stream.
|
||||
* Reader classes allow forward-only reading on a stream.
|
||||
* Writer classes allow forward-only Writing on a stream.
|
||||
|
||||
## Supported Format Table
|
||||
|
||||
| Archive Format | Compression Format(s) | Compress/Decompress | Archive API | Reader API | Writer API |
|
||||
| ---------------------- | ------------------------------------------------- | ------------------- | --------------- | ---------- | ------------- |
|
||||
| Ace | None | Decompress | N/A | AceReader | N/A |
|
||||
| Arc | None, Packed, Squeezed, Crunched | Decompress | N/A | ArcReader | N/A |
|
||||
| Arj | None | Decompress | N/A | ArjReader | N/A |
|
||||
| Rar | Rar | Decompress | RarArchive | RarReader | N/A |
|
||||
| Zip (2) | None, Shrink, Reduce, Implode, DEFLATE, Deflate64, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
|
||||
| Tar | None | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| Tar.GZip | DEFLATE | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| Tar.BZip2 | BZip2 | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| Tar.Zstandard | ZStandard | Decompress | TarArchive | TarReader | N/A |
|
||||
| Tar.LZip | LZMA | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| Tar.XZ | LZMA2 | Decompress | TarArchive | TarReader | TarWriter (3) |
|
||||
| GZip (single file) | DEFLATE | Both | GZipArchive | GZipReader | GZipWriter |
|
||||
| 7Zip (4) | LZMA, LZMA2, BZip2, PPMd, BCJ, BCJ2, Deflate | Decompress | SevenZipArchive | N/A | N/A |
|
||||
|
||||
1. SOLID Rars are only supported in the RarReader API.
|
||||
2. Zip format supports pkware and WinzipAES encryption. However, encrypted LZMA is not supported. Zip64 reading/writing is supported but only with seekable streams as the Zip spec doesn't support Zip64 data in post data descriptors. Deflate64 is only supported for reading. See [Zip Format Notes](#zip-format-notes) for details on multi-volume archives and streaming behavior.
|
||||
3. The Tar format requires a file size in the header. If no size is specified to the TarWriter and the stream is not seekable, then an exception will be thrown.
|
||||
4. The 7Zip format doesn't allow for reading as a forward-only stream so 7Zip is only supported through the Archive API. See [7Zip Format Notes](#7zip-format-notes) for details on async extraction behavior.
|
||||
5. LZip has no support for extra data like the file name or timestamp. There is a default filename used when looking at the entry Key on the archive.
|
||||
|
||||
### Zip Format Notes
|
||||
|
||||
- Multi-volume/split ZIP archives require ZipArchive (seekable streams) as ZipReader cannot seek across volume files.
|
||||
- ZipReader processes entries from LocalEntry headers (which include directory entries ending with `/`) and intentionally skips DirectoryEntry headers from the central directory, as they are redundant in streaming mode - all entry data comes from LocalEntry headers which ZipReader has already processed.
|
||||
|
||||
### 7Zip Format Notes
|
||||
|
||||
- **Async Extraction Performance**: When using async extraction methods (e.g., `ExtractAllEntries()` with `MoveToNextEntryAsync()`), each file creates its own decompression stream to avoid state corruption in the LZMA decoder. This is less efficient than synchronous extraction, which can reuse a single decompression stream for multiple files in the same folder.
|
||||
|
||||
**Performance Impact**: For archives with many small files in the same compression folder, async extraction will be slower than synchronous extraction because it must:
|
||||
1. Create a new LZMA decoder for each file
|
||||
2. Skip through the decompressed data to reach each file's starting position
|
||||
|
||||
**Recommendation**: For best performance with 7Zip archives, use synchronous extraction methods (`MoveToNextEntry()` and `WriteEntryToDirectory()`) when possible. Use async methods only when you need to avoid blocking the thread (e.g., in UI applications or async-only contexts).
|
||||
|
||||
**Technical Details**: 7Zip archives group files into "folders" (compression units), where all files in a folder share one continuous LZMA-compressed stream. The LZMA decoder maintains internal state (dictionary window, decoder positions) that assumes sequential, non-interruptible processing. Async operations can yield control during awaits, which would corrupt this shared state. To avoid this, async extraction creates a fresh decoder stream for each file.
|
||||
|
||||
## Compression Streams
|
||||
|
||||
For those who want to directly compress/decompress bits. The single file formats are represented here as well. However, BZip2, LZip and XZ have no metadata (GZip has a little) so using them without something like a Tar file makes little sense.
|
||||
|
||||
| Compressor | Compress/Decompress |
|
||||
| --------------- | ------------------- |
|
||||
| BZip2Stream | Both |
|
||||
| GZipStream | Both |
|
||||
| DeflateStream | Both |
|
||||
| Deflate64Stream | Decompress |
|
||||
| LZMAStream | Both |
|
||||
| PPMdStream | Both |
|
||||
| ADCStream | Decompress |
|
||||
| LZipStream | Both |
|
||||
| XZStream | Decompress |
|
||||
| ZStandardStream | Decompress |
|
||||
|
||||
## Archive Formats vs Compression
|
||||
|
||||
Sometimes the terminology gets mixed.
|
||||
|
||||
### Compression
|
||||
|
||||
DEFLATE, LZMA are pure compression algorithms
|
||||
|
||||
### Formats
|
||||
|
||||
Formats like Zip, 7Zip, Rar are archive formats only. They use other compression methods (e.g. DEFLATE, LZMA, etc.) or propriatory (e.g RAR)
|
||||
|
||||
### Overlap
|
||||
|
||||
GZip, BZip2 and LZip are single file archival formats. The overlap in the API happens because Tar uses the single file formats as "compression" methods and the API tries to hide this a bit.
|
||||
9
NuGet.config
Normal file
9
NuGet.config
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSourceMapping>
|
||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>sharpcompress</id>
|
||||
<version>0.11.3</version>
|
||||
<title>SharpCompress - Pure C# Decompression/Compression</title>
|
||||
<authors>Adam Hathcock</authors>
|
||||
<owners>Adam Hathcock</owners>
|
||||
<licenseUrl>https://github.com/adamhathcock/sharpcompress/blob/master/LICENSE.txt</licenseUrl>
|
||||
<projectUrl>https://github.com/adamhathcock/sharpcompress</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>SharpCompress is a compression library for .NET/Mono/Silverlight/WP7/WindowsStore that can unrar, decompress 7zip, zip/unzip, tar/untar bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</description>
|
||||
<releaseNotes />
|
||||
<language>en-US</language>
|
||||
<tags>rar unrar zip unzip bzip2 gzip tar 7zip</tags>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\bin\Full\SharpCompress.dll" target="lib\net40\SharpCompress.dll" />
|
||||
<file src="..\bin\WindowsStore\SharpCompress.dll" target="lib\netcore45\SharpCompress.dll" />
|
||||
<file src="..\bin\Portable\SharpCompress.dll" target="lib\portable-net4+sl5+wp8+win8\SharpCompress.dll" />
|
||||
</files>
|
||||
</package>
|
||||
142
OLD_CHANGELOG.md
Normal file
142
OLD_CHANGELOG.md
Normal file
@@ -0,0 +1,142 @@
|
||||
|
||||
# Version Log
|
||||
|
||||
* [Releases](https://github.com/adamhathcock/sharpcompress/releases)
|
||||
|
||||
## Version 0.18
|
||||
|
||||
* [Now on Github releases](https://github.com/adamhathcock/sharpcompress/releases/tag/0.18)
|
||||
|
||||
## Version 0.17.1
|
||||
|
||||
* Fix - [Bug Fix for .NET Core on Windows](https://github.com/adamhathcock/sharpcompress/pull/257)
|
||||
|
||||
## Version 0.17.0
|
||||
|
||||
* New - Full LZip support! Can read and write LZip files and Tars inside LZip files. [Make LZip a first class citizen. #241](https://github.com/adamhathcock/sharpcompress/issues/241)
|
||||
* New - XZ read support! Can read XZ files and Tars inside XZ files. [XZ in SharpCompress #91](https://github.com/adamhathcock/sharpcompress/issues/94)
|
||||
* Fix - [Regression - zip file writing on seekable streams always assumed stream start was 0. Introduced with Zip64 writing.](https://github.com/adamhathcock/sharpcompress/issues/244)
|
||||
* Fix - [Zip files with post-data descriptors can be properly skipped via decompression](https://github.com/adamhathcock/sharpcompress/issues/162)
|
||||
|
||||
## Version 0.16.2
|
||||
|
||||
* Fix [.NET 3.5 should support files and cryptography (was a regression from 0.16.0)](https://github.com/adamhathcock/sharpcompress/pull/251)
|
||||
* Fix [Zip per entry compression customization wrote the wrong method into the zip archive](https://github.com/adamhathcock/sharpcompress/pull/249)
|
||||
|
||||
## Version 0.16.1
|
||||
|
||||
* Fix [Preserve compression method when getting a compressed stream](https://github.com/adamhathcock/sharpcompress/pull/235)
|
||||
* Fix [RAR entry key normalization fix](https://github.com/adamhathcock/sharpcompress/issues/201)
|
||||
|
||||
## Version 0.16.0
|
||||
|
||||
* Breaking - [Progress Event Tracking rethink](https://github.com/adamhathcock/sharpcompress/pull/226)
|
||||
* Update to VS2017 - [VS2017](https://github.com/adamhathcock/sharpcompress/pull/231) - Framework targets have been changed.
|
||||
* New - [Add Zip64 writing](https://github.com/adamhathcock/sharpcompress/pull/211)
|
||||
* [Fix invalid/mismatching Zip version flags.](https://github.com/adamhathcock/sharpcompress/issues/164) - This allows nuget/System.IO.Packaging to read zip files generated by SharpCompress
|
||||
* [Fix 7Zip directory hiding](https://github.com/adamhathcock/sharpcompress/pull/215/files)
|
||||
* [Verify RAR CRC headers](https://github.com/adamhathcock/sharpcompress/pull/220)
|
||||
|
||||
## Version 0.15.2
|
||||
|
||||
* [Fix invalid headers](https://github.com/adamhathcock/sharpcompress/pull/210) - fixes an issue creating large-ish zip archives that was introduced with zip64 reading.
|
||||
|
||||
## Version 0.15.1
|
||||
|
||||
* [Zip64 extending information and ZipReader](https://github.com/adamhathcock/sharpcompress/pull/206)
|
||||
|
||||
## Version 0.15.0
|
||||
|
||||
* [Add zip64 support for ZipArchive extraction](https://github.com/adamhathcock/sharpcompress/pull/205)
|
||||
|
||||
## Version 0.14.1
|
||||
|
||||
* [.NET Assemblies aren't strong named](https://github.com/adamhathcock/sharpcompress/issues/158)
|
||||
* [Pkware encryption for Zip files didn't allow for multiple reads of an entry](https://github.com/adamhathcock/sharpcompress/issues/197)
|
||||
* [GZip Entry couldn't be read multiple times](https://github.com/adamhathcock/sharpcompress/issues/198)
|
||||
|
||||
## Version 0.14.0
|
||||
|
||||
* [Support for LZip reading in for Tars](https://github.com/adamhathcock/sharpcompress/pull/191)
|
||||
|
||||
## Version 0.13.1
|
||||
|
||||
* [Fix null password on ReaderFactory. Fix null options on SevenZipArchive](https://github.com/adamhathcock/sharpcompress/pull/188)
|
||||
* [Make PpmdProperties lazy to avoid unnecessary allocations.](https://github.com/adamhathcock/sharpcompress/pull/185)
|
||||
|
||||
## Version 0.13.0
|
||||
|
||||
* Breaking change: Big refactor of Options on API.
|
||||
* 7Zip supports Deflate
|
||||
|
||||
## Version 0.12.4
|
||||
|
||||
* Forward only zip issue fix https://github.com/adamhathcock/sharpcompress/issues/160
|
||||
* Try to fix frameworks again by copying targets from JSON.NET
|
||||
|
||||
## Version 0.12.3
|
||||
|
||||
* 7Zip fixes https://github.com/adamhathcock/sharpcompress/issues/73
|
||||
* Maybe all profiles will work with project.json now
|
||||
|
||||
## Version 0.12.2
|
||||
|
||||
* Support Profile 259 again
|
||||
|
||||
## Version 0.12.1
|
||||
|
||||
* Support Silverlight 5
|
||||
|
||||
## Version 0.12.0
|
||||
|
||||
* .NET Core RTM!
|
||||
* Bug fix for Tar long paths
|
||||
|
||||
## Version 0.11.6
|
||||
|
||||
* Bug fix for global header in Tar
|
||||
* Writers now have a leaveOpen `bool` overload. They won't close streams if not-requested to.
|
||||
|
||||
## Version 0.11.5
|
||||
|
||||
* Bug fix in Skip method
|
||||
|
||||
## Version 0.11.4
|
||||
|
||||
* SharpCompress is now endian neutral (matters for Mono platforms)
|
||||
* Fix for Inflate (need to change implementation)
|
||||
* Fixes for RAR detection
|
||||
|
||||
## Version 0.11.1
|
||||
|
||||
* Added Cancel on IReader
|
||||
* Removed .NET 2.0 support and LinqBridge dependency
|
||||
|
||||
## Version 0.11
|
||||
|
||||
* Been over a year, contains mainly fixes from contributors!
|
||||
* Possible breaking change: ArchiveEncoding is UTF8 by default now.
|
||||
* TAR supports writing long names using longlink
|
||||
* RAR Protect Header added
|
||||
|
||||
## Version 0.10.3
|
||||
|
||||
* Finally fixed Disposal issue when creating a new archive with the Archive API
|
||||
|
||||
## Version 0.10.2
|
||||
|
||||
* Fixed Rar Header reading for invalid extended time headers.
|
||||
* Windows Store assembly is now strong named
|
||||
* Known issues with Long Tar names being worked on
|
||||
* Updated to VS2013
|
||||
* Portable targets SL5 and Windows Phone 8 (up from SL4 and WP7)
|
||||
|
||||
## Version 0.10.1
|
||||
|
||||
* Fixed 7Zip extraction performance problem
|
||||
|
||||
## Version 0.10:
|
||||
|
||||
* Added support for RAR Decryption (thanks to https://github.com/hrasyid)
|
||||
* Embedded some BouncyCastle crypto classes to allow RAR Decryption and Winzip AES Decryption in Portable and Windows Store DLLs
|
||||
* Built in Release (I think)
|
||||
80
README.md
80
README.md
@@ -1,62 +1,48 @@
|
||||
SharpCompress
|
||||
=============
|
||||
# SharpCompress
|
||||
|
||||
Github mirror of http://sharpcompress.codeplex.com
|
||||
SharpCompress is a compression library in pure C# for .NET Framework 4.8, .NET 8.0 and .NET 10.0 that can unrar, un7zip, unzip, untar unbzip2, ungzip, unlzip, unzstd, unarc and unarj with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip/lzip are implemented.
|
||||
|
||||
SharpCompress is a compression library for .NET/Mono/Silverlight/WP7 that can unrar, un7zip, unzip, untar unbzip2 and ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip are implemented.
|
||||
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
|
||||
|
||||
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
|
||||
**NEW:** All I/O operations now support async/await for improved performance and scalability. See the [USAGE.md](USAGE.md#async-examples) for examples.
|
||||
|
||||
A Simple Request
|
||||
GitHub Actions Build -
|
||||
[](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml)
|
||||
[](https://dndocs.com/d/sharpcompress/api/index.html)
|
||||
|
||||
## Need Help?
|
||||
|
||||
Post Issues on Github!
|
||||
|
||||
Check the [Supported Formats](FORMATS.md) and [Basic Usage.](USAGE.md)
|
||||
|
||||
## Recommended Formats
|
||||
|
||||
In general, I recommend GZip (Deflate)/BZip2 (BZip)/LZip (LZMA) as the simplicity of the formats lend to better long term archival as well as the streamability. Tar is often used in conjunction for multiple files in a single archive (e.g. `.tar.gz`)
|
||||
|
||||
Zip is okay, but it's a very hap-hazard format and the variation in headers and implementations makes it hard to get correct. Uses Deflate by default but supports a lot of compression methods.
|
||||
|
||||
RAR is not recommended as it's a proprietary format and the compression is closed source. Use Tar/LZip for LZMA
|
||||
|
||||
7Zip and XZ both are overly complicated. 7Zip does not support streamable formats. XZ has known holes explained here: (http://www.nongnu.org/lzip/xz_inadequate.html) Use Tar/LZip for LZMA compression instead.
|
||||
|
||||
ZStandard is an efficient format that works well for streaming with a flexible compression level to tweak the speed/performance trade off you are looking for. We currently only implement decompression for ZStandard but as we leverage the [ZstdSharp](https://github.com/oleg-st/ZstdSharp) library one could likely add compression support without much trouble (PRs are welcome!).
|
||||
|
||||
## A Simple Request
|
||||
|
||||
Hi everyone. I hope you're using SharpCompress and finding it useful. Please give me feedback on what you'd like to see changed especially as far as usability goes. New feature suggestions are always welcome as well. I would also like to know what projects SharpCompress is being used in. I like seeing how it is used to give me ideas for future versions. Thanks!
|
||||
|
||||
Want to contribute?
|
||||
Please do not email me directly to ask for help. If you think there is a real issue, please report it here.
|
||||
|
||||
## Want to contribute?
|
||||
|
||||
I'm always looking for help or ideas. Please submit code or email with ideas. Unfortunately, just letting me know you'd like to help is not enough because I really have no overall plan of what needs to be done. I'll definitely accept code submissions and add you as a member of the project!
|
||||
|
||||
TODOs (always lots):
|
||||
* RAR 5 support
|
||||
* 7Zip writing
|
||||
* Zip64
|
||||
* Multi-volume Zip support.
|
||||
## Notes
|
||||
|
||||
Version 0.11.1:
|
||||
==============
|
||||
- Added Cancel on IReader
|
||||
- Removed .NET 2.0 support and LinqBridge dependency
|
||||
XZ implementation based on: https://github.com/sambott/XZ.NET by @sambott
|
||||
|
||||
Version 0.11:
|
||||
==============
|
||||
- Been over a year, contains mainly fixes from contributors!
|
||||
- Possible breaking change: ArchiveEncoding is UTF8 by default now.
|
||||
- TAR supports writing long names using longlink
|
||||
- RAR Protect Header added
|
||||
|
||||
Version 0.10.3:
|
||||
==============
|
||||
- Finally fixed Disposal issue when creating a new archive with the Archive API
|
||||
|
||||
Version 0.10.2:
|
||||
==============
|
||||
- Fixed Rar Header reading for invalid extended time headers.
|
||||
- Windows Store assembly is now strong named
|
||||
- Known issues with Long Tar names being worked on
|
||||
- Updated to VS2013
|
||||
- Portable targets SL5 and Windows Phone 8 (up from SL4 and WP7)
|
||||
|
||||
Version 0.10.1:
|
||||
==============
|
||||
- Fixed 7Zip extraction performance problem
|
||||
|
||||
Version 0.10:
|
||||
==============
|
||||
- Added support for RAR Decryption (thanks to https://github.com/hrasyid)
|
||||
- Embedded some BouncyCastle crypto classes to allow RAR Decryption and Winzip AES Decryption in Portable and Windows Store DLLs
|
||||
- Built in Release (I think)
|
||||
|
||||
Some Help/Discussion:
|
||||
https://sharpcompress.codeplex.com/discussions
|
||||
XZ BCJ filters support contributed by Louis-Michel Bergeron, on behalf of aDolus Technology Inc. - 2022
|
||||
|
||||
7Zip implementation based on: https://code.google.com/p/managed-lzma/
|
||||
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Archive;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
public class ArchiveTests : TestBase
|
||||
{
|
||||
protected void ArchiveStreamReadExtractAll(string testArchive, CompressionType compression)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveStreamReadExtractAll(testArchive.AsEnumerable(), compression);
|
||||
}
|
||||
|
||||
|
||||
protected void ArchiveStreamReadExtractAll(IEnumerable<string> testArchives, CompressionType compression)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(path))
|
||||
using (var archive = ArchiveFactory.Open(stream))
|
||||
{
|
||||
Assert.IsTrue(archive.IsSolid);
|
||||
using (var reader = archive.ExtractAllEntries())
|
||||
{
|
||||
ReaderTests.UseReader(this, reader, compression);
|
||||
}
|
||||
VerifyFiles();
|
||||
|
||||
if (archive.Entries.First().CompressionType == CompressionType.Rar)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(string testArchive)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveStreamRead(testArchive.AsEnumerable());
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(params string[] testArchives)
|
||||
{
|
||||
ArchiveStreamRead(testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x)));
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(IEnumerable<string> testArchives)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(path))
|
||||
using (var archive = ArchiveFactory.Open(stream))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ArchiveFileRead(string testArchive)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveFileRead(testArchive.AsEnumerable());
|
||||
}
|
||||
protected void ArchiveFileRead(IEnumerable<string> testArchives)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
ResetScratch();
|
||||
using (var archive = ArchiveFactory.Open(path))
|
||||
{
|
||||
archive.EntryExtractionBegin += archive_EntryExtractionBegin;
|
||||
archive.FilePartExtractionBegin += archive_FilePartExtractionBegin;
|
||||
archive.CompressedBytesRead += archive_CompressedBytesRead;
|
||||
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
void archive_CompressedBytesRead(object sender, CompressedBytesReadEventArgs e)
|
||||
{
|
||||
Console.WriteLine("Read Compressed File Part Bytes: {0} Percentage: {1}%",
|
||||
e.CurrentFilePartCompressedBytesRead, CreatePercentage(e.CurrentFilePartCompressedBytesRead, partTotal));
|
||||
|
||||
string percentage = entryTotal.HasValue ? CreatePercentage(e.CompressedBytesRead,
|
||||
entryTotal.Value).ToString() : "Unknown";
|
||||
Console.WriteLine("Read Compressed File Entry Bytes: {0} Percentage: {1}%",
|
||||
e.CompressedBytesRead, percentage);
|
||||
}
|
||||
|
||||
void archive_FilePartExtractionBegin(object sender, FilePartExtractionBeginEventArgs e)
|
||||
{
|
||||
this.partTotal = e.Size;
|
||||
Console.WriteLine("Initializing File Part Extraction: " + e.Name);
|
||||
}
|
||||
|
||||
void archive_EntryExtractionBegin(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
|
||||
{
|
||||
this.entryTotal = e.Item.Size;
|
||||
Console.WriteLine("Initializing File Entry Extraction: " + e.Item.Key);
|
||||
}
|
||||
|
||||
private long? entryTotal;
|
||||
private long partTotal;
|
||||
private long totalSize;
|
||||
|
||||
protected void ArchiveFileReadEx(string testArchive)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveFileReadEx(testArchive.AsEnumerable());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate the TotalUncompressSize property, and the ExtractOptions.PreserveFileTime and ExtractOptions.PreserveAttributes extract options
|
||||
/// </summary>
|
||||
protected void ArchiveFileReadEx(IEnumerable<string> testArchives)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
ResetScratch();
|
||||
using (var archive = ArchiveFactory.Open(path))
|
||||
{
|
||||
this.totalSize = archive.TotalUncompressSize;
|
||||
archive.EntryExtractionBegin += Archive_EntryExtractionBeginEx;
|
||||
archive.EntryExtractionEnd += Archive_EntryExtractionEndEx;
|
||||
archive.CompressedBytesRead += Archive_CompressedBytesReadEx;
|
||||
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite | ExtractOptions.PreserveFileTime | ExtractOptions.PreserveAttributes);
|
||||
}
|
||||
}
|
||||
VerifyFilesEx();
|
||||
}
|
||||
}
|
||||
|
||||
private void Archive_EntryExtractionEndEx(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
|
||||
{
|
||||
this.partTotal += e.Item.Size;
|
||||
}
|
||||
|
||||
private void Archive_CompressedBytesReadEx(object sender, CompressedBytesReadEventArgs e)
|
||||
{
|
||||
string percentage = this.entryTotal.HasValue ? this.CreatePercentage(e.CompressedBytesRead, this.entryTotal.Value).ToString() : "-";
|
||||
string tortalPercentage = this.CreatePercentage(this.partTotal + e.CompressedBytesRead, this.totalSize).ToString();
|
||||
Console.WriteLine(@"Read Compressed File Progress: {0}% Total Progress {1}%", percentage, tortalPercentage);
|
||||
}
|
||||
|
||||
private void Archive_EntryExtractionBeginEx(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
|
||||
{
|
||||
this.entryTotal = e.Item.Size;
|
||||
}
|
||||
|
||||
private int CreatePercentage(long n, long d)
|
||||
{
|
||||
return (int)(((double)n / (double)d) * 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Archive;
|
||||
using SharpCompress.Archive.GZip;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class GZipArchiveTests : ArchiveTests
|
||||
{
|
||||
public GZipArchiveTests()
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GZip_Archive_Generic()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
|
||||
using (var archive = ArchiveFactory.Open(stream))
|
||||
{
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GZip_Archive()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
|
||||
using (var archive = GZipArchive.Open(stream))
|
||||
{
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void GZip_Archive_NoAdd()
|
||||
{
|
||||
string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg\\test.jpg");
|
||||
ResetScratch();
|
||||
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
|
||||
using (var archive = GZipArchive.Open(stream))
|
||||
{
|
||||
archive.AddEntry("jpg\\test.jpg", jpg);
|
||||
archive.SaveTo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writer;
|
||||
using SharpCompress.Writer.GZip;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class GZipWriterTests : WriterTests
|
||||
{
|
||||
public GZipWriterTests()
|
||||
: base(ArchiveType.GZip)
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GZip_Writer_Generic()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.Open(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"), FileMode.OpenOrCreate, FileAccess.Write))
|
||||
using (var writer = WriterFactory.Open(stream, ArchiveType.GZip, CompressionType.GZip))
|
||||
{
|
||||
writer.Write("Tar.tar", Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GZip_Writer()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.Open(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"), FileMode.OpenOrCreate, FileAccess.Write))
|
||||
using (var writer = new GZipWriter(stream))
|
||||
{
|
||||
writer.Write("Tar.tar", Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void GZip_Writer_Generic_Bad_Compression()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz")))
|
||||
using (var writer = WriterFactory.Open(stream, ArchiveType.GZip, CompressionType.BZip2))
|
||||
{
|
||||
writer.Write("Tar.tar", Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SharpCompress.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("SharpCompress.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f01fddfb-445f-4548-9f69-88b69a8b71b0")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
63
SharpCompress.Test/Properties/Resources.Designer.cs
generated
63
SharpCompress.Test/Properties/Resources.Designer.cs
generated
@@ -1,63 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.269
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SharpCompress.Test.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SharpCompress.Test.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
SharpCompress.Test/Properties/Settings.Designer.cs
generated
26
SharpCompress.Test/Properties/Settings.Designer.cs
generated
@@ -1,26 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.269
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SharpCompress.Test.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -1,246 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Archive;
|
||||
using SharpCompress.Archive.Rar;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class RarArchiveTests : ArchiveTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Rar_EncryptedFileAndHeader_Archive()
|
||||
{
|
||||
ReadRarPassword("Rar.encrypted_filesAndHeader.rar", "test");
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_EncryptedFileOnly_Archive()
|
||||
{
|
||||
ReadRarPassword("Rar.encrypted_filesOnly.rar", "test");
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Encrypted_Archive()
|
||||
{
|
||||
ReadRarPassword("Encrypted.rar", "test");
|
||||
}
|
||||
|
||||
private void ReadRarPassword(string testArchive, string password)
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testArchive)))
|
||||
using (var archive = RarArchive.Open(stream, Options.KeepStreamsOpen, password))
|
||||
{
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (!entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(entry.CompressionType, CompressionType.Rar);
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void Rar_Multi_Archive_Encrypted()
|
||||
{
|
||||
ArchiveFileReadPassword("EncryptedParts.part01.rar", "test");
|
||||
}
|
||||
|
||||
protected void ArchiveFileReadPassword(string archiveName, string password)
|
||||
{
|
||||
ResetScratch();
|
||||
using (var archive = RarArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, archiveName), Options.None, password))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_None_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Rar.none.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Rar.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_test_invalid_exttime_ArchiveStreamRead()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "test_invalid_exttime.rar")))
|
||||
{
|
||||
using (var archive = ArchiveFactory.Open(stream))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Jpg_ArchiveStreamRead()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "RarJpeg.jpg")))
|
||||
{
|
||||
using (var archive = RarArchive.Open(stream, Options.LookForHeader))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_IsSolidArchiveCheck()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.rar")))
|
||||
{
|
||||
using (var archive = RarArchive.Open(stream))
|
||||
{
|
||||
Assert.IsFalse(archive.IsSolid);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void Rar_Solid_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Rar.solid.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Solid_StreamRead_Extract_All()
|
||||
{
|
||||
ArchiveStreamReadExtractAll("Rar.solid.rar", CompressionType.Rar);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Multi_ArchiveStreamRead()
|
||||
{
|
||||
var testArchives = new string[] { "Rar.multi.part01.rar",
|
||||
"Rar.multi.part02.rar",
|
||||
"Rar.multi.part03.rar",
|
||||
"Rar.multi.part04.rar",
|
||||
"Rar.multi.part05.rar",
|
||||
"Rar.multi.part06.rar"};
|
||||
|
||||
|
||||
ResetScratch();
|
||||
using (var archive = RarArchive.Open(testArchives.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
|
||||
.Select(p => File.OpenRead(p))))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RarNoneArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Rar.none.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Rar.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_ArchiveFileRead_HasDirectories()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.rar")))
|
||||
{
|
||||
using (var archive = RarArchive.Open(stream))
|
||||
{
|
||||
Assert.IsFalse(archive.IsSolid);
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.IsDirectory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Jpg_ArchiveFileRead()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var archive = RarArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, "RarJpeg.jpg"), Options.LookForHeader))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void Rar_Solid_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Rar.solid.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Multi_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Rar.multi.part01.rar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_IsFirstVolume_True()
|
||||
{
|
||||
using (var archive = RarArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, "Rar.multi.part01.rar")))
|
||||
{
|
||||
Assert.IsTrue(archive.IsMultipartVolume());
|
||||
Assert.IsTrue(archive.IsFirstVolume());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_IsFirstVolume_False()
|
||||
{
|
||||
using (var archive = RarArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, "Rar.multi.part03.rar")))
|
||||
{
|
||||
Assert.IsTrue(archive.IsMultipartVolume());
|
||||
Assert.IsFalse(archive.IsFirstVolume());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Test.Rar
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for RarFactoryReaderTest
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class RarHeaderFactoryTest : TestBase
|
||||
{
|
||||
private RarHeaderFactory rarHeaderFactory;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
ResetScratch();
|
||||
rarHeaderFactory = new RarHeaderFactory(StreamingMode.Seekable, Options.KeepStreamsOpen);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ReadHeaders_RecognizeEncryptedFlag()
|
||||
{
|
||||
|
||||
ReadEncryptedFlag("Rar.Encrypted_filesAndHeader.rar", true);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void ReadEncryptedFlag(string testArchive, bool isEncrypted)
|
||||
{
|
||||
using (var stream = GetReaderStream(testArchive))
|
||||
foreach (var header in rarHeaderFactory.ReadHeaders(stream))
|
||||
{
|
||||
if (header.HeaderType == HeaderType.ArchiveHeader)
|
||||
{
|
||||
Assert.AreEqual(isEncrypted, rarHeaderFactory.IsEncrypted);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReadHeaders_RecognizeNoEncryptedFlag()
|
||||
{
|
||||
ReadEncryptedFlag("Rar.rar", false);
|
||||
}
|
||||
|
||||
private FileStream GetReaderStream(string testArchive)
|
||||
{
|
||||
return new FileStream(Path.Combine(TEST_ARCHIVES_PATH, testArchive),
|
||||
FileMode.Open);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.Rar;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class RarReaderTests : ReaderTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Rar_Multi_Reader()
|
||||
{
|
||||
var testArchives = new string[] { "Rar.multi.part01.rar",
|
||||
"Rar.multi.part02.rar",
|
||||
"Rar.multi.part03.rar",
|
||||
"Rar.multi.part04.rar",
|
||||
"Rar.multi.part05.rar",
|
||||
"Rar.multi.part06.rar"};
|
||||
|
||||
|
||||
ResetScratch();
|
||||
using (var reader = RarReader.Open(testArchives.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
|
||||
.Select(p => File.OpenRead(p))))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
//[TestMethod]
|
||||
public void Rar_Multi_Reader_Encrypted()
|
||||
{
|
||||
var testArchives = new string[] { "EncryptedParts.part01.rar",
|
||||
"EncryptedParts.part02.rar",
|
||||
"EncryptedParts.part03.rar",
|
||||
"EncryptedParts.part04.rar",
|
||||
"EncryptedParts.part05.rar",
|
||||
"EncryptedParts.part06.rar"};
|
||||
|
||||
|
||||
ResetScratch();
|
||||
using (var reader = RarReader.Open(testArchives.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
|
||||
.Select(p => File.OpenRead(p))))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Multi_Reader_Delete_Files()
|
||||
{
|
||||
var testArchives = new string[] { "Rar.multi.part01.rar",
|
||||
"Rar.multi.part02.rar",
|
||||
"Rar.multi.part03.rar",
|
||||
"Rar.multi.part04.rar",
|
||||
"Rar.multi.part05.rar",
|
||||
"Rar.multi.part06.rar"};
|
||||
|
||||
|
||||
ResetScratch();
|
||||
|
||||
foreach (var file in testArchives)
|
||||
{
|
||||
File.Copy(Path.Combine(TEST_ARCHIVES_PATH, file), Path.Combine(SCRATCH2_FILES_PATH, file));
|
||||
}
|
||||
var streams = testArchives.Select(s => Path.Combine(SCRATCH2_FILES_PATH, s)).Select(File.OpenRead).ToList();
|
||||
using (var reader = RarReader.Open(streams))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
foreach (var stream in streams)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
VerifyFiles();
|
||||
|
||||
foreach (var file in testArchives.Select(s => Path.Combine(SCRATCH2_FILES_PATH, s)))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_None_Reader()
|
||||
{
|
||||
Read("Rar.none.rar", CompressionType.Rar);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Reader()
|
||||
{
|
||||
Read("Rar.rar", CompressionType.Rar);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_EncryptedFileAndHeader_Reader()
|
||||
{
|
||||
ReadRar("Rar.encrypted_filesAndHeader.rar", "test");
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_EncryptedFileOnly_Reader()
|
||||
{
|
||||
ReadRar("Rar.encrypted_filesOnly.rar", "test");
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Encrypted_Reader()
|
||||
{
|
||||
ReadRar("Encrypted.rar", "test");
|
||||
}
|
||||
|
||||
private void ReadRar(string testArchive, string password)
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testArchive)))
|
||||
using (var reader = RarReader.Open(stream, password))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Entry_Stream()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.rar")))
|
||||
using (var reader = RarReader.Open(stream))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
using (var entryStream = reader.OpenEntryStream())
|
||||
{
|
||||
string file = Path.GetFileName(reader.Entry.Key);
|
||||
string folder = Path.GetDirectoryName(reader.Entry.Key);
|
||||
string destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
|
||||
if (!Directory.Exists(destdir))
|
||||
{
|
||||
Directory.CreateDirectory(destdir);
|
||||
}
|
||||
string destinationFileName = Path.Combine(destdir, file);
|
||||
|
||||
using (FileStream fs = File.OpenWrite(destinationFileName))
|
||||
{
|
||||
entryStream.TransferTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Reader_Audio_program()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Audio_program.rar")))
|
||||
using (var reader = RarReader.Open(stream, Options.LookForHeader))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
CompareFilesByPath(Path.Combine(SCRATCH_FILES_PATH, "test.dat"),
|
||||
Path.Combine(MISC_TEST_FILES_PATH, "test.dat"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Jpg_Reader()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "RarJpeg.jpg")))
|
||||
using (var reader = RarReader.Open(stream, Options.LookForHeader))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Solid_Reader()
|
||||
{
|
||||
Read("Rar.solid.rar", CompressionType.Rar);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Solid_Skip_Reader()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.solid.rar")))
|
||||
using (var reader = RarReader.Open(stream, Options.LookForHeader))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (reader.Entry.Key.Contains("jpg"))
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rar_Reader_Skip()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.rar")))
|
||||
using (var reader = RarReader.Open(stream, Options.LookForHeader))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (reader.Entry.Key.Contains("jpg"))
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
public class ReaderTests : TestBase
|
||||
{
|
||||
protected void Read(string testArchive, CompressionType expectedCompression)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
Read(testArchive.AsEnumerable(), expectedCompression);
|
||||
}
|
||||
|
||||
protected void Read(IEnumerable<string> testArchives, CompressionType expectedCompression)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
using (Stream stream = File.OpenRead(path))
|
||||
using (IReader reader = ReaderFactory.Open(stream))
|
||||
{
|
||||
UseReader(this, reader, expectedCompression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UseReader(TestBase test, IReader reader, CompressionType expectedCompression)
|
||||
{
|
||||
test.ResetScratch();
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, expectedCompression);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
test.VerifyFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class RewindableStreamTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestRewind()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
bw.Write(1);
|
||||
bw.Write(2);
|
||||
bw.Write(3);
|
||||
bw.Write(4);
|
||||
bw.Write(5);
|
||||
bw.Write(6);
|
||||
bw.Write(7);
|
||||
bw.Flush();
|
||||
ms.Position = 0;
|
||||
RewindableStream stream = new RewindableStream(ms);
|
||||
stream.StartRecording();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
Assert.AreEqual(br.ReadInt32(), 1);
|
||||
Assert.AreEqual(br.ReadInt32(), 2);
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
stream.Rewind(true);
|
||||
stream.StartRecording();
|
||||
Assert.AreEqual(br.ReadInt32(), 1);
|
||||
Assert.AreEqual(br.ReadInt32(), 2);
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
Assert.AreEqual(br.ReadInt32(), 5);
|
||||
Assert.AreEqual(br.ReadInt32(), 6);
|
||||
Assert.AreEqual(br.ReadInt32(), 7);
|
||||
stream.Rewind(true);
|
||||
stream.StartRecording();
|
||||
Assert.AreEqual(br.ReadInt32(), 1);
|
||||
Assert.AreEqual(br.ReadInt32(), 2);
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestIncompleteRewind()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
bw.Write(1);
|
||||
bw.Write(2);
|
||||
bw.Write(3);
|
||||
bw.Write(4);
|
||||
bw.Write(5);
|
||||
bw.Write(6);
|
||||
bw.Write(7);
|
||||
bw.Flush();
|
||||
ms.Position = 0;
|
||||
RewindableStream stream = new RewindableStream(ms);
|
||||
stream.StartRecording();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
Assert.AreEqual(br.ReadInt32(), 1);
|
||||
Assert.AreEqual(br.ReadInt32(), 2);
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
stream.Rewind(true);
|
||||
Assert.AreEqual(br.ReadInt32(), 1);
|
||||
Assert.AreEqual(br.ReadInt32(), 2);
|
||||
stream.StartRecording();
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
Assert.AreEqual(br.ReadInt32(), 5);
|
||||
stream.Rewind(true);
|
||||
Assert.AreEqual(br.ReadInt32(), 3);
|
||||
Assert.AreEqual(br.ReadInt32(), 4);
|
||||
Assert.AreEqual(br.ReadInt32(), 5);
|
||||
Assert.AreEqual(br.ReadInt32(), 6);
|
||||
Assert.AreEqual(br.ReadInt32(), 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class SevenZipArchiveTests : ArchiveTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_LZMA_StreamRead()
|
||||
{
|
||||
ArchiveStreamRead("7Zip.LZMA.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_LZMA_PathRead()
|
||||
{
|
||||
ArchiveFileRead("7Zip.LZMA.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_PPMd_StreamRead()
|
||||
{
|
||||
ArchiveStreamRead("7Zip.PPMd.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_PPMd_StreamRead_Extract_All()
|
||||
{
|
||||
ArchiveStreamReadExtractAll("7Zip.PPMd.7z", CompressionType.PPMd);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_PPMd_PathRead()
|
||||
{
|
||||
ArchiveFileRead("7Zip.PPMd.7z");
|
||||
}
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_LZMA2_StreamRead()
|
||||
{
|
||||
ArchiveStreamRead("7Zip.LZMA2.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_LZMA2_PathRead()
|
||||
{
|
||||
ArchiveFileRead("7Zip.LZMA2.7z");
|
||||
}
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_BZip2_StreamRead()
|
||||
{
|
||||
ArchiveStreamRead("7Zip.BZip2.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_BZip2_PathRead()
|
||||
{
|
||||
ArchiveFileRead("7Zip.BZip2.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SevenZipArchive_LZMA_Time_Attributes_PathRead()
|
||||
{
|
||||
ArchiveFileReadEx("7Zip.LZMA.7z");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(IndexOutOfRangeException))]
|
||||
public void SevenZipArchive_BZip2_Split()
|
||||
{
|
||||
ArchiveStreamRead("Original.7z.001", "Original.7z.002",
|
||||
"Original.7z.003", "Original.7z.004", "Original.7z.005",
|
||||
"Original.7z.006", "Original.7z.007");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{E9C3C94B-FB27-4B4F-B225-57513C254D37}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SharpCompress.Test</RootNamespace>
|
||||
<AssemblyName>SharpCompress.Test.Portable</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\sharpcompress\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\DebugPortable\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\SharpCompress\SharpCompress.pfx</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArchiveTests.cs" />
|
||||
<Compile Include="GZip\GZipWriterTests.cs" />
|
||||
<Compile Include="GZip\GZipArchiveTests.cs" />
|
||||
<Compile Include="Rar\RarHeaderFactoryTest.cs" />
|
||||
<Compile Include="SevenZip\SevenZipArchiveTests.cs" />
|
||||
<Compile Include="Streams\StreamTests.cs" />
|
||||
<Compile Include="Tar\TarWriterTests.cs" />
|
||||
<Compile Include="Tar\TarReaderTests.cs" />
|
||||
<Compile Include="Zip\ZipWriterTests.cs" />
|
||||
<Compile Include="WriterTests.cs" />
|
||||
<Compile Include="Rar\RarReaderTests.cs" />
|
||||
<Compile Include="ReaderTests.cs" />
|
||||
<Compile Include="Tar\TarArchiveTests.cs" />
|
||||
<Compile Include="Zip\ZipArchiveTests.cs" />
|
||||
<Compile Include="Rar\RarArchiveTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RewindableStreamTest.cs" />
|
||||
<Compile Include="TestBase.cs" />
|
||||
<Compile Include="TestStream.cs" />
|
||||
<Compile Include="Zip\ZipReaderTests.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="..\SharpCompress\SharpCompress.pfx">
|
||||
<Link>SharpCompress.pfx</Link>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SharpCompress\SharpCompress.PortableTest.csproj">
|
||||
<Project>{efdcaf57-fd4d-4e5d-a3d5-f26b875817ed}</Project>
|
||||
<Name>SharpCompress.PortableTest</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,113 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SharpCompress.Test</RootNamespace>
|
||||
<AssemblyName>SharpCompress.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\sharpcompress\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\SharpCompress\SharpCompress.pfx</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArchiveTests.cs" />
|
||||
<Compile Include="GZip\GZipWriterTests.cs" />
|
||||
<Compile Include="GZip\GZipArchiveTests.cs" />
|
||||
<Compile Include="Rar\RarHeaderFactoryTest.cs" />
|
||||
<Compile Include="SevenZip\SevenZipArchiveTests.cs" />
|
||||
<Compile Include="Streams\StreamTests.cs" />
|
||||
<Compile Include="Tar\TarWriterTests.cs" />
|
||||
<Compile Include="Tar\TarReaderTests.cs" />
|
||||
<Compile Include="Zip\ZipWriterTests.cs" />
|
||||
<Compile Include="WriterTests.cs" />
|
||||
<Compile Include="Rar\RarReaderTests.cs" />
|
||||
<Compile Include="ReaderTests.cs" />
|
||||
<Compile Include="Tar\TarArchiveTests.cs" />
|
||||
<Compile Include="Zip\ZipArchiveTests.cs" />
|
||||
<Compile Include="Rar\RarArchiveTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RewindableStreamTest.cs" />
|
||||
<Compile Include="TestBase.cs" />
|
||||
<Compile Include="TestStream.cs" />
|
||||
<Compile Include="Zip\ZipReaderTests.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="..\SharpCompress\SharpCompress.pfx">
|
||||
<Link>SharpCompress.pfx</Link>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SharpCompress\SharpCompress.Unsigned.csproj">
|
||||
<Project>{27d535cb-2fd3-4621-8c9a-46161fc77a5d}</Project>
|
||||
<Name>SharpCompress.Unsigned</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Compressor.LZMA;
|
||||
|
||||
namespace SharpCompress.Test.Streams
|
||||
{
|
||||
[TestClass]
|
||||
public class StreamTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestLzma2Decompress1Byte()
|
||||
{
|
||||
byte[] properties = new byte[] { 0x01 };
|
||||
byte[] compressedData = new byte[] { 0x01, 0x00, 0x00, 0x58, 0x00 };
|
||||
MemoryStream lzma2Stream = new MemoryStream(compressedData);
|
||||
|
||||
LzmaStream decompressor = new LzmaStream(properties, lzma2Stream, 5, 1);
|
||||
Assert.AreEqual('X', decompressor.ReadByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Archive;
|
||||
using SharpCompress.Archive.Tar;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class TarArchiveTests : ArchiveTests
|
||||
{
|
||||
public TarArchiveTests()
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TarArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Tar.tar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TarArchivePathRead()
|
||||
{
|
||||
ArchiveFileRead("Tar.tar");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne()
|
||||
{
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar");
|
||||
using (var archive = TarArchive.Open(unmodified))
|
||||
{
|
||||
Assert.AreEqual(5, archive.Entries.Count);
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "very long filename/"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 1.txt"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 2.txt"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 3.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_VeryLongFilepathReadback()
|
||||
{
|
||||
string archive = "Tar_VeryLongFilepathReadback.tar";
|
||||
|
||||
ResetScratch();
|
||||
|
||||
// create a very long filename
|
||||
string longFilename = "";
|
||||
for (int i = 0; i < 600; i = longFilename.Length)
|
||||
longFilename += i.ToString("D10") + "-";
|
||||
longFilename += ".txt";
|
||||
|
||||
// Step 1: create a tar file containing a file with a long name
|
||||
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive)))
|
||||
using (var writer = SharpCompress.Writer.WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.None))
|
||||
using (Stream inputStream = new MemoryStream())
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(inputStream);
|
||||
sw.Write("dummy filecontent");
|
||||
sw.Flush();
|
||||
|
||||
inputStream.Position = 0;
|
||||
writer.Write(longFilename, inputStream, null);
|
||||
}
|
||||
|
||||
// Step 2: check if the written tar file can be read correctly
|
||||
string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
|
||||
using (var archive2 = TarArchive.Open(unmodified))
|
||||
{
|
||||
Assert.AreEqual(1, archive2.Entries.Count);
|
||||
Assert.IsTrue(archive2.Entries.Any(entry => entry.Key == longFilename));
|
||||
|
||||
foreach (var entry in archive2.Entries)
|
||||
Assert.AreEqual("dummy filecontent", new StreamReader(entry.OpenEntryStream()).ReadLine());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_UstarArchivePathReadLongName()
|
||||
{
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar");
|
||||
using(var archive = TarArchive.Open(unmodified))
|
||||
{
|
||||
Assert.AreEqual(6, archive.Entries.Count);
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Some file with veeeeeeeeeery loooooooooong name"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/"));
|
||||
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name"));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_Create_New()
|
||||
{
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar");
|
||||
|
||||
base.ResetScratch();
|
||||
using (var archive = TarArchive.Create())
|
||||
{
|
||||
archive.AddAllFromDirectory(ORIGINAL_FILES_PATH);
|
||||
archive.SaveTo(scratchPath, CompressionType.None);
|
||||
}
|
||||
CompareArchivesByPath(unmodified, scratchPath);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Tar_Random_Write_Add()
|
||||
{
|
||||
string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg\\test.jpg");
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar");
|
||||
string modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar");
|
||||
|
||||
base.ResetScratch();
|
||||
using (var archive = TarArchive.Open(unmodified))
|
||||
{
|
||||
archive.AddEntry("jpg\\test.jpg", jpg);
|
||||
archive.SaveTo(scratchPath, CompressionType.None);
|
||||
}
|
||||
CompareArchivesByPath(modified, scratchPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_Random_Write_Remove()
|
||||
{
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar");
|
||||
string modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar");
|
||||
|
||||
base.ResetScratch();
|
||||
using (var archive = TarArchive.Open(unmodified))
|
||||
{
|
||||
var entry = archive.Entries.Where(x => x.Key.EndsWith("jpg")).Single();
|
||||
archive.RemoveEntry(entry);
|
||||
archive.SaveTo(scratchPath, CompressionType.None);
|
||||
}
|
||||
CompareArchivesByPath(modified, scratchPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader.Tar;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class TarReaderTests : ReaderTests
|
||||
{
|
||||
public TarReaderTests()
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_Reader()
|
||||
{
|
||||
Read("Tar.tar", CompressionType.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_BZip2_Reader()
|
||||
{
|
||||
Read("Tar.tar.bz2", CompressionType.BZip2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_GZip_Reader()
|
||||
{
|
||||
Read("Tar.tar.gz", CompressionType.GZip);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_BZip2_Entry_Stream()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2")))
|
||||
using (var reader = TarReader.Open(stream))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.BZip2);
|
||||
using (var entryStream = reader.OpenEntryStream())
|
||||
{
|
||||
string file = Path.GetFileName(reader.Entry.Key);
|
||||
string folder = Path.GetDirectoryName(reader.Entry.Key);
|
||||
string destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
|
||||
if (!Directory.Exists(destdir))
|
||||
{
|
||||
Directory.CreateDirectory(destdir);
|
||||
}
|
||||
string destinationFileName = Path.Combine(destdir, file);
|
||||
|
||||
using (FileStream fs = File.OpenWrite(destinationFileName))
|
||||
{
|
||||
entryStream.TransferTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_BZip2_Skip_Entry_Stream()
|
||||
{
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2")))
|
||||
using (var reader = TarReader.Open(stream))
|
||||
{
|
||||
List<string> names = new List<string>();
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.BZip2);
|
||||
using (var entryStream = reader.OpenEntryStream())
|
||||
{
|
||||
entryStream.SkipEntry();
|
||||
names.Add(reader.Entry.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.AreEqual(names.Count, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class TarWriterTests : WriterTests
|
||||
{
|
||||
public TarWriterTests()
|
||||
: base(ArchiveType.Tar)
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_Writer()
|
||||
{
|
||||
Write(CompressionType.None, "Tar.noEmptyDirs.tar", "Tar.noEmptyDirs.tar");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Tar_BZip2_Writer()
|
||||
{
|
||||
Write(CompressionType.BZip2, "Tar.noEmptyDirs.tar.bz2", "Tar.noEmptyDirs.tar.bz2");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void Tar_Rar_Write()
|
||||
{
|
||||
Write(CompressionType.Rar, "Zip.ppmd.noEmptyDirs.zip", "Zip.ppmd.noEmptyDirs.zip");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class TestBase
|
||||
{
|
||||
protected static string SOLUTION_BASE_PATH=null;
|
||||
protected static string TEST_ARCHIVES_PATH;
|
||||
protected static string ORIGINAL_FILES_PATH;
|
||||
protected static string MISC_TEST_FILES_PATH;
|
||||
protected static string SCRATCH_FILES_PATH;
|
||||
protected static string SCRATCH2_FILES_PATH;
|
||||
protected static IEnumerable<string> GetRarArchives()
|
||||
{
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Rar.none.rar");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Rar.rar");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Rar.solid.rar");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Rar.multi.part01.rar");
|
||||
}
|
||||
protected static IEnumerable<string> GetZipArchives()
|
||||
{
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.dd.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd-.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.dd.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.ppmd.dd.zip");
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Zip.ppmd.zip");
|
||||
}
|
||||
protected static IEnumerable<string> GetTarArchives()
|
||||
{
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar");
|
||||
}
|
||||
protected static IEnumerable<string> GetTarBz2Archives()
|
||||
{
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2");
|
||||
}
|
||||
protected static IEnumerable<string> GetTarGzArchives()
|
||||
{
|
||||
yield return Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz");
|
||||
}
|
||||
|
||||
public void ResetScratch()
|
||||
{
|
||||
if (Directory.Exists(SCRATCH_FILES_PATH))
|
||||
{
|
||||
Directory.Delete(SCRATCH_FILES_PATH, true);
|
||||
}
|
||||
Directory.CreateDirectory(SCRATCH_FILES_PATH);
|
||||
if (Directory.Exists(SCRATCH2_FILES_PATH))
|
||||
{
|
||||
Directory.Delete(SCRATCH2_FILES_PATH, true);
|
||||
}
|
||||
Directory.CreateDirectory(SCRATCH2_FILES_PATH);
|
||||
|
||||
}
|
||||
|
||||
public void VerifyFiles()
|
||||
{
|
||||
if (UseExtensionInsteadOfNameToVerify)
|
||||
{
|
||||
VerifyFilesByExtension();
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyFilesByName();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the files also check modified time and attributes.
|
||||
/// </summary>
|
||||
public void VerifyFilesEx()
|
||||
{
|
||||
if (UseExtensionInsteadOfNameToVerify)
|
||||
{
|
||||
VerifyFilesByExtensionEx();
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyFilesByNameEx();
|
||||
}
|
||||
}
|
||||
|
||||
protected void VerifyFilesByName()
|
||||
{
|
||||
var extracted =
|
||||
Directory.EnumerateFiles(SCRATCH_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => path.Substring(SCRATCH_FILES_PATH.Length));
|
||||
var original =
|
||||
Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => path.Substring(ORIGINAL_FILES_PATH.Length));
|
||||
|
||||
Assert.AreEqual(extracted.Count, original.Count);
|
||||
|
||||
foreach (var orig in original)
|
||||
{
|
||||
Assert.IsTrue(extracted.Contains(orig.Key));
|
||||
|
||||
CompareFilesByPath(orig.Single(), extracted[orig.Key].Single());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the files by name also check modified time and attributes.
|
||||
/// </summary>
|
||||
protected void VerifyFilesByNameEx()
|
||||
{
|
||||
var extracted =
|
||||
Directory.EnumerateFiles(SCRATCH_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => path.Substring(SCRATCH_FILES_PATH.Length));
|
||||
var original =
|
||||
Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => path.Substring(ORIGINAL_FILES_PATH.Length));
|
||||
|
||||
Assert.AreEqual(extracted.Count, original.Count);
|
||||
|
||||
foreach (var orig in original)
|
||||
{
|
||||
Assert.IsTrue(extracted.Contains(orig.Key));
|
||||
|
||||
CompareFilesByPath(orig.Single(), extracted[orig.Key].Single());
|
||||
CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the files by extension also check modified time and attributes.
|
||||
/// </summary>
|
||||
protected void VerifyFilesByExtensionEx()
|
||||
{
|
||||
var extracted =
|
||||
Directory.EnumerateFiles(SCRATCH_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => Path.GetExtension(path));
|
||||
var original =
|
||||
Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => Path.GetExtension(path));
|
||||
|
||||
Assert.AreEqual(extracted.Count, original.Count);
|
||||
|
||||
foreach (var orig in original)
|
||||
{
|
||||
Assert.IsTrue(extracted.Contains(orig.Key));
|
||||
|
||||
CompareFilesByPath(orig.Single(), extracted[orig.Key].Single());
|
||||
CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single());
|
||||
}
|
||||
}
|
||||
|
||||
protected bool UseExtensionInsteadOfNameToVerify { get; set; }
|
||||
|
||||
protected void VerifyFilesByExtension()
|
||||
{
|
||||
var extracted =
|
||||
Directory.EnumerateFiles(SCRATCH_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => Path.GetExtension(path));
|
||||
var original =
|
||||
Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories)
|
||||
.ToLookup(path => Path.GetExtension(path));
|
||||
|
||||
Assert.AreEqual(extracted.Count, original.Count);
|
||||
|
||||
foreach (var orig in original)
|
||||
{
|
||||
Assert.IsTrue(extracted.Contains(orig.Key));
|
||||
|
||||
CompareFilesByPath(orig.Single(), extracted[orig.Key].Single());
|
||||
}
|
||||
}
|
||||
|
||||
protected void CompareFilesByPath(string file1, string file2)
|
||||
{
|
||||
using (var file1Stream = File.OpenRead(file1))
|
||||
using (var file2Stream = File.OpenRead(file2))
|
||||
{
|
||||
Assert.AreEqual(file1Stream.Length, file2Stream.Length);
|
||||
int byte1 = 0;
|
||||
int byte2 = 0;
|
||||
for (int counter = 0; byte1 != -1; counter++)
|
||||
{
|
||||
byte1 = file1Stream.ReadByte();
|
||||
byte2 = file2Stream.ReadByte();
|
||||
if (byte1 != byte2)
|
||||
Assert.AreEqual(byte1, byte2, string.Format("Byte {0} differ between {1} and {2}",
|
||||
counter, file1, file2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void CompareFilesByTimeAndAttribut(string file1, string file2)
|
||||
{
|
||||
FileInfo fi1 = new FileInfo(file1);
|
||||
FileInfo fi2 = new FileInfo(file2);
|
||||
Assert.AreNotEqual(fi1.LastWriteTime, fi2.LastWriteTime);
|
||||
Assert.AreEqual(fi1.Attributes, fi2.Attributes);
|
||||
}
|
||||
|
||||
protected void CompareArchivesByPath(string file1, string file2)
|
||||
{
|
||||
using (var archive1 = ReaderFactory.Open(File.OpenRead(file1), Options.None))
|
||||
using (var archive2 = ReaderFactory.Open(File.OpenRead(file2), Options.None))
|
||||
{
|
||||
while (archive1.MoveToNextEntry())
|
||||
{
|
||||
Assert.IsTrue(archive2.MoveToNextEntry());
|
||||
Assert.AreEqual(archive1.Entry.Key, archive2.Entry.Key);
|
||||
}
|
||||
Assert.IsFalse(archive2.MoveToNextEntry());
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object testLock = new object();
|
||||
|
||||
[AssemblyInitialize]
|
||||
public static void InitializePaths(TestContext ctx)
|
||||
{
|
||||
SOLUTION_BASE_PATH = Path.GetDirectoryName(Path.GetDirectoryName(ctx.TestDir));
|
||||
TEST_ARCHIVES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Archives");
|
||||
ORIGINAL_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Original");
|
||||
MISC_TEST_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "MiscTest");
|
||||
SCRATCH_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Scratch");
|
||||
SCRATCH2_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Scratch2");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
public class TestStream : Stream
|
||||
{
|
||||
private Stream stream;
|
||||
private bool read;
|
||||
private bool write;
|
||||
private bool seek;
|
||||
|
||||
public TestStream(Stream stream)
|
||||
: this(stream, true, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public TestStream(Stream stream, bool read, bool write, bool seek)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.read = read;
|
||||
this.write = write;
|
||||
this.seek = seek;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
stream.Dispose();
|
||||
IsDisposed = true;
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return read; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return seek; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return write; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { return stream.Length; }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return stream.Position; }
|
||||
set { stream.Position = value; }
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return stream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return stream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
stream.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
stream.Write(buffer, offset, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Writer;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
public class WriterTests : TestBase
|
||||
{
|
||||
private ArchiveType type;
|
||||
|
||||
protected WriterTests(ArchiveType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
protected void Write(CompressionType compressionType, string archive, string archiveToVerifyAgainst)
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive)))
|
||||
using (var writer = WriterFactory.Open(stream, type, compressionType))
|
||||
{
|
||||
writer.WriteAll(ORIGINAL_FILES_PATH, "*", SearchOption.AllDirectories);
|
||||
}
|
||||
CompareArchivesByPath(Path.Combine(SCRATCH2_FILES_PATH, archive),
|
||||
Path.Combine(TEST_ARCHIVES_PATH, archiveToVerifyAgainst));
|
||||
|
||||
using (Stream stream = File.OpenRead(Path.Combine(SCRATCH2_FILES_PATH, archive)))
|
||||
using (var reader = ReaderFactory.Open(stream))
|
||||
{
|
||||
reader.WriteAllToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath);
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,407 +0,0 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Archive;
|
||||
using SharpCompress.Archive.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writer;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class ZipArchiveTests : ArchiveTests
|
||||
{
|
||||
public ZipArchiveTests()
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_ZipX_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.zipx");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Streamed_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.bzip2.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.bzip2.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed2_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.deflate.dd-.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.deflate.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.deflate.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_Streamed_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.lzma.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.lzma.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_Streamed_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.ppmd.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.ppmd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_None_ArchiveStreamRead()
|
||||
{
|
||||
ArchiveStreamRead("Zip.none.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Streamed_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.bzip2.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.bzip2.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed2_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.deflate.dd-.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.deflate.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.deflate.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_Streamed_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.lzma.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.lzma.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_Streamed_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.ppmd.dd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.ppmd.zip");
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_None_ArchiveFileRead()
|
||||
{
|
||||
ArchiveFileRead("Zip.none.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Random_Write_Remove()
|
||||
{
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
string modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip");
|
||||
|
||||
base.ResetScratch();
|
||||
using (var archive = ZipArchive.Open(unmodified))
|
||||
{
|
||||
var entry = archive.Entries.Single(x => x.Key.EndsWith("jpg"));
|
||||
archive.RemoveEntry(entry);
|
||||
archive.SaveTo(scratchPath, CompressionType.Deflate);
|
||||
}
|
||||
CompareArchivesByPath(modified, scratchPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Random_Write_Add()
|
||||
{
|
||||
string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg\\test.jpg");
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip");
|
||||
string modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod2.zip");
|
||||
|
||||
base.ResetScratch();
|
||||
using (var archive = ZipArchive.Open(unmodified))
|
||||
{
|
||||
archive.AddEntry("jpg\\test.jpg", jpg);
|
||||
archive.SaveTo(scratchPath, CompressionType.Deflate);
|
||||
}
|
||||
CompareArchivesByPath(modified, scratchPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Save_Twice()
|
||||
{
|
||||
string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip");
|
||||
string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip");
|
||||
|
||||
ResetScratch();
|
||||
using (var arc = ZipArchive.Create())
|
||||
{
|
||||
string str = "test.txt";
|
||||
var source = new MemoryStream(Encoding.UTF8.GetBytes(str));
|
||||
arc.AddEntry("test.txt", source, true, source.Length);
|
||||
arc.SaveTo(scratchPath1, CompressionType.Deflate);
|
||||
arc.SaveTo(scratchPath2, CompressionType.Deflate);
|
||||
}
|
||||
|
||||
Assert.AreEqual(new FileInfo(scratchPath1).Length, new FileInfo(scratchPath2).Length);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Removal_Poly()
|
||||
{
|
||||
ResetScratch();
|
||||
|
||||
string scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
|
||||
|
||||
|
||||
using (ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath))
|
||||
{
|
||||
var e = vfs.Entries.First(v => v.Key.EndsWith("jpg"));
|
||||
vfs.RemoveEntry(e);
|
||||
Assert.IsNull(vfs.Entries.FirstOrDefault(v => v.Key.EndsWith("jpg")));
|
||||
Assert.IsNull(((IArchive)vfs).Entries.FirstOrDefault(v => v.Key.EndsWith("jpg")));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArchiveException))]
|
||||
public void Zip_Create_NoDups()
|
||||
{
|
||||
using (var arc = ZipArchive.Create())
|
||||
{
|
||||
arc.AddEntry("1.txt", new MemoryStream());
|
||||
arc.AddEntry("\\1.txt", new MemoryStream());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Create_Same_Stream()
|
||||
{
|
||||
string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip");
|
||||
string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip");
|
||||
|
||||
using (var arc = ZipArchive.Create())
|
||||
{
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("qwert")))
|
||||
{
|
||||
arc.AddEntry("1.txt", stream, false, stream.Length);
|
||||
arc.AddEntry("2.txt", stream, false, stream.Length);
|
||||
arc.SaveTo(scratchPath1, CompressionType.Deflate);
|
||||
arc.SaveTo(scratchPath2, CompressionType.Deflate);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(new FileInfo(scratchPath1).Length, new FileInfo(scratchPath2).Length);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Create_New()
|
||||
{
|
||||
base.ResetScratch();
|
||||
foreach (var file in Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
var newFileName = file.Substring(ORIGINAL_FILES_PATH.Length);
|
||||
if (newFileName.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
newFileName = newFileName.Substring(1);
|
||||
}
|
||||
newFileName = Path.Combine(SCRATCH_FILES_PATH, newFileName);
|
||||
var newDir = Path.GetDirectoryName(newFileName);
|
||||
if (!Directory.Exists(newDir))
|
||||
{
|
||||
Directory.CreateDirectory(newDir);
|
||||
}
|
||||
File.Copy(file, newFileName);
|
||||
}
|
||||
string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
|
||||
using (var archive = ZipArchive.Create())
|
||||
{
|
||||
archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
|
||||
archive.SaveTo(scratchPath, CompressionType.Deflate);
|
||||
}
|
||||
CompareArchivesByPath(unmodified, scratchPath);
|
||||
Directory.Delete(SCRATCH_FILES_PATH, true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Create_New_Add_Remove()
|
||||
{
|
||||
base.ResetScratch();
|
||||
foreach (var file in Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
var newFileName = file.Substring(ORIGINAL_FILES_PATH.Length);
|
||||
if (newFileName.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
newFileName = newFileName.Substring(1);
|
||||
}
|
||||
newFileName = Path.Combine(SCRATCH_FILES_PATH, newFileName);
|
||||
var newDir = Path.GetDirectoryName(newFileName);
|
||||
if (!Directory.Exists(newDir))
|
||||
{
|
||||
Directory.CreateDirectory(newDir);
|
||||
}
|
||||
File.Copy(file, newFileName);
|
||||
}
|
||||
string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
|
||||
using (var archive = ZipArchive.Create())
|
||||
{
|
||||
archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
|
||||
archive.RemoveEntry(archive.Entries.Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)));
|
||||
Assert.IsFalse(archive.Entries.Any(x => x.Key.EndsWith("jpg")));
|
||||
}
|
||||
Directory.Delete(SCRATCH_FILES_PATH, true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_WinzipAES_Read()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var reader = ZipArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip"), "test"))
|
||||
{
|
||||
foreach (var entry in reader.Entries.Where(x => !x.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Pkware_Read()
|
||||
{
|
||||
ResetScratch();
|
||||
using (var reader = ZipArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.pkware.zip"), "test"))
|
||||
{
|
||||
foreach (var entry in reader.Entries.Where(x => !x.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Random_Entry_Access()
|
||||
{
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
|
||||
|
||||
base.ResetScratch();
|
||||
ZipArchive a = ZipArchive.Open(unmodified);
|
||||
int count = 0;
|
||||
foreach (var e in a.Entries)
|
||||
count++;
|
||||
|
||||
//Prints 3
|
||||
Assert.AreEqual(count, 3);
|
||||
a.Dispose();
|
||||
|
||||
a = ZipArchive.Open(unmodified);
|
||||
int count2 = 0;
|
||||
|
||||
foreach (var e in a.Entries)
|
||||
{
|
||||
count2++;
|
||||
|
||||
//Stop at last file
|
||||
if (count2 == count)
|
||||
{
|
||||
var s = e.OpenEntryStream();
|
||||
s.ReadByte(); //Actually access stream
|
||||
s.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int count3 = 0;
|
||||
foreach (var e in a.Entries)
|
||||
count3++;
|
||||
|
||||
Assert.AreEqual(count3, 3);
|
||||
}
|
||||
|
||||
|
||||
class NonSeekableMemoryStream : MemoryStream
|
||||
{
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSharpCompressWithEmptyStream()
|
||||
{
|
||||
MemoryStream stream = new NonSeekableMemoryStream();
|
||||
|
||||
using (IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
|
||||
{
|
||||
zipWriter.Write("foo.txt", new MemoryStream(new byte[0]));
|
||||
zipWriter.Write("foo2.txt", new MemoryStream(new byte[10]));
|
||||
}
|
||||
|
||||
stream = new MemoryStream(stream.ToArray());
|
||||
File.WriteAllBytes("foo.zip", stream.ToArray());
|
||||
|
||||
using (var zipArchive = ZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipArchive.Entries)
|
||||
{
|
||||
using (var entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
MemoryStream tempStream = new MemoryStream();
|
||||
const int bufSize = 0x1000;
|
||||
byte[] buf = new byte[bufSize];
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = entryStream.Read(buf, 0, bufSize)) > 0)
|
||||
tempStream.Write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.Zip;
|
||||
using SharpCompress.Writer;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class ZipReaderTests : ReaderTests
|
||||
{
|
||||
public ZipReaderTests()
|
||||
{
|
||||
UseExtensionInsteadOfNameToVerify = true;
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_ZipX_Streamed_Read()
|
||||
{
|
||||
Read("Zip.Zipx", CompressionType.LZMA);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Streamed_Read()
|
||||
{
|
||||
Read("Zip.bzip2.dd.zip", CompressionType.BZip2);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Read()
|
||||
{
|
||||
Read("Zip.bzip2.zip", CompressionType.BZip2);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed2_Read()
|
||||
{
|
||||
Read("Zip.deflate.dd-.zip", CompressionType.Deflate);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Streamed_Read()
|
||||
{
|
||||
Read("Zip.deflate.dd.zip", CompressionType.Deflate);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Read()
|
||||
{
|
||||
Read("Zip.deflate.zip", CompressionType.Deflate);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_Streamed_Read()
|
||||
{
|
||||
Read("Zip.lzma.dd.zip", CompressionType.LZMA);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_Read()
|
||||
{
|
||||
Read("Zip.lzma.zip", CompressionType.LZMA);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_Streamed_Read()
|
||||
{
|
||||
Read("Zip.ppmd.dd.zip", CompressionType.PPMd);
|
||||
}
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_Read()
|
||||
{
|
||||
Read("Zip.ppmd.zip", CompressionType.PPMd);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_None_Read()
|
||||
{
|
||||
Read("Zip.none.zip", CompressionType.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_NoEmptyDirs_Read()
|
||||
{
|
||||
Read("Zip.deflate.noEmptyDirs.zip", CompressionType.Deflate);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_PkwareEncryption_Read()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.pkware.zip")))
|
||||
using (var reader = ZipReader.Open(stream, "test"))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.BZip2);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Reader_Disposal_Test()
|
||||
{
|
||||
ResetScratch();
|
||||
using (TestStream stream = new TestStream(File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip"))))
|
||||
{
|
||||
using (var reader = ReaderFactory.Open(stream, Options.None))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.IsTrue(stream.IsDisposed);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Reader_Disposal_Test2()
|
||||
{
|
||||
ResetScratch();
|
||||
using (TestStream stream = new TestStream(File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip"))))
|
||||
{
|
||||
var reader = ReaderFactory.Open(stream, Options.None);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(stream.IsDisposed);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NotSupportedException))]
|
||||
public void Zip_LZMA_WinzipAES_Read()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.winzipaes.zip")))
|
||||
using (var reader = ZipReader.Open(stream, "test"))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Unknown);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_WinzipAES_Read()
|
||||
{
|
||||
ResetScratch();
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip")))
|
||||
using (var reader = ZipReader.Open(stream, "test"))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Unknown);
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH,
|
||||
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
class NonSeekableMemoryStream : MemoryStream
|
||||
{
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSharpCompressWithEmptyStream()
|
||||
{
|
||||
MemoryStream stream = new NonSeekableMemoryStream();
|
||||
|
||||
using (IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
|
||||
{
|
||||
zipWriter.Write("foo.txt", new MemoryStream(new byte[0]));
|
||||
zipWriter.Write("foo2.txt", new MemoryStream(new byte[10]));
|
||||
}
|
||||
|
||||
stream = new MemoryStream(stream.ToArray());
|
||||
File.WriteAllBytes("foo.zip", stream.ToArray());
|
||||
|
||||
using (IReader zipReader = ZipReader.Open(stream))
|
||||
{
|
||||
while (zipReader.MoveToNextEntry())
|
||||
{
|
||||
using (EntryStream entry = zipReader.OpenEntryStream())
|
||||
{
|
||||
MemoryStream tempStream = new MemoryStream();
|
||||
const int bufSize = 0x1000;
|
||||
byte[] buf = new byte[bufSize];
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = entry.Read(buf, 0, bufSize)) > 0)
|
||||
tempStream.Write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class ZipWriterTests : WriterTests
|
||||
{
|
||||
public ZipWriterTests()
|
||||
: base(ArchiveType.Zip)
|
||||
{
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_Deflate_Write()
|
||||
{
|
||||
Write(CompressionType.Deflate, "Zip.deflate.noEmptyDirs.zip", "Zip.deflate.noEmptyDirs.zip");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_BZip2_Write()
|
||||
{
|
||||
Write(CompressionType.BZip2, "Zip.bzip2.noEmptyDirs.zip", "Zip.bzip2.noEmptyDirs.zip");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_None_Write()
|
||||
{
|
||||
Write(CompressionType.None, "Zip.none.noEmptyDirs.zip", "Zip.none.noEmptyDirs.zip");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_LZMA_Write()
|
||||
{
|
||||
Write(CompressionType.LZMA, "Zip.lzma.noEmptyDirs.zip", "Zip.lzma.noEmptyDirs.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Zip_PPMd_Write()
|
||||
{
|
||||
Write(CompressionType.PPMd, "Zip.ppmd.noEmptyDirs.zip", "Zip.ppmd.noEmptyDirs.zip");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidFormatException))]
|
||||
public void Zip_Rar_Write()
|
||||
{
|
||||
Write(CompressionType.Rar, "Zip.ppmd.noEmptyDirs.zip", "Zip.ppmd.noEmptyDirs.zip");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<!-- The configuration and platform will be used to determine which
|
||||
assemblies to include from solution and project documentation
|
||||
sources -->
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{a226cac9-f2c4-4cc2-94f9-163b3e221817}</ProjectGuid>
|
||||
<SHFBSchemaVersion>1.9.3.0</SHFBSchemaVersion>
|
||||
<!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
|
||||
Studio adds them anyway -->
|
||||
<AssemblyName>Documentation</AssemblyName>
|
||||
<RootNamespace>Documentation</RootNamespace>
|
||||
<Name>Documentation</Name>
|
||||
<!-- SHFB properties -->
|
||||
<OutputPath>.\Help\</OutputPath>
|
||||
<HtmlHelpName>sharpcompress</HtmlHelpName>
|
||||
<Language>en-US</Language>
|
||||
<RootNamespaceTitle>SharpCompress</RootNamespaceTitle>
|
||||
<SandcastlePath>..\..\Program Files (x86)\Sandcastle\</SandcastlePath>
|
||||
<DocumentationSources>
|
||||
<DocumentationSource sourceFile="bin\SharpCompress.dll" />
|
||||
<DocumentationSource sourceFile="bin\SharpCompress.xml" />
|
||||
</DocumentationSources>
|
||||
<HelpTitle>SharpCompress</HelpTitle>
|
||||
<PresentationStyle>Prototype</PresentationStyle>
|
||||
<HelpFileFormat>HtmlHelp1, Website</HelpFileFormat>
|
||||
<MissingTags>AutoDocumentCtors, AutoDocumentDispose</MissingTags>
|
||||
</PropertyGroup>
|
||||
<!-- There are no properties for these groups. AnyCPU needs to appear in
|
||||
order for Visual Studio to perform the build. The others are optional
|
||||
common platform types that may appear. -->
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
|
||||
</PropertyGroup>
|
||||
<!-- Import the SHFB build targets -->
|
||||
<Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
|
||||
</Project>
|
||||
Binary file not shown.
@@ -1,71 +1,63 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F18F1765-4A02-42FD-9BEF-F0E2FCBD9D17}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
NuGet\sharpcompress.nuspec = NuGet\sharpcompress.nuspec
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress", "SharpCompress\SharpCompress.csproj", "{10A689CF-76A2-4A4F-96E4-553C33398438}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Test", "SharpCompress.Test\SharpCompress.Test.csproj", "{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Portable", "SharpCompress\SharpCompress.Portable.csproj", "{7FA7D133-1417-4F85-9998-4C618AC8FEDA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.WindowsStore", "SharpCompress\SharpCompress.WindowsStore.csproj", "{1DF6D83C-31FF-47B6-82FE-C4603BE916B5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.PortableTest", "SharpCompress\SharpCompress.PortableTest.csproj", "{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Test.Portable", "SharpCompress.Test\SharpCompress.Test.Portable.csproj", "{E9C3C94B-FB27-4B4F-B225-57513C254D37}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Unsigned", "SharpCompress\SharpCompress.Unsigned.csproj", "{27D535CB-2FD3-4621-8C9A-46161FC77A5D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{10A689CF-76A2-4A4F-96E4-553C33398438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{10A689CF-76A2-4A4F-96E4-553C33398438}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{10A689CF-76A2-4A4F-96E4-553C33398438}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{10A689CF-76A2-4A4F-96E4-553C33398438}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7FA7D133-1417-4F85-9998-4C618AC8FEDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7FA7D133-1417-4F85-9998-4C618AC8FEDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7FA7D133-1417-4F85-9998-4C618AC8FEDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7FA7D133-1417-4F85-9998-4C618AC8FEDA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1DF6D83C-31FF-47B6-82FE-C4603BE916B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1DF6D83C-31FF-47B6-82FE-C4603BE916B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1DF6D83C-31FF-47B6-82FE-C4603BE916B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1DF6D83C-31FF-47B6-82FE-C4603BE916B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
|
||||
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
|
||||
{E9C3C94B-FB27-4B4F-B225-57513C254D37} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
|
||||
{27D535CB-2FD3-4621-8C9A-46161FC77A5D} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.6
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C5BE746-03E5-4895-9988-0B57F162F86C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0F0901FF-E8D9-426A-B5A2-17C7F47C1529}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpCompress", "src\SharpCompress\SharpCompress.csproj", "{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpCompress.Test", "tests\SharpCompress.Test\SharpCompress.Test.csproj", "{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "build", "build\build.csproj", "{D4D613CB-5E94-47FB-85BE-B8423D20C545}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB42573-7D22-4490-BA12-1B7FB99CE7FB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Directory.Build.props = Directory.Build.props
|
||||
global.json = global.json
|
||||
.editorconfig = .editorconfig
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
NuGet.config = NuGet.config
|
||||
.github\workflows\nuget-release.yml = .github\workflows\nuget-release.yml
|
||||
USAGE.md = USAGE.md
|
||||
README.md = README.md
|
||||
FORMATS.md = FORMATS.md
|
||||
AGENTS.md = AGENTS.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Performance", "tests\SharpCompress.Performance\SharpCompress.Performance.csproj", "{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998} = {3C5BE746-03E5-4895-9988-0B57F162F86C}
|
||||
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F} = {0F0901FF-E8D9-426A-B5A2-17C7F47C1529}
|
||||
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17} = {0F0901FF-E8D9-426A-B5A2-17C7F47C1529}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,6 +1,138 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=181069325DAB1C4287CD564D6CDDEDB3/AbsolutePath/@EntryValue">D:\Git\sharpcompress\SharpCompress\sharpcompress.DotSettings</s:String>
|
||||
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=181069325DAB1C4287CD564D6CDDEDB3/RelativePath/@EntryValue">..\SharpCompress\sharpcompress.DotSettings</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=181069325DAB1C4287CD564D6CDDEDB3/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File181069325DAB1C4287CD564D6CDDEDB3/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File181069325DAB1C4287CD564D6CDDEDB3/RelativePriority/@EntryValue">1</s:Double></wpf:ResourceDictionary>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArgumentsStyleNamedExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Fdowhile/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Ffixed/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Ffor/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Fforeach/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Fifelse/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Flock/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Fusing/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeBraces_005Fwhile/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MethodSupportsCancellation/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExplicitParamsArrayCreation/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Basic_0020Clean/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Basic Clean"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="False" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="True" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSReformatCode>True</CSReformatCode></Profile></s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">Basic Clean</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/APPLY_ON_COMPLETION/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ARGUMENTS_NAMED/@EntryValue">Positional</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_FIRST_ARG_BY_PAREN/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_LINQ_QUERY/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARGUMENT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXPRESSION/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_FOR_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_CONSTRAINS/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_LIST/@EntryValue">True</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_START_COMMENT/@EntryValue">0</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_SINGLE_LINE_COMMENT/@EntryValue">1</s:Int64>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_ATTRIBUTE_STYLE/@EntryValue">SEPARATE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_ANONYMOUS_METHOD_BLOCK/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSORHOLDER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">False</s:Boolean>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_ARROW_OP/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean>
|
||||
|
||||
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SIZEOF_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVar</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVar</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVar</s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue"><Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue"><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=6af8f80e_002D9fdd_002D4223_002D8e02_002D473db916f9b2/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from Solution" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Solution />
|
||||
</SessionState></s:String></wpf:ResourceDictionary>
|
||||
|
||||
BIN
SharpCompress.snk
Normal file
BIN
SharpCompress.snk
Normal file
Binary file not shown.
@@ -1,212 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IArchiveExtractionListener
|
||||
where TEntry : IArchiveEntry
|
||||
where TVolume : IVolume
|
||||
{
|
||||
private readonly LazyReadOnlyCollection<TVolume> lazyVolumes;
|
||||
private readonly LazyReadOnlyCollection<TEntry> lazyEntries;
|
||||
|
||||
public event EventHandler<ArchiveExtractionEventArgs<IArchiveEntry>> EntryExtractionBegin;
|
||||
public event EventHandler<ArchiveExtractionEventArgs<IArchiveEntry>> EntryExtractionEnd;
|
||||
|
||||
public event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
|
||||
public event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
|
||||
|
||||
protected string Password { get; private set; }
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
internal AbstractArchive(ArchiveType type, FileInfo fileInfo, Options options, string password)
|
||||
{
|
||||
Type = type;
|
||||
Password = password;
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
throw new ArgumentException("File does not exist: " + fileInfo.FullName);
|
||||
}
|
||||
options = (Options) FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
|
||||
lazyVolumes = new LazyReadOnlyCollection<TVolume>(LoadVolumes(fileInfo, options));
|
||||
lazyEntries = new LazyReadOnlyCollection<TEntry>(LoadEntries(Volumes));
|
||||
}
|
||||
|
||||
|
||||
protected abstract IEnumerable<TVolume> LoadVolumes(FileInfo file, Options options);
|
||||
#endif
|
||||
|
||||
internal AbstractArchive(ArchiveType type, IEnumerable<Stream> streams, Options options, string password)
|
||||
{
|
||||
Type = type;
|
||||
Password = password;
|
||||
lazyVolumes = new LazyReadOnlyCollection<TVolume>(LoadVolumes(streams.Select(CheckStreams), options));
|
||||
lazyEntries = new LazyReadOnlyCollection<TEntry>(LoadEntries(Volumes));
|
||||
}
|
||||
|
||||
internal AbstractArchive(ArchiveType type)
|
||||
{
|
||||
Type = type;
|
||||
lazyVolumes = new LazyReadOnlyCollection<TVolume>(Enumerable.Empty<TVolume>());
|
||||
lazyEntries = new LazyReadOnlyCollection<TEntry>(Enumerable.Empty<TEntry>());
|
||||
}
|
||||
public ArchiveType Type { get; private set; }
|
||||
|
||||
void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry)
|
||||
{
|
||||
if (EntryExtractionBegin != null)
|
||||
{
|
||||
EntryExtractionBegin(this, new ArchiveExtractionEventArgs<IArchiveEntry>(entry));
|
||||
}
|
||||
}
|
||||
|
||||
void IArchiveExtractionListener.FireEntryExtractionEnd(IArchiveEntry entry)
|
||||
{
|
||||
if (EntryExtractionEnd != null)
|
||||
{
|
||||
EntryExtractionEnd(this, new ArchiveExtractionEventArgs<IArchiveEntry>(entry));
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream CheckStreams(Stream stream)
|
||||
{
|
||||
if (!stream.CanSeek || !stream.CanRead)
|
||||
{
|
||||
throw new ArgumentException("Archive streams must be Readable and Seekable");
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an ReadOnlyCollection of all the RarArchiveEntries across the one or many parts of the RarArchive.
|
||||
/// </summary>
|
||||
public virtual ICollection<TEntry> Entries
|
||||
{
|
||||
get { return lazyEntries; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an ReadOnlyCollection of all the RarArchiveVolumes across the one or many parts of the RarArchive.
|
||||
/// </summary>
|
||||
public ICollection<TVolume> Volumes
|
||||
{
|
||||
get { return lazyVolumes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files compressed in the archive.
|
||||
/// </summary>
|
||||
public virtual long TotalSize
|
||||
{
|
||||
get { return Entries.Aggregate(0L, (total, cf) => total + cf.CompressedSize); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files as uncompressed in the archive.
|
||||
/// </summary>
|
||||
public virtual long TotalUncompressSize
|
||||
{
|
||||
get { return Entries.Aggregate(0L, (total, cf) => total + cf.Size); }
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TVolume> LoadVolumes(IEnumerable<Stream> streams, Options options);
|
||||
protected abstract IEnumerable<TEntry> LoadEntries(IEnumerable<TVolume> volumes);
|
||||
|
||||
IEnumerable<IArchiveEntry> IArchive.Entries
|
||||
{
|
||||
get { return Entries.Cast<IArchiveEntry>(); }
|
||||
}
|
||||
|
||||
IEnumerable<IVolume> IArchive.Volumes
|
||||
{
|
||||
get { return lazyVolumes.Cast<IVolume>(); }
|
||||
}
|
||||
|
||||
private bool disposed;
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
lazyVolumes.ForEach(v => v.Dispose());
|
||||
lazyEntries.GetLoaded().Cast<Entry>().ForEach(x => x.Close());
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void IArchiveExtractionListener.EnsureEntriesLoaded()
|
||||
{
|
||||
lazyEntries.EnsureFullyLoaded();
|
||||
lazyVolumes.EnsureFullyLoaded();
|
||||
}
|
||||
|
||||
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
|
||||
{
|
||||
if (CompressedBytesRead != null)
|
||||
{
|
||||
CompressedBytesRead(this, new CompressedBytesReadEventArgs()
|
||||
{
|
||||
CurrentFilePartCompressedBytesRead = currentPartCompressedBytes,
|
||||
CompressedBytesRead = compressedReadBytes
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
{
|
||||
if (FilePartExtractionBegin != null)
|
||||
{
|
||||
FilePartExtractionBegin(this, new FilePartExtractionBeginEventArgs()
|
||||
{
|
||||
CompressedSize = compressedSize,
|
||||
Size = size,
|
||||
Name = name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to extract all entries in an archive in order.
|
||||
/// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be
|
||||
/// extracted sequentially for the best performance.
|
||||
///
|
||||
/// This method will load all entry information from the archive.
|
||||
///
|
||||
/// WARNING: this will reuse the underlying stream for the archive. Errors may
|
||||
/// occur if this is used at the same time as other extraction methods on this instance.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IReader ExtractAllEntries()
|
||||
{
|
||||
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
|
||||
return CreateReaderForSolidExtraction();
|
||||
}
|
||||
|
||||
protected abstract IReader CreateReaderForSolidExtraction();
|
||||
|
||||
/// <summary>
|
||||
/// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
|
||||
/// </summary>
|
||||
public virtual bool IsSolid
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The archive can find all the parts of the archive needed to fully extract the archive. This forces the parsing of the entire archive.
|
||||
/// </summary>
|
||||
public bool IsComplete
|
||||
{
|
||||
get
|
||||
{
|
||||
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
|
||||
return Entries.All(x => x.IsComplete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public abstract class AbstractWritableArchive<TEntry, TVolume> : AbstractArchive<TEntry, TVolume>, IWritableArchive
|
||||
where TEntry : IArchiveEntry
|
||||
where TVolume : IVolume
|
||||
{
|
||||
private readonly List<TEntry> newEntries = new List<TEntry>();
|
||||
private readonly List<TEntry> removedEntries = new List<TEntry>();
|
||||
|
||||
private readonly List<TEntry> modifiedEntries = new List<TEntry>();
|
||||
private bool hasModifications;
|
||||
|
||||
internal AbstractWritableArchive(ArchiveType type)
|
||||
: base(type)
|
||||
{
|
||||
}
|
||||
|
||||
internal AbstractWritableArchive(ArchiveType type, Stream stream, Options options)
|
||||
: base(type, stream.AsEnumerable(), options, null)
|
||||
{
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
internal AbstractWritableArchive(ArchiveType type, FileInfo fileInfo, Options options)
|
||||
: base(type, fileInfo, options, null)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
public override ICollection<TEntry> Entries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hasModifications)
|
||||
{
|
||||
return modifiedEntries;
|
||||
}
|
||||
return base.Entries;
|
||||
}
|
||||
}
|
||||
|
||||
private void RebuildModifiedCollection()
|
||||
{
|
||||
hasModifications = true;
|
||||
newEntries.RemoveAll(v => removedEntries.Contains(v));
|
||||
modifiedEntries.Clear();
|
||||
modifiedEntries.AddRange(OldEntries.Concat(newEntries));
|
||||
}
|
||||
|
||||
private IEnumerable<TEntry> OldEntries
|
||||
{
|
||||
get { return base.Entries.Where(x => !removedEntries.Contains(x)); }
|
||||
}
|
||||
|
||||
public void RemoveEntry(TEntry entry)
|
||||
{
|
||||
if (!removedEntries.Contains(entry))
|
||||
{
|
||||
removedEntries.Add(entry);
|
||||
RebuildModifiedCollection();
|
||||
}
|
||||
}
|
||||
void IWritableArchive.RemoveEntry(IArchiveEntry entry)
|
||||
{
|
||||
RemoveEntry((TEntry)entry);
|
||||
}
|
||||
|
||||
public TEntry AddEntry(string key, Stream source,
|
||||
long size = 0, DateTime? modified = null)
|
||||
{
|
||||
return AddEntry(key, source, false, size, modified);
|
||||
}
|
||||
|
||||
|
||||
IArchiveEntry IWritableArchive.AddEntry(string key, Stream source, bool closeStream, long size, DateTime? modified)
|
||||
{
|
||||
return AddEntry(key, source, closeStream, size, modified);
|
||||
}
|
||||
|
||||
public TEntry AddEntry(string key, Stream source, bool closeStream,
|
||||
long size = 0, DateTime? modified = null)
|
||||
{
|
||||
if (key.StartsWith("/")
|
||||
|| key.StartsWith("\\"))
|
||||
{
|
||||
key = key.Substring(1);
|
||||
}
|
||||
if (DoesKeyMatchExisting(key))
|
||||
{
|
||||
throw new ArchiveException("Cannot add entry with duplicate key: " + key);
|
||||
}
|
||||
var entry = CreateEntry(key, source, size, modified, closeStream);
|
||||
newEntries.Add(entry);
|
||||
RebuildModifiedCollection();
|
||||
return entry;
|
||||
}
|
||||
|
||||
private bool DoesKeyMatchExisting(string key)
|
||||
{
|
||||
foreach (var path in Entries.Select(x => x.Key))
|
||||
{
|
||||
var p = path.Replace('/','\\');
|
||||
if (p.StartsWith("\\"))
|
||||
{
|
||||
p = p.Substring(1);
|
||||
}
|
||||
return string.Equals(p, key, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveTo(Stream stream, CompressionInfo compressionType)
|
||||
{
|
||||
//reset streams of new entries
|
||||
newEntries.Cast<IWritableArchiveEntry>().ForEach(x => x.Stream.Seek(0, SeekOrigin.Begin));
|
||||
SaveTo(stream, compressionType, OldEntries, newEntries);
|
||||
}
|
||||
|
||||
protected TEntry CreateEntry(string key, Stream source, long size, DateTime? modified,
|
||||
bool closeStream)
|
||||
{
|
||||
if (!source.CanRead || !source.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Streams must be readable and seekable to use the Writing Archive API");
|
||||
}
|
||||
return CreateEntryInternal(key, source, size, modified, closeStream);
|
||||
}
|
||||
|
||||
protected abstract TEntry CreateEntryInternal(string key, Stream source, long size, DateTime? modified,
|
||||
bool closeStream);
|
||||
|
||||
protected abstract void SaveTo(Stream stream, CompressionInfo compressionType,
|
||||
IEnumerable<TEntry> oldEntries, IEnumerable<TEntry> newEntries);
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
newEntries.Cast<Entry>().ForEach(x => x.Close());
|
||||
removedEntries.Cast<Entry>().ForEach(x => x.Close());
|
||||
modifiedEntries.Cast<Entry>().ForEach(x => x.Close());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Archive.GZip;
|
||||
using SharpCompress.Archive.Rar;
|
||||
using SharpCompress.Archive.SevenZip;
|
||||
using SharpCompress.Archive.Tar;
|
||||
using SharpCompress.Archive.Zip;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public class ArchiveFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens an Archive for random access
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static IArchive Open(Stream stream, Options options = Options.KeepStreamsOpen)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return ZipArchive.Open(stream, options, null);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (TarArchive.IsTarFile(stream))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return TarArchive.Open(stream, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (SevenZipArchive.IsSevenZipFile(stream))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return SevenZipArchive.Open(stream, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (GZipArchive.IsGZipFile(stream))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return GZipArchive.Open(stream, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return RarArchive.Open(stream, options);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
}
|
||||
|
||||
public static IWritableArchive Create(ArchiveType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
{
|
||||
return ZipArchive.Create();
|
||||
}
|
||||
case ArchiveType.Tar:
|
||||
{
|
||||
return TarArchive.Create();
|
||||
}
|
||||
case ArchiveType.GZip:
|
||||
{
|
||||
return GZipArchive.Create();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException("Cannot create Archives of type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
public static IArchive Open(string filePath)
|
||||
{
|
||||
return Open(filePath, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
public static IArchive Open(FileInfo fileInfo)
|
||||
{
|
||||
return Open(fileInfo, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
public static IArchive Open(string filePath, Options options)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
public static IArchive Open(FileInfo fileInfo, Options options)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
using (var stream = fileInfo.OpenRead())
|
||||
{
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
{
|
||||
stream.Dispose();
|
||||
return ZipArchive.Open(fileInfo, options, null);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (TarArchive.IsTarFile(stream))
|
||||
{
|
||||
stream.Dispose();
|
||||
return TarArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (SevenZipArchive.IsSevenZipFile(stream))
|
||||
{
|
||||
stream.Dispose();
|
||||
return SevenZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (GZipArchive.IsGZipFile(stream))
|
||||
{
|
||||
stream.Dispose();
|
||||
return GZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
|
||||
{
|
||||
stream.Dispose();
|
||||
return RarArchive.Open(fileInfo, options);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
/// </summary>
|
||||
public static void WriteToDirectory(string sourceArchive, string destinationDirectory,
|
||||
ExtractOptions options = ExtractOptions.Overwrite)
|
||||
{
|
||||
using (IArchive archive = Open(sourceArchive))
|
||||
{
|
||||
foreach (IArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
entry.WriteToDirectory(destinationDirectory, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.GZip;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.GZip;
|
||||
using SharpCompress.Writer.GZip;
|
||||
|
||||
namespace SharpCompress.Archive.GZip
|
||||
{
|
||||
public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
|
||||
{
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
public static GZipArchive Open(string filePath)
|
||||
{
|
||||
return Open(filePath, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
public static GZipArchive Open(FileInfo fileInfo)
|
||||
{
|
||||
return Open(fileInfo, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
public static GZipArchive Open(string filePath, Options options)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
public static GZipArchive Open(FileInfo fileInfo, Options options)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
return new GZipArchive(fileInfo, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
public static GZipArchive Open(Stream stream)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return Open(stream, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
public static GZipArchive Open(Stream stream, Options options)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return new GZipArchive(stream, options);
|
||||
}
|
||||
|
||||
public static GZipArchive Create()
|
||||
{
|
||||
return new GZipArchive();
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
internal GZipArchive(FileInfo fileInfo, Options options)
|
||||
: base(ArchiveType.GZip, fileInfo, options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<GZipVolume> LoadVolumes(FileInfo file, Options options)
|
||||
{
|
||||
return new GZipVolume(file, options).AsEnumerable();
|
||||
}
|
||||
|
||||
public static bool IsGZipFile(string filePath)
|
||||
{
|
||||
return IsGZipFile(new FileInfo(filePath));
|
||||
}
|
||||
|
||||
public static bool IsGZipFile(FileInfo fileInfo)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsGZipFile(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveTo(string filePath)
|
||||
{
|
||||
SaveTo(new FileInfo(filePath));
|
||||
}
|
||||
|
||||
public void SaveTo(FileInfo fileInfo)
|
||||
{
|
||||
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
SaveTo(stream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsGZipFile(Stream stream)
|
||||
{
|
||||
// read the header on the first read
|
||||
byte[] header = new byte[10];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
return false;
|
||||
|
||||
if (n != 10)
|
||||
return false;
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes multiple seekable Streams for a multi-part archive
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
internal GZipArchive(Stream stream, Options options)
|
||||
: base(ArchiveType.GZip, stream, options)
|
||||
{
|
||||
}
|
||||
|
||||
internal GZipArchive()
|
||||
: base(ArchiveType.GZip)
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveTo(Stream stream)
|
||||
{
|
||||
SaveTo(stream, CompressionType.GZip);
|
||||
}
|
||||
|
||||
protected override GZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
|
||||
bool closeStream)
|
||||
{
|
||||
if (Entries.Any())
|
||||
{
|
||||
throw new InvalidOperationException("Only one entry is allowed in a GZip Archive");
|
||||
}
|
||||
return new GZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream);
|
||||
}
|
||||
|
||||
protected override void SaveTo(Stream stream, CompressionInfo compressionInfo,
|
||||
IEnumerable<GZipArchiveEntry> oldEntries,
|
||||
IEnumerable<GZipArchiveEntry> newEntries)
|
||||
{
|
||||
if (Entries.Count > 1)
|
||||
{
|
||||
throw new InvalidOperationException("Only one entry is allowed in a GZip Archive");
|
||||
}
|
||||
using (var writer = new GZipWriter(stream))
|
||||
{
|
||||
foreach (var entry in oldEntries.Concat(newEntries)
|
||||
.Where(x => !x.IsDirectory))
|
||||
{
|
||||
using (var entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
writer.Write(entry.Key, entryStream, entry.LastModifiedTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<GZipVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
|
||||
{
|
||||
return new GZipVolume(streams.First(), options).AsEnumerable();
|
||||
}
|
||||
|
||||
protected override IEnumerable<GZipArchiveEntry> LoadEntries(IEnumerable<GZipVolume> volumes)
|
||||
{
|
||||
Stream stream = volumes.Single().Stream;
|
||||
yield return new GZipArchiveEntry(this, new GZipFilePart(stream));
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
{
|
||||
var stream = Volumes.Single().Stream;
|
||||
stream.Position = 0;
|
||||
return GZipReader.Open(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common.GZip;
|
||||
|
||||
namespace SharpCompress.Archive.GZip
|
||||
{
|
||||
public class GZipArchiveEntry : GZipEntry, IArchiveEntry
|
||||
{
|
||||
|
||||
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
{
|
||||
return Parts.Single().GetCompressedStream();
|
||||
}
|
||||
|
||||
#region IArchiveEntry Members
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive.GZip
|
||||
{
|
||||
internal class GZipWritableArchiveEntry : GZipArchiveEntry, IWritableArchiveEntry
|
||||
{
|
||||
private readonly string path;
|
||||
private readonly long size;
|
||||
private readonly DateTime? lastModified;
|
||||
private readonly bool closeStream;
|
||||
private readonly Stream stream;
|
||||
|
||||
internal GZipWritableArchiveEntry(GZipArchive archive, Stream stream,
|
||||
string path, long size, DateTime? lastModified, bool closeStream)
|
||||
: base(archive, null)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.path = path;
|
||||
this.size = size;
|
||||
this.lastModified = lastModified;
|
||||
this.closeStream = closeStream;
|
||||
}
|
||||
|
||||
public override long Crc
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override string Key
|
||||
{
|
||||
get { return path; }
|
||||
}
|
||||
|
||||
public override long CompressedSize
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override long Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public override DateTime? LastModifiedTime
|
||||
{
|
||||
get { return lastModified; }
|
||||
}
|
||||
|
||||
public override DateTime? CreatedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? LastAccessedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? ArchivedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override bool IsEncrypted
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsDirectory
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsSplit
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
internal override IEnumerable<FilePart> Parts
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
Stream IWritableArchiveEntry.Stream
|
||||
{
|
||||
get
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream OpenEntryStream()
|
||||
{
|
||||
//ensure new stream is at the start, this could be reset
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return new NonDisposingStream(stream);
|
||||
}
|
||||
|
||||
internal override void Close()
|
||||
{
|
||||
if (closeStream)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public static class IArchiveExtensions
|
||||
{
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
/// </summary>
|
||||
public static void WriteToDirectory(this IArchive archive, string destinationDirectory,
|
||||
ExtractOptions options = ExtractOptions.Overwrite)
|
||||
{
|
||||
foreach (IArchiveEntry entry in archive.Entries.Where(x => !x.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(destinationDirectory, options);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public interface IArchive : IDisposable
|
||||
{
|
||||
event EventHandler<ArchiveExtractionEventArgs<IArchiveEntry>> EntryExtractionBegin;
|
||||
event EventHandler<ArchiveExtractionEventArgs<IArchiveEntry>> EntryExtractionEnd;
|
||||
|
||||
event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
|
||||
event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
|
||||
|
||||
IEnumerable<IArchiveEntry> Entries { get; }
|
||||
IEnumerable<IVolume> Volumes { get; }
|
||||
|
||||
ArchiveType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to extract all entries in an archive in order.
|
||||
/// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be
|
||||
/// extracted sequentially for the best performance.
|
||||
/// </summary>
|
||||
IReader ExtractAllEntries();
|
||||
|
||||
/// <summary>
|
||||
/// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
|
||||
/// Rar Archives can be SOLID while all 7Zip archives are considered SOLID.
|
||||
/// </summary>
|
||||
bool IsSolid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This checks to see if all the known entries have IsComplete = true
|
||||
/// </summary>
|
||||
bool IsComplete { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files compressed in the archive.
|
||||
/// </summary>
|
||||
long TotalSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files as uncompressed in the archive.
|
||||
/// </summary>
|
||||
long TotalUncompressSize { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public static class IArchiveEntryExtensions
|
||||
{
|
||||
public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo)
|
||||
{
|
||||
if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid)
|
||||
{
|
||||
throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files.");
|
||||
}
|
||||
|
||||
if (archiveEntry.IsDirectory)
|
||||
{
|
||||
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
|
||||
}
|
||||
|
||||
var streamListener = archiveEntry.Archive as IArchiveExtractionListener;
|
||||
streamListener.EnsureEntriesLoaded();
|
||||
streamListener.FireEntryExtractionBegin(archiveEntry);
|
||||
streamListener.FireFilePartExtractionBegin(archiveEntry.Key, archiveEntry.Size, archiveEntry.CompressedSize);
|
||||
var entryStream = archiveEntry.OpenEntryStream();
|
||||
if (entryStream == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using(entryStream)
|
||||
using (Stream s = new ListeningStream(streamListener, entryStream))
|
||||
{
|
||||
s.TransferTo(streamToWriteTo);
|
||||
}
|
||||
streamListener.FireEntryExtractionEnd(archiveEntry);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
/// </summary>
|
||||
public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory,
|
||||
ExtractOptions options = ExtractOptions.Overwrite)
|
||||
{
|
||||
string destinationFileName;
|
||||
string file = Path.GetFileName(entry.Key);
|
||||
|
||||
|
||||
if (options.HasFlag(ExtractOptions.ExtractFullPath))
|
||||
{
|
||||
string folder = Path.GetDirectoryName(entry.Key);
|
||||
string destdir = Path.Combine(destinationDirectory, folder);
|
||||
if (!Directory.Exists(destdir))
|
||||
{
|
||||
Directory.CreateDirectory(destdir);
|
||||
}
|
||||
destinationFileName = Path.Combine(destdir, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
destinationFileName = Path.Combine(destinationDirectory, file);
|
||||
}
|
||||
entry.WriteToFile(destinationFileName, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract to specific file
|
||||
/// </summary>
|
||||
public static void WriteToFile(this IArchiveEntry entry, string destinationFileName,
|
||||
ExtractOptions options = ExtractOptions.Overwrite)
|
||||
{
|
||||
if (entry.IsDirectory)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FileMode fm = FileMode.Create;
|
||||
|
||||
if (!options.HasFlag(ExtractOptions.Overwrite))
|
||||
{
|
||||
fm = FileMode.CreateNew;
|
||||
}
|
||||
using (FileStream fs = File.Open(destinationFileName, fm))
|
||||
{
|
||||
entry.WriteTo(fs);
|
||||
}
|
||||
|
||||
if (options.HasFlag(ExtractOptions.PreserveFileTime) || options.HasFlag(ExtractOptions.PreserveAttributes))
|
||||
{
|
||||
// update file time to original packed time
|
||||
FileInfo nf = new FileInfo(destinationFileName);
|
||||
if (nf.Exists)
|
||||
{
|
||||
if (options.HasFlag(ExtractOptions.PreserveFileTime))
|
||||
{
|
||||
if (entry.CreatedTime.HasValue)
|
||||
{
|
||||
nf.CreationTime = entry.CreatedTime.Value;
|
||||
}
|
||||
|
||||
if (entry.LastModifiedTime.HasValue)
|
||||
{
|
||||
nf.LastWriteTime = entry.LastModifiedTime.Value;
|
||||
}
|
||||
|
||||
if (entry.LastAccessedTime.HasValue)
|
||||
{
|
||||
nf.LastAccessTime = entry.CreatedTime.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.HasFlag(ExtractOptions.PreserveAttributes))
|
||||
{
|
||||
if (entry.Attrib.HasValue)
|
||||
{
|
||||
nf.Attributes = (FileAttributes)System.Enum.ToObject(typeof(FileAttributes), entry.Attrib.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public interface IArchiveEntry : IEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the current entry as a stream that will decompress as it is read.
|
||||
/// Read the entire stream or use SkipEntry on EntryStream.
|
||||
/// </summary>
|
||||
Stream OpenEntryStream();
|
||||
|
||||
/// <summary>
|
||||
/// The archive can find all the parts of the archive needed to extract this entry.
|
||||
/// </summary>
|
||||
bool IsComplete { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The archive instance this entry belongs to
|
||||
/// </summary>
|
||||
IArchive Archive { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
internal interface IArchiveExtractionListener : IExtractionListener
|
||||
{
|
||||
void EnsureEntriesLoaded();
|
||||
void FireEntryExtractionBegin(IArchiveEntry entry);
|
||||
void FireEntryExtractionEnd(IArchiveEntry entry);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public static class IWritableArchiveExtensions
|
||||
{
|
||||
public static void SaveTo(this IWritableArchive writableArchive,
|
||||
Stream stream, CompressionType compressionType)
|
||||
{
|
||||
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
|
||||
public static void AddEntry(this IWritableArchive writableArchive,
|
||||
string entryPath, string filePath)
|
||||
{
|
||||
var fileInfo = new FileInfo(filePath);
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
throw new FileNotFoundException("Could not AddEntry: " + filePath);
|
||||
}
|
||||
writableArchive.AddEntry(entryPath, new FileInfo(filePath).OpenRead(), true, fileInfo.Length,
|
||||
fileInfo.LastWriteTime);
|
||||
}
|
||||
|
||||
public static void SaveTo(this IWritableArchive writableArchive,
|
||||
string filePath, CompressionType compressionType)
|
||||
{
|
||||
writableArchive.SaveTo(new FileInfo(filePath), new CompressionInfo {Type = compressionType});
|
||||
}
|
||||
|
||||
public static void SaveTo(this IWritableArchive writableArchive,
|
||||
FileInfo fileInfo, CompressionType compressionType)
|
||||
{
|
||||
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveTo(this IWritableArchive writableArchive,
|
||||
string filePath, CompressionInfo compressionInfo)
|
||||
{
|
||||
writableArchive.SaveTo(new FileInfo(filePath), compressionInfo);
|
||||
}
|
||||
|
||||
public static void SaveTo(this IWritableArchive writableArchive,
|
||||
FileInfo fileInfo, CompressionInfo compressionInfo)
|
||||
{
|
||||
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
writableArchive.SaveTo(stream, compressionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddAllFromDirectory(
|
||||
this IWritableArchive writableArchive,
|
||||
string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
|
||||
{
|
||||
#if NET2
|
||||
foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption))
|
||||
#else
|
||||
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
|
||||
#endif
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
|
||||
fileInfo.LastWriteTime);
|
||||
}
|
||||
}
|
||||
public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
throw new ArgumentException("FileInfo does not exist.");
|
||||
}
|
||||
return writableArchive.AddEntry(key, fileInfo.OpenRead(), true, fileInfo.Length, fileInfo.LastWriteTime);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public interface IWritableArchive : IArchive
|
||||
{
|
||||
void RemoveEntry(IArchiveEntry entry);
|
||||
|
||||
IArchiveEntry AddEntry(string key, Stream source, bool closeStream, long size = 0, DateTime? modified = null);
|
||||
|
||||
void SaveTo(Stream stream, CompressionInfo compressionType);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
internal interface IWritableArchiveEntry
|
||||
{
|
||||
Stream Stream { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
/// <summary>
|
||||
/// A rar part based on a FileInfo object
|
||||
/// </summary>
|
||||
internal class FileInfoRarArchiveVolume : RarVolume
|
||||
{
|
||||
internal FileInfoRarArchiveVolume(FileInfo fileInfo, string password, Options options)
|
||||
: base(StreamingMode.Seekable, fileInfo.OpenRead(), password, FixOptions(options))
|
||||
{
|
||||
FileInfo = fileInfo;
|
||||
FileParts = base.GetVolumeFileParts().ToReadOnly();
|
||||
}
|
||||
|
||||
private static Options FixOptions(Options options)
|
||||
{
|
||||
//make sure we're closing streams with fileinfo
|
||||
if (options.HasFlag(Options.KeepStreamsOpen))
|
||||
{
|
||||
options = (Options) FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
internal ReadOnlyCollection<RarFilePart> FileParts { get; private set; }
|
||||
|
||||
internal FileInfo FileInfo { get; private set; }
|
||||
|
||||
internal override RarFilePart CreateFilePart(FileHeader fileHeader, MarkHeader markHeader)
|
||||
{
|
||||
return new FileInfoRarFilePart(this, markHeader, fileHeader, FileInfo);
|
||||
}
|
||||
|
||||
internal override IEnumerable<RarFilePart> ReadFileParts()
|
||||
{
|
||||
return FileParts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
internal class FileInfoRarFilePart : SeekableFilePart
|
||||
{
|
||||
private readonly FileInfoRarArchiveVolume volume;
|
||||
|
||||
internal FileInfoRarFilePart(FileInfoRarArchiveVolume volume, MarkHeader mh, FileHeader fh, FileInfo fi)
|
||||
: base(mh, fh, volume.Stream, volume.Password)
|
||||
{
|
||||
this.volume = volume;
|
||||
FileInfo = fi;
|
||||
}
|
||||
|
||||
internal FileInfo FileInfo { get; private set; }
|
||||
|
||||
internal override string FilePartName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Rar File: " + FileInfo.FullName
|
||||
+ " File Entry: " + FileHeader.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
public static class RarArchiveExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// RarArchive is the first volume of a multi-part archive. If MultipartVolume is true and IsFirstVolume is false then the first volume file must be missing.
|
||||
/// </summary>
|
||||
public static bool IsFirstVolume(this RarArchive archive)
|
||||
{
|
||||
return archive.Volumes.First().IsFirstVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RarArchive is part of a multi-part archive.
|
||||
/// </summary>
|
||||
public static bool IsMultipartVolume(this RarArchive archive)
|
||||
{
|
||||
return archive.Volumes.First().IsMultiVolume;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.Compressor.Rar;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.Rar;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
|
||||
{
|
||||
private readonly Unpack unpack = new Unpack();
|
||||
|
||||
internal Unpack Unpack
|
||||
{
|
||||
get { return unpack; }
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
internal RarArchive(FileInfo fileInfo, Options options, string password)
|
||||
: base(ArchiveType.Rar, fileInfo, options, password)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<RarVolume> LoadVolumes(FileInfo file, Options options)
|
||||
{
|
||||
return RarArchiveVolumeFactory.GetParts(file, Password, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes multiple seekable Streams for a multi-part archive
|
||||
/// </summary>
|
||||
/// <param name="streams"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
internal RarArchive(IEnumerable<Stream> streams, Options options, string password)
|
||||
: base(ArchiveType.Rar, streams, options, password)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<RarArchiveEntry> LoadEntries(IEnumerable<RarVolume> volumes)
|
||||
{
|
||||
return RarArchiveEntryFactory.GetEntries(this, volumes);
|
||||
}
|
||||
|
||||
protected override IEnumerable<RarVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
|
||||
{
|
||||
return RarArchiveVolumeFactory.GetParts(streams, Password, options);
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
{
|
||||
var stream = Volumes.First().Stream;
|
||||
stream.Position = 0;
|
||||
return RarReader.Open(stream);
|
||||
}
|
||||
|
||||
public override bool IsSolid
|
||||
{
|
||||
get { return Volumes.First().IsSolidArchive; }
|
||||
}
|
||||
|
||||
#region Creation
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static RarArchive Open(string filePath, Options options = Options.None, string password = null)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static RarArchive Open(FileInfo fileInfo, Options options = Options.None, string password = null)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
return new RarArchive(fileInfo, options, password);
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static RarArchive Open(Stream stream, Options options = Options.KeepStreamsOpen, string password = null)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return Open(stream.AsEnumerable(), options, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes multiple seekable Streams for a multi-part archive
|
||||
/// </summary>
|
||||
/// <param name="streams"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static RarArchive Open(IEnumerable<Stream> streams, Options options = Options.KeepStreamsOpen, string password = null)
|
||||
{
|
||||
streams.CheckNotNull("streams");
|
||||
return new RarArchive(streams, options, password);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
public static bool IsRarFile(string filePath)
|
||||
{
|
||||
return IsRarFile(new FileInfo(filePath));
|
||||
}
|
||||
|
||||
public static bool IsRarFile(FileInfo fileInfo)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsRarFile(stream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsRarFile(Stream stream)
|
||||
{
|
||||
return IsRarFile(stream, Options.None);
|
||||
}
|
||||
|
||||
public static bool IsRarFile(Stream stream, Options options)
|
||||
{
|
||||
try
|
||||
{
|
||||
var headerFactory = new RarHeaderFactory(StreamingMode.Seekable, options);
|
||||
RarHeader header = headerFactory.ReadHeaders(stream).FirstOrDefault();
|
||||
if (header == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Enum.IsDefined(typeof (HeaderType), header.HeaderType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.Compressor.Rar;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
public class RarArchiveEntry : RarEntry, IArchiveEntry
|
||||
{
|
||||
private readonly ICollection<RarFilePart> parts;
|
||||
private readonly RarArchive archive;
|
||||
|
||||
internal RarArchiveEntry(RarArchive archive, IEnumerable<RarFilePart> parts)
|
||||
{
|
||||
this.parts = parts.ToList();
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
public override CompressionType CompressionType
|
||||
{
|
||||
get { return CompressionType.Rar; }
|
||||
}
|
||||
|
||||
public IArchive Archive
|
||||
{
|
||||
get
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
}
|
||||
|
||||
internal override IEnumerable<FilePart> Parts
|
||||
{
|
||||
get { return parts.Cast<FilePart>(); }
|
||||
}
|
||||
|
||||
internal override FileHeader FileHeader
|
||||
{
|
||||
get { return parts.First().FileHeader; }
|
||||
}
|
||||
|
||||
public override long Crc
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIncomplete();
|
||||
return parts.Select(fp => fp.FileHeader)
|
||||
.Single(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)).FileCRC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override long Size
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIncomplete();
|
||||
return parts.First().FileHeader.UncompressedSize;
|
||||
}
|
||||
}
|
||||
|
||||
public override long CompressedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIncomplete();
|
||||
return parts.Aggregate(0L, (total, fp) => { return total + fp.FileHeader.CompressedSize; });
|
||||
}
|
||||
}
|
||||
|
||||
public Stream OpenEntryStream()
|
||||
{
|
||||
return new RarStream(archive.Unpack, FileHeader,
|
||||
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
|
||||
}
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get { return parts.Select(fp => fp.FileHeader).Any(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)); }
|
||||
}
|
||||
|
||||
private void CheckIncomplete()
|
||||
{
|
||||
if (!IsComplete)
|
||||
{
|
||||
throw new IncompleteArchiveException("ArchiveEntry is incomplete and cannot perform this operation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
internal static class RarArchiveEntryFactory
|
||||
{
|
||||
private static IEnumerable<RarFilePart> GetFileParts(IEnumerable<RarVolume> parts)
|
||||
{
|
||||
foreach (RarVolume rarPart in parts)
|
||||
{
|
||||
foreach (RarFilePart fp in rarPart.ReadFileParts())
|
||||
{
|
||||
yield return fp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IEnumerable<RarFilePart>> GetMatchedFileParts(IEnumerable<RarVolume> parts)
|
||||
{
|
||||
var groupedParts = new List<RarFilePart>();
|
||||
foreach (RarFilePart fp in GetFileParts(parts))
|
||||
{
|
||||
groupedParts.Add(fp);
|
||||
|
||||
if (!FlagUtility.HasFlag((long) fp.FileHeader.FileFlags, (long) FileFlags.SPLIT_AFTER))
|
||||
{
|
||||
yield return groupedParts;
|
||||
groupedParts = new List<RarFilePart>();
|
||||
}
|
||||
}
|
||||
if (groupedParts.Count > 0)
|
||||
{
|
||||
yield return groupedParts;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<RarArchiveEntry> GetEntries(RarArchive archive,
|
||||
IEnumerable<RarVolume> rarParts)
|
||||
{
|
||||
foreach (var groupedParts in GetMatchedFileParts(rarParts))
|
||||
{
|
||||
yield return new RarArchiveEntry(archive, groupedParts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if !PORTABLE
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
#endif
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
internal static class RarArchiveVolumeFactory
|
||||
{
|
||||
internal static IEnumerable<RarVolume> GetParts(IEnumerable<Stream> streams, string password, Options options)
|
||||
{
|
||||
foreach (Stream s in streams)
|
||||
{
|
||||
if (!s.CanRead || !s.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream is not readable and seekable");
|
||||
}
|
||||
StreamRarArchiveVolume part = new StreamRarArchiveVolume(s, password, options);
|
||||
yield return part;
|
||||
}
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
internal static IEnumerable<RarVolume> GetParts(FileInfo fileInfo, string password, Options options)
|
||||
{
|
||||
FileInfoRarArchiveVolume part = new FileInfoRarArchiveVolume(fileInfo, password, options);
|
||||
yield return part;
|
||||
|
||||
if (!part.ArchiveHeader.ArchiveHeaderFlags.HasFlag(ArchiveFlags.VOLUME))
|
||||
{
|
||||
yield break; //if file isn't volume then there is no reason to look
|
||||
}
|
||||
ArchiveHeader ah = part.ArchiveHeader;
|
||||
fileInfo = GetNextFileInfo(ah, part.FileParts.FirstOrDefault() as FileInfoRarFilePart);
|
||||
//we use fileinfo because rar is dumb and looks at file names rather than archive info for another volume
|
||||
while (fileInfo != null && fileInfo.Exists)
|
||||
{
|
||||
part = new FileInfoRarArchiveVolume(fileInfo, password, options);
|
||||
|
||||
fileInfo = GetNextFileInfo(ah, part.FileParts.FirstOrDefault() as FileInfoRarFilePart);
|
||||
yield return part;
|
||||
}
|
||||
}
|
||||
|
||||
private static FileInfo GetNextFileInfo(ArchiveHeader ah, FileInfoRarFilePart currentFilePart)
|
||||
{
|
||||
if (currentFilePart == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
bool oldNumbering = !ah.ArchiveHeaderFlags.HasFlag(ArchiveFlags.NEWNUMBERING)
|
||||
|| currentFilePart.MarkHeader.OldFormat;
|
||||
if (oldNumbering)
|
||||
{
|
||||
return FindNextFileWithOldNumbering(currentFilePart.FileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FindNextFileWithNewNumbering(currentFilePart.FileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private static FileInfo FindNextFileWithOldNumbering(FileInfo currentFileInfo)
|
||||
{
|
||||
// .rar, .r00, .r01, ...
|
||||
string extension = currentFileInfo.Extension;
|
||||
|
||||
StringBuilder buffer = new StringBuilder(currentFileInfo.FullName.Length);
|
||||
buffer.Append(currentFileInfo.FullName.Substring(0,
|
||||
currentFileInfo.FullName.Length - extension.Length));
|
||||
if (string.Compare(extension, ".rar", StringComparison.InvariantCultureIgnoreCase) == 0)
|
||||
{
|
||||
buffer.Append(".r00");
|
||||
}
|
||||
else
|
||||
{
|
||||
int num = 0;
|
||||
if (int.TryParse(extension.Substring(2, 2), out num))
|
||||
{
|
||||
num++;
|
||||
buffer.Append(".r");
|
||||
if (num < 10)
|
||||
{
|
||||
buffer.Append('0');
|
||||
}
|
||||
buffer.Append(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowInvalidFileName(currentFileInfo);
|
||||
}
|
||||
}
|
||||
return new FileInfo(buffer.ToString());
|
||||
}
|
||||
|
||||
private static FileInfo FindNextFileWithNewNumbering(FileInfo currentFileInfo)
|
||||
{
|
||||
// part1.rar, part2.rar, ...
|
||||
string extension = currentFileInfo.Extension;
|
||||
if (string.Compare(extension, ".rar", StringComparison.InvariantCultureIgnoreCase) != 0)
|
||||
{
|
||||
throw new ArgumentException("Invalid extension, expected 'rar': " + currentFileInfo.FullName);
|
||||
}
|
||||
int startIndex = currentFileInfo.FullName.LastIndexOf(".part");
|
||||
if (startIndex < 0)
|
||||
{
|
||||
ThrowInvalidFileName(currentFileInfo);
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(currentFileInfo.FullName.Length);
|
||||
buffer.Append(currentFileInfo.FullName, 0, startIndex);
|
||||
int num = 0;
|
||||
string numString = currentFileInfo.FullName.Substring(startIndex + 5,
|
||||
currentFileInfo.FullName.IndexOf('.', startIndex + 5) -
|
||||
startIndex - 5);
|
||||
buffer.Append(".part");
|
||||
if (int.TryParse(numString, out num))
|
||||
{
|
||||
num++;
|
||||
for (int i = 0; i < numString.Length - num.ToString().Length; i++)
|
||||
{
|
||||
buffer.Append('0');
|
||||
}
|
||||
buffer.Append(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowInvalidFileName(currentFileInfo);
|
||||
}
|
||||
buffer.Append(".rar");
|
||||
return new FileInfo(buffer.ToString());
|
||||
}
|
||||
|
||||
private static void ThrowInvalidFileName(FileInfo fileInfo)
|
||||
{
|
||||
throw new ArgumentException("Filename invalid or next archive could not be found:"
|
||||
+ fileInfo.FullName);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
internal class SeekableFilePart : RarFilePart
|
||||
{
|
||||
private readonly Stream stream;
|
||||
private readonly string password;
|
||||
|
||||
internal SeekableFilePart(MarkHeader mh, FileHeader fh, Stream stream, string password)
|
||||
: base(mh, fh)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
internal override Stream GetCompressedStream()
|
||||
{
|
||||
stream.Position = FileHeader.DataStartPosition;
|
||||
if (FileHeader.Salt != null)
|
||||
{
|
||||
#if PORTABLE
|
||||
throw new NotSupportedException("Encrypted Rar files aren't supported in portable distro.");
|
||||
#else
|
||||
return new RarCryptoWrapper(stream, password, FileHeader.Salt);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
internal override string FilePartName
|
||||
{
|
||||
get { return "Unknown Stream - File Entry: " + FileHeader.FileName; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
internal class StreamRarArchiveVolume : RarVolume
|
||||
{
|
||||
internal StreamRarArchiveVolume(Stream stream, string password, Options options)
|
||||
: base(StreamingMode.Seekable, stream, password, options)
|
||||
{
|
||||
}
|
||||
|
||||
internal override IEnumerable<RarFilePart> ReadFileParts()
|
||||
{
|
||||
return GetVolumeFileParts();
|
||||
}
|
||||
|
||||
internal override RarFilePart CreateFilePart(FileHeader fileHeader, MarkHeader markHeader)
|
||||
{
|
||||
return new SeekableFilePart(markHeader, fileHeader, Stream, Password);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.SevenZip;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Archive.SevenZip
|
||||
{
|
||||
public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVolume>
|
||||
{
|
||||
private ArchiveDatabase database;
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
public static SevenZipArchive Open(string filePath)
|
||||
{
|
||||
return Open(filePath, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
public static SevenZipArchive Open(FileInfo fileInfo)
|
||||
{
|
||||
return Open(fileInfo, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
public static SevenZipArchive Open(string filePath, Options options)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
public static SevenZipArchive Open(FileInfo fileInfo, Options options)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
return new SevenZipArchive(fileInfo, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
public static SevenZipArchive Open(Stream stream)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return Open(stream, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
public static SevenZipArchive Open(Stream stream, Options options)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return new SevenZipArchive(stream, options);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
internal SevenZipArchive(FileInfo fileInfo, Options options)
|
||||
: base(ArchiveType.SevenZip, fileInfo, options, null)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<SevenZipVolume> LoadVolumes(FileInfo file, Options options)
|
||||
{
|
||||
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
|
||||
{
|
||||
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
|
||||
}
|
||||
return new SevenZipVolume(file.OpenRead(), options).AsEnumerable();
|
||||
}
|
||||
|
||||
public static bool IsSevenZipFile(string filePath)
|
||||
{
|
||||
return IsSevenZipFile(new FileInfo(filePath));
|
||||
}
|
||||
|
||||
public static bool IsSevenZipFile(FileInfo fileInfo)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsSevenZipFile(stream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal SevenZipArchive(Stream stream, Options options)
|
||||
: base(ArchiveType.SevenZip, stream.AsEnumerable(), options, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal SevenZipArchive()
|
||||
: base(ArchiveType.SevenZip)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<SevenZipVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
|
||||
{
|
||||
foreach (Stream s in streams)
|
||||
{
|
||||
if (!s.CanRead || !s.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream is not readable and seekable");
|
||||
}
|
||||
SevenZipVolume volume = new SevenZipVolume(s, options);
|
||||
yield return volume;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<SevenZipArchiveEntry> LoadEntries(IEnumerable<SevenZipVolume> volumes)
|
||||
{
|
||||
var stream = volumes.Single().Stream;
|
||||
LoadFactory(stream);
|
||||
for (int i = 0; i < database.Files.Count; i++)
|
||||
{
|
||||
var file = database.Files[i];
|
||||
if (!file.IsDir)
|
||||
{
|
||||
yield return new SevenZipArchiveEntry(this, new SevenZipFilePart(stream, database, i, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadFactory(Stream stream)
|
||||
{
|
||||
if (database == null)
|
||||
{
|
||||
stream.Position = 0;
|
||||
var reader = new ArchiveReader();
|
||||
reader.Open(stream);
|
||||
database = reader.ReadDatabase(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool IsSevenZipFile(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
return SignatureMatch(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly byte[] SIGNATURE = new byte[] {(byte) '7', (byte) 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
|
||||
private static bool SignatureMatch(Stream stream)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
byte[] signatureBytes = reader.ReadBytes(6);
|
||||
return signatureBytes.BinaryEquals(SIGNATURE);
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
{
|
||||
return new SevenZipReader(this);
|
||||
}
|
||||
|
||||
public override bool IsSolid
|
||||
{
|
||||
get { return Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; }
|
||||
}
|
||||
|
||||
public override long TotalSize
|
||||
{
|
||||
get
|
||||
{
|
||||
int i = Entries.Count;
|
||||
return database.PackSizes.Aggregate(0L, (total, packSize) => total + packSize);
|
||||
}
|
||||
}
|
||||
|
||||
private class SevenZipReader : AbstractReader<SevenZipEntry, SevenZipVolume>
|
||||
{
|
||||
private readonly SevenZipArchive archive;
|
||||
private CFolder currentFolder;
|
||||
private Stream currentStream;
|
||||
private CFileItem currentItem;
|
||||
|
||||
internal SevenZipReader(SevenZipArchive archive)
|
||||
: base(Options.KeepStreamsOpen, ArchiveType.SevenZip)
|
||||
{
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
|
||||
public override SevenZipVolume Volume
|
||||
{
|
||||
get { return archive.Volumes.Single(); }
|
||||
}
|
||||
|
||||
internal override IEnumerable<SevenZipEntry> GetEntries(Stream stream)
|
||||
{
|
||||
List<SevenZipArchiveEntry> entries = archive.Entries.ToList();
|
||||
stream.Position = 0;
|
||||
foreach (var dir in entries.Where(x => x.IsDirectory))
|
||||
{
|
||||
yield return dir;
|
||||
}
|
||||
foreach (var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder))
|
||||
{
|
||||
currentFolder = group.Key;
|
||||
if (group.Key == null)
|
||||
{
|
||||
currentStream = Stream.Null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStream = archive.database.GetFolderStream(stream, currentFolder, null);
|
||||
}
|
||||
foreach (var entry in group)
|
||||
{
|
||||
currentItem = entry.FilePart.Header;
|
||||
yield return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override EntryStream GetEntryStream()
|
||||
{
|
||||
return CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common.SevenZip;
|
||||
|
||||
namespace SharpCompress.Archive.SevenZip
|
||||
{
|
||||
public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry
|
||||
{
|
||||
internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public Stream OpenEntryStream()
|
||||
{
|
||||
return FilePart.GetCompressedStream();
|
||||
}
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a 7Zip Anti item
|
||||
/// </summary>
|
||||
public bool IsAnti
|
||||
{
|
||||
get { return FilePart.Header.IsAnti; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Tar;
|
||||
using SharpCompress.Common.Tar.Headers;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.Tar;
|
||||
using SharpCompress.Writer.Tar;
|
||||
|
||||
namespace SharpCompress.Archive.Tar
|
||||
{
|
||||
public class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVolume>
|
||||
{
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
public static TarArchive Open(string filePath)
|
||||
{
|
||||
return Open(filePath, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
public static TarArchive Open(FileInfo fileInfo)
|
||||
{
|
||||
return Open(fileInfo, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
public static TarArchive Open(string filePath, Options options)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
public static TarArchive Open(FileInfo fileInfo, Options options)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
return new TarArchive(fileInfo, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
public static TarArchive Open(Stream stream)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return Open(stream, Options.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
public static TarArchive Open(Stream stream, Options options)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return new TarArchive(stream, options);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
public static bool IsTarFile(string filePath)
|
||||
{
|
||||
return IsTarFile(new FileInfo(filePath));
|
||||
}
|
||||
|
||||
public static bool IsTarFile(FileInfo fileInfo)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsTarFile(stream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsTarFile(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
TarHeader tar = new TarHeader();
|
||||
tar.Read(new BinaryReader(stream));
|
||||
return tar.Name.Length > 0 && Enum.IsDefined(typeof (EntryType), tar.EntryType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
internal TarArchive(FileInfo fileInfo, Options options)
|
||||
: base(ArchiveType.Tar, fileInfo, options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<TarVolume> LoadVolumes(FileInfo file, Options options)
|
||||
{
|
||||
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
|
||||
{
|
||||
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
|
||||
}
|
||||
return new TarVolume(file.OpenRead(), options).AsEnumerable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes multiple seekable Streams for a multi-part archive
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
internal TarArchive(Stream stream, Options options)
|
||||
: base(ArchiveType.Tar, stream, options)
|
||||
{
|
||||
}
|
||||
|
||||
internal TarArchive()
|
||||
: base(ArchiveType.Tar)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<TarVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
|
||||
{
|
||||
return new TarVolume(streams.First(), options).AsEnumerable();
|
||||
}
|
||||
|
||||
protected override IEnumerable<TarArchiveEntry> LoadEntries(IEnumerable<TarVolume> volumes)
|
||||
{
|
||||
Stream stream = volumes.Single().Stream;
|
||||
TarHeader previousHeader = null;
|
||||
foreach (TarHeader header in TarHeaderFactory.ReadHeader(StreamingMode.Seekable, stream))
|
||||
{
|
||||
if (header != null)
|
||||
{
|
||||
if (header.EntryType == EntryType.LongName)
|
||||
{
|
||||
previousHeader = header;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (previousHeader != null)
|
||||
{
|
||||
var entry = new TarArchiveEntry(this, new TarFilePart(previousHeader, stream),
|
||||
CompressionType.None);
|
||||
|
||||
var oldStreamPos = stream.Position;
|
||||
|
||||
using(var entryStream = entry.OpenEntryStream())
|
||||
using(var memoryStream = new MemoryStream())
|
||||
{
|
||||
entryStream.TransferTo(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
var bytes = memoryStream.ToArray();
|
||||
|
||||
header.Name = ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length).TrimNulls();
|
||||
}
|
||||
|
||||
stream.Position = oldStreamPos;
|
||||
|
||||
previousHeader = null;
|
||||
}
|
||||
yield return new TarArchiveEntry(this, new TarFilePart(header, stream), CompressionType.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TarArchive Create()
|
||||
{
|
||||
return new TarArchive();
|
||||
}
|
||||
|
||||
protected override TarArchiveEntry CreateEntryInternal(string filePath, Stream source,
|
||||
long size, DateTime? modified, bool closeStream)
|
||||
{
|
||||
return new TarWritableArchiveEntry(this, source, CompressionType.Unknown, filePath, size, modified,
|
||||
closeStream);
|
||||
}
|
||||
|
||||
protected override void SaveTo(Stream stream, CompressionInfo compressionInfo,
|
||||
IEnumerable<TarArchiveEntry> oldEntries,
|
||||
IEnumerable<TarArchiveEntry> newEntries)
|
||||
{
|
||||
using (var writer = new TarWriter(stream, compressionInfo))
|
||||
{
|
||||
foreach (var entry in oldEntries.Concat(newEntries)
|
||||
.Where(x => !x.IsDirectory))
|
||||
{
|
||||
using (var entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
writer.Write(entry.Key, entryStream, entry.LastModifiedTime, entry.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
{
|
||||
var stream = Volumes.Single().Stream;
|
||||
stream.Position = 0;
|
||||
return TarReader.Open(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Tar;
|
||||
|
||||
namespace SharpCompress.Archive.Tar
|
||||
{
|
||||
public class TarArchiveEntry : TarEntry, IArchiveEntry
|
||||
{
|
||||
internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType)
|
||||
: base(part, compressionType)
|
||||
{
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
{
|
||||
return Parts.Single().GetCompressedStream();
|
||||
}
|
||||
|
||||
#region IArchiveEntry Members
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive.Tar
|
||||
{
|
||||
internal class TarWritableArchiveEntry : TarArchiveEntry, IWritableArchiveEntry
|
||||
{
|
||||
private readonly string path;
|
||||
private readonly long size;
|
||||
private readonly DateTime? lastModified;
|
||||
private readonly bool closeStream;
|
||||
private readonly Stream stream;
|
||||
|
||||
internal TarWritableArchiveEntry(TarArchive archive, Stream stream, CompressionType compressionType,
|
||||
string path, long size, DateTime? lastModified, bool closeStream)
|
||||
: base(archive, null, compressionType)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.path = path;
|
||||
this.size = size;
|
||||
this.lastModified = lastModified;
|
||||
this.closeStream = closeStream;
|
||||
}
|
||||
|
||||
public override long Crc
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override string Key
|
||||
{
|
||||
get { return path; }
|
||||
}
|
||||
|
||||
public override long CompressedSize
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override long Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public override DateTime? LastModifiedTime
|
||||
{
|
||||
get { return lastModified; }
|
||||
}
|
||||
|
||||
public override DateTime? CreatedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? LastAccessedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? ArchivedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override bool IsEncrypted
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsDirectory
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsSplit
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
internal override IEnumerable<FilePart> Parts
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
Stream IWritableArchiveEntry.Stream
|
||||
{
|
||||
get
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream OpenEntryStream()
|
||||
{
|
||||
//ensure new stream is at the start, this could be reset
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return new NonDisposingStream(stream);
|
||||
}
|
||||
|
||||
internal override void Close()
|
||||
{
|
||||
if (closeStream)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Zip;
|
||||
using SharpCompress.Common.Zip.Headers;
|
||||
using SharpCompress.Compressor.Deflate;
|
||||
using SharpCompress.Reader;
|
||||
using SharpCompress.Reader.Zip;
|
||||
using SharpCompress.Writer.Zip;
|
||||
|
||||
namespace SharpCompress.Archive.Zip
|
||||
{
|
||||
public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
|
||||
{
|
||||
private readonly SeekableZipHeaderFactory headerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the compression level applied to files added to the archive,
|
||||
/// if the compression method is set to deflate
|
||||
/// </summary>
|
||||
public CompressionLevel DeflateCompressionLevel { get; set; }
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(string filePath, string password = null)
|
||||
{
|
||||
return Open(filePath, Options.None, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(FileInfo fileInfo, string password = null)
|
||||
{
|
||||
return Open(fileInfo, Options.None, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(string filePath, Options options, string password = null)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty("filePath");
|
||||
return Open(new FileInfo(filePath), options, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(FileInfo fileInfo, Options options, string password = null)
|
||||
{
|
||||
fileInfo.CheckNotNull("fileInfo");
|
||||
return new ZipArchive(fileInfo, options, password);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(Stream stream, string password = null)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return Open(stream, Options.None, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a seekable Stream as a source
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
public static ZipArchive Open(Stream stream, Options options, string password = null)
|
||||
{
|
||||
stream.CheckNotNull("stream");
|
||||
return new ZipArchive(stream, options, password);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
public static bool IsZipFile(string filePath, string password = null)
|
||||
{
|
||||
return IsZipFile(new FileInfo(filePath), password);
|
||||
}
|
||||
|
||||
public static bool IsZipFile(FileInfo fileInfo, string password = null)
|
||||
{
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsZipFile(stream, password);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsZipFile(Stream stream, string password = null)
|
||||
{
|
||||
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password);
|
||||
try
|
||||
{
|
||||
ZipHeader header =
|
||||
headerFactory.ReadStreamHeader(stream).FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
|
||||
if (header == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Enum.IsDefined(typeof (ZipHeaderType), header.ZipHeaderType);
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
internal ZipArchive(FileInfo fileInfo, Options options, string password = null)
|
||||
: base(ArchiveType.Zip, fileInfo, options)
|
||||
{
|
||||
headerFactory = new SeekableZipHeaderFactory(password);
|
||||
}
|
||||
|
||||
protected override IEnumerable<ZipVolume> LoadVolumes(FileInfo file, Options options)
|
||||
{
|
||||
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
|
||||
{
|
||||
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
|
||||
}
|
||||
return new ZipVolume(file.OpenRead(), options).AsEnumerable();
|
||||
}
|
||||
#endif
|
||||
|
||||
internal ZipArchive()
|
||||
: base(ArchiveType.Zip)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes multiple seekable Streams for a multi-part archive
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="password"></param>
|
||||
internal ZipArchive(Stream stream, Options options, string password = null)
|
||||
: base(ArchiveType.Zip, stream, options)
|
||||
{
|
||||
headerFactory = new SeekableZipHeaderFactory(password);
|
||||
}
|
||||
|
||||
protected override IEnumerable<ZipVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
|
||||
{
|
||||
return new ZipVolume(streams.First(), options).AsEnumerable();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ZipArchiveEntry> LoadEntries(IEnumerable<ZipVolume> volumes)
|
||||
{
|
||||
var volume = volumes.Single();
|
||||
Stream stream = volume.Stream;
|
||||
foreach (ZipHeader h in headerFactory.ReadSeekableHeader(stream))
|
||||
{
|
||||
if (h != null)
|
||||
{
|
||||
switch (h.ZipHeaderType)
|
||||
{
|
||||
case ZipHeaderType.DirectoryEntry:
|
||||
{
|
||||
yield return new ZipArchiveEntry(this,
|
||||
new SeekableZipFilePart(headerFactory,
|
||||
h as DirectoryEntryHeader,
|
||||
stream));
|
||||
}
|
||||
break;
|
||||
case ZipHeaderType.DirectoryEnd:
|
||||
{
|
||||
byte[] bytes = (h as DirectoryEndHeader).Comment;
|
||||
volume.Comment = ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveTo(Stream stream, CompressionInfo compressionInfo,
|
||||
IEnumerable<ZipArchiveEntry> oldEntries,
|
||||
IEnumerable<ZipArchiveEntry> newEntries)
|
||||
{
|
||||
using (var writer = new ZipWriter(stream, compressionInfo, string.Empty))
|
||||
{
|
||||
foreach (var entry in oldEntries.Concat(newEntries)
|
||||
.Where(x => !x.IsDirectory))
|
||||
{
|
||||
using (var entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
writer.Write(entry.Key, entryStream, entry.LastModifiedTime, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override ZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
|
||||
bool closeStream)
|
||||
{
|
||||
return new ZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream);
|
||||
}
|
||||
|
||||
public static ZipArchive Create()
|
||||
{
|
||||
return new ZipArchive();
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
{
|
||||
var stream = Volumes.Single().Stream;
|
||||
stream.Position = 0;
|
||||
return ZipReader.Open(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common.Zip;
|
||||
|
||||
namespace SharpCompress.Archive.Zip
|
||||
{
|
||||
public class ZipArchiveEntry : ZipEntry, IArchiveEntry
|
||||
{
|
||||
internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
{
|
||||
return Parts.Single().GetCompressedStream();
|
||||
}
|
||||
|
||||
#region IArchiveEntry Members
|
||||
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string Comment
|
||||
{
|
||||
get { return (Parts.Single() as SeekableZipFilePart).Comment; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive.Zip
|
||||
{
|
||||
internal class ZipWritableArchiveEntry : ZipArchiveEntry, IWritableArchiveEntry
|
||||
{
|
||||
private readonly string path;
|
||||
private readonly long size;
|
||||
private readonly DateTime? lastModified;
|
||||
private readonly bool closeStream;
|
||||
private readonly Stream stream;
|
||||
private bool isDisposed;
|
||||
|
||||
internal ZipWritableArchiveEntry(ZipArchive archive, Stream stream, string path, long size,
|
||||
DateTime? lastModified, bool closeStream)
|
||||
: base(archive, null)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.path = path;
|
||||
this.size = size;
|
||||
this.lastModified = lastModified;
|
||||
this.closeStream = closeStream;
|
||||
}
|
||||
|
||||
public override long Crc
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override string Key
|
||||
{
|
||||
get { return path; }
|
||||
}
|
||||
|
||||
public override long CompressedSize
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override long Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public override DateTime? LastModifiedTime
|
||||
{
|
||||
get { return lastModified; }
|
||||
}
|
||||
|
||||
public override DateTime? CreatedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? LastAccessedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override DateTime? ArchivedTime
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override bool IsEncrypted
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsDirectory
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsSplit
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
internal override IEnumerable<FilePart> Parts
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
Stream IWritableArchiveEntry.Stream
|
||||
{
|
||||
get
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream OpenEntryStream()
|
||||
{
|
||||
//ensure new stream is at the start, this could be reset
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return new NonDisposingStream(stream);
|
||||
}
|
||||
|
||||
internal override void Close()
|
||||
{
|
||||
if (closeStream && !isDisposed)
|
||||
{
|
||||
stream.Dispose();
|
||||
isDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
#if PORTABLE
|
||||
[assembly: AssemblyTitle("SharpCompress.Portable")]
|
||||
[assembly: AssemblyProduct("SharpCompress.Portable")]
|
||||
#else
|
||||
|
||||
[assembly: AssemblyTitle("SharpCompress")]
|
||||
[assembly: AssemblyProduct("SharpCompress")]
|
||||
#endif
|
||||
|
||||
#if UNSIGNED
|
||||
[assembly: InternalsVisibleTo("SharpCompress.Test")]
|
||||
[assembly: InternalsVisibleTo("SharpCompress.Test.Portable")]
|
||||
#endif
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public static class ArchiveEncoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Default encoding to use when archive format doesn't specify one.
|
||||
/// </summary>
|
||||
public static Encoding Default { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Encoding used by encryption schemes which don't comply with RFC 2898.
|
||||
/// </summary>
|
||||
public static Encoding Password { get; set; }
|
||||
|
||||
static ArchiveEncoding()
|
||||
{
|
||||
Default = Encoding.UTF8;
|
||||
Password = Encoding.UTF8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class ArchiveException : Exception
|
||||
{
|
||||
public ArchiveException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class ArchiveExtractionEventArgs<T> : EventArgs
|
||||
{
|
||||
internal ArchiveExtractionEventArgs(T entry)
|
||||
{
|
||||
Item = entry;
|
||||
}
|
||||
|
||||
public T Item { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public enum ArchiveType
|
||||
{
|
||||
Rar,
|
||||
Zip,
|
||||
Tar,
|
||||
SevenZip,
|
||||
GZip,
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class CompressedBytesReadEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Compressed bytes read for the current entry
|
||||
/// </summary>
|
||||
public long CompressedBytesRead { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current file part read for Multipart files (e.g. Rar)
|
||||
/// </summary>
|
||||
public long CurrentFilePartCompressedBytesRead { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using SharpCompress.Compressor.Deflate;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Detailed compression properties when saving.
|
||||
/// </summary>
|
||||
public class CompressionInfo
|
||||
{
|
||||
public CompressionInfo()
|
||||
{
|
||||
DeflateCompressionLevel = CompressionLevel.Default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The algorthm to use. Must be valid for the format type.
|
||||
/// </summary>
|
||||
public CompressionType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When CompressionType.Deflate is used, this property is referenced. Defaults to CompressionLevel.Default.
|
||||
/// </summary>
|
||||
public CompressionLevel DeflateCompressionLevel { get; set; }
|
||||
|
||||
public static implicit operator CompressionInfo(CompressionType compressionType)
|
||||
{
|
||||
return new CompressionInfo() {Type = compressionType};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public enum CompressionType
|
||||
{
|
||||
None,
|
||||
GZip,
|
||||
BZip2,
|
||||
PPMd,
|
||||
Deflate,
|
||||
Rar,
|
||||
LZMA,
|
||||
BCJ,
|
||||
BCJ2,
|
||||
Unknown,
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class CryptographicException : Exception
|
||||
{
|
||||
public CryptographicException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public abstract class Entry : IEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The File's 32 bit CRC Hash
|
||||
/// </summary>
|
||||
public abstract long Crc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The string key of the file internal to the Archive.
|
||||
/// </summary>
|
||||
public abstract string Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The compressed file size
|
||||
/// </summary>
|
||||
public abstract long CompressedSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression type
|
||||
/// </summary>
|
||||
public abstract CompressionType CompressionType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The uncompressed file size
|
||||
/// </summary>
|
||||
public abstract long Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The entry last modified time in the archive, if recorded
|
||||
/// </summary>
|
||||
public abstract DateTime? LastModifiedTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The entry create time in the archive, if recorded
|
||||
/// </summary>
|
||||
public abstract DateTime? CreatedTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The entry last accessed time in the archive, if recorded
|
||||
/// </summary>
|
||||
public abstract DateTime? LastAccessedTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The entry time when archived, if recorded
|
||||
/// </summary>
|
||||
public abstract DateTime? ArchivedTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry is password protected and encrypted and cannot be extracted.
|
||||
/// </summary>
|
||||
public abstract bool IsEncrypted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry is password protected and encrypted and cannot be extracted.
|
||||
/// </summary>
|
||||
public abstract bool IsDirectory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry is split among multiple volumes
|
||||
/// </summary>
|
||||
public abstract bool IsSplit { get; }
|
||||
|
||||
internal abstract IEnumerable<FilePart> Parts { get; }
|
||||
internal bool IsSolid { get; set; }
|
||||
|
||||
internal virtual void Close()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry file attribute.
|
||||
/// </summary>
|
||||
public virtual int? Attrib
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class EntryStream : Stream
|
||||
{
|
||||
public IReader Reader { get; private set; }
|
||||
private Stream stream;
|
||||
private bool completed;
|
||||
private bool isDisposed;
|
||||
|
||||
internal EntryStream(IReader reader, Stream stream)
|
||||
{
|
||||
this.Reader = reader;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When reading a stream from OpenEntryStream, the stream must be completed so use this to finish reading the entire entry.
|
||||
/// </summary>
|
||||
public void SkipEntry()
|
||||
{
|
||||
var buffer = new byte[4096];
|
||||
while (Read(buffer, 0, buffer.Length) > 0)
|
||||
{
|
||||
}
|
||||
completed = true;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!(completed || Reader.Cancelled))
|
||||
{
|
||||
SkipEntry();
|
||||
}
|
||||
if (isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int read = stream.Read(buffer, offset, count);
|
||||
if (read <= 0)
|
||||
{
|
||||
completed = true;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
[Flags]
|
||||
public enum ExtractOptions
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// overwrite target if it exists
|
||||
/// </summary>
|
||||
Overwrite = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// extract with internal directory structure
|
||||
/// </summary>
|
||||
ExtractFullPath = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// preserve file time
|
||||
/// </summary>
|
||||
PreserveFileTime = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// preserve windows file attributes
|
||||
/// </summary>
|
||||
PreserveAttributes = 1 << 3,
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class ExtractionException : Exception
|
||||
{
|
||||
public ExtractionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ExtractionException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public abstract class FilePart
|
||||
{
|
||||
internal abstract string FilePartName { get; }
|
||||
|
||||
internal abstract Stream GetCompressedStream();
|
||||
internal abstract Stream GetRawStream();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user