diff options
Diffstat (limited to 'vendor/zip')
-rw-r--r-- | vendor/zip/.cargo-checksum.json | 2 | ||||
-rw-r--r-- | vendor/zip/CHANGELOG.md | 10 | ||||
-rw-r--r-- | vendor/zip/Cargo.lock | 110 | ||||
-rw-r--r-- | vendor/zip/Cargo.toml | 7 | ||||
-rw-r--r-- | vendor/zip/README.md | 7 | ||||
-rw-r--r-- | vendor/zip/src/aes_ctr.rs | 11 | ||||
-rw-r--r-- | vendor/zip/src/lib.rs | 11 | ||||
-rw-r--r-- | vendor/zip/src/read.rs | 64 | ||||
-rw-r--r-- | vendor/zip/src/read/stream.rs | 372 | ||||
-rw-r--r-- | vendor/zip/src/types.rs | 72 | ||||
-rw-r--r-- | vendor/zip/src/unstable.rs | 20 | ||||
-rw-r--r-- | vendor/zip/src/write.rs | 67 | ||||
-rw-r--r-- | vendor/zip/src/zipcrypto.rs | 46 | ||||
-rw-r--r-- | vendor/zip/tests/issue_234.rs | 2 | ||||
-rw-r--r-- | vendor/zip/tests/zip_crypto.rs | 17 |
15 files changed, 657 insertions, 161 deletions
diff --git a/vendor/zip/.cargo-checksum.json b/vendor/zip/.cargo-checksum.json index 9766507eb..be96805bf 100644 --- a/vendor/zip/.cargo-checksum.json +++ b/vendor/zip/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"da022ffbfcbf04616fc8e31b7a38fd7c8f2ad47a7fb42750fc04de110cf95857","CODE_OF_CONDUCT.md":"77930b2129928632cae79e10d0863885b34729e4f144f3ae5443cff65997196a","Cargo.lock":"5c81aacae00a3838358fed3e453cbb128f9870162a280d91b77f20c7b4c94390","Cargo.toml":"69d71445861d823f30fbd330f74cb395ed1f4e981f3c61e4754eda2f1f1cb0b4","LICENSE":"6ac8711fb340c62ce0a4ecd463342d3fa0e8e70de697c863a2e1c0c53006003c","README.md":"4da0a964d8fb78a5caae4674b4f69fc24f080167af56927d1a5c15412f9f672d","benches/read_entry.rs":"700235ee560887f33da56895d2a4da901c070b2a6a59aef90331046af4ddadad","benches/read_metadata.rs":"591e5adb9d36bf66da21d7e0d36a129c9bcf1331fa11714df8c53c860aee65ff","examples/extract.rs":"81f58da293553fe019319348e1d226a2d192480667877e72d77ab58812f5de1b","examples/extract_lorem.rs":"2d438706ca6e02468f362a54f4f2125598d2be1051e7ce40b71be58cfd703669","examples/file_info.rs":"20639234293511022938c8204488d182ccbcdfb59d962000acd8ac8f2f6db667","examples/stdin_info.rs":"5735801c9692a9b6ec35da6e6a65807db48b577068ab9df0018343df5161034b","examples/write_dir.rs":"224239e040c583f2e1ca4b1328ebe1a63b3c2213df6da8232cd62e004db05587","examples/write_sample.rs":"f723bf69676492599c2684aa995177f80e2aa922f1c9ae1681ed39e0a15959ad","src/aes.rs":"c1b19bdf15c75cc27b5657d1dc574b5c5ebcdc7ca2573e9909cc6ba1ffe7f6d8","src/aes_ctr.rs":"6a7a07c9538daf53624818f82084c6655db3862ca00751f3679c8b0bc346b70d","src/compression.rs":"84f8ded41182155cfbdb1ce79b9dc84cae0a6e55557021cf9f2d7168d8913b48","src/cp437.rs":"e3a044ddefc947f6d9c26ba50ebd438955d90b8971ad8b15e5dd1194495f3b93","src/crc32.rs":"6c5a48834dfa1ab33590fcc63f4121ee6d3f8fbcc5018e905c4d8570096874cf","src/lib.rs":"7c2f6bc3dde9575eeeaef9569139f28351333c29362f74569e627ad7be5a10b2","src/read.rs":"1c8e60c37a7016399d5bdf3796bcd4ad8a5cdf7450498233c7d056fd7533692a","src/result.rs":"7dc62da507ef2228313ed617d01f4d207eacb0b66352a497d24f04298e90e5df","src/spec.rs":"2a249aeb3c58ca475b5c7da6919cb61ac3cbe07b94a0cb3c730646d46fb265a8","src/types.rs":"21a37a8632bd9b2572a7ccd19e6048dcc453a3c4fd7583f3eddefbec7dd641a5","src/write.rs":"16ccc971f2858042d2f92e0448a72849745ea0a25449fd7c8961b78a466b6e6e","src/zipcrypto.rs":"4fe362af2a8e419d9cff6acc165acdc0dccaacc53baec7269b5f55dfcd396f5c","tests/aes_encryption.rs":"3733df1f5dcab4e9f9b9ec25cc7660f23c917759670e9b2e6fe77cfcd771faa9","tests/data/aes_archive.zip":"4abb3f304d1ab669453b7c4eae80db6ce8aff4ab91c8ab9a6edf90bbfede12f4","tests/data/comment_garbage.zip":"4a908af18691e50fc7773b34669a8ab6cb60875bee4d60fb7cd66d90eed55d2b","tests/data/files_and_dirs.zip":"e54cd8d084739f8d0b119d769c1263507b4da915cc38e4e2d3e4ef17c718f317","tests/data/invalid_cde_number_of_files_allocation_greater_offset.zip":"c680ed5ad622aae23eea3b5d90145cb79550e413cc6e9a7b67bb1043851512ee","tests/data/invalid_cde_number_of_files_allocation_smaller_offset.zip":"7c272255e825aff7167dc8d1f2e1d16583e58347bb56ecf9879bdb07c6ad18e9","tests/data/invalid_offset.zip":"c5534a1803145f6344b04c437d436bd583852c78dd3937f4a73a2a39aa2d76b2","tests/data/invalid_offset2.zip":"0f0f3d654f303eaf90f599c0b0266be476ce34857cff932070a86e9853dcb4f9","tests/data/mimetype.zip":"aad4289745bd89016181a35653c9a483c6b9b632e06d002736c7040d61c562a2","tests/data/zip64_demo.zip":"223072a480f60d6a700e427b294e575ae2d6265f3e9881b647927f31d96c7e01","tests/end_to_end.rs":"ba69c247e2f555a954ae97615a46a9b21092671f7ff1abebaba058b30a53bb66","tests/invalid_date.rs":"72d5425ffe2887e05646ba56f5116ac760cbeeb7889da5c9be612fe57477bc94","tests/issue_234.rs":"1a3d68d79108140100709c188841c6bf54af8500c819072a440ec72df5d8ab26","tests/zip64_large.rs":"d4859f551be83c2ae3bd4a8e37c7e617fb54bb27310e725de6c7076c5e566d6b","tests/zip_comment_garbage.rs":"ab0e2e3ace1ca5459977a092ee96836f58c7f7a7cfc8de258ab448d8d24f1cbb","tests/zip_crypto.rs":"7f4f9670e5d971ac4234c7ab2cafecf43801baf0be0cfca6e34c651f6fc6a80d"},"package":"0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"}
\ No newline at end of file +{"files":{"CHANGELOG.md":"385ad47ed19c64c42186eac68bedbf36c017077e41eafa6b13b2ecac2fc9699d","CODE_OF_CONDUCT.md":"77930b2129928632cae79e10d0863885b34729e4f144f3ae5443cff65997196a","Cargo.lock":"c70ccadfe0fb083a4bb7856df630cd9194a78641b6cb8d13cacd7675524aa989","Cargo.toml":"7cb213851ac9541dc7dd3ce163ef72c302985c9fb7d5bfed8859cb7988afd766","LICENSE":"6ac8711fb340c62ce0a4ecd463342d3fa0e8e70de697c863a2e1c0c53006003c","README.md":"fc2e679d51b854f3c7836a6537b47b6014d7c419ff553ffb45b71b9ade460985","benches/read_entry.rs":"700235ee560887f33da56895d2a4da901c070b2a6a59aef90331046af4ddadad","benches/read_metadata.rs":"591e5adb9d36bf66da21d7e0d36a129c9bcf1331fa11714df8c53c860aee65ff","examples/extract.rs":"81f58da293553fe019319348e1d226a2d192480667877e72d77ab58812f5de1b","examples/extract_lorem.rs":"2d438706ca6e02468f362a54f4f2125598d2be1051e7ce40b71be58cfd703669","examples/file_info.rs":"20639234293511022938c8204488d182ccbcdfb59d962000acd8ac8f2f6db667","examples/stdin_info.rs":"5735801c9692a9b6ec35da6e6a65807db48b577068ab9df0018343df5161034b","examples/write_dir.rs":"224239e040c583f2e1ca4b1328ebe1a63b3c2213df6da8232cd62e004db05587","examples/write_sample.rs":"f723bf69676492599c2684aa995177f80e2aa922f1c9ae1681ed39e0a15959ad","src/aes.rs":"c1b19bdf15c75cc27b5657d1dc574b5c5ebcdc7ca2573e9909cc6ba1ffe7f6d8","src/aes_ctr.rs":"1b5e4ae423b1652353c56f436a50c3a7c27cf3b78138e09b29e2b0c054b8e827","src/compression.rs":"84f8ded41182155cfbdb1ce79b9dc84cae0a6e55557021cf9f2d7168d8913b48","src/cp437.rs":"e3a044ddefc947f6d9c26ba50ebd438955d90b8971ad8b15e5dd1194495f3b93","src/crc32.rs":"6c5a48834dfa1ab33590fcc63f4121ee6d3f8fbcc5018e905c4d8570096874cf","src/lib.rs":"9503371bc4978006c6f2b15dbf3a781dddf40923875480df068f06ff60159050","src/read.rs":"3b802c0c01da2e18efa8cbfb8c3ad91df315674424e93414a9b43d128d7628e9","src/read/stream.rs":"a5fba4cf1abacc3d7d8e0ee7734dd3d6f2f0a5a90fd9b595d8b18877a0f06a6d","src/result.rs":"7dc62da507ef2228313ed617d01f4d207eacb0b66352a497d24f04298e90e5df","src/spec.rs":"2a249aeb3c58ca475b5c7da6919cb61ac3cbe07b94a0cb3c730646d46fb265a8","src/types.rs":"e77ddc1dc8c8f45107688c7ea54559dd696e1e2532ea285f3c3810860bfa4e37","src/unstable.rs":"15ecc548d32da535834bd5c67ddd6ddcd9f4a81e786853661e3d07eea7c4aa23","src/write.rs":"ada88e695ba2e1ae295b183921613c6b81a192a9942da35bf5491ea0e140e99e","src/zipcrypto.rs":"a43d0c42fe78e395c4f66cd3e3c6380821637fc1951934294caa7572b2dc7b67","tests/aes_encryption.rs":"3733df1f5dcab4e9f9b9ec25cc7660f23c917759670e9b2e6fe77cfcd771faa9","tests/data/aes_archive.zip":"4abb3f304d1ab669453b7c4eae80db6ce8aff4ab91c8ab9a6edf90bbfede12f4","tests/data/comment_garbage.zip":"4a908af18691e50fc7773b34669a8ab6cb60875bee4d60fb7cd66d90eed55d2b","tests/data/files_and_dirs.zip":"e54cd8d084739f8d0b119d769c1263507b4da915cc38e4e2d3e4ef17c718f317","tests/data/invalid_cde_number_of_files_allocation_greater_offset.zip":"c680ed5ad622aae23eea3b5d90145cb79550e413cc6e9a7b67bb1043851512ee","tests/data/invalid_cde_number_of_files_allocation_smaller_offset.zip":"7c272255e825aff7167dc8d1f2e1d16583e58347bb56ecf9879bdb07c6ad18e9","tests/data/invalid_offset.zip":"c5534a1803145f6344b04c437d436bd583852c78dd3937f4a73a2a39aa2d76b2","tests/data/invalid_offset2.zip":"0f0f3d654f303eaf90f599c0b0266be476ce34857cff932070a86e9853dcb4f9","tests/data/mimetype.zip":"aad4289745bd89016181a35653c9a483c6b9b632e06d002736c7040d61c562a2","tests/data/zip64_demo.zip":"223072a480f60d6a700e427b294e575ae2d6265f3e9881b647927f31d96c7e01","tests/end_to_end.rs":"ba69c247e2f555a954ae97615a46a9b21092671f7ff1abebaba058b30a53bb66","tests/invalid_date.rs":"72d5425ffe2887e05646ba56f5116ac760cbeeb7889da5c9be612fe57477bc94","tests/issue_234.rs":"48bbb0280b2cadfb30add0bc2eac730260ee4c0b98eda6c8f4efee499c894a4e","tests/zip64_large.rs":"d4859f551be83c2ae3bd4a8e37c7e617fb54bb27310e725de6c7076c5e566d6b","tests/zip_comment_garbage.rs":"ab0e2e3ace1ca5459977a092ee96836f58c7f7a7cfc8de258ab448d8d24f1cbb","tests/zip_crypto.rs":"9e1dc04a7fe627fa7ad3f31c7e70d5fa27759d583d63f8288208e1429dfacecb"},"package":"760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"}
\ No newline at end of file diff --git a/vendor/zip/CHANGELOG.md b/vendor/zip/CHANGELOG.md index cd79e3913..96c6994fe 100644 --- a/vendor/zip/CHANGELOG.md +++ b/vendor/zip/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.6.6] +### Changed + +- Updated `aes` dependency to `0.8.2` (https://github.com/zip-rs/zip/pull/354) + +## [0.6.5] +### Changed + +- Added experimental [`zip::unstable::write::FileOptions::with_deprecated_encryption`] API to enable encrypting files with PKWARE encryption. + ## [0.6.4] ### Changed diff --git a/vendor/zip/Cargo.lock b/vendor/zip/Cargo.lock index f0f4b2bd0..f1886669a 100644 --- a/vendor/zip/Cargo.lock +++ b/vendor/zip/Cargo.lock @@ -10,21 +10,20 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "opaque-debug", ] [[package]] name = "base64ct" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bencher" @@ -34,9 +33,9 @@ checksum = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -70,9 +69,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -85,11 +84,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] @@ -100,9 +100,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -118,9 +118,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -148,9 +148,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "libz-sys", @@ -159,9 +159,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "libc", @@ -188,31 +188,40 @@ dependencies = [ ] [[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jobserver" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.139" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" dependencies = [ "cc", "pkg-config", @@ -221,20 +230,14 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] name = "password-hash" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -259,9 +262,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "rand_core" @@ -280,9 +283,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" [[package]] name = "sha1" @@ -314,9 +317,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "time" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" dependencies = [ "itoa", "serde", @@ -326,15 +329,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" dependencies = [ "time-core", ] @@ -359,12 +362,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -407,7 +409,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zip" -version = "0.6.4" +version = "0.6.6" dependencies = [ "aes", "bencher", @@ -447,9 +449,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.5+zstd.1.5.2" +version = "2.0.8+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc50ffce891ad571e9f9afe5039c4837bede781ac4bb13052ed7ae695518596" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" dependencies = [ "cc", "libc", diff --git a/vendor/zip/Cargo.toml b/vendor/zip/Cargo.toml index 7a1b656b2..da0180ec4 100644 --- a/vendor/zip/Cargo.toml +++ b/vendor/zip/Cargo.toml @@ -10,9 +10,10 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" +rust-version = "1.59.0" name = "zip" -version = "0.6.4" +version = "0.6.6" authors = [ "Mathijs van de Nes <git@mathijs.vd-nes.nl>", "Marli Frost <marli@frost.red>", @@ -38,7 +39,7 @@ name = "read_metadata" harness = false [dependencies.aes] -version = "0.7.5" +version = "0.8.2" optional = true [dependencies.byteorder] diff --git a/vendor/zip/README.md b/vendor/zip/README.md index 3754a7c0f..f06cdbb57 100644 --- a/vendor/zip/README.md +++ b/vendor/zip/README.md @@ -7,9 +7,6 @@ zip-rs [Documentation](https://docs.rs/zip/0.6.3/zip/) -> PSA: This version of the ZIP crate will not gain any new features, -> and will only be updated if major security issues are found. - Info ---- @@ -35,14 +32,14 @@ With all default features: ```toml [dependencies] -zip = "0.6.4" +zip = "0.6" ``` Without the default features: ```toml [dependencies] -zip = { version = "0.6.4", default-features = false } +zip = { version = "0.6.6", default-features = false } ``` The features available are: diff --git a/vendor/zip/src/aes_ctr.rs b/vendor/zip/src/aes_ctr.rs index 0f34335cb..211727c0a 100644 --- a/vendor/zip/src/aes_ctr.rs +++ b/vendor/zip/src/aes_ctr.rs @@ -2,10 +2,11 @@ //! //! This was implemented since the zip specification requires the mode to not use a nonce and uses a //! different byte order (little endian) than NIST (big endian). -//! See [AesCtrZipKeyStream](./struct.AesCtrZipKeyStream.html) for more information. +//! See [AesCtrZipKeyStream] for more information. use aes::cipher::generic_array::GenericArray; -use aes::{BlockEncrypt, NewBlockCipher}; +// use aes::{BlockEncrypt, NewBlockCipher}; +use aes::cipher::{BlockEncrypt, KeyInit}; use byteorder::WriteBytesExt; use std::{any, fmt}; @@ -82,7 +83,7 @@ where impl<C> AesCtrZipKeyStream<C> where C: AesKind, - C::Cipher: NewBlockCipher, + C::Cipher: KeyInit, { /// Creates a new zip variant AES-CTR key stream. /// @@ -150,14 +151,14 @@ fn xor(dest: &mut [u8], src: &[u8]) { #[cfg(test)] mod tests { use super::{Aes128, Aes192, Aes256, AesCipher, AesCtrZipKeyStream, AesKind}; - use aes::{BlockEncrypt, NewBlockCipher}; + use aes::cipher::{BlockEncrypt, KeyInit}; /// Checks whether `crypt_in_place` produces the correct plaintext after one use and yields the /// cipertext again after applying it again. fn roundtrip<Aes>(key: &[u8], ciphertext: &mut [u8], expected_plaintext: &[u8]) where Aes: AesKind, - Aes::Cipher: NewBlockCipher + BlockEncrypt, + Aes::Cipher: KeyInit + BlockEncrypt, { let mut key_stream = AesCtrZipKeyStream::<Aes>::new(key); diff --git a/vendor/zip/src/lib.rs b/vendor/zip/src/lib.rs index 0fee99cc8..e2228e5b1 100644 --- a/vendor/zip/src/lib.rs +++ b/vendor/zip/src/lib.rs @@ -42,3 +42,14 @@ mod spec; mod types; pub mod write; mod zipcrypto; + +/// Unstable APIs +/// +/// All APIs accessible by importing this module are unstable; They may be changed in patch releases. +/// You MUST you an exact version specifier in `Cargo.toml`, to indicate the version of this API you're using: +/// +/// ```toml +/// [dependencies] +/// zip = "=0.6.6" +/// ``` +pub mod unstable; diff --git a/vendor/zip/src/read.rs b/vendor/zip/src/read.rs index dad20c260..b702b4f21 100644 --- a/vendor/zip/src/read.rs +++ b/vendor/zip/src/read.rs @@ -13,7 +13,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use std::borrow::Cow; use std::collections::HashMap; use std::io::{self, prelude::*}; -use std::path::{Component, Path}; +use std::path::Path; use std::sync::Arc; #[cfg(any( @@ -29,10 +29,8 @@ use bzip2::read::BzDecoder; #[cfg(feature = "zstd")] use zstd::stream::read::Decoder as ZstdDecoder; -mod ffi { - pub const S_IFDIR: u32 = 0o0040000; - pub const S_IFREG: u32 = 0o0100000; -} +/// Provides high level API for reading from a stream. +pub(crate) mod stream; // Put the struct declaration in a private module to convince rustdoc to display ZipArchive nicely pub(crate) mod zip_archive { @@ -650,12 +648,22 @@ pub(crate) fn central_header_to_zip_file<R: Read + io::Seek>( archive_offset: u64, ) -> ZipResult<ZipFileData> { let central_header_start = reader.stream_position()?; + // Parse central header let signature = reader.read_u32::<LittleEndian>()?; if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE { - return Err(ZipError::InvalidArchive("Invalid Central Directory header")); + Err(ZipError::InvalidArchive("Invalid Central Directory header")) + } else { + central_header_to_zip_file_inner(reader, archive_offset, central_header_start) } +} +/// Parse a central directory entry to collect the information for the file. +fn central_header_to_zip_file_inner<R: Read>( + reader: &mut R, + archive_offset: u64, + central_header_start: u64, +) -> ZipResult<ZipFileData> { let version_made_by = reader.read_u16::<LittleEndian>()?; let _version_to_extract = reader.read_u16::<LittleEndian>()?; let flags = reader.read_u16::<LittleEndian>()?; @@ -896,20 +904,7 @@ impl<'a> ZipFile<'a> { /// to path-based exploits. It is recommended over /// [`ZipFile::mangled_name`]. pub fn enclosed_name(&self) -> Option<&Path> { - if self.data.file_name.contains('\0') { - return None; - } - let path = Path::new(&self.data.file_name); - let mut depth = 0usize; - for component in path.components() { - match component { - Component::Prefix(_) | Component::RootDir => return None, - Component::ParentDir => depth = depth.checked_sub(1)?, - Component::Normal(_) => depth += 1, - Component::CurDir => (), - } - } - Some(path) + self.data.enclosed_name() } /// Get the comment of the file @@ -952,27 +947,7 @@ impl<'a> ZipFile<'a> { /// Get unix mode for the file pub fn unix_mode(&self) -> Option<u32> { - if self.data.external_attributes == 0 { - return None; - } - - match self.data.system { - System::Unix => Some(self.data.external_attributes >> 16), - System::Dos => { - // Interpret MS-DOS directory bit - let mut mode = if 0x10 == (self.data.external_attributes & 0x10) { - ffi::S_IFDIR | 0o0775 - } else { - ffi::S_IFREG | 0o0664 - }; - if 0x01 == (self.data.external_attributes & 0x01) { - // Read-only bit; strip write permissions - mode &= 0o0555; - } - Some(mode) - } - _ => None, - } + self.data.unix_mode() } /// Get the CRC32 hash of the original file @@ -1029,10 +1004,9 @@ impl<'a> Drop for ZipFile<'a> { match reader.read(&mut buffer) { Ok(0) => break, Ok(_) => (), - Err(e) => panic!( - "Could not consume all of the output of the current ZipFile: {:?}", - e - ), + Err(e) => { + panic!("Could not consume all of the output of the current ZipFile: {e:?}") + } } } } diff --git a/vendor/zip/src/read/stream.rs b/vendor/zip/src/read/stream.rs new file mode 100644 index 000000000..5a01b23f9 --- /dev/null +++ b/vendor/zip/src/read/stream.rs @@ -0,0 +1,372 @@ +use std::fs; +use std::io::{self, Read}; +use std::path::Path; + +use super::{ + central_header_to_zip_file_inner, read_zipfile_from_stream, spec, ZipError, ZipFile, + ZipFileData, ZipResult, +}; + +use byteorder::{LittleEndian, ReadBytesExt}; + +/// Stream decoder for zip. +#[derive(Debug)] +pub struct ZipStreamReader<R>(R); + +impl<R> ZipStreamReader<R> { + /// Create a new ZipStreamReader + pub fn new(reader: R) -> Self { + Self(reader) + } +} + +impl<R: Read> ZipStreamReader<R> { + fn parse_central_directory(&mut self) -> ZipResult<Option<ZipStreamFileMetadata>> { + // Give archive_offset and central_header_start dummy value 0, since + // they are not used in the output. + let archive_offset = 0; + let central_header_start = 0; + + // Parse central header + let signature = self.0.read_u32::<LittleEndian>()?; + if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE { + Ok(None) + } else { + central_header_to_zip_file_inner(&mut self.0, archive_offset, central_header_start) + .map(ZipStreamFileMetadata) + .map(Some) + } + } + + /// Iteraate over the stream and extract all file and their + /// metadata. + pub fn visit<V: ZipStreamVisitor>(mut self, visitor: &mut V) -> ZipResult<()> { + while let Some(mut file) = read_zipfile_from_stream(&mut self.0)? { + visitor.visit_file(&mut file)?; + } + + while let Some(metadata) = self.parse_central_directory()? { + visitor.visit_additional_metadata(&metadata)?; + } + + Ok(()) + } + + /// Extract a Zip archive into a directory, overwriting files if they + /// already exist. Paths are sanitized with [`ZipFile::enclosed_name`]. + /// + /// Extraction is not atomic; If an error is encountered, some of the files + /// may be left on disk. + pub fn extract<P: AsRef<Path>>(self, directory: P) -> ZipResult<()> { + struct Extractor<'a>(&'a Path); + impl ZipStreamVisitor for Extractor<'_> { + fn visit_file(&mut self, file: &mut ZipFile<'_>) -> ZipResult<()> { + let filepath = file + .enclosed_name() + .ok_or(ZipError::InvalidArchive("Invalid file path"))?; + + let outpath = self.0.join(filepath); + + if file.name().ends_with('/') { + fs::create_dir_all(&outpath)?; + } else { + if let Some(p) = outpath.parent() { + fs::create_dir_all(p)?; + } + let mut outfile = fs::File::create(&outpath)?; + io::copy(file, &mut outfile)?; + } + + Ok(()) + } + + #[allow(unused)] + fn visit_additional_metadata( + &mut self, + metadata: &ZipStreamFileMetadata, + ) -> ZipResult<()> { + #[cfg(unix)] + { + let filepath = metadata + .enclosed_name() + .ok_or(ZipError::InvalidArchive("Invalid file path"))?; + + let outpath = self.0.join(filepath); + + use std::os::unix::fs::PermissionsExt; + if let Some(mode) = metadata.unix_mode() { + fs::set_permissions(outpath, fs::Permissions::from_mode(mode))?; + } + } + + Ok(()) + } + } + + self.visit(&mut Extractor(directory.as_ref())) + } +} + +/// Visitor for ZipStreamReader +pub trait ZipStreamVisitor { + /// * `file` - contains the content of the file and most of the metadata, + /// except: + /// - `comment`: set to an empty string + /// - `data_start`: set to 0 + /// - `external_attributes`: `unix_mode()`: will return None + fn visit_file(&mut self, file: &mut ZipFile<'_>) -> ZipResult<()>; + + /// This function is guranteed to be called after all `visit_file`s. + /// + /// * `metadata` - Provides missing metadata in `visit_file`. + fn visit_additional_metadata(&mut self, metadata: &ZipStreamFileMetadata) -> ZipResult<()>; +} + +/// Additional metadata for the file. +#[derive(Debug)] +pub struct ZipStreamFileMetadata(ZipFileData); + +impl ZipStreamFileMetadata { + /// Get the name of the file + /// + /// # Warnings + /// + /// It is dangerous to use this name directly when extracting an archive. + /// It may contain an absolute path (`/etc/shadow`), or break out of the + /// current directory (`../runtime`). Carelessly writing to these paths + /// allows an attacker to craft a ZIP archive that will overwrite critical + /// files. + /// + /// You can use the [`ZipFile::enclosed_name`] method to validate the name + /// as a safe path. + pub fn name(&self) -> &str { + &self.0.file_name + } + + /// Get the name of the file, in the raw (internal) byte representation. + /// + /// The encoding of this data is currently undefined. + pub fn name_raw(&self) -> &[u8] { + &self.0.file_name_raw + } + + /// Rewrite the path, ignoring any path components with special meaning. + /// + /// - Absolute paths are made relative + /// - [`ParentDir`]s are ignored + /// - Truncates the filename at a NULL byte + /// + /// This is appropriate if you need to be able to extract *something* from + /// any archive, but will easily misrepresent trivial paths like + /// `foo/../bar` as `foo/bar` (instead of `bar`). Because of this, + /// [`ZipFile::enclosed_name`] is the better option in most scenarios. + /// + /// [`ParentDir`]: `Component::ParentDir` + pub fn mangled_name(&self) -> ::std::path::PathBuf { + self.0.file_name_sanitized() + } + + /// Ensure the file path is safe to use as a [`Path`]. + /// + /// - It can't contain NULL bytes + /// - It can't resolve to a path outside the current directory + /// > `foo/../bar` is fine, `foo/../../bar` is not. + /// - It can't be an absolute path + /// + /// This will read well-formed ZIP files correctly, and is resistant + /// to path-based exploits. It is recommended over + /// [`ZipFile::mangled_name`]. + pub fn enclosed_name(&self) -> Option<&Path> { + self.0.enclosed_name() + } + + /// Returns whether the file is actually a directory + pub fn is_dir(&self) -> bool { + self.name() + .chars() + .rev() + .next() + .map_or(false, |c| c == '/' || c == '\\') + } + + /// Returns whether the file is a regular file + pub fn is_file(&self) -> bool { + !self.is_dir() + } + + /// Get the comment of the file + pub fn comment(&self) -> &str { + &self.0.file_comment + } + + /// Get the starting offset of the data of the compressed file + pub fn data_start(&self) -> u64 { + self.0.data_start.load() + } + + /// Get unix mode for the file + pub fn unix_mode(&self) -> Option<u32> { + self.0.unix_mode() + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::collections::BTreeSet; + use std::io; + + struct DummyVisitor; + impl ZipStreamVisitor for DummyVisitor { + fn visit_file(&mut self, _file: &mut ZipFile<'_>) -> ZipResult<()> { + Ok(()) + } + + fn visit_additional_metadata( + &mut self, + _metadata: &ZipStreamFileMetadata, + ) -> ZipResult<()> { + Ok(()) + } + } + + #[derive(Default, Debug, Eq, PartialEq)] + struct CounterVisitor(u64, u64); + impl ZipStreamVisitor for CounterVisitor { + fn visit_file(&mut self, _file: &mut ZipFile<'_>) -> ZipResult<()> { + self.0 += 1; + Ok(()) + } + + fn visit_additional_metadata( + &mut self, + _metadata: &ZipStreamFileMetadata, + ) -> ZipResult<()> { + self.1 += 1; + Ok(()) + } + } + + #[test] + fn invalid_offset() { + ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/invalid_offset.zip" + ))) + .visit(&mut DummyVisitor) + .unwrap_err(); + } + + #[test] + fn invalid_offset2() { + ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/invalid_offset2.zip" + ))) + .visit(&mut DummyVisitor) + .unwrap_err(); + } + + #[test] + fn zip_read_streaming() { + let reader = ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/mimetype.zip" + ))); + + #[derive(Default)] + struct V { + filenames: BTreeSet<Box<str>>, + } + impl ZipStreamVisitor for V { + fn visit_file(&mut self, file: &mut ZipFile<'_>) -> ZipResult<()> { + if file.is_file() { + self.filenames.insert(file.name().into()); + } + + Ok(()) + } + fn visit_additional_metadata( + &mut self, + metadata: &ZipStreamFileMetadata, + ) -> ZipResult<()> { + if metadata.is_file() { + assert!( + self.filenames.contains(metadata.name()), + "{} is missing its file content", + metadata.name() + ); + } + + Ok(()) + } + } + + reader.visit(&mut V::default()).unwrap(); + } + + #[test] + fn file_and_dir_predicates() { + let reader = ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/files_and_dirs.zip" + ))); + + #[derive(Default)] + struct V { + filenames: BTreeSet<Box<str>>, + } + impl ZipStreamVisitor for V { + fn visit_file(&mut self, file: &mut ZipFile<'_>) -> ZipResult<()> { + let full_name = file.enclosed_name().unwrap(); + let file_name = full_name.file_name().unwrap().to_str().unwrap(); + assert!( + (file_name.starts_with("dir") && file.is_dir()) + || (file_name.starts_with("file") && file.is_file()) + ); + + if file.is_file() { + self.filenames.insert(file.name().into()); + } + + Ok(()) + } + fn visit_additional_metadata( + &mut self, + metadata: &ZipStreamFileMetadata, + ) -> ZipResult<()> { + if metadata.is_file() { + assert!( + self.filenames.contains(metadata.name()), + "{} is missing its file content", + metadata.name() + ); + } + + Ok(()) + } + } + + reader.visit(&mut V::default()).unwrap(); + } + + /// test case to ensure we don't preemptively over allocate based on the + /// declared number of files in the CDE of an invalid zip when the number of + /// files declared is more than the alleged offset in the CDE + #[test] + fn invalid_cde_number_of_files_allocation_smaller_offset() { + ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/invalid_cde_number_of_files_allocation_smaller_offset.zip" + ))) + .visit(&mut DummyVisitor) + .unwrap_err(); + } + + /// test case to ensure we don't preemptively over allocate based on the + /// declared number of files in the CDE of an invalid zip when the number of + /// files declared is less than the alleged offset in the CDE + #[test] + fn invalid_cde_number_of_files_allocation_greater_offset() { + ZipStreamReader::new(io::Cursor::new(include_bytes!( + "../../tests/data/invalid_cde_number_of_files_allocation_greater_offset.zip" + ))) + .visit(&mut DummyVisitor) + .unwrap_err(); + } +} diff --git a/vendor/zip/src/types.rs b/vendor/zip/src/types.rs index ad3a5700b..c3d0a45db 100644 --- a/vendor/zip/src/types.rs +++ b/vendor/zip/src/types.rs @@ -1,6 +1,6 @@ //! Types that specify what is contained in a ZIP. -#[cfg(feature = "time")] -use std::convert::{TryFrom, TryInto}; +use std::path; + #[cfg(not(any( all(target_arch = "arm", target_pointer_width = "32"), target_arch = "mips", @@ -12,6 +12,11 @@ use std::time::SystemTime; #[cfg(doc)] use {crate::read::ZipFile, crate::write::FileOptions}; +mod ffi { + pub const S_IFDIR: u32 = 0o0040000; + pub const S_IFREG: u32 = 0o0100000; +} + #[cfg(any( all(target_arch = "arm", target_pointer_width = "32"), target_arch = "mips", @@ -375,6 +380,48 @@ impl ZipFileData { }) } + pub(crate) fn enclosed_name(&self) -> Option<&path::Path> { + if self.file_name.contains('\0') { + return None; + } + let path = path::Path::new(&self.file_name); + let mut depth = 0usize; + for component in path.components() { + match component { + path::Component::Prefix(_) | path::Component::RootDir => return None, + path::Component::ParentDir => depth = depth.checked_sub(1)?, + path::Component::Normal(_) => depth += 1, + path::Component::CurDir => (), + } + } + Some(path) + } + + /// Get unix mode for the file + pub(crate) fn unix_mode(&self) -> Option<u32> { + if self.external_attributes == 0 { + return None; + } + + match self.system { + System::Unix => Some(self.external_attributes >> 16), + System::Dos => { + // Interpret MS-DOS directory bit + let mut mode = if 0x10 == (self.external_attributes & 0x10) { + ffi::S_IFDIR | 0o0775 + } else { + ffi::S_IFREG | 0o0664 + }; + if 0x01 == (self.external_attributes & 0x01) { + // Read-only bit; strip write permissions + mode &= 0o0555; + } + Some(mode) + } + _ => None, + } + } + pub fn zip64_extension(&self) -> bool { self.uncompressed_size > 0xFFFFFFFF || self.compressed_size > 0xFFFFFFFF @@ -510,27 +557,6 @@ mod test { #[cfg(feature = "time")] #[test] - fn datetime_from_time_bounds() { - use std::convert::TryFrom; - - use super::DateTime; - use time::macros::datetime; - - // 1979-12-31 23:59:59 - assert!(DateTime::try_from(datetime!(1979-12-31 23:59:59 UTC)).is_err()); - - // 1980-01-01 00:00:00 - assert!(DateTime::try_from(datetime!(1980-01-01 00:00:00 UTC)).is_ok()); - - // 2107-12-31 23:59:59 - assert!(DateTime::try_from(datetime!(2107-12-31 23:59:59 UTC)).is_ok()); - - // 2108-01-01 00:00:00 - assert!(DateTime::try_from(datetime!(2108-01-01 00:00:00 UTC)).is_err()); - } - - #[cfg(feature = "time")] - #[test] fn datetime_try_from_bounds() { use std::convert::TryFrom; diff --git a/vendor/zip/src/unstable.rs b/vendor/zip/src/unstable.rs new file mode 100644 index 000000000..f8b46a970 --- /dev/null +++ b/vendor/zip/src/unstable.rs @@ -0,0 +1,20 @@ +/// Provides high level API for reading from a stream. +pub mod stream { + pub use crate::read::stream::*; +} +/// Types for creating ZIP archives. +pub mod write { + use crate::write::FileOptions; + /// Unstable methods for [`FileOptions`]. + pub trait FileOptionsExt { + /// Write the file with the given password using the deprecated ZipCrypto algorithm. + /// + /// This is not recommended for new archives, as ZipCrypto is not secure. + fn with_deprecated_encryption(self, password: &[u8]) -> Self; + } + impl FileOptionsExt for FileOptions { + fn with_deprecated_encryption(self, password: &[u8]) -> Self { + self.with_deprecated_encryption(password) + } + } +}
\ No newline at end of file diff --git a/vendor/zip/src/write.rs b/vendor/zip/src/write.rs index 14252b4d5..4cdc031b0 100644 --- a/vendor/zip/src/write.rs +++ b/vendor/zip/src/write.rs @@ -29,19 +29,37 @@ use time::OffsetDateTime; #[cfg(feature = "zstd")] use zstd::stream::write::Encoder as ZstdEncoder; +enum MaybeEncrypted<W> { + Unencrypted(W), + Encrypted(crate::zipcrypto::ZipCryptoWriter<W>), +} +impl<W: Write> Write for MaybeEncrypted<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + match self { + MaybeEncrypted::Unencrypted(w) => w.write(buf), + MaybeEncrypted::Encrypted(w) => w.write(buf), + } + } + fn flush(&mut self) -> io::Result<()> { + match self { + MaybeEncrypted::Unencrypted(w) => w.flush(), + MaybeEncrypted::Encrypted(w) => w.flush(), + } + } +} enum GenericZipWriter<W: Write + io::Seek> { Closed, - Storer(W), + Storer(MaybeEncrypted<W>), #[cfg(any( feature = "deflate", feature = "deflate-miniz", feature = "deflate-zlib" ))] - Deflater(DeflateEncoder<W>), + Deflater(DeflateEncoder<MaybeEncrypted<W>>), #[cfg(feature = "bzip2")] - Bzip2(BzEncoder<W>), + Bzip2(BzEncoder<MaybeEncrypted<W>>), #[cfg(feature = "zstd")] - Zstd(ZstdEncoder<'static, W>), + Zstd(ZstdEncoder<'static, MaybeEncrypted<W>>), } // Put the struct declaration in a private module to convince rustdoc to display ZipWriter nicely pub(crate) mod zip_writer { @@ -108,6 +126,7 @@ pub struct FileOptions { last_modified_time: DateTime, permissions: Option<u32>, large_file: bool, + encrypt_with: Option<crate::zipcrypto::ZipCryptoKeys>, } impl FileOptions { @@ -171,6 +190,10 @@ impl FileOptions { self.large_file = large; self } + pub(crate) fn with_deprecated_encryption(mut self, password: &[u8]) -> FileOptions { + self.encrypt_with = Some(crate::zipcrypto::ZipCryptoKeys::derive(password)); + self + } } impl Default for FileOptions { @@ -196,6 +219,7 @@ impl Default for FileOptions { last_modified_time: DateTime::default(), permissions: None, large_file: false, + encrypt_with: None, } } } @@ -284,7 +308,7 @@ impl<A: Read + Write + io::Seek> ZipWriter<A> { let _ = readwriter.seek(io::SeekFrom::Start(directory_start)); // seek directory_start to overwrite it Ok(ZipWriter { - inner: GenericZipWriter::Storer(readwriter), + inner: GenericZipWriter::Storer(MaybeEncrypted::Unencrypted(readwriter)), files, stats: Default::default(), writing_to_file: false, @@ -302,7 +326,7 @@ impl<W: Write + io::Seek> ZipWriter<W> { /// Before writing to this object, the [`ZipWriter::start_file`] function should be called. pub fn new(inner: W) -> ZipWriter<W> { ZipWriter { - inner: GenericZipWriter::Storer(inner), + inner: GenericZipWriter::Storer(MaybeEncrypted::Unencrypted(inner)), files: Vec::new(), stats: Default::default(), writing_to_file: false, @@ -355,7 +379,7 @@ impl<W: Write + io::Seek> ZipWriter<W> { let mut file = ZipFileData { system: System::Unix, version_made_by: DEFAULT_VERSION, - encrypted: false, + encrypted: options.encrypt_with.is_some(), using_data_descriptor: false, compression_method: options.compression_method, compression_level: options.compression_level, @@ -385,7 +409,13 @@ impl<W: Write + io::Seek> ZipWriter<W> { self.files.push(file); } + if let Some(keys) = options.encrypt_with { + let mut zipwriter = crate::zipcrypto::ZipCryptoWriter { writer: core::mem::replace(&mut self.inner, GenericZipWriter::Closed).unwrap(), buffer: vec![], keys }; + let mut crypto_header = [0u8; 12]; + zipwriter.write_all(&crypto_header)?; + self.inner = GenericZipWriter::Storer(MaybeEncrypted::Encrypted(zipwriter)); + } Ok(()) } @@ -395,6 +425,14 @@ impl<W: Write + io::Seek> ZipWriter<W> { self.end_extra_data()?; } self.inner.switch_to(CompressionMethod::Stored, None)?; + match core::mem::replace(&mut self.inner, GenericZipWriter::Closed) { + GenericZipWriter::Storer(MaybeEncrypted::Encrypted(writer)) => { + let crc32 = self.stats.hasher.clone().finalize(); + self.inner = GenericZipWriter::Storer(MaybeEncrypted::Unencrypted(writer.finish(crc32)?)) + } + GenericZipWriter::Storer(w) => self.inner = GenericZipWriter::Storer(w), + _ => unreachable!() + } let writer = self.inner.get_plain(); if !self.writing_raw { @@ -699,7 +737,7 @@ impl<W: Write + io::Seek> ZipWriter<W> { /// Add a directory entry. /// - /// You can't write data to the file afterwards. + /// As directories have no content, you must not call [`ZipWriter::write`] before adding a new file. pub fn add_directory<S>(&mut self, name: S, mut options: FileOptions) -> ZipResult<()> where S: Into<String>, @@ -985,8 +1023,8 @@ impl<W: Write + io::Seek> GenericZipWriter<W> { fn get_plain(&mut self) -> &mut W { match *self { - GenericZipWriter::Storer(ref mut w) => w, - _ => panic!("Should have switched to stored beforehand"), + GenericZipWriter::Storer(MaybeEncrypted::Unencrypted(ref mut w)) => w, + _ => panic!("Should have switched to stored and unencrypted beforehand"), } } @@ -1009,8 +1047,8 @@ impl<W: Write + io::Seek> GenericZipWriter<W> { fn unwrap(self) -> W { match self { - GenericZipWriter::Storer(w) => w, - _ => panic!("Should have switched to stored beforehand"), + GenericZipWriter::Storer(MaybeEncrypted::Unencrypted(w)) => w, + _ => panic!("Should have switched to stored and unencrypted beforehand"), } } } @@ -1058,7 +1096,7 @@ fn write_local_file_header<T: Write>(writer: &mut T, file: &ZipFileData) -> ZipR 1u16 << 11 } else { 0 - }; + } | if file.encrypted { 1u16 << 0 } else { 0 }; writer.write_u16::<LittleEndian>(flag)?; // Compression method #[allow(deprecated)] @@ -1133,7 +1171,7 @@ fn write_central_directory_header<T: Write>(writer: &mut T, file: &ZipFileData) 1u16 << 11 } else { 0 - }; + } | if file.encrypted { 1u16 << 0 } else { 0 }; writer.write_u16::<LittleEndian>(flag)?; // compression method #[allow(deprecated)] @@ -1428,6 +1466,7 @@ mod test { last_modified_time: DateTime::default(), permissions: Some(33188), large_file: false, + encrypt_with: None, }; writer.start_file("mimetype", options).unwrap(); writer diff --git a/vendor/zip/src/zipcrypto.rs b/vendor/zip/src/zipcrypto.rs index 91d403951..c3696e4d7 100644 --- a/vendor/zip/src/zipcrypto.rs +++ b/vendor/zip/src/zipcrypto.rs @@ -6,7 +6,8 @@ use std::num::Wrapping; /// A container to hold the current key state -struct ZipCryptoKeys { +#[derive(Clone, Copy)] +pub(crate) struct ZipCryptoKeys { key_0: Wrapping<u32>, key_1: Wrapping<u32>, key_2: Wrapping<u32>, @@ -49,6 +50,13 @@ impl ZipCryptoKeys { fn crc32(crc: Wrapping<u32>, input: u8) -> Wrapping<u32> { (crc >> 8) ^ Wrapping(CRCTABLE[((crc & Wrapping(0xff)).0 as u8 ^ input) as usize]) } + pub(crate) fn derive(password: &[u8]) -> ZipCryptoKeys { + let mut keys = ZipCryptoKeys::new(); + for byte in password.iter() { + keys.update(*byte); + } + keys + } } /// A ZipCrypto reader with unverified password @@ -70,17 +78,10 @@ impl<R: std::io::Read> ZipCryptoReader<R> { /// would be impossible to decrypt files that were encrypted with a /// password byte sequence that is unrepresentable in UTF-8. pub fn new(file: R, password: &[u8]) -> ZipCryptoReader<R> { - let mut result = ZipCryptoReader { + ZipCryptoReader { file, - keys: ZipCryptoKeys::new(), - }; - - // Key the cipher by updating the keys with the password. - for byte in password.iter() { - result.keys.update(*byte); + keys: ZipCryptoKeys::derive(password), } - - result } /// Read the ZipCrypto header bytes and validate the password. @@ -122,6 +123,31 @@ impl<R: std::io::Read> ZipCryptoReader<R> { Ok(Some(ZipCryptoReaderValid { reader: self })) } } +pub(crate) struct ZipCryptoWriter<W> { + pub(crate) writer: W, + pub(crate) buffer: Vec<u8>, + pub(crate) keys: ZipCryptoKeys, +} +impl<W: std::io::Write> ZipCryptoWriter<W> { + pub(crate) fn finish(mut self, crc32: u32) -> std::io::Result<W> { + self.buffer[11] = (crc32 >> 24) as u8; + for byte in self.buffer.iter_mut() { + *byte = self.keys.encrypt_byte(*byte); + } + self.writer.write_all(&self.buffer)?; + self.writer.flush()?; + Ok(self.writer) + } +} +impl<W: std::io::Write> std::io::Write for ZipCryptoWriter<W> { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + self.buffer.extend_from_slice(buf); + Ok(buf.len()) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} /// A ZipCrypto reader with verified password pub struct ZipCryptoReaderValid<R> { diff --git a/vendor/zip/tests/issue_234.rs b/vendor/zip/tests/issue_234.rs index bd01d1d08..f8c1d2c81 100644 --- a/vendor/zip/tests/issue_234.rs +++ b/vendor/zip/tests/issue_234.rs @@ -26,6 +26,6 @@ fn invalid_header() { let archive = zip::ZipArchive::new(reader); match archive { Err(ZipError::InvalidArchive(_)) => {} - value => panic!("Unexpected value: {:?}", value), + value => panic!("Unexpected value: {value:?}"), } } diff --git a/vendor/zip/tests/zip_crypto.rs b/vendor/zip/tests/zip_crypto.rs index 6c4d6b811..d831c1e62 100644 --- a/vendor/zip/tests/zip_crypto.rs +++ b/vendor/zip/tests/zip_crypto.rs @@ -21,6 +21,23 @@ use std::io::Cursor; use std::io::Read; #[test] +fn encrypting_file() { + use zip::unstable::write::FileOptionsExt; + use std::io::{Read, Write}; + let mut buf = vec![0; 2048]; + let mut archive = zip::write::ZipWriter::new(std::io::Cursor::new(&mut buf)); + archive.start_file("name", zip::write::FileOptions::default().with_deprecated_encryption(b"password")).unwrap(); + archive.write_all(b"test").unwrap(); + archive.finish().unwrap(); + drop(archive); + let mut archive = zip::ZipArchive::new(std::io::Cursor::new(&mut buf)).unwrap(); + let mut file = archive.by_index_decrypt(0, b"password").unwrap().unwrap(); + let mut buf = Vec::new(); + file.read_to_end(&mut buf).unwrap(); + assert_eq!(buf, b"test"); + +} +#[test] fn encrypted_file() { let zip_file_bytes = &mut Cursor::new(vec![ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x54, 0xbd, 0xb5, 0x50, 0x2f, |