pax_global_header 0000666 0000000 0000000 00000000064 13576501616 0014524 g ustar 00root root 0000000 0000000 52 comment=1ca1244c2028c47aabcbd836436a7bbb53ef6015
zip4j-2.2.8/ 0000775 0000000 0000000 00000000000 13576501616 0012575 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/.gitignore 0000664 0000000 0000000 00000000037 13576501616 0014565 0 ustar 00root root 0000000 0000000 .idea/
target/
*.iml
.DS_Store
zip4j-2.2.8/.travis.yml 0000664 0000000 0000000 00000000074 13576501616 0014707 0 ustar 00root root 0000000 0000000 language: java
script:
- travis_wait 30 mvn clean verify
zip4j-2.2.8/LICENSE 0000664 0000000 0000000 00000026135 13576501616 0013611 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
zip4j-2.2.8/README.md 0000664 0000000 0000000 00000051252 13576501616 0014061 0 ustar 00root root 0000000 0000000
[](https://travis-ci.org/srikanth-lingala/zip4j)
[](https://maven-badges.herokuapp.com/maven-central/net.lingala.zip4j/zip4j)
[](https://snyk.io//test/github/srikanth-lingala/zip4j?targetFile=pom.xml)
Zip4j - A java library for zip files / streams
=========================
## Thank you
for rating Zip4j as the best java library for zip files [[1][1], [2][2], [3][3], [4][4]]. It has encouraged me to
bring this project to life again after a gap of several years. I tried to add some of the important features that
were requested over this time, and also made api much more neater. The newer version (> 2.0.0) now supports streams,
which was understandably, one of the most requested feature. If you have any feedback, bugs to report, feature
requests, etc, please open an issue here on github. I will try to address them as soon as I can. I also monitor the
tag `zip4j` on [stackoverflow][10].
## About
Zip4j is the most comprehensive java library for Zip files or streams. As of this writing, it is the only java library
which has support for zip encryption, apart from several other features. It tries to make handling zip files/streams
a lot more easier. No more clunky boiler plate code with input streams and output streams. As you can see in the usage
section below, working with zip files can now even be a single line of code, compared to [this][5]. I mean no offense
to the Java's in-built zip support. In fact, this library depends on Java's in-built zip code and it would have been
significantly more ~~complicated~~ challenging if I had to write compression logic as well. But lets be honest, working with zip
files or streams can be a lot of boiler plate code. The main goal of this library is to provide a simple api for all
usual actions of a zip file or streams by doing the heavy lifting within the library and not have developers worry about
having to deal with streams, etc. Apart from usability, other important goal of this library is to provide support for
as many zip features as possible, which brings me to:
## Features
~~~
* Create, Add, Extract, Update, Remove files from a Zip file
* Support for streams (ZipInputStream and ZipOutputStream)
* Read/Write password protected Zip files and streams
* Support for both AES and Zip-Standard encryption methods
* Support for Zip64 format
* Store (No Compression) and Deflate compression method
* Create or extract files from Split Zip files (Ex: z01, z02,...zip)
* Support for Unicode file names and comments in zip
* Progress Monitor - for integration into apps and user facing applications
~~~
## Background
Zip4j was started by me (Srikanth Reddy Lingala) back in 2008/2009, when I realized the lack of support for majority of zip format
features in Java. And also working with zip files was, as mentioned several times above, a lot of boiler plate code,
having to deal with streams (worse still, it was back in the days when there was no try-with-resources in java). There
was also no comprehensive library which supports zip features. So, I decided to write one, and approximately after a
year, the first version was out. The response was truly overwhelming, and I got a lot of support right from the next
day of release. It was not put on github as git/github was not as popular as it is now. Code was hosted on my website,
as, guess what, a zip file :). And unfortunately, after a year or two after the initial release, life got busy and I was
not able to support Zip4j as much as I wanted to. But the overwhelming encouragement I got over the years made me start working on Zip4j
once again, and makes me support Zip4j as much as I can.
## Maven
~~~~
net.lingala.zip4j
zip4j
2.2.8
~~~~
Please check the latest version number on [Zip4j's Maven repository][6]
## Usage
### Creating a zip file with single file in it / Adding single file to an existing zip
~~~~
new ZipFile("filename.zip").addFile("filename.ext");
~~~~
Or
~~~~
new ZipFile("filename.zip").addFile(new File("filename.ext"));
~~~~
### Creating a zip file with multiple files / Adding multiple files to an existing zip
~~~~
new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));
~~~~
### Creating a zip file by adding a folder to it / Adding a folder to an existing zip
~~~~
new ZipFile("filename.zip").addFolder(new File("/user/myuser/folder_to_add"));
~~~~
### Creating a zip file from stream / Adding a stream to an existing zip
~~~~
new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());
~~~~
Passing in `new ZipParameters()`, as in the above example, will make Zip4j use default zip parameters. Please look at
[ZipParameters][7] to see the default configuration.
### Creating a zip file of compression method store / Adding entries to zip file of compression method store
By default Zip4j uses Deflate compression algorithm to compress files. However, if you would like to not use any
compression (called STORE compression), you can do so as shown in the example below:
~~~~
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
new ZipFile("filename.zip").addFile("fileToAdd", zipParameters);
~~~~
You can similarly pass in zip parameters to all the other examples to create a zip file of STORE compression.
### Creating a password protected zip file / Adding files to an existing zip with password protection
##### AES encryption
~~~~
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
// Below line is optional. AES 256 is used by default. You can override it to use AES 128. AES 192 is supported only for extracting.
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
List filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip", "password".toCharArray());
zipFile.addFiles(filesToAdd, zipParameters);
~~~~
##### Zip Standard encryption:
Instead of AES, replace `zipParameters.setEncryptionMethod(EncryptionMethod.AES);` with
`zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);`. You can omit the line to set Aes Key strength. As
the name suggests, this is only applicable for AES encryption.
In all the above examples, you can similarly pass in zip parameters with appropriate password configuration to create
a password protected zip file
### Creating a split zip file
If you want to split the zip file over several files when the size exceeds a particular limit, you can do so like this:
~~~~
List filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip");
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, 10485760); // using 10MB in this example
~~~~
Passing in `new ZipParameters()`, as in the above example, will make Zip4j use default zip parameters. Please look at
[ZipParameters][7] to see the default configuration.
Zip file format specifies a minimum of 65536 bytes (64kb) as a minimum length for split files. Zip4j will throw an
exception if anything less than this value is specified.
To create a split zip with password protection, pass in appropriate ZipParameters as shown in the example below:
~~~~
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
List filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip", "password".toCharArray());
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, 10485760); // using 10MB in this example
~~~~
### Zip64 format
Zip64 is a zip feature which allows support for zip files when the size of the zip file exceeds the maximum that can be
stored in 4 bytes (i.e., greater than 4,294,967,295 bytes). Traditionally, zip headers have a provision of 4 bytes to store
for file sizes. But with growing file sizes compared to a few decades back, zip file format extended support of file
sizes which extends 4 bytes by adding additional headers which uses 8 bytes for file sizes (compressed and
uncompressed file sizes). This feature is known as Zip64.
Zip4j will automatically make a zip file a Zip64 format and add appropriate headers, when it detects the zip file to be
crossing this file size limit. You do not have to explicitly specify any flag for Zip4j to use this feature.
### Extracting All files in a zip
~~~~
new ZipFile("filename.zip").extractAll("/destination_directory");
~~~~
### Extracting All files in a password protected zip
~~~~
new ZipFile("filename.zip", "password".toCharArray()).extractAll("/destination_directory");
~~~~
### Extracting a single file from zip
~~~~
new ZipFile("filename.zip").extractFile("fileNameInZip.txt", "/destination_directory");
~~~~
### Extracting a single file from zip which is password protected
~~~~
new ZipFile("filename.zip", "password".toCharArray()).extractFile("fileNameInZip.txt", "/destination_directory");
~~~~
### Extracting a single file from zip and giving it a new file name
Below example will extract the file `fileNameInZip.txt` from the zip file to the output directory `/destination_directory`
and will give the file a name `newfileName.txt`. Without the third parameter of the new file name, the same name as the
file in the zip will be used, which in this case is `fileNameInZip.txt`
~~~~
new ZipFile("filename.zip", "password".toCharArray()).extractFile("fileNameInZip.txt", "/destination_directory", "newfileName.txt");
~~~~
### Get an input stream for an entry in a zip file
~~~~
ZipFile zipFile = new ZipFile("filename.zip");
FileHeader fileHeader = zipFile.getFileHeader("entry_name_in_zip.txt");
InputStream inputStream = zipFile.getInputStream(fileHeader);
~~~~
You can now use this input stream to read content from it/write content to an output stream. Please note that the
entry/file name is relative to the directory it is in. If `entry_name_in_zip.txt` is in a folder called "root_folder" in
the zip, then you can use `zipFile.getFileHeader("root_folder/entry_name_in_zip.txt");`
### Remove a file/entry from a zip file
~~~~
new ZipFile("filename.zip").removeFile("fileNameInZipToRemove");
~~~~
Please note that the file name is relative the root folder in zip. That is, if the file you want to remove exists in a
folder called "folder1", which in-turn exists in a folder called "root-folder", removing this file from zip can be done
as below:
~~~~
new ZipFile("filename.zip").removeFile("root-folder/folder1/fileNameInZipToRemove");
~~~~
If you want to be sure that the file you want to remove exists in zip file or if you don't want to deal with file names
as string when dealing `removeFile` api, you can use the other overloaded method which takes in a `FileHeader`:
~~~~
ZipFile zipFile = new ZipFile("someZip.zip");
FileHeader fileHeader = zipFile.getFileHeader("fileNameInZipToRemove");
if (fileHeader == null) {
// file does not exist
}
zipFile.removeFile(fileHeader);
~~~~
### Merging split zip files into a single zip
This is the reverse of creating a split zip file, that is, this feature will merge a zip file which is split across
several files into a single zip file
~~~~
new ZipFile("split_zip_file.zip").mergeZipFile("merged_zip_file.zip");
~~~~
This method will throw an exception if the split zip file (in this case `split_zip_file.zip`) is not a split zip file
### List all files in a zip
~~~~
List fileHeaders = new ZipFile("zipfile.zip").getFileHeaders();
fileHeaders.stream().forEach(fileHeader -> System.out.println(fileHeader.getFileName()));
~~~~
You can get all other information from the `FileHeader` object corresponding to each file/entry in the zip.
### Check if a zip file is password protected
~~~~
new ZipFile("encrypted_zip_file.zip").isEncrypted();
~~~~
### Check if a zip file is a split zip file
~~~~
new ZipFile("split_zip_file.zip").isSplitArchive();
~~~~
### Set comment for a zip file
~~~~
new ZipFile("some_zip_file.zip").setComment("Some comment");
~~~~
### Remove comment of a zip file
~~~~
new ZipFile("some_zip_file.zip").setComment("");
~~~~
### Get comment of a zip file
~~~~
new ZipFile("some_zip_file.zip").getComment();
~~~~
### Check if a zip file is valid
Note: This will only check for the validity of the headers and not the validity of each entry in the zip file.
~~~~
new ZipFile("valid_zip_file.zip").isValidZipFile();
~~~~
## Working with streams
### Adding entries with ZipOutputStream
~~~~
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class ZipOutputStreamExample {
public void zipOutputStreamExample(File outputZipFile, List filesToAdd, char[] password,
CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength)
throws IOException {
ZipParameters zipParameters = buildZipParameters(compressionMethod, encrypt, encryptionMethod, aesKeyStrength);
byte[] buff = new byte[4096];
int readLen;
try(ZipOutputStream zos = initializeZipOutputStream(outputZipFile, encrypt, password)) {
for (File fileToAdd : filesToAdd) {
// Entry size has to be set if you want to add entries of STORE compression method (no compression)
// This is not required for deflate compression
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
zipParameters.setEntrySize(fileToAdd.length());
}
zipParameters.setFileNameInZip(fileToAdd.getName());
zos.putNextEntry(zipParameters);
try(InputStream inputStream = new FileInputStream(fileToAdd)) {
while ((readLen = inputStream.read(buff)) != -1) {
zos.write(buff, 0, readLen);
}
}
zos.closeEntry();
}
}
}
private ZipOutputStream initializeZipOutputStream(File outputZipFile, boolean encrypt, char[] password)
throws IOException {
FileOutputStream fos = new FileOutputStream(outputZipFile);
if (encrypt) {
return new ZipOutputStream(fos, password);
}
return new ZipOutputStream(fos);
}
private ZipParameters buildZipParameters(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(compressionMethod);
zipParameters.setEncryptionMethod(encryptionMethod);
zipParameters.setAesKeyStrength(aesKeyStrength);
zipParameters.setEncryptFiles(encrypt);
return zipParameters;
}
}
~~~~
### Extract files with ZipInputStream
~~~~
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ZipInputStreamExample {
public void extractWithZipInputStream(File zipFile, char[] password) throws IOException {
LocalFileHeader localFileHeader;
int readLen;
byte[] readBuffer = new byte[4096];
try (FileInputStream fileInputStream = new FileInputStream(zipFile);
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, password)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
File extractedFile = new File(localFileHeader.getFileName());
try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
}
}
}
}
~~~~
## Working with Progress Monitor
ProgressMonitor makes it easier for applications (especially user facing) to integrate Zip4j. It is useful to show
progress (example: updating a progress bar, displaying the current action, show file name being worked on, etc). To use
ProgressMonitor, you have to set `ZipFile.setRunInThread(true)`. This will make any actions being done on the zip file
to run in a background thread. You can then access ProgressMonitor `Zipfile.getProgressMonitor()` and get details of the
current action being done along with the percentage work done, etc. Below is an example:
~~~
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
zipFile.setRunInThread(true);
zipFile.addFolder("/some/folder");
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
System.out.println("Percentage done: " + progressMonitor.getPercentDone());
System.out.println("Current file: " + progressMonitor.getFileName());
System.out.println("Current task: " + progressMonitor.getCurrentTask());
Thread.sleep(100);
}
~~~
Note that in the above example, `addFolder()` will almost immediately return back the control to the caller. The client
code can then perform a loop until the state gets back to "Ready" as shown in the above example.
Similarly, ProgressMonitor can be used with other actions like, `addFiles`, `removeFiles` and `extractFiles`.
## Contribution
It is hard to find as much free time as I used to have when I first started Zip4j 10 years back in 2009. I would
highly appreciate any support I can get for this project. You can fork this project, and send me pull requests for
any bug fixes, issues mentioned here or new features. If you need any support in understanding the code or zip specification,
just drop me a mail and I will help you as best as I can. (See FAQ for my email id.)
## FAQ
1. **Why do I have to pass in password as char array and not as a string?**
[That's why][8]
2. **How can I contact you?**
srikanth.mailbox@gmail.com
3. **Are unicode file names supported?**
Yes, unicode file names (UTF-8) are supported as specified by the zip format specification. Zip4j will use utf-8 file
name and file comment encoding when creating a zip file. When extracting a zip file, Zip4j will only use utf-8 encoding,
only if the appropriate header flag is set as specified by zip file format specification. If this flag is not set,
Zip4j will use Cp437 encoding which only supports English alphabetical characters.
4. **Where can I find Zip file format specification?**
[Here][9]
5. **Why are there so many changes in version 2.x compared to 1.x?**
Because 1.x was written about 10 years back, Zip4j was badly in need of a face-lift and code modernization. Also, my
coding standards have also improved over the years (or at least that's what I like to think). Although I am proud of
the work I did with Zip4j 10 years back, some parts of the code make me feel like hiding my face in shame. One such example
is the usage of `ArrayList` instead of `List`. Api and code should look much neater now. And also, Zip4j now supports
a minimum of JRE 8, as compared to JRE 5 with 1.x, which obviously will bring some nice features that I can make use of. (For
example: no more explicitly closing the streams all over the code). If you still feel like something can be improved (and
I am pretty sure that there are things to be improved), please let me know by opening an issue here or writing to me
(My email id is in point #2 above).
[1]: https://stackoverflow.com/questions/9324933/what-is-a-good-java-library-to-zip-unzip-files
[2]: https://stackoverflow.com/questions/5362364/java-library-to-work-with-zip-files
[3]: https://stackoverflow.com/questions/166340/recommendations-on-a-free-library-to-be-used-for-zipping-files
[4]: https://stackoverflow.com/questions/18201279/file-compression-library-for-java/18201553
[5]: https://www.baeldung.com/java-compress-and-uncompress
[6]: https://mvnrepository.com/artifact/net.lingala.zip4j/zip4j
[7]: https://github.com/srikanth-lingala/zip4j/blob/master/src/main/java/net/lingala/zip4j/model/ZipParameters.java
[8]: https://www.baeldung.com/java-storing-passwords
[9]: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
[10]: https://stackoverflow.com/questions/tagged/zip4j
zip4j-2.2.8/pom.xml 0000664 0000000 0000000 00000014572 13576501616 0014123 0 ustar 00root root 0000000 0000000
4.0.0
net.lingala.zip4j
zip4j
2.2.9-SNAPSHOT
Zip4j
Zip4j - A Java library for zip files and streams
https://github.com/srikanth-lingala/zip4j
git@github.com:srikanth-lingala/zip4j.git
Srikanth Reddy Lingala
srikanth.mailbox@gmail.com
Apache License, Version 2.0
https://www.apache.org/licenses/LICENSE-2.0.txt
1.8
1.8
4.12
1.18.8
3.12.2
2.28.2
2.0.2
UTF-8
ossrh
https://oss.sonatype.org/content/repositories/snapshots
ossrh
https://oss.sonatype.org/service/local/staging/deploy/maven2/
junit
junit
${junit.version}
test
org.assertj
assertj-core
${assertj.version}
test
org.mockito
mockito-core
${mockito.version}
test
org.powermock
powermock-module-junit4
${powermock.version}
test
org.powermock
powermock-api-mockito2
${powermock.version}
test
src/main/java
org.apache.maven.plugins
maven-failsafe-plugin
3.0.0-M3
integration-test
verify
org.apache.maven.plugins
maven-source-plugin
2.2.1
attach-sources
deploy
jar-no-fork
org.apache.maven.plugins
maven-javadoc-plugin
2.9.1
attach-javadocs
deploy
jar
org.apache.maven.plugins
maven-gpg-plugin
1.5
sign-artifacts
deploy
sign
org.sonatype.plugins
nexus-staging-maven-plugin
1.6.8
true
ossrh
https://oss.sonatype.org/
true
org.apache.felix
maven-bundle-plugin
true
net.lingala.zip4j.*
bundle-manifest
package
bundle
zip4j-2.2.8/src/ 0000775 0000000 0000000 00000000000 13576501616 0013364 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/ 0000775 0000000 0000000 00000000000 13576501616 0014310 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/ 0000775 0000000 0000000 00000000000 13576501616 0015231 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/ 0000775 0000000 0000000 00000000000 13576501616 0016017 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/ 0000775 0000000 0000000 00000000000 13576501616 0017426 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/ 0000775 0000000 0000000 00000000000 13576501616 0020466 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/ZipFile.java 0000775 0000000 0000000 00000072227 13576501616 0022710 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderReader;
import net.lingala.zip4j.headers.HeaderUtil;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.AddFilesToZipTask;
import net.lingala.zip4j.tasks.AddFilesToZipTask.AddFilesToZipTaskParameters;
import net.lingala.zip4j.tasks.AddFolderToZipTask;
import net.lingala.zip4j.tasks.AddFolderToZipTask.AddFolderToZipTaskParameters;
import net.lingala.zip4j.tasks.AddStreamToZipTask;
import net.lingala.zip4j.tasks.AddStreamToZipTask.AddStreamToZipTaskParameters;
import net.lingala.zip4j.tasks.ExtractAllFilesTask;
import net.lingala.zip4j.tasks.ExtractAllFilesTask.ExtractAllFilesTaskParameters;
import net.lingala.zip4j.tasks.ExtractFileTask;
import net.lingala.zip4j.tasks.ExtractFileTask.ExtractFileTaskParameters;
import net.lingala.zip4j.tasks.MergeSplitZipFileTask;
import net.lingala.zip4j.tasks.MergeSplitZipFileTask.MergeSplitZipFileTaskParameters;
import net.lingala.zip4j.tasks.RemoveEntryFromZipFileTask;
import net.lingala.zip4j.tasks.RemoveEntryFromZipFileTask.RemoveEntryFromZipFileTaskParameters;
import net.lingala.zip4j.tasks.SetCommentTask;
import net.lingala.zip4j.tasks.SetCommentTask.SetCommentTaskTaskParameters;
import net.lingala.zip4j.util.FileUtils;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import static net.lingala.zip4j.util.FileUtils.assertFilesExist;
import static net.lingala.zip4j.util.InternalZipConstants.CHARSET_UTF_8;
import static net.lingala.zip4j.util.UnzipUtil.createZipInputStream;
import static net.lingala.zip4j.util.Zip4jUtil.isStringNotNullAndNotEmpty;
/**
* Base class to handle zip files. Some of the operations supported
* in this class are:
*
* - Create Zip File
* - Add files to zip file
* - Add folder to zip file
* - Extract files from zip files
* - Remove files from zip file
*
*/
public class ZipFile {
private File zipFile;
private ZipModel zipModel;
private boolean isEncrypted;
private ProgressMonitor progressMonitor;
private boolean runInThread;
private char[] password;
private HeaderWriter headerWriter = new HeaderWriter();
private Charset charset = CHARSET_UTF_8;
/**
* Creates a new ZipFile instance with the zip file at the location specified in zipFile.
* This constructor does not yet create a zip file if it does not exist. Creation happens when adding files
* to this ZipFile instance
* @param zipFile
*/
public ZipFile(String zipFile) {
this(new File(zipFile), null);
}
/**
* Creates a new ZipFile instance with the zip file at the location specified in zipFile.
* Input password will be used for any zip operations like adding files or extracting files.
* This constructor does not yet create a zip file if it does not exist. Creation happens when adding files
* to this ZipFile instance
* @param zipFile
*/
public ZipFile(String zipFile, char[] password) {
this(new File(zipFile), password);
}
/**
* Creates a new Zip File Object with the input file.
* If the zip file does not exist, it is not created at this point.
*
* @param zipFile
*/
public ZipFile(File zipFile) {
this(zipFile, null);
}
public ZipFile(File zipFile, char[] password) {
this.zipFile = zipFile;
this.password = password;
this.runInThread = false;
this.progressMonitor = new ProgressMonitor();
}
/**
* Creates a zip file and adds the list of source file(s) to the zip file. If the zip file
* exists then this method throws an exception. Parameters such as compression type, etc
* can be set in the input parameters. While the method addFile/addFiles also creates the
* zip file if it does not exist, the main functionality of this method is to create a split
* zip file. To create a split zip file, set the splitArchive parameter to true with a valid
* splitLength. Split Length has to be more than 65536 bytes
*
* @param filesToAdd - File to be added to the zip file
* @param parameters - zip parameters for this file list
* @param splitArchive - if archive has to be split or not
* @param splitLength - if archive has to be split, then length in bytes at which it has to be split
* @throws ZipException
*/
public void createSplitZipFile(List filesToAdd, ZipParameters parameters, boolean splitArchive,
long splitLength) throws ZipException {
if (zipFile.exists()) {
throw new ZipException("zip file: " + zipFile
+ " already exists. To add files to existing zip file use addFile method");
}
if (filesToAdd == null || filesToAdd.size() == 0) {
throw new ZipException("input file List is null, cannot create zip file");
}
createNewZipModel();
zipModel.setSplitArchive(splitArchive);
zipModel.setSplitLength(splitLength);
new AddFilesToZipTask(progressMonitor, runInThread, zipModel, password, headerWriter).execute(
new AddFilesToZipTaskParameters(filesToAdd, parameters, charset));
}
/**
* Creates a zip file and adds the files/folders from the specified folder to the zip file.
* This method does the same functionality as in addFolder method except that this method
* can also create split zip files when adding a folder. To create a split zip file, set the
* splitArchive parameter to true and specify the splitLength. Split length has to be more than
* or equal to 65536 bytes. Note that this method throws an exception if the zip file already
* exists.
*
* @param folderToAdd
* @param parameters
* @param splitArchive
* @param splitLength
* @throws ZipException
*/
public void createSplitZipFileFromFolder(File folderToAdd, ZipParameters parameters, boolean splitArchive,
long splitLength) throws ZipException {
if (folderToAdd == null) {
throw new ZipException("folderToAdd is null, cannot create zip file from folder");
}
if (parameters == null) {
throw new ZipException("input parameters are null, cannot create zip file from folder");
}
if (zipFile.exists()) {
throw new ZipException("zip file: " + zipFile
+ " already exists. To add files to existing zip file use addFolder method");
}
createNewZipModel();
zipModel.setSplitArchive(splitArchive);
if (splitArchive) {
zipModel.setSplitLength(splitLength);
}
addFolder(folderToAdd, parameters, false);
}
/**
* Adds input source file to the zip file with default zip parameters. If zip file does not exist,
* this method creates a new zip file.
*
* @param fileToAdd - File with path to be added to the zip file
* @throws ZipException
*/
public void addFile(String fileToAdd) throws ZipException {
addFile(fileToAdd, new ZipParameters());
}
/**
* Adds input source file to the zip file with provided zip parameters. If zip file does not exist,
* this method creates a new zip file.
*
* @param fileToAdd - File with path to be added to the zip file
* @param zipParameters - parameters for the entry to be added to zip
* @throws ZipException
*/
public void addFile(String fileToAdd, ZipParameters zipParameters) throws ZipException {
if (!isStringNotNullAndNotEmpty(fileToAdd)) {
throw new ZipException("file to add is null or empty");
}
addFiles(Collections.singletonList(new File(fileToAdd)), zipParameters);
}
/**
* Adds input source file to the zip file with default zip parameters. If zip file does not exist,
* this method creates a new zip file.
*
* @param fileToAdd - File to be added to the zip file
* @throws ZipException
*/
public void addFile(File fileToAdd) throws ZipException {
addFiles(Collections.singletonList(fileToAdd), new ZipParameters());
}
/**
* Adds input source file to the zip file. If zip file does not exist,
* this method creates a new zip file. Parameters such as compression type, etc
* can be set in the input parameters.
*
* @param fileToAdd - File to be added to the zip file
* @param parameters - zip parameters for this file
* @throws ZipException
*/
public void addFile(File fileToAdd, ZipParameters parameters) throws ZipException {
addFiles(Collections.singletonList(fileToAdd), parameters);
}
/**
* Adds the list of input files to the zip file with default zip parameters. If zip file does not exist,
* this method creates a new zip file.
*
* @param filesToAdd
* @throws ZipException
*/
public void addFiles(List filesToAdd) throws ZipException {
addFiles(filesToAdd, new ZipParameters());
}
/**
* Adds the list of input files to the zip file. If zip file does not exist, then
* this method creates a new zip file. Parameters such as compression type, etc
* can be set in the input parameters.
*
* @param filesToAdd
* @param parameters
* @throws ZipException
*/
public void addFiles(List filesToAdd, ZipParameters parameters) throws ZipException {
if (filesToAdd == null || filesToAdd.size() == 0) {
throw new ZipException("input file List is null or empty");
}
if (parameters == null) {
throw new ZipException("input parameters are null");
}
if (progressMonitor.getState() == ProgressMonitor.State.BUSY) {
throw new ZipException("invalid operation - Zip4j is in busy state");
}
assertFilesExist(filesToAdd);
readZipInfo();
if (zipModel == null) {
throw new ZipException("internal error: zip model is null");
}
if (zipFile.exists() && zipModel.isSplitArchive()) {
throw new ZipException("Zip file already exists. Zip file format does not allow updating split/spanned files");
}
new AddFilesToZipTask(progressMonitor, runInThread, zipModel, password, headerWriter).execute(
new AddFilesToZipTaskParameters(filesToAdd, parameters, charset));
}
/**
* Adds the folder in the given file object to the zip file with default zip parameters. If zip file does not exist,
* then a new zip file is created. If input folder is invalid then an exception
* is thrown.
*
* @param folderToAdd
* @throws ZipException
*/
public void addFolder(File folderToAdd) throws ZipException {
addFolder(folderToAdd, new ZipParameters());
}
/**
* Adds the folder in the given file object to the zip file. If zip file does not exist,
* then a new zip file is created. If input folder is invalid then an exception
* is thrown. Zip parameters for the files in the folder to be added can be set in
* the input parameters
*
* @param folderToAdd
* @param zipParameters
* @throws ZipException
*/
public void addFolder(File folderToAdd, ZipParameters zipParameters) throws ZipException {
if (folderToAdd == null) {
throw new ZipException("input path is null, cannot add folder to zip file");
}
if (!folderToAdd.exists()) {
throw new ZipException("folder does not exist");
}
if (!folderToAdd.isDirectory()) {
throw new ZipException("input folder is not a directory");
}
if (!folderToAdd.canRead()) {
throw new ZipException("cannot read input folder");
}
if (zipParameters == null) {
throw new ZipException("input parameters are null, cannot add folder to zip file");
}
addFolder(folderToAdd, zipParameters, true);
}
/**
* Internal method to add a folder to the zip file.
*
* @param folderToAdd
* @param zipParameters
* @param checkSplitArchive
* @throws ZipException
*/
private void addFolder(File folderToAdd, ZipParameters zipParameters, boolean checkSplitArchive) throws ZipException {
readZipInfo();
if (zipModel == null) {
throw new ZipException("internal error: zip model is null");
}
if (checkSplitArchive) {
if (zipModel.isSplitArchive()) {
throw new ZipException("This is a split archive. Zip file format does not allow updating split/spanned files");
}
}
new AddFolderToZipTask(progressMonitor, runInThread, zipModel, password, headerWriter).execute(
new AddFolderToZipTaskParameters(folderToAdd, zipParameters, charset));
}
/**
* Creates a new entry in the zip file and adds the content of the input stream to the
* zip file. ZipParameters.isSourceExternalStream and ZipParameters.fileNameInZip have to be
* set before in the input parameters. If the file name ends with / or \, this method treats the
* content as a directory. Setting the flag ProgressMonitor.setRunInThread to true will have
* no effect for this method and hence this method cannot be used to add content to zip in
* thread mode
*
* @param inputStream
* @param parameters
* @throws ZipException
*/
public void addStream(InputStream inputStream, ZipParameters parameters) throws ZipException {
if (inputStream == null) {
throw new ZipException("inputstream is null, cannot add file to zip");
}
if (parameters == null) {
throw new ZipException("zip parameters are null");
}
this.setRunInThread(false);
readZipInfo();
if (zipModel == null) {
throw new ZipException("internal error: zip model is null");
}
if (zipFile.exists() && zipModel.isSplitArchive()) {
throw new ZipException("Zip file already exists. Zip file format does not allow updating split/spanned files");
}
new AddStreamToZipTask(progressMonitor, runInThread, zipModel, password, headerWriter).execute(
new AddStreamToZipTaskParameters(inputStream, parameters, charset));
}
/**
* Extracts all the files in the given zip file to the input destination path.
* If zip file does not exist or destination path is invalid then an
* exception is thrown.
*
* @param destinationPath
* @throws ZipException
*/
public void extractAll(String destinationPath) throws ZipException {
if (!isStringNotNullAndNotEmpty(destinationPath)) {
throw new ZipException("output path is null or invalid");
}
if (!Zip4jUtil.createDirectoryIfNotExists(new File(destinationPath))) {
throw new ZipException("invalid output path");
}
if (zipModel == null) {
readZipInfo();
}
// Throw an exception if zipModel is still null
if (zipModel == null) {
throw new ZipException("Internal error occurred when extracting zip file");
}
if (progressMonitor.getState() == ProgressMonitor.State.BUSY) {
throw new ZipException("invalid operation - Zip4j is in busy state");
}
new ExtractAllFilesTask(progressMonitor, runInThread, zipModel, password).execute(
new ExtractAllFilesTaskParameters(destinationPath, charset));
}
/**
* Extracts a specific file from the zip file to the destination path.
* If destination path is invalid, then this method throws an exception.
*
* If newFileName is not null or empty, newly created file name will be replaced by
* the value in newFileName. If this value is null, then the file name will be the
* value in FileHeader.getFileName
*
* @param fileHeader
* @param destinationPath
* @throws ZipException
*/
public void extractFile(FileHeader fileHeader, String destinationPath) throws ZipException {
extractFile(fileHeader, destinationPath, null);
}
/**
* Extracts a specific file from the zip file to the destination path.
* If destination path is invalid, then this method throws an exception.
*
* @param fileHeader
* @param destinationPath
* @param newFileName
* @throws ZipException
*/
public void extractFile(FileHeader fileHeader, String destinationPath, String newFileName) throws ZipException {
if (fileHeader == null) {
throw new ZipException("input file header is null, cannot extract file");
}
if (!isStringNotNullAndNotEmpty(destinationPath)) {
throw new ZipException("destination path is empty or null, cannot extract file");
}
if (progressMonitor.getState() == ProgressMonitor.State.BUSY) {
throw new ZipException("invalid operation - Zip4j is in busy state");
}
readZipInfo();
new ExtractFileTask(progressMonitor, runInThread, zipModel, password).execute(
new ExtractFileTaskParameters(destinationPath, fileHeader, newFileName, charset));
}
/**
* Extracts a specific file from the zip file to the destination path.
* This method first finds the necessary file header from the input file name.
*
* File name is relative file name in the zip file. For example if a zip file contains
* a file "a.txt", then to extract this file, input file name has to be "a.txt". Another
* example is if there is a file "b.txt" in a folder "abc" in the zip file, then the
* input file name has to be abc/b.txt
*
* Throws an exception if file header could not be found for the given file name or if
* the destination path is invalid
*
* @param fileName
* @param destinationPath
* @throws ZipException
*/
public void extractFile(String fileName, String destinationPath) throws ZipException {
extractFile(fileName, destinationPath, null);
}
/**
* Extracts a specific file from the zip file to the destination path.
* This method first finds the necessary file header from the input file name.
*
* File name is relative file name in the zip file. For example if a zip file contains
* a file "a.txt", then to extract this file, input file name has to be "a.txt". Another
* example is if there is a file "b.txt" in a folder "abc" in the zip file, then the
* input file name has to be abc/b.txt
*
* If newFileName is not null or empty, newly created file name will be replaced by
* the value in newFileName. If this value is null, then the file name will be the
* value in FileHeader.getFileName
*
* Throws an exception if file header could not be found for the given file name or if
* the destination path is invalid
*
* @param fileName
* @param destinationPath
* @param newFileName
* @throws ZipException
*/
public void extractFile(String fileName, String destinationPath, String newFileName) throws ZipException {
if (!isStringNotNullAndNotEmpty(fileName)) {
throw new ZipException("file to extract is null or empty, cannot extract file");
}
readZipInfo();
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, fileName);
if (fileHeader == null) {
throw new ZipException("No file found with name " + fileName + " in zip file");
}
extractFile(fileHeader, destinationPath, newFileName);
}
/**
* Returns the list of file headers in the zip file. Returns an empty list if the zip file does not exist.
*
* @return list of file headers
* @throws ZipException
*/
public List getFileHeaders() throws ZipException {
readZipInfo();
if (zipModel == null || zipModel.getCentralDirectory() == null) {
return Collections.emptyList();
}
return zipModel.getCentralDirectory().getFileHeaders();
}
/**
* Returns FileHeader if a file header with the given fileHeader
* string exists in the zip model: If not returns null
*
* @param fileName
* @return FileHeader
* @throws ZipException
*/
public FileHeader getFileHeader(String fileName) throws ZipException {
if (!isStringNotNullAndNotEmpty(fileName)) {
throw new ZipException("input file name is emtpy or null, cannot get FileHeader");
}
readZipInfo();
if (zipModel == null || zipModel.getCentralDirectory() == null) {
return null;
}
return HeaderUtil.getFileHeader(zipModel, fileName);
}
/**
* Checks to see if the zip file is encrypted
*
* @return true if encrypted, false if not
* @throws ZipException
*/
public boolean isEncrypted() throws ZipException {
if (zipModel == null) {
readZipInfo();
if (zipModel == null) {
throw new ZipException("Zip Model is null");
}
}
if (zipModel.getCentralDirectory() == null || zipModel.getCentralDirectory().getFileHeaders() == null) {
throw new ZipException("invalid zip file");
}
for (FileHeader fileHeader : zipModel.getCentralDirectory().getFileHeaders()) {
if (fileHeader != null) {
if (fileHeader.isEncrypted()) {
isEncrypted = true;
break;
}
}
}
return isEncrypted;
}
/**
* Checks if the zip file is a split archive
*
* @return true if split archive, false if not
* @throws ZipException
*/
public boolean isSplitArchive() throws ZipException {
if (zipModel == null) {
readZipInfo();
if (zipModel == null) {
throw new ZipException("Zip Model is null");
}
}
return zipModel.isSplitArchive();
}
/**
* Removes the file provided in the input parameters from the zip file.
* This method first finds the file header and then removes the file.
* If file does not exist, then this method throws an exception.
* If zip file is a split zip file, then this method throws an exception as
* zip specification does not allow for updating split zip archives.
*
* @param fileName
* @throws ZipException
*/
public void removeFile(String fileName) throws ZipException {
if (!isStringNotNullAndNotEmpty(fileName)) {
throw new ZipException("file name is empty or null, cannot remove file");
}
if (zipModel == null) {
readZipInfo();
}
if (zipModel.isSplitArchive()) {
throw new ZipException("Zip file format does not allow updating split/spanned files");
}
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, fileName);
if (fileHeader == null) {
throw new ZipException("could not find file header for file: " + fileName);
}
removeFile(fileHeader);
}
/**
* Removes the file provided in the input file header from the zip file.
* If zip file is a split zip file, then this method throws an exception as
* zip specification does not allow for updating split zip archives.
*
* @param fileHeader
* @throws ZipException
*/
public void removeFile(FileHeader fileHeader) throws ZipException {
if (fileHeader == null) {
throw new ZipException("input file header is null, cannot remove file");
}
if (zipModel == null) {
readZipInfo();
}
if (zipModel.isSplitArchive()) {
throw new ZipException("Zip file format does not allow updating split/spanned files");
}
new RemoveEntryFromZipFileTask(progressMonitor, runInThread, zipModel).execute(
new RemoveEntryFromZipFileTaskParameters(fileHeader, charset));
}
/**
* Merges split zip files into a single zip file without the need to extract the
* files in the archive
*
* @param outputZipFile
* @throws ZipException
*/
public void mergeSplitFiles(File outputZipFile) throws ZipException {
if (outputZipFile == null) {
throw new ZipException("outputZipFile is null, cannot merge split files");
}
if (outputZipFile.exists()) {
throw new ZipException("output Zip File already exists");
}
readZipInfo();
if (this.zipModel == null) {
throw new ZipException("zip model is null, corrupt zip file?");
}
new MergeSplitZipFileTask(progressMonitor, runInThread, zipModel).execute(
new MergeSplitZipFileTaskParameters(outputZipFile, charset));
}
/**
* Sets comment for the Zip file
*
* @param comment
* @throws ZipException
*/
public void setComment(String comment) throws ZipException {
if (comment == null) {
throw new ZipException("input comment is null, cannot update zip file");
}
if (!zipFile.exists()) {
throw new ZipException("zip file does not exist, cannot set comment for zip file");
}
readZipInfo();
if (zipModel == null) {
throw new ZipException("zipModel is null, cannot update zip file");
}
if (zipModel.getEndOfCentralDirectoryRecord() == null) {
throw new ZipException("end of central directory is null, cannot set comment");
}
new SetCommentTask(progressMonitor, runInThread, zipModel).execute(
new SetCommentTaskTaskParameters(comment, charset));
}
/**
* Returns the comment set for the Zip file
*
* @return String
* @throws ZipException
*/
public String getComment() throws ZipException {
if (!zipFile.exists()) {
throw new ZipException("zip file does not exist, cannot read comment");
}
readZipInfo();
if (zipModel == null) {
throw new ZipException("zip model is null, cannot read comment");
}
if (zipModel.getEndOfCentralDirectoryRecord() == null) {
throw new ZipException("end of central directory record is null, cannot read comment");
}
return zipModel.getEndOfCentralDirectoryRecord().getComment();
}
/**
* Returns an input stream for reading the contents of the Zip file corresponding
* to the input FileHeader. Throws an exception if the FileHeader does not exist
* in the ZipFile
*
* @param fileHeader
* @return ZipInputStream
* @throws ZipException
*/
public ZipInputStream getInputStream(FileHeader fileHeader) throws IOException {
if (fileHeader == null) {
throw new ZipException("FileHeader is null, cannot get InputStream");
}
readZipInfo();
if (zipModel == null) {
throw new ZipException("zip model is null, cannot get inputstream");
}
return createZipInputStream(zipModel, fileHeader, password);
}
/**
* Checks to see if the input zip file is a valid zip file. This method
* will try to read zip headers. If headers are read successfully, this
* method returns true else false
*
* @return boolean
* @since 1.2.3
*/
public boolean isValidZipFile() {
if (!zipFile.exists()) {
return false;
}
try {
readZipInfo();
return true;
} catch (Exception e) {
return false;
}
}
/**
* Returns the full file path+names of all split zip files
* in an ArrayList. For example: If a split zip file(abc.zip) has a 10 split parts
* this method returns an array list with path + "abc.z01", path + "abc.z02", etc.
* Returns null if the zip file does not exist
*
* @return List of Split zip Files
* @throws ZipException
*/
public List getSplitZipFiles() throws ZipException {
readZipInfo();
return FileUtils.getSplitZipFiles(zipModel);
}
/**
* Sets a password to be used for the zip file. Will override if a password supplied via ZipFile constructor
* @param password - char array of the password to be used
*/
public void setPassword(char[] password) {
this.password = password;
}
/**
* Reads the zip header information for this zip file. If the zip file
* does not exist, it creates an empty zip model.
* Note: This method does not read local file header information
*
* @throws ZipException
*/
private void readZipInfo() throws ZipException {
if (zipModel != null) {
return;
}
if (!zipFile.exists()) {
createNewZipModel();
return;
}
if (!zipFile.canRead()) {
throw new ZipException("no read access for the input zip file");
}
try (RandomAccessFile randomAccessFile = new RandomAccessFile(zipFile, RandomAccessFileMode.READ.getValue())) {
HeaderReader headerReader = new HeaderReader();
zipModel = headerReader.readAllHeaders(randomAccessFile, charset);
zipModel.setZipFile(zipFile);
} catch (ZipException e) {
throw e;
} catch (IOException e) {
throw new ZipException(e);
}
}
/**
* Creates a new instance of zip model
*
* @throws ZipException
*/
private void createNewZipModel() {
zipModel = new ZipModel();
zipModel.setZipFile(zipFile);
}
public ProgressMonitor getProgressMonitor() {
return progressMonitor;
}
public boolean isRunInThread() {
return runInThread;
}
public void setRunInThread(boolean runInThread) {
this.runInThread = runInThread;
}
public File getFile() {
return zipFile;
}
public Charset getCharset() {
return charset;
}
public void setCharset(Charset charset) throws IllegalArgumentException {
if(charset == null) {
throw new IllegalArgumentException("charset cannot be null");
}
this.charset = charset;
}
@Override
public String toString() {
return zipFile.toString();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/ 0000775 0000000 0000000 00000000000 13576501616 0022006 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/AESDecrypter.java 0000775 0000000 0000000 00000010347 13576501616 0025153 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.crypto.PBKDF2.MacBasedPRF;
import net.lingala.zip4j.crypto.PBKDF2.PBKDF2Engine;
import net.lingala.zip4j.crypto.PBKDF2.PBKDF2Parameters;
import net.lingala.zip4j.crypto.engine.AESEngine;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import java.util.Arrays;
import static net.lingala.zip4j.crypto.AesCipherUtil.prepareBuffAESIVBytes;
import static net.lingala.zip4j.util.InternalZipConstants.AES_BLOCK_SIZE;
public class AESDecrypter implements Decrypter {
public static final int PASSWORD_VERIFIER_LENGTH = 2;
private AESExtraDataRecord aesExtraDataRecord;
private char[] password;
private AESEngine aesEngine;
private MacBasedPRF mac;
private int nonce = 1;
private byte[] iv;
private byte[] counterBlock;
public AESDecrypter(AESExtraDataRecord aesExtraDataRecord, char[] password, byte[] salt, byte[] passwordVerifier) throws ZipException {
this.aesExtraDataRecord = aesExtraDataRecord;
this.password = password;
iv = new byte[AES_BLOCK_SIZE];
counterBlock = new byte[AES_BLOCK_SIZE];
init(salt, passwordVerifier);
}
private void init(byte[] salt, byte[] passwordVerifier) throws ZipException {
AesKeyStrength aesKeyStrength = aesExtraDataRecord.getAesKeyStrength();
if (password == null || password.length <= 0) {
throw new ZipException("empty or null password provided for AES Decryptor");
}
byte[] derivedKey = deriveKey(salt, password, aesKeyStrength.getKeyLength(), aesKeyStrength.getMacLength());
if (derivedKey == null || derivedKey.length != (aesKeyStrength.getKeyLength() + aesKeyStrength.getMacLength()
+ PASSWORD_VERIFIER_LENGTH)) {
throw new ZipException("invalid derived key");
}
byte[] aesKey = new byte[aesKeyStrength.getKeyLength()];
byte[] macKey = new byte[aesKeyStrength.getMacLength()];
byte[] derivedPasswordVerifier = new byte[PASSWORD_VERIFIER_LENGTH];
System.arraycopy(derivedKey, 0, aesKey, 0, aesKeyStrength.getKeyLength());
System.arraycopy(derivedKey, aesKeyStrength.getKeyLength(), macKey, 0, aesKeyStrength.getMacLength());
System.arraycopy(derivedKey, aesKeyStrength.getKeyLength() + aesKeyStrength.getMacLength(), derivedPasswordVerifier,
0, PASSWORD_VERIFIER_LENGTH);
if (!Arrays.equals(passwordVerifier, derivedPasswordVerifier)) {
throw new ZipException("Wrong Password", ZipException.Type.WRONG_PASSWORD);
}
aesEngine = new AESEngine(aesKey);
mac = new MacBasedPRF("HmacSHA1");
mac.init(macKey);
}
@Override
public int decryptData(byte[] buff, int start, int len) throws ZipException {
for (int j = start; j < (start + len); j += AES_BLOCK_SIZE) {
int loopCount = (j + AES_BLOCK_SIZE <= (start + len)) ?
AES_BLOCK_SIZE : ((start + len) - j);
mac.update(buff, j, loopCount);
prepareBuffAESIVBytes(iv, nonce);
aesEngine.processBlock(iv, counterBlock);
for (int k = 0; k < loopCount; k++) {
buff[j + k] = (byte) (buff[j + k] ^ counterBlock[k]);
}
nonce++;
}
return len;
}
private byte[] deriveKey(byte[] salt, char[] password, int keyLength, int macLength) {
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", salt, 1000);
PBKDF2Engine e = new PBKDF2Engine(p);
return e.deriveKey(password, keyLength + macLength + PASSWORD_VERIFIER_LENGTH);
}
public byte[] getCalculatedAuthenticationBytes() {
return mac.doFinal();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/AESEncrpyter.java 0000775 0000000 0000000 00000013461 13576501616 0025165 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.crypto.PBKDF2.MacBasedPRF;
import net.lingala.zip4j.crypto.PBKDF2.PBKDF2Engine;
import net.lingala.zip4j.crypto.PBKDF2.PBKDF2Parameters;
import net.lingala.zip4j.crypto.engine.AESEngine;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import java.util.Random;
import static net.lingala.zip4j.crypto.AesCipherUtil.prepareBuffAESIVBytes;
import static net.lingala.zip4j.util.InternalZipConstants.AES_BLOCK_SIZE;
public class AESEncrpyter implements Encrypter {
private static final int PASSWORD_VERIFIER_LENGTH = 2;
private char[] password;
private AesKeyStrength aesKeyStrength;
private AESEngine aesEngine;
private MacBasedPRF mac;
private boolean finished;
private int nonce = 1;
private int loopCount = 0;
private byte[] iv;
private byte[] counterBlock;
private byte[] derivedPasswordVerifier;
private byte[] saltBytes;
public AESEncrpyter(char[] password, AesKeyStrength aesKeyStrength) throws ZipException {
if (password == null || password.length == 0) {
throw new ZipException("input password is empty or null");
}
if (aesKeyStrength != AesKeyStrength.KEY_STRENGTH_128 &&
aesKeyStrength != AesKeyStrength.KEY_STRENGTH_256) {
throw new ZipException("Invalid AES key strength");
}
this.password = password;
this.aesKeyStrength = aesKeyStrength;
this.finished = false;
counterBlock = new byte[AES_BLOCK_SIZE];
iv = new byte[AES_BLOCK_SIZE];
init();
}
private void init() throws ZipException {
int keyLength = aesKeyStrength.getKeyLength();
int macLength = aesKeyStrength.getMacLength();
int saltLength = aesKeyStrength.getSaltLength();
saltBytes = generateSalt(saltLength);
byte[] keyBytes = deriveKey(saltBytes, password, keyLength, macLength);
if (keyBytes == null || keyBytes.length != (keyLength + macLength + PASSWORD_VERIFIER_LENGTH)) {
throw new ZipException("invalid key generated, cannot decrypt file");
}
byte[] aesKey = new byte[keyLength];
byte[] macKey = new byte[macLength];
derivedPasswordVerifier = new byte[PASSWORD_VERIFIER_LENGTH];
System.arraycopy(keyBytes, 0, aesKey, 0, keyLength);
System.arraycopy(keyBytes, keyLength, macKey, 0, macLength);
System.arraycopy(keyBytes, keyLength + macLength, derivedPasswordVerifier, 0, PASSWORD_VERIFIER_LENGTH);
aesEngine = new AESEngine(aesKey);
mac = new MacBasedPRF("HmacSHA1");
mac.init(macKey);
}
private byte[] deriveKey(byte[] salt, char[] password, int keyLength, int macLength) throws ZipException {
try {
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1",
salt, 1000);
PBKDF2Engine e = new PBKDF2Engine(p);
byte[] derivedKey = e.deriveKey(password, keyLength + macLength + PASSWORD_VERIFIER_LENGTH);
return derivedKey;
} catch (Exception e) {
throw new ZipException(e);
}
}
public int encryptData(byte[] buff) throws ZipException {
if (buff == null) {
throw new ZipException("input bytes are null, cannot perform AES encrpytion");
}
return encryptData(buff, 0, buff.length);
}
public int encryptData(byte[] buff, int start, int len) throws ZipException {
if (finished) {
// A non 16 byte block has already been passed to encrypter
// non 16 byte block should be the last block of compressed data in AES encryption
// any more encryption will lead to corruption of data
throw new ZipException("AES Encrypter is in finished state (A non 16 byte block has already been passed to encrypter)");
}
if (len % 16 != 0) {
this.finished = true;
}
for (int j = start; j < (start + len); j += AES_BLOCK_SIZE) {
loopCount = (j + AES_BLOCK_SIZE <= (start + len)) ?
AES_BLOCK_SIZE : ((start + len) - j);
prepareBuffAESIVBytes(iv, nonce);
aesEngine.processBlock(iv, counterBlock);
for (int k = 0; k < loopCount; k++) {
buff[j + k] = (byte) (buff[j + k] ^ counterBlock[k]);
}
mac.update(buff, j, loopCount);
nonce++;
}
return len;
}
private static byte[] generateSalt(int size) throws ZipException {
if (size != 8 && size != 16) {
throw new ZipException("invalid salt size, cannot generate salt");
}
int rounds = 0;
if (size == 8)
rounds = 2;
if (size == 16)
rounds = 4;
byte[] salt = new byte[size];
for (int j = 0; j < rounds; j++) {
Random rand = new Random();
int i = rand.nextInt();
salt[0 + j * 4] = (byte) (i >> 24);
salt[1 + j * 4] = (byte) (i >> 16);
salt[2 + j * 4] = (byte) (i >> 8);
salt[3 + j * 4] = (byte) i;
}
return salt;
}
public byte[] getFinalMac() {
byte[] rawMacBytes = mac.doFinal();
byte[] macBytes = new byte[10];
System.arraycopy(rawMacBytes, 0, macBytes, 0, 10);
return macBytes;
}
public byte[] getDerivedPasswordVerifier() {
return derivedPasswordVerifier;
}
public byte[] getSaltBytes() {
return saltBytes;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/AesCipherUtil.java 0000664 0000000 0000000 00000000522 13576501616 0025351 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.crypto;
public class AesCipherUtil {
public static void prepareBuffAESIVBytes(byte[] buff, int nonce) {
buff[0] = (byte) nonce;
buff[1] = (byte) (nonce >> 8);
buff[2] = (byte) (nonce >> 16);
buff[3] = (byte) (nonce >> 24);
for (int i = 4; i <= 15; i++) {
buff[i] = 0;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/Decrypter.java 0000775 0000000 0000000 00000001462 13576501616 0024620 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.exception.ZipException;
public interface Decrypter {
int decryptData(byte[] buff, int start, int len) throws ZipException;
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/Encrypter.java 0000775 0000000 0000000 00000001551 13576501616 0024631 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.exception.ZipException;
public interface Encrypter {
int encryptData(byte[] buff) throws ZipException;
int encryptData(byte[] buff, int start, int len) throws ZipException;
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/ 0000775 0000000 0000000 00000000000 13576501616 0022716 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/BinTools.java 0000775 0000000 0000000 00000004040 13576501616 0025313 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
class BinTools {
public static final String hex = "0123456789ABCDEF";
public static String bin2hex(final byte[] b) {
if (b == null) {
return "";
}
StringBuffer sb = new StringBuffer(2 * b.length);
for (int i = 0; i < b.length; i++) {
int v = (256 + b[i]) % 256;
sb.append(hex.charAt((v / 16) & 15));
sb.append(hex.charAt((v % 16) & 15));
}
return sb.toString();
}
public static byte[] hex2bin(final String s) {
String m = s;
if (s == null) {
// Allow empty input string.
m = "";
} else if (s.length() % 2 != 0) {
// Assume leading zero for odd string length
m = "0" + s;
}
byte r[] = new byte[m.length() / 2];
for (int i = 0, n = 0; i < m.length(); n++) {
char h = m.charAt(i++);
char l = m.charAt(i++);
r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
}
return r;
}
public static int hex2bin(char c) {
if (c >= '0' && c <= '9') {
return (c - '0');
}
if (c >= 'A' && c <= 'F') {
return (c - 'A' + 10);
}
if (c >= 'a' && c <= 'f') {
return (c - 'a' + 10);
}
throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'");
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/MacBasedPRF.java 0000775 0000000 0000000 00000004014 13576501616 0025572 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
public class MacBasedPRF implements PRF {
private Mac mac;
private int hLen;
private String macAlgorithm;
public MacBasedPRF(String macAlgorithm) {
this.macAlgorithm = macAlgorithm;
try {
mac = Mac.getInstance(macAlgorithm);
hLen = mac.getMacLength();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public byte[] doFinal(byte[] M) {
return mac.doFinal(M);
}
public byte[] doFinal() {
return mac.doFinal();
}
public int getHLen() {
return hLen;
}
public void init(byte[] P) {
try {
mac.init(new SecretKeySpec(P, macAlgorithm));
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
}
}
public void update(byte[] U) {
try {
mac.update(U);
} catch (IllegalStateException e) {
throw new RuntimeException(e);
}
}
public void update(byte[] U, int start, int len) {
try {
mac.update(U, start, len);
} catch (IllegalStateException e) {
throw new RuntimeException(e);
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/PBKDF2Engine.java 0000775 0000000 0000000 00000010174 13576501616 0025625 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
import static net.lingala.zip4j.util.Zip4jUtil.convertCharArrayToByteArray;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
public class PBKDF2Engine {
private PBKDF2Parameters parameters;
private PRF prf;
public PBKDF2Engine(PBKDF2Parameters parameters) {
this(parameters, null);
}
public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf) {
this.parameters = parameters;
this.prf = prf;
}
public byte[] deriveKey(char[] inputPassword) {
return deriveKey(inputPassword, 0);
}
public byte[] deriveKey(char[] inputPassword, int dkLen) {
byte p[];
if (inputPassword == null) {
throw new NullPointerException();
}
p = convertCharArrayToByteArray(inputPassword);
assertPRF(p);
if (dkLen == 0) {
dkLen = prf.getHLen();
}
return PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), dkLen);
}
public boolean verifyKey(char[] inputPassword) {
byte[] referenceKey = getParameters().getDerivedKey();
if (referenceKey == null || referenceKey.length == 0) {
return false;
}
byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
if (inputKey == null || inputKey.length != referenceKey.length) {
return false;
}
for (int i = 0; i < inputKey.length; i++) {
if (inputKey[i] != referenceKey[i]) {
return false;
}
}
return true;
}
private void assertPRF(byte[] P) {
if (prf == null) {
prf = new MacBasedPRF(parameters.getHashAlgorithm());
}
prf.init(P);
}
public PRF getPseudoRandomFunction() {
return prf;
}
private byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen) {
if (S == null) {
S = new byte[0];
}
int hLen = prf.getHLen();
int l = ceil(dkLen, hLen);
int r = dkLen - (l - 1) * hLen;
byte T[] = new byte[l * hLen];
int ti_offset = 0;
for (int i = 1; i <= l; i++) {
_F(T, ti_offset, prf, S, c, i);
ti_offset += hLen;
}
if (r < hLen) {
// Incomplete last block
byte DK[] = new byte[dkLen];
System.arraycopy(T, 0, DK, 0, dkLen);
return DK;
}
return T;
}
private int ceil(int a, int b) {
int m = 0;
if (a % b > 0) {
m = 1;
}
return a / b + m;
}
private void _F(byte[] dest, int offset, PRF prf, byte[] S, int c,
int blockIndex) {
int hLen = prf.getHLen();
byte U_r[] = new byte[hLen];
// U0 = S || INT (i);
byte U_i[] = new byte[S.length + 4];
System.arraycopy(S, 0, U_i, 0, S.length);
INT(U_i, S.length, blockIndex);
for (int i = 0; i < c; i++) {
U_i = prf.doFinal(U_i);
xor(U_r, U_i);
}
System.arraycopy(U_r, 0, dest, offset, hLen);
}
private void xor(byte[] dest, byte[] src) {
for (int i = 0; i < dest.length; i++) {
dest[i] ^= src[i];
}
}
protected void INT(byte[] dest, int offset, int i) {
dest[offset] = (byte) (i / (256 * 256 * 256));
dest[offset + 1] = (byte) (i / (256 * 256));
dest[offset + 2] = (byte) (i / (256));
dest[offset + 3] = (byte) (i);
}
public PBKDF2Parameters getParameters() {
return parameters;
}
public void setParameters(PBKDF2Parameters parameters) {
this.parameters = parameters;
}
public void setPseudoRandomFunction(PRF prf) {
this.prf = prf;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/PBKDF2HexFormatter.java 0000775 0000000 0000000 00000002765 13576501616 0027037 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
class PBKDF2HexFormatter {
public boolean fromString(PBKDF2Parameters p, String s) {
if (p == null || s == null) {
return true;
}
String[] pSplit = s.split(":");
if (pSplit.length != 3) {
return true;
}
byte salt[] = BinTools.hex2bin(pSplit[0]);
int iterationCount = Integer.parseInt(pSplit[1]);
byte bDK[] = BinTools.hex2bin(pSplit[2]);
p.setSalt(salt);
p.setIterationCount(iterationCount);
p.setDerivedKey(bDK);
return false;
}
public String toString(PBKDF2Parameters p) {
String s = BinTools.bin2hex(p.getSalt()) + ":" + String.valueOf(p.getIterationCount()) + ":"
+ BinTools.bin2hex(p.getDerivedKey());
return s;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/PBKDF2Parameters.java 0000775 0000000 0000000 00000004660 13576501616 0026526 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
public class PBKDF2Parameters {
protected byte[] salt;
protected int iterationCount;
protected String hashAlgorithm;
protected String hashCharset;
protected byte[] derivedKey;
public PBKDF2Parameters() {
this.hashAlgorithm = null;
this.hashCharset = "UTF-8";
this.salt = null;
this.iterationCount = 1000;
this.derivedKey = null;
}
public PBKDF2Parameters(String hashAlgorithm, String hashCharset, byte[] salt, int iterationCount) {
this(hashAlgorithm, hashCharset, salt, iterationCount, null);
}
public PBKDF2Parameters(String hashAlgorithm, String hashCharset, byte[] salt, int iterationCount,
byte[] derivedKey) {
this.hashAlgorithm = hashAlgorithm;
this.hashCharset = hashCharset;
this.salt = salt;
this.iterationCount = iterationCount;
this.derivedKey = derivedKey;
}
public int getIterationCount() {
return iterationCount;
}
public void setIterationCount(int iterationCount) {
this.iterationCount = iterationCount;
}
public byte[] getSalt() {
return salt;
}
public void setSalt(byte[] salt) {
this.salt = salt;
}
public byte[] getDerivedKey() {
return derivedKey;
}
public void setDerivedKey(byte[] derivedKey) {
this.derivedKey = derivedKey;
}
public String getHashAlgorithm() {
return hashAlgorithm;
}
public void setHashAlgorithm(String hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
public String getHashCharset() {
return hashCharset;
}
public void setHashCharset(String hashCharset) {
this.hashCharset = hashCharset;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/PBKDF2/PRF.java 0000775 0000000 0000000 00000001564 13576501616 0024221 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.PBKDF2;
/*
* Source referred from Matthias Gartner's PKCS#5 implementation -
* see http://rtner.de/software/PBKDF2.html
*/
interface PRF {
void init(byte[] P);
byte[] doFinal(byte[] M);
int getHLen();
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/StandardDecrypter.java 0000775 0000000 0000000 00000005732 13576501616 0026305 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.crypto.engine.ZipCryptoEngine;
import net.lingala.zip4j.exception.ZipException;
import static net.lingala.zip4j.util.InternalZipConstants.STD_DEC_HDR_SIZE;
public class StandardDecrypter implements Decrypter {
private char[] password;
private byte[] crcBytes;
private byte[] crc = new byte[4];
private ZipCryptoEngine zipCryptoEngine;
public StandardDecrypter(char[] password, byte[] crcBytes , byte[] headerBytes) throws ZipException {
this.password = password;
this.crcBytes = crcBytes;
this.zipCryptoEngine = new ZipCryptoEngine();
init(headerBytes);
}
public int decryptData(byte[] buff, int start, int len) throws ZipException {
if (start < 0 || len < 0) {
throw new ZipException("one of the input parameters were null in standard decrypt data");
}
for (int i = start; i < start + len; i++) {
int val = buff[i] & 0xff;
val = (val ^ zipCryptoEngine.decryptByte()) & 0xff;
zipCryptoEngine.updateKeys((byte) val);
buff[i] = (byte) val;
}
return len;
}
private void init(byte[] headerBytes) throws ZipException {
crc[3] = (byte) (crcBytes[3] & 0xFF);
crc[2] = (byte) ((crcBytes[3] >> 8) & 0xFF);
crc[1] = (byte) ((crcBytes[3] >> 16) & 0xFF);
crc[0] = (byte) ((crcBytes[3] >> 24) & 0xFF);
if (crc[2] > 0 || crc[1] > 0 || crc[0] > 0)
throw new IllegalStateException("Invalid CRC in File Header");
if (password == null || password.length <= 0) {
throw new ZipException("Wrong password!", ZipException.Type.WRONG_PASSWORD);
}
zipCryptoEngine.initKeys(password);
int result = headerBytes[0];
for (int i = 0; i < STD_DEC_HDR_SIZE; i++) {
// Commented this as this check cannot always be trusted
// New functionality: If there is an error in extracting a password protected file,
// "Wrong Password?" text is appended to the exception message
// if(i+1 == InternalZipConstants.STD_DEC_HDR_SIZE && ((byte)(result ^ zipCryptoEngine.decryptByte()) != crc[3]) && !isSplit)
// throw new ZipException("Wrong password!", ZipExceptionConstants.WRONG_PASSWORD);
zipCryptoEngine.updateKeys((byte) (result ^ zipCryptoEngine.decryptByte()));
if (i + 1 != STD_DEC_HDR_SIZE)
result = headerBytes[i + 1];
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/StandardEncrypter.java 0000775 0000000 0000000 00000006256 13576501616 0026321 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto;
import net.lingala.zip4j.crypto.engine.ZipCryptoEngine;
import net.lingala.zip4j.exception.ZipException;
import java.util.Random;
import static net.lingala.zip4j.util.InternalZipConstants.STD_DEC_HDR_SIZE;
public class StandardEncrypter implements Encrypter {
private ZipCryptoEngine zipCryptoEngine;
private byte[] headerBytes;
public StandardEncrypter(char[] password, long key) throws ZipException {
this.zipCryptoEngine = new ZipCryptoEngine();
this.headerBytes = new byte[STD_DEC_HDR_SIZE];
init(password, key);
}
private void init(char[] password, long key) throws ZipException {
if (password == null || password.length <= 0) {
throw new ZipException("input password is null or empty, cannot initialize standard encrypter");
}
zipCryptoEngine.initKeys(password);
headerBytes = generateRandomBytes(STD_DEC_HDR_SIZE);
// Initialize again since the generated bytes were encrypted.
zipCryptoEngine.initKeys(password);
headerBytes[STD_DEC_HDR_SIZE - 1] = (byte) ((key >>> 24));
headerBytes[STD_DEC_HDR_SIZE - 2] = (byte) ((key >>> 16));
if (headerBytes.length < STD_DEC_HDR_SIZE) {
throw new ZipException("invalid header bytes generated, cannot perform standard encryption");
}
encryptData(headerBytes);
}
public int encryptData(byte[] buff) throws ZipException {
if (buff == null) {
throw new NullPointerException();
}
return encryptData(buff, 0, buff.length);
}
public int encryptData(byte[] buff, int start, int len) throws ZipException {
if (len < 0) {
throw new ZipException("invalid length specified to decrpyt data");
}
for (int i = start; i < start + len; i++) {
buff[i] = encryptByte(buff[i]);
}
return len;
}
protected byte encryptByte(byte val) {
byte temp_val = (byte) (val ^ zipCryptoEngine.decryptByte() & 0xff);
zipCryptoEngine.updateKeys(val);
return temp_val;
}
protected byte[] generateRandomBytes(int size) throws ZipException {
if (size <= 0) {
throw new ZipException("size is either 0 or less than 0, cannot generate header for standard encryptor");
}
byte[] buff = new byte[size];
Random rand = new Random();
for (int i = 0; i < buff.length; i++) {
// Encrypted to get less predictability for poorly implemented rand functions.
buff[i] = encryptByte((byte) rand.nextInt(256));
}
return buff;
}
public byte[] getHeaderBytes() {
return headerBytes;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/engine/ 0000775 0000000 0000000 00000000000 13576501616 0023253 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/engine/AESEngine.java 0000775 0000000 0000000 00000033356 13576501616 0025671 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.engine;
import net.lingala.zip4j.exception.ZipException;
import static net.lingala.zip4j.util.InternalZipConstants.AES_BLOCK_SIZE;
/**
* Core Engine for AES Encryption
*
* @author Srikanth Reddy Lingala
*/
public class AESEngine {
private int rounds;
private int[][] workingKey = null;
private int C0, C1, C2, C3;
public AESEngine(byte[] key) throws ZipException {
init(key);
}
private void init(byte[] key) throws ZipException {
workingKey = generateWorkingKey(key);
}
private int[][] generateWorkingKey(byte[] key) throws ZipException {
int kc = key.length / 4;
int t;
if (((kc != 4) && (kc != 6) && (kc != 8)) || ((kc * 4) != key.length)) {
throw new ZipException("invalid key length (not 128/192/256)");
}
rounds = kc + 6;
int[][] W = new int[rounds + 1][4];
t = 0;
int i = 0;
while (i < key.length) {
W[t >> 2][t & 3] = (key[i] & 0xff) | ((key[i + 1] & 0xff) << 8) | ((key[i + 2] & 0xff) << 16)
| (key[i + 3] << 24);
i += 4;
t++;
}
int k = (rounds + 1) << 2;
for (i = kc; (i < k); i++) {
int temp = W[(i - 1) >> 2][(i - 1) & 3];
if ((i % kc) == 0) {
temp = subWord(shift(temp, 8)) ^ rcon[(i / kc) - 1];
} else if ((kc > 6) && ((i % kc) == 4)) {
temp = subWord(temp);
}
W[i >> 2][i & 3] = W[(i - kc) >> 2][(i - kc) & 3] ^ temp;
}
return W;
}
public int processBlock(byte[] in, byte[] out) throws ZipException {
return processBlock(in, 0, out, 0);
}
public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws ZipException {
if (workingKey == null) {
throw new ZipException("AES engine not initialised");
}
if ((inOff + (32 / 2)) > in.length) {
throw new ZipException("input buffer too short");
}
if ((outOff + (32 / 2)) > out.length) {
throw new ZipException("output buffer too short");
}
stateIn(in, inOff);
encryptBlock(workingKey);
stateOut(out, outOff);
return AES_BLOCK_SIZE;
}
private void stateIn(byte[] bytes, int off) {
int index = off;
C0 = (bytes[index++] & 0xff);
C0 |= (bytes[index++] & 0xff) << 8;
C0 |= (bytes[index++] & 0xff) << 16;
C0 |= bytes[index++] << 24;
C1 = (bytes[index++] & 0xff);
C1 |= (bytes[index++] & 0xff) << 8;
C1 |= (bytes[index++] & 0xff) << 16;
C1 |= bytes[index++] << 24;
C2 = (bytes[index++] & 0xff);
C2 |= (bytes[index++] & 0xff) << 8;
C2 |= (bytes[index++] & 0xff) << 16;
C2 |= bytes[index++] << 24;
C3 = (bytes[index++] & 0xff);
C3 |= (bytes[index++] & 0xff) << 8;
C3 |= (bytes[index++] & 0xff) << 16;
C3 |= bytes[index++] << 24;
}
private void stateOut(byte[] bytes, int off) {
int index = off;
bytes[index++] = (byte) C0;
bytes[index++] = (byte) (C0 >> 8);
bytes[index++] = (byte) (C0 >> 16);
bytes[index++] = (byte) (C0 >> 24);
bytes[index++] = (byte) C1;
bytes[index++] = (byte) (C1 >> 8);
bytes[index++] = (byte) (C1 >> 16);
bytes[index++] = (byte) (C1 >> 24);
bytes[index++] = (byte) C2;
bytes[index++] = (byte) (C2 >> 8);
bytes[index++] = (byte) (C2 >> 16);
bytes[index++] = (byte) (C2 >> 24);
bytes[index++] = (byte) C3;
bytes[index++] = (byte) (C3 >> 8);
bytes[index++] = (byte) (C3 >> 16);
bytes[index++] = (byte) (C3 >> 24);
}
private void encryptBlock(int[][] KW) {
int r, r0, r1, r2, r3;
C0 ^= KW[0][0];
C1 ^= KW[0][1];
C2 ^= KW[0][2];
C3 ^= KW[0][3];
r = 1;
while (r < rounds - 1) {
r0 = T0[C0 & 255] ^ shift(T0[(C1 >> 8) & 255], 24) ^ shift(T0[(C2 >> 16) & 255], 16) ^ shift(T0[(C3 >> 24) & 255], 8) ^ KW[r][0];
r1 = T0[C1 & 255] ^ shift(T0[(C2 >> 8) & 255], 24) ^ shift(T0[(C3 >> 16) & 255], 16) ^ shift(T0[(C0 >> 24) & 255], 8) ^ KW[r][1];
r2 = T0[C2 & 255] ^ shift(T0[(C3 >> 8) & 255], 24) ^ shift(T0[(C0 >> 16) & 255], 16) ^ shift(T0[(C1 >> 24) & 255], 8) ^ KW[r][2];
r3 = T0[C3 & 255] ^ shift(T0[(C0 >> 8) & 255], 24) ^ shift(T0[(C1 >> 16) & 255], 16) ^ shift(T0[(C2 >> 24) & 255], 8) ^ KW[r++][3];
C0 = T0[r0 & 255] ^ shift(T0[(r1 >> 8) & 255], 24) ^ shift(T0[(r2 >> 16) & 255], 16) ^ shift(T0[(r3 >> 24) & 255], 8) ^ KW[r][0];
C1 = T0[r1 & 255] ^ shift(T0[(r2 >> 8) & 255], 24) ^ shift(T0[(r3 >> 16) & 255], 16) ^ shift(T0[(r0 >> 24) & 255], 8) ^ KW[r][1];
C2 = T0[r2 & 255] ^ shift(T0[(r3 >> 8) & 255], 24) ^ shift(T0[(r0 >> 16) & 255], 16) ^ shift(T0[(r1 >> 24) & 255], 8) ^ KW[r][2];
C3 = T0[r3 & 255] ^ shift(T0[(r0 >> 8) & 255], 24) ^ shift(T0[(r1 >> 16) & 255], 16) ^ shift(T0[(r2 >> 24) & 255], 8) ^ KW[r++][3];
}
r0 = T0[C0 & 255] ^ shift(T0[(C1 >> 8) & 255], 24) ^ shift(T0[(C2 >> 16) & 255], 16) ^ shift(T0[(C3 >> 24) & 255], 8) ^ KW[r][0];
r1 = T0[C1 & 255] ^ shift(T0[(C2 >> 8) & 255], 24) ^ shift(T0[(C3 >> 16) & 255], 16) ^ shift(T0[(C0 >> 24) & 255], 8) ^ KW[r][1];
r2 = T0[C2 & 255] ^ shift(T0[(C3 >> 8) & 255], 24) ^ shift(T0[(C0 >> 16) & 255], 16) ^ shift(T0[(C1 >> 24) & 255], 8) ^ KW[r][2];
r3 = T0[C3 & 255] ^ shift(T0[(C0 >> 8) & 255], 24) ^ shift(T0[(C1 >> 16) & 255], 16) ^ shift(T0[(C2 >> 24) & 255], 8) ^ KW[r++][3];
C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16) ^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0];
C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16) ^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1];
C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16) ^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2];
C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16) ^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3];
}
private int shift(int r, int shift) {
return (r >>> shift) | (r << -shift);
}
private int subWord(int x) {
return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16) | S[(x >> 24) & 255] << 24);
}
private static final byte[] S = {
(byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, (byte) 111, (byte) 197,
(byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, (byte) 118,
(byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240,
(byte) 173, (byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192,
(byte) 183, (byte) 253, (byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204,
(byte) 52, (byte) 165, (byte) 229, (byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21,
(byte) 4, (byte) 199, (byte) 35, (byte) 195, (byte) 24, (byte) 150, (byte) 5, (byte) 154,
(byte) 7, (byte) 18, (byte) 128, (byte) 226, (byte) 235, (byte) 39, (byte) 178, (byte) 117,
(byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, (byte) 110, (byte) 90, (byte) 160,
(byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, (byte) 47, (byte) 132,
(byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, (byte) 91,
(byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207,
(byte) 208, (byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133,
(byte) 69, (byte) 249, (byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168,
(byte) 81, (byte) 163, (byte) 64, (byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245,
(byte) 188, (byte) 182, (byte) 218, (byte) 33, (byte) 16, (byte) 255, (byte) 243, (byte) 210,
(byte) 205, (byte) 12, (byte) 19, (byte) 236, (byte) 95, (byte) 151, (byte) 68, (byte) 23,
(byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, (byte) 93, (byte) 25, (byte) 115,
(byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, (byte) 144, (byte) 136,
(byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, (byte) 219,
(byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92,
(byte) 194, (byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121,
(byte) 231, (byte) 200, (byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169,
(byte) 108, (byte) 86, (byte) 244, (byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8,
(byte) 186, (byte) 120, (byte) 37, (byte) 46, (byte) 28, (byte) 166, (byte) 180, (byte) 198,
(byte) 232, (byte) 221, (byte) 116, (byte) 31, (byte) 75, (byte) 189, (byte) 139, (byte) 138,
(byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, (byte) 3, (byte) 246, (byte) 14,
(byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, (byte) 29, (byte) 158,
(byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, (byte) 148,
(byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223,
(byte) 140, (byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104,
(byte) 65, (byte) 153, (byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22,
};
private static final int[] rcon = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91};
private static final int[] T0 =
{
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
0x3a16162c};
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/crypto/engine/ZipCryptoEngine.java 0000775 0000000 0000000 00000003330 13576501616 0027211 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.crypto.engine;
public class ZipCryptoEngine {
private final int keys[] = new int[3];
private static final int[] CRC_TABLE = new int[256];
static {
for (int i = 0; i < 256; i++) {
int r = i;
for (int j = 0; j < 8; j++) {
if ((r & 1) == 1) {
r = (r >>> 1) ^ 0xedb88320;
} else {
r >>>= 1;
}
}
CRC_TABLE[i] = r;
}
}
public void initKeys(char[] password) {
keys[0] = 305419896;
keys[1] = 591751049;
keys[2] = 878082192;
for (int i = 0; i < password.length; i++) {
updateKeys((byte) (password[i] & 0xff));
}
}
public void updateKeys(byte charAt) {
keys[0] = crc32(keys[0], charAt);
keys[1] += keys[0] & 0xff;
keys[1] = keys[1] * 134775813 + 1;
keys[2] = crc32(keys[2], (byte) (keys[1] >> 24));
}
private int crc32(int oldCrc, byte charAt) {
return ((oldCrc >>> 8) ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]);
}
public byte decryptByte() {
int temp = keys[2] | 2;
return (byte) ((temp * (temp ^ 1)) >>> 8);
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/exception/ 0000775 0000000 0000000 00000000000 13576501616 0022464 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/exception/ZipException.java 0000775 0000000 0000000 00000003002 13576501616 0025746 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.exception;
import java.io.IOException;
public class ZipException extends IOException {
private static final long serialVersionUID = 1L;
private Type type = Type.UNKNOWN;
public ZipException(String message) {
super(message);
}
public ZipException(Exception rootException) {
super(rootException);
}
public ZipException(String message, Exception rootException) {
super(message, rootException);
}
public ZipException(String message, Type type) {
super(message);
this.type = type;
}
public ZipException(String message, Throwable throwable, Type type) {
super(message, throwable);
this.type = type;
}
public Type getType() {
return type;
}
public enum Type {
WRONG_PASSWORD,
TASK_CANCELLED_EXCEPTION,
CHECKSUM_MISMATCH,
UNKNOWN_COMPRESSION_METHOD,
UNKNOWN
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/ 0000775 0000000 0000000 00000000000 13576501616 0022101 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/FileHeaderFactory.java 0000664 0000000 0000000 00000016430 13576501616 0026270 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.Zip4jUtil;
import java.nio.charset.Charset;
import static net.lingala.zip4j.util.BitUtils.setBit;
import static net.lingala.zip4j.util.BitUtils.unsetBit;
import static net.lingala.zip4j.util.FileUtils.isZipEntryDirectory;
public class FileHeaderFactory {
public FileHeader generateFileHeader(ZipParameters zipParameters, boolean isSplitZip, int currentDiskNumberStart, Charset charset)
throws ZipException {
FileHeader fileHeader = new FileHeader();
fileHeader.setSignature(HeaderSignature.CENTRAL_DIRECTORY);
fileHeader.setVersionMadeBy(20);
fileHeader.setVersionNeededToExtract(20);
if (zipParameters.isEncryptFiles() && zipParameters.getEncryptionMethod() == EncryptionMethod.AES) {
fileHeader.setCompressionMethod(CompressionMethod.AES_INTERNAL_ONLY);
fileHeader.setAesExtraDataRecord(generateAESExtraDataRecord(zipParameters));
} else {
fileHeader.setCompressionMethod(zipParameters.getCompressionMethod());
}
if (zipParameters.isEncryptFiles()) {
if (zipParameters.getEncryptionMethod() == null || zipParameters.getEncryptionMethod() == EncryptionMethod.NONE) {
throw new ZipException("Encryption method has to be set when encryptFiles flag is set in zip parameters");
}
fileHeader.setEncrypted(true);
fileHeader.setEncryptionMethod(zipParameters.getEncryptionMethod());
}
String fileName = validateAndGetFileName(zipParameters.getFileNameInZip());
fileHeader.setFileName(fileName);
fileHeader.setFileNameLength(determineFileNameLength(fileName, charset));
fileHeader.setDiskNumberStart(isSplitZip ? currentDiskNumberStart : 0);
if (zipParameters.getLastModifiedFileTime() > 0) {
fileHeader.setLastModifiedTime(Zip4jUtil.javaToDosTime(zipParameters.getLastModifiedFileTime()));
} else {
fileHeader.setLastModifiedTime(Zip4jUtil.javaToDosTime(System.currentTimeMillis()));
}
//For files added by this library, this attribute will be set after closeEntry is done
fileHeader.setExternalFileAttributes(new byte[4]);
fileHeader.setDirectory(isZipEntryDirectory(fileName));
if (zipParameters.isWriteExtendedLocalFileHeader() && zipParameters.getEntrySize() == -1) {
fileHeader.setUncompressedSize(0);
} else {
fileHeader.setUncompressedSize(zipParameters.getEntrySize());
}
if (zipParameters.isEncryptFiles() && zipParameters.getEncryptionMethod() == EncryptionMethod.ZIP_STANDARD) {
fileHeader.setCrc(zipParameters.getEntryCRC());
}
fileHeader.setGeneralPurposeFlag(determineGeneralPurposeBitFlag(fileHeader.isEncrypted(), zipParameters, charset));
fileHeader.setDataDescriptorExists(zipParameters.isWriteExtendedLocalFileHeader());
return fileHeader;
}
public LocalFileHeader generateLocalFileHeader(FileHeader fileHeader) {
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setSignature(HeaderSignature.LOCAL_FILE_HEADER);
localFileHeader.setVersionNeededToExtract(fileHeader.getVersionNeededToExtract());
localFileHeader.setCompressionMethod(fileHeader.getCompressionMethod());
localFileHeader.setLastModifiedTime(fileHeader.getLastModifiedTime());
localFileHeader.setUncompressedSize(fileHeader.getUncompressedSize());
localFileHeader.setFileNameLength(fileHeader.getFileNameLength());
localFileHeader.setFileName(fileHeader.getFileName());
localFileHeader.setEncrypted(fileHeader.isEncrypted());
localFileHeader.setEncryptionMethod(fileHeader.getEncryptionMethod());
localFileHeader.setAesExtraDataRecord(fileHeader.getAesExtraDataRecord());
localFileHeader.setCrc(fileHeader.getCrc());
localFileHeader.setCompressedSize(fileHeader.getCompressedSize());
localFileHeader.setGeneralPurposeFlag(fileHeader.getGeneralPurposeFlag().clone());
localFileHeader.setDataDescriptorExists(fileHeader.isDataDescriptorExists());
return localFileHeader;
}
private byte[] determineGeneralPurposeBitFlag(boolean isEncrypted, ZipParameters zipParameters, Charset charset) {
byte[] generalPurposeBitFlag = new byte[2];
generalPurposeBitFlag[0] = generateFirstGeneralPurposeByte(isEncrypted, zipParameters);
if(charset.equals(InternalZipConstants.CHARSET_UTF_8)) {
generalPurposeBitFlag[1] = setBit(generalPurposeBitFlag[1], 3); // set 3rd bit which corresponds to utf-8 file name charset
}
return generalPurposeBitFlag;
}
private byte generateFirstGeneralPurposeByte(boolean isEncrypted, ZipParameters zipParameters) {
byte firstByte = 0;
if (isEncrypted) {
firstByte = setBit(firstByte, 0);
}
if (zipParameters.getCompressionMethod() == CompressionMethod.DEFLATE) {
if (zipParameters.getCompressionLevel() == CompressionLevel.NORMAL) {
firstByte = unsetBit(firstByte, 1);
firstByte = unsetBit(firstByte, 2);
} else if (zipParameters.getCompressionLevel() == CompressionLevel.MAXIMUM) {
firstByte = setBit(firstByte, 1);
firstByte = unsetBit(firstByte, 2);
} else if (zipParameters.getCompressionLevel() == CompressionLevel.FAST) {
firstByte = unsetBit(firstByte, 1);
firstByte = setBit(firstByte, 2);
} else if (zipParameters.getCompressionLevel() == CompressionLevel.FASTEST) {
firstByte = setBit(firstByte, 1);
firstByte = setBit(firstByte, 2);
}
}
if (zipParameters.isWriteExtendedLocalFileHeader()) {
firstByte = setBit(firstByte, 3);
}
return firstByte;
}
private String validateAndGetFileName(String fileNameInZip) throws ZipException {
if (!Zip4jUtil.isStringNotNullAndNotEmpty(fileNameInZip)) {
throw new ZipException("fileNameInZip is null or empty");
}
return fileNameInZip;
}
private AESExtraDataRecord generateAESExtraDataRecord(ZipParameters parameters) throws ZipException {
AESExtraDataRecord aesExtraDataRecord = new AESExtraDataRecord();
if (parameters.getAesVersion() != null) {
aesExtraDataRecord.setAesVersion(parameters.getAesVersion());
}
if (parameters.getAesKeyStrength() == AesKeyStrength.KEY_STRENGTH_128) {
aesExtraDataRecord.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_128);
} else if (parameters.getAesKeyStrength() == AesKeyStrength.KEY_STRENGTH_192) {
aesExtraDataRecord.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_192);
} else if (parameters.getAesKeyStrength() == AesKeyStrength.KEY_STRENGTH_256) {
aesExtraDataRecord.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
} else {
throw new ZipException("invalid AES key strength");
}
aesExtraDataRecord.setCompressionMethod(parameters.getCompressionMethod());
return aesExtraDataRecord;
}
private int determineFileNameLength(String fileName, Charset charset) {
return fileName.getBytes(charset).length;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/HeaderReader.java 0000775 0000000 0000000 00000071370 13576501616 0025272 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.CentralDirectory;
import net.lingala.zip4j.model.DataDescriptor;
import net.lingala.zip4j.model.DigitalSignature;
import net.lingala.zip4j.model.EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.ExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryLocator;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.Zip64ExtendedInfo;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.RawIO;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static net.lingala.zip4j.headers.HeaderUtil.decodeStringWithCharset;
import static net.lingala.zip4j.util.BitUtils.isBitSet;
import static net.lingala.zip4j.util.InternalZipConstants.ENDHDR;
import static net.lingala.zip4j.util.InternalZipConstants.ZIP_64_SIZE_LIMIT;
import static net.lingala.zip4j.util.Zip4jUtil.readFully;
/**
* Helper class to read header information for the zip file
*/
public class HeaderReader {
private ZipModel zipModel;
private RawIO rawIO = new RawIO();
private byte[] intBuff = new byte[4];
public ZipModel readAllHeaders(RandomAccessFile zip4jRaf, Charset charset) throws IOException {
if (zip4jRaf.length() < ENDHDR) {
throw new ZipException("Zip file size less than minimum expected zip file size. " +
"Probably not a zip file or a corrupted zip file");
}
zipModel = new ZipModel();
try {
zipModel.setEndOfCentralDirectoryRecord(readEndOfCentralDirectoryRecord(zip4jRaf, rawIO, charset));
} catch (ZipException e){
throw e;
} catch (IOException e) {
throw new ZipException("Zip headers not found. Probably not a zip file or a corrupted zip file", e);
}
// If file is Zip64 format, Zip64 headers have to be read before reading central directory
zipModel.setZip64EndOfCentralDirectoryLocator(readZip64EndOfCentralDirectoryLocator(zip4jRaf, rawIO));
if (zipModel.isZip64Format()) {
zipModel.setZip64EndOfCentralDirectoryRecord(readZip64EndCentralDirRec(zip4jRaf, rawIO));
if (zipModel.getZip64EndOfCentralDirectoryRecord() != null
&& zipModel.getZip64EndOfCentralDirectoryRecord().getNumberOfThisDisk() > 0) {
zipModel.setSplitArchive(true);
} else {
zipModel.setSplitArchive(false);
}
}
zipModel.setCentralDirectory(readCentralDirectory(zip4jRaf, rawIO, charset));
return zipModel;
}
private EndOfCentralDirectoryRecord readEndOfCentralDirectoryRecord(RandomAccessFile zip4jRaf, RawIO rawIO, Charset charset)
throws IOException {
long pos = zip4jRaf.length() - ENDHDR;
EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = new EndOfCentralDirectoryRecord();
int counter = 0;
int headerSignature;
do {
zip4jRaf.seek(pos--);
counter++;
} while (((headerSignature = rawIO.readIntLittleEndian(zip4jRaf))
!= HeaderSignature.END_OF_CENTRAL_DIRECTORY.getValue()) && counter <= 3000);
if (headerSignature != HeaderSignature.END_OF_CENTRAL_DIRECTORY.getValue()) {
throw new ZipException("Zip headers not found. Probably not a zip file");
}
endOfCentralDirectoryRecord.setSignature(HeaderSignature.END_OF_CENTRAL_DIRECTORY);
endOfCentralDirectoryRecord.setNumberOfThisDisk(rawIO.readShortLittleEndian(zip4jRaf));
endOfCentralDirectoryRecord.setNumberOfThisDiskStartOfCentralDir(rawIO.readShortLittleEndian(zip4jRaf));
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
rawIO.readShortLittleEndian(zip4jRaf));
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectory(rawIO.readShortLittleEndian(zip4jRaf));
endOfCentralDirectoryRecord.setSizeOfCentralDirectory(rawIO.readIntLittleEndian(zip4jRaf));
zip4jRaf.readFully(intBuff);
endOfCentralDirectoryRecord.setOffsetOfStartOfCentralDirectory(rawIO.readLongLittleEndian(intBuff, 0));
int commentLength = rawIO.readShortLittleEndian(zip4jRaf);
if (commentLength > 0) {
byte[] commentBuf = new byte[commentLength];
zip4jRaf.readFully(commentBuf);
endOfCentralDirectoryRecord.setComment(new String(commentBuf, charset));
} else {
endOfCentralDirectoryRecord.setComment(null);
}
zipModel.setSplitArchive(endOfCentralDirectoryRecord.getNumberOfThisDisk() > 0);
return endOfCentralDirectoryRecord;
}
private CentralDirectory readCentralDirectory(RandomAccessFile zip4jRaf, RawIO rawIO, Charset charset) throws IOException {
CentralDirectory centralDirectory = new CentralDirectory();
List fileHeaders = new ArrayList<>();
long offSetStartCentralDir = getOffsetCentralDirectory(zipModel);
long centralDirEntryCount = getNumberOfEntriesInCentralDirectory(zipModel);
if (zipModel.isZip64Format()) {
offSetStartCentralDir = zipModel.getZip64EndOfCentralDirectoryRecord()
.getOffsetStartCentralDirectoryWRTStartDiskNumber();
centralDirEntryCount = (int) zipModel.getZip64EndOfCentralDirectoryRecord()
.getTotalNumberOfEntriesInCentralDirectory();
}
zip4jRaf.seek(offSetStartCentralDir);
byte[] shortBuff = new byte[2];
byte[] intBuff = new byte[4];
for (int i = 0; i < centralDirEntryCount; i++) {
FileHeader fileHeader = new FileHeader();
if (rawIO.readIntLittleEndian(zip4jRaf) != HeaderSignature.CENTRAL_DIRECTORY.getValue()) {
throw new ZipException("Expected central directory entry not found (#" + (i + 1) + ")");
}
fileHeader.setSignature(HeaderSignature.CENTRAL_DIRECTORY);
fileHeader.setVersionMadeBy(rawIO.readShortLittleEndian(zip4jRaf));
fileHeader.setVersionNeededToExtract(rawIO.readShortLittleEndian(zip4jRaf));
byte[] generalPurposeFlags = new byte[2];
zip4jRaf.readFully(generalPurposeFlags);
fileHeader.setEncrypted(isBitSet(generalPurposeFlags[0], 0));
fileHeader.setDataDescriptorExists(isBitSet(generalPurposeFlags[0], 3));
fileHeader.setFileNameUTF8Encoded(isBitSet(generalPurposeFlags[1], 3));
fileHeader.setGeneralPurposeFlag(generalPurposeFlags.clone());
fileHeader.setCompressionMethod(CompressionMethod.getCompressionMethodFromCode(rawIO.readShortLittleEndian(
zip4jRaf)));
fileHeader.setLastModifiedTime(rawIO.readIntLittleEndian(zip4jRaf));
zip4jRaf.readFully(intBuff);
fileHeader.setCrc(rawIO.readLongLittleEndian(intBuff, 0));
fileHeader.setCrcRawData(intBuff);
fileHeader.setCompressedSize(rawIO.readLongLittleEndian(zip4jRaf, 4));
fileHeader.setUncompressedSize(rawIO.readLongLittleEndian(zip4jRaf, 4));
int fileNameLength = rawIO.readShortLittleEndian(zip4jRaf);
fileHeader.setFileNameLength(fileNameLength);
fileHeader.setExtraFieldLength(rawIO.readShortLittleEndian(zip4jRaf));
int fileCommentLength = rawIO.readShortLittleEndian(zip4jRaf);
fileHeader.setFileCommentLength(fileCommentLength);
fileHeader.setDiskNumberStart(rawIO.readShortLittleEndian(zip4jRaf));
zip4jRaf.readFully(shortBuff);
fileHeader.setInternalFileAttributes(shortBuff.clone());
zip4jRaf.readFully(intBuff);
fileHeader.setExternalFileAttributes(intBuff.clone());
zip4jRaf.readFully(intBuff);
fileHeader.setOffsetLocalHeader(rawIO.readLongLittleEndian(intBuff, 0));
if (fileNameLength > 0) {
byte[] fileNameBuff = new byte[fileNameLength];
zip4jRaf.readFully(fileNameBuff);
String fileName = decodeStringWithCharset(fileNameBuff, fileHeader.isFileNameUTF8Encoded(), charset);
if (fileName.contains(":\\")) {
fileName = fileName.substring(fileName.indexOf(":\\") + 2);
}
fileHeader.setFileName(fileName);
fileHeader.setDirectory(fileName.endsWith("/") || fileName.endsWith("\\"));
} else {
fileHeader.setFileName(null);
}
readExtraDataRecords(zip4jRaf, fileHeader);
readZip64ExtendedInfo(fileHeader, rawIO);
readAesExtraDataRecord(fileHeader, rawIO);
if (fileCommentLength > 0) {
byte[] fileCommentBuff = new byte[fileCommentLength];
zip4jRaf.readFully(fileCommentBuff);
fileHeader.setFileComment(decodeStringWithCharset(fileCommentBuff, fileHeader.isFileNameUTF8Encoded(), charset));
}
if (fileHeader.isEncrypted()) {
if (fileHeader.getAesExtraDataRecord() != null) {
fileHeader.setEncryptionMethod(EncryptionMethod.AES);
} else {
fileHeader.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
}
}
fileHeaders.add(fileHeader);
}
centralDirectory.setFileHeaders(fileHeaders);
DigitalSignature digitalSignature = new DigitalSignature();
if (rawIO.readIntLittleEndian(zip4jRaf) == HeaderSignature.DIGITAL_SIGNATURE.getValue()) {
digitalSignature.setSignature(HeaderSignature.DIGITAL_SIGNATURE);
digitalSignature.setSizeOfData(rawIO.readShortLittleEndian(zip4jRaf));
if (digitalSignature.getSizeOfData() > 0) {
byte[] signatureDataBuff = new byte[digitalSignature.getSizeOfData()];
zip4jRaf.readFully(signatureDataBuff);
digitalSignature.setSignatureData(new String(signatureDataBuff));
}
}
return centralDirectory;
}
private void readExtraDataRecords(RandomAccessFile zip4jRaf, FileHeader fileHeader)
throws IOException {
int extraFieldLength = fileHeader.getExtraFieldLength();
if (extraFieldLength <= 0) {
return;
}
fileHeader.setExtraDataRecords(readExtraDataRecords(zip4jRaf, extraFieldLength));
}
private void readExtraDataRecords(InputStream inputStream, LocalFileHeader localFileHeader)
throws IOException {
int extraFieldLength = localFileHeader.getExtraFieldLength();
if (extraFieldLength <= 0) {
return;
}
localFileHeader.setExtraDataRecords(readExtraDataRecords(inputStream, extraFieldLength));
}
private List readExtraDataRecords(RandomAccessFile zip4jRaf, int extraFieldLength)
throws IOException {
if (extraFieldLength < 4) {
if (extraFieldLength > 0) {
zip4jRaf.skipBytes(extraFieldLength);
}
return null;
}
byte[] extraFieldBuf = new byte[extraFieldLength];
zip4jRaf.read(extraFieldBuf);
try {
return parseExtraDataRecords(extraFieldBuf, extraFieldLength);
} catch (Exception e) {
// Ignore any errors when parsing extra data records
return Collections.emptyList();
}
}
private List readExtraDataRecords(InputStream inputStream, int extraFieldLength)
throws IOException {
if (extraFieldLength < 4) {
if (extraFieldLength > 0) {
inputStream.skip(extraFieldLength);
}
return null;
}
byte[] extraFieldBuf = new byte[extraFieldLength];
readFully(inputStream, extraFieldBuf);
try {
return parseExtraDataRecords(extraFieldBuf, extraFieldLength);
} catch (Exception e) {
// Ignore any errors when parsing extra data records
return Collections.emptyList();
}
}
private List parseExtraDataRecords(byte[] extraFieldBuf, int extraFieldLength) {
int counter = 0;
List extraDataRecords = new ArrayList<>();
while (counter < extraFieldLength) {
ExtraDataRecord extraDataRecord = new ExtraDataRecord();
int header = rawIO.readShortLittleEndian(extraFieldBuf, counter);
extraDataRecord.setHeader(header);
counter += 2;
int sizeOfRec = rawIO.readShortLittleEndian(extraFieldBuf, counter);
extraDataRecord.setSizeOfData(sizeOfRec);
counter += 2;
if (sizeOfRec > 0) {
byte[] data = new byte[sizeOfRec];
System.arraycopy(extraFieldBuf, counter, data, 0, sizeOfRec);
extraDataRecord.setData(data);
}
counter += sizeOfRec;
extraDataRecords.add(extraDataRecord);
}
return extraDataRecords.size() > 0 ? extraDataRecords : null;
}
private Zip64EndOfCentralDirectoryLocator readZip64EndOfCentralDirectoryLocator(RandomAccessFile zip4jRaf,
RawIO rawIO) throws IOException {
Zip64EndOfCentralDirectoryLocator zip64EndOfCentralDirectoryLocator = new Zip64EndOfCentralDirectoryLocator();
setFilePointerToReadZip64EndCentralDirLoc(zip4jRaf, rawIO);
int signature = rawIO.readIntLittleEndian(zip4jRaf);
if (signature == HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_LOCATOR.getValue()) {
zipModel.setZip64Format(true);
zip64EndOfCentralDirectoryLocator.setSignature(HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_LOCATOR);
} else {
zipModel.setZip64Format(false);
return null;
}
zip64EndOfCentralDirectoryLocator.setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(
rawIO.readIntLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryLocator.setOffsetZip64EndOfCentralDirectoryRecord(
rawIO.readLongLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryLocator.setTotalNumberOfDiscs(rawIO.readIntLittleEndian(zip4jRaf));
return zip64EndOfCentralDirectoryLocator;
}
private Zip64EndOfCentralDirectoryRecord readZip64EndCentralDirRec(RandomAccessFile zip4jRaf, RawIO rawIO)
throws IOException {
if (zipModel.getZip64EndOfCentralDirectoryLocator() == null) {
throw new ZipException("invalid zip64 end of central directory locator");
}
long offSetStartOfZip64CentralDir = zipModel.getZip64EndOfCentralDirectoryLocator()
.getOffsetZip64EndOfCentralDirectoryRecord();
if (offSetStartOfZip64CentralDir < 0) {
throw new ZipException("invalid offset for start of end of central directory record");
}
zip4jRaf.seek(offSetStartOfZip64CentralDir);
Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectoryRecord = new Zip64EndOfCentralDirectoryRecord();
int signature = rawIO.readIntLittleEndian(zip4jRaf);
if (signature != HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_RECORD.getValue()) {
throw new ZipException("invalid signature for zip64 end of central directory record");
}
zip64EndOfCentralDirectoryRecord.setSignature(HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_RECORD);
zip64EndOfCentralDirectoryRecord.setSizeOfZip64EndCentralDirectoryRecord(rawIO.readLongLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setVersionMadeBy(rawIO.readShortLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setVersionNeededToExtract(rawIO.readShortLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setNumberOfThisDisk(rawIO.readIntLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setNumberOfThisDiskStartOfCentralDirectory(rawIO.readIntLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
rawIO.readLongLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectory(rawIO.readLongLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setSizeOfCentralDirectory(rawIO.readLongLittleEndian(zip4jRaf));
zip64EndOfCentralDirectoryRecord.setOffsetStartCentralDirectoryWRTStartDiskNumber(
rawIO.readLongLittleEndian(zip4jRaf));
//zip64 extensible data sector
//44 is the size of fixed variables in this record
long extDataSecSize = zip64EndOfCentralDirectoryRecord.getSizeOfZip64EndCentralDirectoryRecord() - 44;
if (extDataSecSize > 0) {
byte[] extDataSecRecBuf = new byte[(int) extDataSecSize];
zip4jRaf.readFully(extDataSecRecBuf);
zip64EndOfCentralDirectoryRecord.setExtensibleDataSector(extDataSecRecBuf);
}
return zip64EndOfCentralDirectoryRecord;
}
private void readZip64ExtendedInfo(FileHeader fileHeader, RawIO rawIO) throws ZipException {
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() <= 0) {
return;
}
Zip64ExtendedInfo zip64ExtendedInfo = readZip64ExtendedInfo(fileHeader.getExtraDataRecords(), rawIO,
fileHeader.getUncompressedSize(), fileHeader.getCompressedSize(), fileHeader.getOffsetLocalHeader());
if (zip64ExtendedInfo == null) {
return;
}
fileHeader.setZip64ExtendedInfo(zip64ExtendedInfo);
if (zip64ExtendedInfo.getUncompressedSize() != -1) {
fileHeader.setUncompressedSize(zip64ExtendedInfo.getUncompressedSize());
}
if (zip64ExtendedInfo.getCompressedSize() != -1) {
fileHeader.setCompressedSize(zip64ExtendedInfo.getCompressedSize());
}
if (zip64ExtendedInfo.getOffsetLocalHeader() != -1) {
fileHeader.setOffsetLocalHeader(zip64ExtendedInfo.getOffsetLocalHeader());
}
if (zip64ExtendedInfo.getDiskNumberStart() != -1) {
fileHeader.setDiskNumberStart(zip64ExtendedInfo.getDiskNumberStart());
}
}
private void readZip64ExtendedInfo(LocalFileHeader localFileHeader, RawIO rawIO) throws ZipException {
if (localFileHeader == null) {
throw new ZipException("file header is null in reading Zip64 Extended Info");
}
if (localFileHeader.getExtraDataRecords() == null || localFileHeader.getExtraDataRecords().size() <= 0) {
return;
}
Zip64ExtendedInfo zip64ExtendedInfo = readZip64ExtendedInfo(localFileHeader.getExtraDataRecords(), rawIO,
localFileHeader.getUncompressedSize(), localFileHeader.getCompressedSize(), 0);
if (zip64ExtendedInfo == null) {
return;
}
localFileHeader.setZip64ExtendedInfo(zip64ExtendedInfo);
if (zip64ExtendedInfo.getUncompressedSize() != -1) {
localFileHeader.setUncompressedSize(zip64ExtendedInfo.getUncompressedSize());
}
if (zip64ExtendedInfo.getCompressedSize() != -1) {
localFileHeader.setCompressedSize(zip64ExtendedInfo.getCompressedSize());
}
}
private Zip64ExtendedInfo readZip64ExtendedInfo(List extraDataRecords, RawIO rawIO,
long uncompressedSize, long compressedSize, long offsetLocalHeader)
throws ZipException {
for (ExtraDataRecord extraDataRecord : extraDataRecords) {
if (extraDataRecord == null) {
continue;
}
if (HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue() == extraDataRecord.getHeader()) {
Zip64ExtendedInfo zip64ExtendedInfo = new Zip64ExtendedInfo();
byte[] extraData = extraDataRecord.getData();
if (extraDataRecord.getSizeOfData() <= 0) {
throw new ZipException("No data present for Zip64Extended info");
}
int counter = 0;
if (counter < extraDataRecord.getSizeOfData() && uncompressedSize == ZIP_64_SIZE_LIMIT) {
zip64ExtendedInfo.setUncompressedSize(rawIO.readLongLittleEndian(extraData, counter));
counter += 8;
}
if ( counter < extraDataRecord.getSizeOfData() && compressedSize == ZIP_64_SIZE_LIMIT) {
zip64ExtendedInfo.setCompressedSize(rawIO.readLongLittleEndian(extraData, counter));
counter += 8;
}
if (counter < extraDataRecord.getSizeOfData() && offsetLocalHeader == ZIP_64_SIZE_LIMIT) {
zip64ExtendedInfo.setOffsetLocalHeader(rawIO.readLongLittleEndian(extraData, counter));
counter += 8;
}
if (counter < extraDataRecord.getSizeOfData()) {
zip64ExtendedInfo.setDiskNumberStart(rawIO.readIntLittleEndian(extraData, counter));
}
return zip64ExtendedInfo;
}
}
return null;
}
private void setFilePointerToReadZip64EndCentralDirLoc(RandomAccessFile zip4jRaf, RawIO rawIO) throws IOException {
long pos = zip4jRaf.length() - ENDHDR;
do {
zip4jRaf.seek(pos--);
} while (rawIO.readIntLittleEndian(zip4jRaf) != HeaderSignature.END_OF_CENTRAL_DIRECTORY.getValue());
// Now the file pointer is at the end of signature of Central Dir Rec
// Seek back with the following values
// 4 -> end of central dir signature
// 4 -> total number of disks
// 8 -> relative offset of the zip64 end of central directory record
// 4 -> number of the disk with the start of the zip64 end of central directory
// 4 -> zip64 end of central dir locator signature
// Refer to Appnote for more information
zip4jRaf.seek(zip4jRaf.getFilePointer() - 4 - 4 - 8 - 4 - 4);
}
public LocalFileHeader readLocalFileHeader(InputStream inputStream, Charset charset) throws IOException {
LocalFileHeader localFileHeader = new LocalFileHeader();
byte[] intBuff = new byte[4];
//signature
int sig = rawIO.readIntLittleEndian(inputStream);
if (sig != HeaderSignature.LOCAL_FILE_HEADER.getValue()) {
return null;
}
localFileHeader.setSignature(HeaderSignature.LOCAL_FILE_HEADER);
localFileHeader.setVersionNeededToExtract(rawIO.readShortLittleEndian(inputStream));
byte[] generalPurposeFlags = new byte[2];
if (readFully(inputStream, generalPurposeFlags) != 2) {
throw new ZipException("Could not read enough bytes for generalPurposeFlags");
}
localFileHeader.setEncrypted(isBitSet(generalPurposeFlags[0], 0));
localFileHeader.setDataDescriptorExists(isBitSet(generalPurposeFlags[0], 3));
localFileHeader.setFileNameUTF8Encoded(isBitSet(generalPurposeFlags[1], 3));
localFileHeader.setGeneralPurposeFlag(generalPurposeFlags.clone());
localFileHeader.setCompressionMethod(CompressionMethod.getCompressionMethodFromCode(
rawIO.readShortLittleEndian(inputStream)));
localFileHeader.setLastModifiedTime(rawIO.readIntLittleEndian(inputStream));
readFully(inputStream, intBuff);
localFileHeader.setCrc(rawIO.readLongLittleEndian(intBuff, 0));
localFileHeader.setCrcRawData(intBuff.clone());
localFileHeader.setCompressedSize(rawIO.readLongLittleEndian(inputStream, 4));
localFileHeader.setUncompressedSize(rawIO.readLongLittleEndian(inputStream, 4));
int fileNameLength = rawIO.readShortLittleEndian(inputStream);
localFileHeader.setFileNameLength(fileNameLength);
localFileHeader.setExtraFieldLength(rawIO.readShortLittleEndian(inputStream));
if (fileNameLength > 0) {
byte[] fileNameBuf = new byte[fileNameLength];
readFully(inputStream, fileNameBuf);
// Modified after user reported an issue http://www.lingala.net/zip4j/forum/index.php?topic=2.0
// String fileName = new String(fileNameBuf, "Cp850");
// String fileName = Zip4jUtil.getCp850EncodedString(fileNameBuf);
String fileName = decodeStringWithCharset(fileNameBuf, localFileHeader.isFileNameUTF8Encoded(), charset);
if (fileName == null) {
throw new ZipException("file name is null, cannot assign file name to local file header");
}
if (fileName.contains(":" + System.getProperty("file.separator"))) {
fileName = fileName.substring(fileName.indexOf(":" + System.getProperty("file.separator")) + 2);
}
localFileHeader.setFileName(fileName);
localFileHeader.setDirectory(fileName.endsWith("/") || fileName.endsWith("\\"));
} else {
localFileHeader.setFileName(null);
}
readExtraDataRecords(inputStream, localFileHeader);
readZip64ExtendedInfo(localFileHeader, rawIO);
readAesExtraDataRecord(localFileHeader, rawIO);
if (localFileHeader.isEncrypted()) {
if (localFileHeader.getEncryptionMethod() == EncryptionMethod.AES) {
//Do nothing
} else {
if (BigInteger.valueOf(localFileHeader.getGeneralPurposeFlag()[0]).testBit(6)) {
localFileHeader.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD_VARIANT_STRONG);
} else {
localFileHeader.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
}
}
}
return localFileHeader;
}
public DataDescriptor readDataDescriptor(InputStream inputStream, boolean isZip64Format) throws IOException {
DataDescriptor dataDescriptor = new DataDescriptor();
byte[] intBuff = new byte[4];
readFully(inputStream, intBuff);
long sigOrCrc = rawIO.readLongLittleEndian(intBuff, 0);
//According to zip specification, presence of extra data record header signature is optional.
//If this signature is present, read it and read the next 4 bytes for crc
//If signature not present, assign the read 4 bytes for crc
if (sigOrCrc == HeaderSignature.EXTRA_DATA_RECORD.getValue()) {
dataDescriptor.setSignature(HeaderSignature.EXTRA_DATA_RECORD);
readFully(inputStream, intBuff);
dataDescriptor.setCrc(rawIO.readLongLittleEndian(intBuff, 0));
} else {
dataDescriptor.setCrc(sigOrCrc);
}
if (isZip64Format) {
dataDescriptor.setCompressedSize(rawIO.readLongLittleEndian(inputStream));
dataDescriptor.setUncompressedSize(rawIO.readLongLittleEndian(inputStream));
} else {
dataDescriptor.setCompressedSize(rawIO.readIntLittleEndian(inputStream));
dataDescriptor.setUncompressedSize(rawIO.readIntLittleEndian(inputStream));
}
return dataDescriptor;
}
private void readAesExtraDataRecord(FileHeader fileHeader, RawIO rawIO) throws ZipException {
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() <= 0) {
return;
}
AESExtraDataRecord aesExtraDataRecord = readAesExtraDataRecord(fileHeader.getExtraDataRecords(), rawIO);
if (aesExtraDataRecord != null) {
fileHeader.setAesExtraDataRecord(aesExtraDataRecord);
fileHeader.setEncryptionMethod(EncryptionMethod.AES);
}
}
private void readAesExtraDataRecord(LocalFileHeader localFileHeader, RawIO rawIO) throws ZipException {
if (localFileHeader.getExtraDataRecords() == null || localFileHeader.getExtraDataRecords().size() <= 0) {
return;
}
AESExtraDataRecord aesExtraDataRecord = readAesExtraDataRecord(localFileHeader.getExtraDataRecords(), rawIO);
if (aesExtraDataRecord != null) {
localFileHeader.setAesExtraDataRecord(aesExtraDataRecord);
localFileHeader.setEncryptionMethod(EncryptionMethod.AES);
}
}
private AESExtraDataRecord readAesExtraDataRecord(List extraDataRecords, RawIO rawIO)
throws ZipException {
if (extraDataRecords == null) {
return null;
}
for (ExtraDataRecord extraDataRecord : extraDataRecords) {
if (extraDataRecord == null) {
continue;
}
if (extraDataRecord.getHeader() == HeaderSignature.AES_EXTRA_DATA_RECORD.getValue()) {
if (extraDataRecord.getData() == null) {
throw new ZipException("corrupt AES extra data records");
}
AESExtraDataRecord aesExtraDataRecord = new AESExtraDataRecord();
aesExtraDataRecord.setSignature(HeaderSignature.AES_EXTRA_DATA_RECORD);
aesExtraDataRecord.setDataSize(extraDataRecord.getSizeOfData());
byte[] aesData = extraDataRecord.getData();
aesExtraDataRecord.setAesVersion(AesVersion.getFromVersionNumber(rawIO.readShortLittleEndian(aesData, 0)));
byte[] vendorIDBytes = new byte[2];
System.arraycopy(aesData, 2, vendorIDBytes, 0, 2);
aesExtraDataRecord.setVendorID(new String(vendorIDBytes));
aesExtraDataRecord.setAesKeyStrength(AesKeyStrength.getAesKeyStrengthFromRawCode(aesData[4] & 0xFF));
aesExtraDataRecord.setCompressionMethod(
CompressionMethod.getCompressionMethodFromCode(rawIO.readShortLittleEndian(aesData, 5)));
return aesExtraDataRecord;
}
}
return null;
}
private long getOffsetCentralDirectory(ZipModel zipModel) {
if (zipModel.isZip64Format()) {
return zipModel.getZip64EndOfCentralDirectoryRecord().getOffsetStartCentralDirectoryWRTStartDiskNumber();
}
return zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory();
}
private long getNumberOfEntriesInCentralDirectory(ZipModel zipModel) {
if (zipModel.isZip64Format()) {
return zipModel.getZip64EndOfCentralDirectoryRecord().getTotalNumberOfEntriesInCentralDirectory();
}
return zipModel.getEndOfCentralDirectoryRecord().getTotalNumberOfEntriesInCentralDirectory();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/HeaderSignature.java 0000664 0000000 0000000 00000001245 13576501616 0026020 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
public enum HeaderSignature {
LOCAL_FILE_HEADER(0x04034b50L), // "PK\003\004"
EXTRA_DATA_RECORD(0x08074b50L), // "PK\007\008"
CENTRAL_DIRECTORY(0x02014b50L), // "PK\001\002"
END_OF_CENTRAL_DIRECTORY(0x06054b50L), // "PK\005\006"
DIGITAL_SIGNATURE(0x05054b50L),
ARCEXTDATREC(0x08064b50L),
SPLIT_ZIP(0x08074b50L),
ZIP64_END_CENTRAL_DIRECTORY_LOCATOR(0x07064b50L),
ZIP64_END_CENTRAL_DIRECTORY_RECORD(0x06064b50),
ZIP64_EXTRA_FIELD_SIGNATURE(0x0001),
AES_EXTRA_DATA_RECORD(0x9901);
private long value;
HeaderSignature(long value) {
this.value = value;
}
public long getValue() {
return value;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/HeaderUtil.java 0000664 0000000 0000000 00000007610 13576501616 0024776 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.List;
import static net.lingala.zip4j.util.InternalZipConstants.ZIP_STANDARD_CHARSET;
import static net.lingala.zip4j.util.Zip4jUtil.isStringNotNullAndNotEmpty;
public class HeaderUtil {
public static FileHeader getFileHeader(ZipModel zipModel, String fileName) throws ZipException {
FileHeader fileHeader = getFileHeaderWithExactMatch(zipModel, fileName);
if (fileHeader == null) {
fileName = fileName.replaceAll("\\\\", "/");
fileHeader = getFileHeaderWithExactMatch(zipModel, fileName);
if (fileHeader == null) {
fileName = fileName.replaceAll("/", "\\\\");
fileHeader = getFileHeaderWithExactMatch(zipModel, fileName);
}
}
return fileHeader;
}
public static int getIndexOfFileHeader(ZipModel zipModel, FileHeader fileHeader) throws ZipException {
if (zipModel == null || fileHeader == null) {
throw new ZipException("input parameters is null, cannot determine index of file header");
}
if (zipModel.getCentralDirectory() == null
|| zipModel.getCentralDirectory().getFileHeaders() == null
|| zipModel.getCentralDirectory().getFileHeaders().size() <= 0) {
return -1;
}
String fileName = fileHeader.getFileName();
if (!isStringNotNullAndNotEmpty(fileName)) {
throw new ZipException("file name in file header is empty or null, cannot determine index of file header");
}
List fileHeadersFromCentralDir = zipModel.getCentralDirectory().getFileHeaders();
for (int i = 0; i < fileHeadersFromCentralDir.size(); i++) {
FileHeader fileHeaderFromCentralDir = fileHeadersFromCentralDir.get(i);
String fileNameForHdr = fileHeaderFromCentralDir.getFileName();
if (!isStringNotNullAndNotEmpty(fileNameForHdr)) {
continue;
}
if (fileName.equalsIgnoreCase(fileNameForHdr)) {
return i;
}
}
return -1;
}
public static String decodeStringWithCharset(byte[] data, boolean isUtf8Encoded, Charset charset) {
if(charset != null) {
return new String(data, charset);
}
if (isUtf8Encoded) {
return new String(data, InternalZipConstants.CHARSET_UTF_8);
}
try {
return new String(data, ZIP_STANDARD_CHARSET);
} catch (UnsupportedEncodingException e) {
return new String(data);
}
}
private static FileHeader getFileHeaderWithExactMatch(ZipModel zipModel, String fileName) throws ZipException {
if (zipModel == null) {
throw new ZipException("zip model is null, cannot determine file header with exact match for fileName: "
+ fileName);
}
if (!isStringNotNullAndNotEmpty(fileName)) {
throw new ZipException("file name is null, cannot determine file header with exact match for fileName: "
+ fileName);
}
if (zipModel.getCentralDirectory() == null) {
throw new ZipException("central directory is null, cannot determine file header with exact match for fileName: "
+ fileName);
}
if (zipModel.getCentralDirectory().getFileHeaders() == null) {
throw new ZipException("file Headers are null, cannot determine file header with exact match for fileName: "
+ fileName);
}
if (zipModel.getCentralDirectory().getFileHeaders().size() == 0) {
return null;
}
for (FileHeader fileHeader : zipModel.getCentralDirectory().getFileHeaders()) {
String fileNameForHdr = fileHeader.getFileName();
if (!isStringNotNullAndNotEmpty(fileNameForHdr)) {
continue;
}
if (fileName.equalsIgnoreCase(fileNameForHdr)) {
return fileHeader;
}
}
return null;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/headers/HeaderWriter.java 0000775 0000000 0000000 00000074014 13576501616 0025342 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.CountingOutputStream;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.ExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryLocator;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.RawIO;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import static net.lingala.zip4j.util.FileUtils.getZipFileNameWithoutExtension;
import static net.lingala.zip4j.util.InternalZipConstants.ZIP_64_SIZE_LIMIT;
import static net.lingala.zip4j.util.Zip4jUtil.isStringNotNullAndNotEmpty;
public class HeaderWriter {
private static final short ZIP64_EXTRA_DATA_RECORD_SIZE_LFH = 16;
private static final short ZIP64_EXTRA_DATA_RECORD_SIZE_FH = 28;
private static final short AES_EXTRA_DATA_RECORD_SIZE = 11;
private RawIO rawIO = new RawIO();
private byte[] longBuff = new byte[8];
public void writeLocalFileHeader(ZipModel zipModel, LocalFileHeader localFileHeader, OutputStream outputStream,
Charset charset) throws IOException {
try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
rawIO.writeIntLittleEndian(byteArrayOutputStream, (int) localFileHeader.getSignature().getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream, localFileHeader.getVersionNeededToExtract());
byteArrayOutputStream.write(localFileHeader.getGeneralPurposeFlag());
rawIO.writeShortLittleEndian(byteArrayOutputStream, localFileHeader.getCompressionMethod().getCode());
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getLastModifiedTime());
byteArrayOutputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getCrc());
byteArrayOutputStream.write(longBuff, 0, 4);
boolean writeZip64Header = localFileHeader.getCompressedSize() >= ZIP_64_SIZE_LIMIT
|| localFileHeader.getUncompressedSize() >= ZIP_64_SIZE_LIMIT;
if (writeZip64Header) {
rawIO.writeLongLittleEndian(longBuff, 0, ZIP_64_SIZE_LIMIT);
//Set the uncompressed size to ZipConstants.ZIP_64_SIZE_LIMIT as
//these values will be stored in Zip64 extra record
byteArrayOutputStream.write(longBuff, 0, 4);
byteArrayOutputStream.write(longBuff, 0, 4);
zipModel.setZip64Format(true);
localFileHeader.setWriteCompressedSizeInZip64ExtraRecord(true);
} else {
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getCompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getUncompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
localFileHeader.setWriteCompressedSizeInZip64ExtraRecord(false);
}
byte[] fileNameBytes = new byte[0];
if (isStringNotNullAndNotEmpty(localFileHeader.getFileName())) {
fileNameBytes = localFileHeader.getFileName().getBytes(charset);
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileNameBytes.length);
int extraFieldLength = 0;
if (writeZip64Header) {
extraFieldLength += ZIP64_EXTRA_DATA_RECORD_SIZE_LFH + 4; // 4 for signature + size of record
}
if (localFileHeader.getAesExtraDataRecord() != null) {
extraFieldLength += AES_EXTRA_DATA_RECORD_SIZE;
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, extraFieldLength);
if (fileNameBytes.length > 0) {
byteArrayOutputStream.write(fileNameBytes);
}
//Zip64 should be the first extra data record that should be written
//This is NOT according to any specification but if this is changed
//corresponding logic for updateLocalFileHeader for compressed size
//has to be modified as well
if (writeZip64Header) {
rawIO.writeShortLittleEndian(byteArrayOutputStream,
(int) HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream, ZIP64_EXTRA_DATA_RECORD_SIZE_LFH);
rawIO.writeLongLittleEndian(byteArrayOutputStream, localFileHeader.getUncompressedSize());
rawIO.writeLongLittleEndian(byteArrayOutputStream, localFileHeader.getCompressedSize());
}
if (localFileHeader.getAesExtraDataRecord() != null) {
AESExtraDataRecord aesExtraDataRecord = localFileHeader.getAesExtraDataRecord();
rawIO.writeShortLittleEndian(byteArrayOutputStream, (int) aesExtraDataRecord.getSignature().getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getDataSize());
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getAesVersion().getVersionNumber());
byteArrayOutputStream.write(aesExtraDataRecord.getVendorID().getBytes());
byte[] aesStrengthBytes = new byte[1];
aesStrengthBytes[0] = (byte) aesExtraDataRecord.getAesKeyStrength().getRawCode();
byteArrayOutputStream.write(aesStrengthBytes);
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getCompressionMethod().getCode());
}
outputStream.write(byteArrayOutputStream.toByteArray());
}
}
public void writeExtendedLocalHeader(LocalFileHeader localFileHeader, OutputStream outputStream)
throws IOException {
if (localFileHeader == null || outputStream == null) {
throw new ZipException("input parameters is null, cannot write extended local header");
}
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
rawIO.writeIntLittleEndian(byteArrayOutputStream, (int) HeaderSignature.EXTRA_DATA_RECORD.getValue());
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getCrc());
byteArrayOutputStream.write(longBuff, 0, 4);
if (localFileHeader.isWriteCompressedSizeInZip64ExtraRecord()) {
rawIO.writeLongLittleEndian(byteArrayOutputStream, localFileHeader.getCompressedSize());
rawIO.writeLongLittleEndian(byteArrayOutputStream, localFileHeader.getUncompressedSize());
} else {
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getCompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, localFileHeader.getUncompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
}
outputStream.write(byteArrayOutputStream.toByteArray());
}
}
public void finalizeZipFile(ZipModel zipModel, OutputStream outputStream, Charset charset) throws IOException {
if (zipModel == null || outputStream == null) {
throw new ZipException("input parameters is null, cannot finalize zip file");
}
try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
processHeaderData(zipModel, outputStream);
long offsetCentralDir = zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory();
writeCentralDirectory(zipModel, byteArrayOutputStream, rawIO, charset);
int sizeOfCentralDir = byteArrayOutputStream.size();
if (zipModel.isZip64Format() || offsetCentralDir >= InternalZipConstants.ZIP_64_SIZE_LIMIT
|| zipModel.getCentralDirectory().getFileHeaders().size() >= InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT) {
if (zipModel.getZip64EndOfCentralDirectoryRecord() == null) {
zipModel.setZip64EndOfCentralDirectoryRecord(new Zip64EndOfCentralDirectoryRecord());
}
if (zipModel.getZip64EndOfCentralDirectoryLocator() == null) {
zipModel.setZip64EndOfCentralDirectoryLocator(new Zip64EndOfCentralDirectoryLocator());
}
zipModel.getZip64EndOfCentralDirectoryLocator().setOffsetZip64EndOfCentralDirectoryRecord(offsetCentralDir
+ sizeOfCentralDir);
if (isSplitZipFile(outputStream)) {
int currentSplitFileCounter = getCurrentSplitFileCounter(outputStream);
zipModel.getZip64EndOfCentralDirectoryLocator().setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(
currentSplitFileCounter);
zipModel.getZip64EndOfCentralDirectoryLocator().setTotalNumberOfDiscs(currentSplitFileCounter + 1);
} else {
zipModel.getZip64EndOfCentralDirectoryLocator().setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(0);
zipModel.getZip64EndOfCentralDirectoryLocator().setTotalNumberOfDiscs(1);
}
writeZip64EndOfCentralDirectoryRecord(zipModel, sizeOfCentralDir, offsetCentralDir, byteArrayOutputStream,
rawIO);
writeZip64EndOfCentralDirectoryLocator(zipModel, byteArrayOutputStream, rawIO);
}
writeEndOfCentralDirectoryRecord(zipModel, sizeOfCentralDir, offsetCentralDir, byteArrayOutputStream, rawIO, charset);
writeZipHeaderBytes(zipModel, outputStream, byteArrayOutputStream.toByteArray(), charset);
}
}
public void finalizeZipFileWithoutValidations(ZipModel zipModel, OutputStream outputStream, Charset charset) throws IOException {
if (zipModel == null || outputStream == null) {
throw new ZipException("input parameters is null, cannot finalize zip file without validations");
}
try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
long offsetCentralDir = zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory();
writeCentralDirectory(zipModel, byteArrayOutputStream, rawIO, charset);
int sizeOfCentralDir = byteArrayOutputStream.size();
if (zipModel.isZip64Format() || offsetCentralDir >= InternalZipConstants.ZIP_64_SIZE_LIMIT
|| zipModel.getCentralDirectory().getFileHeaders().size() >= InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT) {
if (zipModel.getZip64EndOfCentralDirectoryRecord() == null) {
zipModel.setZip64EndOfCentralDirectoryRecord(new Zip64EndOfCentralDirectoryRecord());
}
if (zipModel.getZip64EndOfCentralDirectoryLocator() == null) {
zipModel.setZip64EndOfCentralDirectoryLocator(new Zip64EndOfCentralDirectoryLocator());
}
zipModel.getZip64EndOfCentralDirectoryLocator().setOffsetZip64EndOfCentralDirectoryRecord(offsetCentralDir
+ sizeOfCentralDir);
writeZip64EndOfCentralDirectoryRecord(zipModel, sizeOfCentralDir, offsetCentralDir, byteArrayOutputStream,
rawIO);
writeZip64EndOfCentralDirectoryLocator(zipModel, byteArrayOutputStream, rawIO);
}
writeEndOfCentralDirectoryRecord(zipModel, sizeOfCentralDir, offsetCentralDir, byteArrayOutputStream, rawIO, charset);
writeZipHeaderBytes(zipModel, outputStream, byteArrayOutputStream.toByteArray(), charset);
}
}
public void updateLocalFileHeader(FileHeader fileHeader, ZipModel zipModel, SplitOutputStream outputStream)
throws IOException {
if (fileHeader == null || zipModel == null) {
throw new ZipException("invalid input parameters, cannot update local file header");
}
boolean closeFlag = false;
SplitOutputStream currOutputStream;
if (fileHeader.getDiskNumberStart() != outputStream.getCurrentSplitFileCounter()) {
String parentFile = zipModel.getZipFile().getParent();
String fileNameWithoutExt = getZipFileNameWithoutExtension(zipModel.getZipFile().getName());
String fileName = parentFile + System.getProperty("file.separator");
if (fileHeader.getDiskNumberStart() < 9) {
fileName += fileNameWithoutExt + ".z0" + (fileHeader.getDiskNumberStart() + 1);
} else {
fileName += fileNameWithoutExt + ".z" + (fileHeader.getDiskNumberStart() + 1);
}
currOutputStream = new SplitOutputStream(new File(fileName));
closeFlag = true;
} else {
currOutputStream = outputStream;
}
long currOffset = currOutputStream.getFilePointer();
currOutputStream.seek(fileHeader.getOffsetLocalHeader() + InternalZipConstants.UPDATE_LFH_CRC);
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getCrc());
currOutputStream.write(longBuff, 0, 4);
updateFileSizesInLocalFileHeader(currOutputStream, fileHeader);
if (closeFlag) {
currOutputStream.close();
} else {
outputStream.seek(currOffset);
}
}
private void updateFileSizesInLocalFileHeader(SplitOutputStream outputStream, FileHeader fileHeader)
throws IOException {
if (fileHeader.getUncompressedSize() >= ZIP_64_SIZE_LIMIT) {
rawIO.writeLongLittleEndian(longBuff, 0, ZIP_64_SIZE_LIMIT);
outputStream.write(longBuff, 0, 4);
outputStream.write(longBuff, 0, 4);
//2 - file name length
//2 - extra field length
//variable - file name which can be determined by fileNameLength
//2 - Zip64 signature
//2 - size of zip64 data
//8 - uncompressed size
//8 - compressed size
int zip64CompressedSizeOffset = 2 + 2 + fileHeader.getFileNameLength() + 2 + 2;
if (outputStream.skipBytes(zip64CompressedSizeOffset) != zip64CompressedSizeOffset) {
throw new ZipException("Unable to skip " + zip64CompressedSizeOffset + " bytes to update LFH");
}
rawIO.writeLongLittleEndian(outputStream, fileHeader.getUncompressedSize());
rawIO.writeLongLittleEndian(outputStream, fileHeader.getCompressedSize());
} else {
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getCompressedSize());
outputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getUncompressedSize());
outputStream.write(longBuff, 0, 4);
}
}
private boolean isSplitZipFile(OutputStream outputStream) {
if (outputStream instanceof SplitOutputStream) {
return ((SplitOutputStream) outputStream).isSplitZipFile();
} else if (outputStream instanceof CountingOutputStream) {
return ((CountingOutputStream) outputStream).isSplitZipFile();
}
return false;
}
private int getCurrentSplitFileCounter(OutputStream outputStream) {
if (outputStream instanceof SplitOutputStream) {
return ((SplitOutputStream) outputStream).getCurrentSplitFileCounter();
}
return ((CountingOutputStream) outputStream).getCurrentSplitFileCounter();
}
private void writeZipHeaderBytes(ZipModel zipModel, OutputStream outputStream, byte[] buff, Charset charset) throws IOException {
if (buff == null) {
throw new ZipException("invalid buff to write as zip headers");
}
if (outputStream instanceof CountingOutputStream) {
if (((CountingOutputStream) outputStream).checkBuffSizeAndStartNextSplitFile(buff.length)) {
finalizeZipFile(zipModel, outputStream, charset);
return;
}
}
outputStream.write(buff);
}
private void processHeaderData(ZipModel zipModel, OutputStream outputStream) throws IOException {
int currentSplitFileCounter = 0;
if (outputStream instanceof CountingOutputStream) {
zipModel.getEndOfCentralDirectoryRecord().setOffsetOfStartOfCentralDirectory(
((CountingOutputStream) outputStream).getFilePointer());
currentSplitFileCounter = ((CountingOutputStream) outputStream).getCurrentSplitFileCounter();
}
if (zipModel.isZip64Format()) {
if (zipModel.getZip64EndOfCentralDirectoryRecord() == null) {
zipModel.setZip64EndOfCentralDirectoryRecord(new Zip64EndOfCentralDirectoryRecord());
}
if (zipModel.getZip64EndOfCentralDirectoryLocator() == null) {
zipModel.setZip64EndOfCentralDirectoryLocator(new Zip64EndOfCentralDirectoryLocator());
}
zipModel.getZip64EndOfCentralDirectoryLocator().setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(
currentSplitFileCounter);
zipModel.getZip64EndOfCentralDirectoryLocator().setTotalNumberOfDiscs(currentSplitFileCounter + 1);
}
zipModel.getEndOfCentralDirectoryRecord().setNumberOfThisDisk(currentSplitFileCounter);
zipModel.getEndOfCentralDirectoryRecord().setNumberOfThisDiskStartOfCentralDir(currentSplitFileCounter);
}
private void writeCentralDirectory(ZipModel zipModel, ByteArrayOutputStream byteArrayOutputStream, RawIO rawIO, Charset charset)
throws ZipException {
if (zipModel.getCentralDirectory() == null || zipModel.getCentralDirectory().getFileHeaders() == null
|| zipModel.getCentralDirectory().getFileHeaders().size() <= 0) {
return;
}
for (FileHeader fileHeader: zipModel.getCentralDirectory().getFileHeaders()) {
writeFileHeader(zipModel, fileHeader, byteArrayOutputStream, rawIO, charset);
}
}
private void writeFileHeader(ZipModel zipModel, FileHeader fileHeader, ByteArrayOutputStream byteArrayOutputStream,
RawIO rawIO, Charset charset) throws ZipException {
if (fileHeader == null) {
throw new ZipException("input parameters is null, cannot write local file header");
}
try {
final byte[] emptyShortByte = {0, 0};
boolean writeZip64ExtendedInfo = false;
if (isZip64Entry(fileHeader)) {
writeZip64ExtendedInfo = true;
}
rawIO.writeIntLittleEndian(byteArrayOutputStream, (int) fileHeader.getSignature().getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileHeader.getVersionMadeBy());
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileHeader.getVersionNeededToExtract());
byteArrayOutputStream.write(fileHeader.getGeneralPurposeFlag());
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileHeader.getCompressionMethod().getCode());
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getLastModifiedTime());
byteArrayOutputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getCrc());
byteArrayOutputStream.write(longBuff, 0, 4);
if (writeZip64ExtendedInfo) {
rawIO.writeLongLittleEndian(longBuff, 0, ZIP_64_SIZE_LIMIT);
byteArrayOutputStream.write(longBuff, 0, 4);
byteArrayOutputStream.write(longBuff, 0, 4);
zipModel.setZip64Format(true);
} else {
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getCompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getUncompressedSize());
byteArrayOutputStream.write(longBuff, 0, 4);
}
byte[] fileNameBytes = new byte[0];
if (isStringNotNullAndNotEmpty(fileHeader.getFileName())) {
fileNameBytes = fileHeader.getFileName().getBytes(charset);
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileNameBytes.length);
//Compute offset bytes before extra field is written for Zip64 compatibility
//NOTE: this data is not written now, but written at a later point
byte[] offsetLocalHeaderBytes = new byte[4];
if (writeZip64ExtendedInfo) {
rawIO.writeLongLittleEndian(longBuff, 0, ZIP_64_SIZE_LIMIT);
System.arraycopy(longBuff, 0, offsetLocalHeaderBytes, 0, 4);
} else {
rawIO.writeLongLittleEndian(longBuff, 0, fileHeader.getOffsetLocalHeader());
System.arraycopy(longBuff, 0, offsetLocalHeaderBytes, 0, 4);
}
int extraFieldLength = calculateExtraDataRecordsSize(fileHeader, writeZip64ExtendedInfo);
rawIO.writeShortLittleEndian(byteArrayOutputStream, extraFieldLength);
String fileComment = fileHeader.getFileComment();
byte[] fileCommentBytes = new byte[0];
if (isStringNotNullAndNotEmpty(fileComment)) {
fileCommentBytes = fileComment.getBytes(charset);
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileCommentBytes.length);
//Skip disk number start for now
rawIO.writeShortLittleEndian(byteArrayOutputStream, fileHeader.getDiskNumberStart());
//Skip internal file attributes for now
byteArrayOutputStream.write(emptyShortByte);
//External file attributes
byteArrayOutputStream.write(fileHeader.getExternalFileAttributes());
//offset local header - this data is computed above
byteArrayOutputStream.write(offsetLocalHeaderBytes);
if (fileNameBytes.length > 0) {
byteArrayOutputStream.write(fileNameBytes);
}
if (writeZip64ExtendedInfo) {
zipModel.setZip64Format(true);
//Zip64 header
rawIO.writeShortLittleEndian(byteArrayOutputStream,
(int) HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue());
//size of data
rawIO.writeShortLittleEndian(byteArrayOutputStream, ZIP64_EXTRA_DATA_RECORD_SIZE_FH);
rawIO.writeLongLittleEndian(byteArrayOutputStream, fileHeader.getUncompressedSize());
rawIO.writeLongLittleEndian(byteArrayOutputStream, fileHeader.getCompressedSize());
rawIO.writeLongLittleEndian(byteArrayOutputStream, fileHeader.getOffsetLocalHeader());
rawIO.writeIntLittleEndian(byteArrayOutputStream, fileHeader.getDiskNumberStart());
}
if (fileHeader.getAesExtraDataRecord() != null) {
AESExtraDataRecord aesExtraDataRecord = fileHeader.getAesExtraDataRecord();
rawIO.writeShortLittleEndian(byteArrayOutputStream, (int) aesExtraDataRecord.getSignature().getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getDataSize());
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getAesVersion().getVersionNumber());
byteArrayOutputStream.write(aesExtraDataRecord.getVendorID().getBytes());
byte[] aesStrengthBytes = new byte[1];
aesStrengthBytes[0] = (byte) aesExtraDataRecord.getAesKeyStrength().getRawCode();
byteArrayOutputStream.write(aesStrengthBytes);
rawIO.writeShortLittleEndian(byteArrayOutputStream, aesExtraDataRecord.getCompressionMethod().getCode());
}
writeRemainingExtraDataRecordsIfPresent(fileHeader, byteArrayOutputStream);
if (fileCommentBytes.length > 0) {
byteArrayOutputStream.write(fileCommentBytes);
}
} catch (Exception e) {
throw new ZipException(e);
}
}
private int calculateExtraDataRecordsSize(FileHeader fileHeader, boolean writeZip64ExtendedInfo) throws IOException {
int extraFieldLength = 0;
if (writeZip64ExtendedInfo) {
extraFieldLength += ZIP64_EXTRA_DATA_RECORD_SIZE_FH + 4; // 4 for signature + size of record
}
if (fileHeader.getAesExtraDataRecord() != null) {
extraFieldLength += AES_EXTRA_DATA_RECORD_SIZE;
}
if (fileHeader.getExtraDataRecords() != null) {
for (ExtraDataRecord extraDataRecord : fileHeader.getExtraDataRecords()) {
if (extraDataRecord.getHeader() == HeaderSignature.AES_EXTRA_DATA_RECORD.getValue()
|| extraDataRecord.getHeader() == HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue()) {
continue;
}
extraFieldLength += 4 + extraDataRecord.getSizeOfData(); // 4 = 2 for header + 2 for size of data
}
}
return extraFieldLength;
}
private void writeRemainingExtraDataRecordsIfPresent(FileHeader fileHeader, OutputStream outputStream) throws IOException {
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() == 0) {
return;
}
for (ExtraDataRecord extraDataRecord : fileHeader.getExtraDataRecords()) {
if (extraDataRecord.getHeader() == HeaderSignature.AES_EXTRA_DATA_RECORD.getValue()
|| extraDataRecord.getHeader() == HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue()) {
continue;
}
rawIO.writeShortLittleEndian(outputStream, (int) extraDataRecord.getHeader());
rawIO.writeShortLittleEndian(outputStream, extraDataRecord.getSizeOfData());
outputStream.write(extraDataRecord.getData());
}
}
private void writeZip64EndOfCentralDirectoryRecord(ZipModel zipModel, int sizeOfCentralDir, long offsetCentralDir,
ByteArrayOutputStream byteArrayOutputStream, RawIO rawIO)
throws IOException {
byte[] emptyShortByte = {0, 0};
rawIO.writeIntLittleEndian(byteArrayOutputStream,
(int) HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_RECORD.getValue());
rawIO.writeLongLittleEndian(byteArrayOutputStream, (long) 44);
if (zipModel.getCentralDirectory() != null &&
zipModel.getCentralDirectory().getFileHeaders() != null &&
zipModel.getCentralDirectory().getFileHeaders().size() > 0) {
rawIO.writeShortLittleEndian(byteArrayOutputStream,
zipModel.getCentralDirectory().getFileHeaders().get(0).getVersionMadeBy());
rawIO.writeShortLittleEndian(byteArrayOutputStream,
zipModel.getCentralDirectory().getFileHeaders().get(0).getVersionNeededToExtract());
} else {
byteArrayOutputStream.write(emptyShortByte);
byteArrayOutputStream.write(emptyShortByte);
}
rawIO.writeIntLittleEndian(byteArrayOutputStream,
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
rawIO.writeIntLittleEndian(byteArrayOutputStream, zipModel.getEndOfCentralDirectoryRecord()
.getNumberOfThisDiskStartOfCentralDir());
long numEntries = zipModel.getCentralDirectory().getFileHeaders().size();
long numEntriesOnThisDisk = numEntries;
if (zipModel.isSplitArchive()) {
numEntriesOnThisDisk = countNumberOfFileHeaderEntriesOnDisk(zipModel.getCentralDirectory().getFileHeaders(),
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
}
rawIO.writeLongLittleEndian(byteArrayOutputStream, numEntriesOnThisDisk);
rawIO.writeLongLittleEndian(byteArrayOutputStream, numEntries);
rawIO.writeLongLittleEndian(byteArrayOutputStream, sizeOfCentralDir);
rawIO.writeLongLittleEndian(byteArrayOutputStream, offsetCentralDir);
}
private void writeZip64EndOfCentralDirectoryLocator(ZipModel zipModel, ByteArrayOutputStream byteArrayOutputStream,
RawIO rawIO) throws IOException {
rawIO.writeIntLittleEndian(byteArrayOutputStream, (int) HeaderSignature.ZIP64_END_CENTRAL_DIRECTORY_LOCATOR.getValue());
rawIO.writeIntLittleEndian(byteArrayOutputStream,
zipModel.getZip64EndOfCentralDirectoryLocator().getNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord());
rawIO.writeLongLittleEndian(byteArrayOutputStream,
zipModel.getZip64EndOfCentralDirectoryLocator().getOffsetZip64EndOfCentralDirectoryRecord());
rawIO.writeIntLittleEndian(byteArrayOutputStream,
zipModel.getZip64EndOfCentralDirectoryLocator().getTotalNumberOfDiscs());
}
private void writeEndOfCentralDirectoryRecord(ZipModel zipModel, int sizeOfCentralDir, long offsetCentralDir,
ByteArrayOutputStream byteArrayOutputStream, RawIO rawIO, Charset charset)
throws IOException {
byte[] longByte = new byte[8];
rawIO.writeIntLittleEndian(byteArrayOutputStream, (int) HeaderSignature.END_OF_CENTRAL_DIRECTORY.getValue());
rawIO.writeShortLittleEndian(byteArrayOutputStream,
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
rawIO.writeShortLittleEndian(byteArrayOutputStream,
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDiskStartOfCentralDir());
long numEntries = zipModel.getCentralDirectory().getFileHeaders().size();
long numEntriesOnThisDisk = numEntries;
if (zipModel.isSplitArchive()) {
numEntriesOnThisDisk = countNumberOfFileHeaderEntriesOnDisk(zipModel.getCentralDirectory().getFileHeaders(),
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
}
if (numEntriesOnThisDisk > InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT) {
numEntriesOnThisDisk = InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT;
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, (int) numEntriesOnThisDisk);
if (numEntries > InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT) {
numEntries = InternalZipConstants.ZIP_64_NUMBER_OF_ENTRIES_LIMIT;
}
rawIO.writeShortLittleEndian(byteArrayOutputStream, (int) numEntries);
rawIO.writeIntLittleEndian(byteArrayOutputStream, sizeOfCentralDir);
if (offsetCentralDir > ZIP_64_SIZE_LIMIT) {
rawIO.writeLongLittleEndian(longByte, 0, ZIP_64_SIZE_LIMIT);
byteArrayOutputStream.write(longByte, 0, 4);
} else {
rawIO.writeLongLittleEndian(longByte, 0, offsetCentralDir);
byteArrayOutputStream.write(longByte, 0, 4);
}
String comment = zipModel.getEndOfCentralDirectoryRecord().getComment();
if (isStringNotNullAndNotEmpty(comment)) {
byte[] commentBytes = comment.getBytes(charset);
rawIO.writeShortLittleEndian(byteArrayOutputStream, commentBytes.length);
byteArrayOutputStream.write(commentBytes);
} else {
rawIO.writeShortLittleEndian(byteArrayOutputStream, 0);
}
}
private long countNumberOfFileHeaderEntriesOnDisk(List fileHeaders, int numOfDisk) throws ZipException {
if (fileHeaders == null) {
throw new ZipException("file headers are null, cannot calculate number of entries on this disk");
}
int noEntries = 0;
for (FileHeader fileHeader : fileHeaders) {
if (fileHeader.getDiskNumberStart() == numOfDisk) {
noEntries++;
}
}
return noEntries;
}
private boolean isZip64Entry(FileHeader fileHeader) {
return fileHeader.getCompressedSize() >= ZIP_64_SIZE_LIMIT
|| fileHeader.getUncompressedSize() >= ZIP_64_SIZE_LIMIT
|| fileHeader.getOffsetLocalHeader() >= ZIP_64_SIZE_LIMIT;
}
} zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/ 0000775 0000000 0000000 00000000000 13576501616 0021075 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/ 0000775 0000000 0000000 00000000000 13576501616 0023450 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/AesCipherInputStream.java 0000664 0000000 0000000 00000014270 13576501616 0030356 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.crypto.AESDecrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import static net.lingala.zip4j.util.InternalZipConstants.AES_AUTH_LENGTH;
import static net.lingala.zip4j.util.Zip4jUtil.readFully;
class AesCipherInputStream extends CipherInputStream {
private byte[] singleByteBuffer = new byte[1];
private byte[] aes16ByteBlock = new byte[16];
private int aes16ByteBlockPointer = 0;
private int remainingAes16ByteBlockLength = 0;
private int lengthToRead = 0;
private int offsetWithAesBlock = 0;
private int bytesCopiedInThisIteration = 0;
private int lengthToCopyInThisIteration = 0;
private int aes16ByteBlockReadLength = 0;
public AesCipherInputStream(ZipEntryInputStream zipEntryInputStream, LocalFileHeader localFileHeader, char[] password)
throws IOException {
super(zipEntryInputStream, localFileHeader, password);
}
@Override
protected AESDecrypter initializeDecrypter(LocalFileHeader localFileHeader, char[] password) throws IOException {
return new AESDecrypter(localFileHeader.getAesExtraDataRecord(), password, getSalt(localFileHeader), getPasswordVerifier());
}
@Override
public int read() throws IOException {
int readLen = read(singleByteBuffer);
if (readLen == -1) {
return -1;
}
return singleByteBuffer[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
lengthToRead = len;
offsetWithAesBlock = off;
bytesCopiedInThisIteration = 0;
if (remainingAes16ByteBlockLength != 0) {
copyBytesFromBuffer(b, offsetWithAesBlock);
if (bytesCopiedInThisIteration == len) {
return bytesCopiedInThisIteration;
}
}
if (lengthToRead < 16) {
aes16ByteBlockReadLength = super.read(aes16ByteBlock, 0, aes16ByteBlock.length);
aes16ByteBlockPointer = 0;
if (aes16ByteBlockReadLength == -1) {
remainingAes16ByteBlockLength = 0;
if (bytesCopiedInThisIteration > 0) {
return bytesCopiedInThisIteration;
}
return -1;
}
remainingAes16ByteBlockLength = aes16ByteBlockReadLength;
copyBytesFromBuffer(b, offsetWithAesBlock);
if (bytesCopiedInThisIteration == len) {
return bytesCopiedInThisIteration;
}
}
int readLen = super.read(b, offsetWithAesBlock, (lengthToRead - lengthToRead %16));
if (readLen == -1) {
if (bytesCopiedInThisIteration > 0) {
return bytesCopiedInThisIteration;
} else {
return -1;
}
} else {
return readLen + bytesCopiedInThisIteration;
}
}
private void copyBytesFromBuffer(byte[] b, int off) {
lengthToCopyInThisIteration = lengthToRead < remainingAes16ByteBlockLength ? lengthToRead : remainingAes16ByteBlockLength;
System.arraycopy(aes16ByteBlock, aes16ByteBlockPointer, b, off, lengthToCopyInThisIteration);
incrementAesByteBlockPointer(lengthToCopyInThisIteration);
decrementRemainingAesBytesLength(lengthToCopyInThisIteration);
bytesCopiedInThisIteration += lengthToCopyInThisIteration;
lengthToRead -= lengthToCopyInThisIteration;
offsetWithAesBlock += lengthToCopyInThisIteration;
}
@Override
protected void endOfEntryReached(InputStream inputStream) throws IOException {
verifyContent(readStoredMac(inputStream));
}
private void verifyContent(byte[] storedMac) throws IOException {
if (getLocalFileHeader().isDataDescriptorExists()
&& CompressionMethod.DEFLATE.equals(Zip4jUtil.getCompressionMethod(getLocalFileHeader()))) {
// Skip content verification in case of Deflate compression and if data descriptor exists.
// In this case, we do not know the exact size of compressed data before hand and it is possible that we read
// and pass more than required data into inflater, thereby corrupting the aes mac bytes.
// See usage of PushBackInputStream in the project for how this push back of data is done
// Unfortunately, in this case we cannot perform a content verification and have to skip
return;
}
byte[] calculatedMac = getDecrypter().getCalculatedAuthenticationBytes();
byte[] first10BytesOfCalculatedMac = new byte[AES_AUTH_LENGTH];
System.arraycopy(calculatedMac, 0, first10BytesOfCalculatedMac, 0, InternalZipConstants.AES_AUTH_LENGTH);
if (!Arrays.equals(storedMac, first10BytesOfCalculatedMac)) {
throw new IOException("Reached end of data for this entry, but aes verification failed");
}
}
protected byte[] readStoredMac(InputStream inputStream) throws IOException {
byte[] storedMac = new byte[AES_AUTH_LENGTH];
int readLen = readFully(inputStream, storedMac);
if (readLen != AES_AUTH_LENGTH) {
throw new ZipException("Invalid AES Mac bytes. Could not read sufficient data");
}
return storedMac;
}
private byte[] getSalt(LocalFileHeader localFileHeader) throws IOException {
if (localFileHeader.getAesExtraDataRecord() == null) {
throw new IOException("invalid aes extra data record");
}
AESExtraDataRecord aesExtraDataRecord = localFileHeader.getAesExtraDataRecord();
byte[] saltBytes = new byte[aesExtraDataRecord.getAesKeyStrength().getSaltLength()];
readRaw(saltBytes);
return saltBytes;
}
private byte[] getPasswordVerifier() throws IOException {
byte[] pvBytes = new byte[2];
readRaw(pvBytes);
return pvBytes;
}
private void incrementAesByteBlockPointer(int incrementBy) {
aes16ByteBlockPointer += incrementBy;
if (aes16ByteBlockPointer >= 15) {
aes16ByteBlockPointer = 15;
}
}
private void decrementRemainingAesBytesLength(int decrementBy) {
remainingAes16ByteBlockLength -= decrementBy;
if (remainingAes16ByteBlockLength <= 0) {
remainingAes16ByteBlockLength = 0;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/CipherInputStream.java 0000664 0000000 0000000 00000006162 13576501616 0027726 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.crypto.Decrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.IOException;
import java.io.InputStream;
import static net.lingala.zip4j.util.Zip4jUtil.readFully;
abstract class CipherInputStream extends InputStream {
private ZipEntryInputStream zipEntryInputStream;
private T decrypter;
private byte[] lastReadRawDataCache;
private byte[] singleByteBuffer = new byte[1];
private LocalFileHeader localFileHeader;
public CipherInputStream(ZipEntryInputStream zipEntryInputStream, LocalFileHeader localFileHeader, char[] password) throws IOException, ZipException {
this.zipEntryInputStream = zipEntryInputStream;
this.decrypter = initializeDecrypter(localFileHeader, password);
this.localFileHeader = localFileHeader;
if (getCompressionMethod(localFileHeader) == CompressionMethod.DEFLATE) {
lastReadRawDataCache = new byte[InternalZipConstants.BUFF_SIZE];
}
}
@Override
public int read() throws IOException {
int readLen = read(singleByteBuffer);
if (readLen == -1) {
return -1;
}
return singleByteBuffer[0] & 0xff;
}
@Override
public int read(byte[] b) throws IOException {
return this.read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int readLen = readFully(zipEntryInputStream, b, off, len);
if (readLen > 0) {
cacheRawData(b, readLen);
decrypter.decryptData(b, off, readLen);
}
return readLen;
}
@Override
public void close() throws IOException {
zipEntryInputStream.close();
}
public byte[] getLastReadRawDataCache() {
return lastReadRawDataCache;
}
protected int readRaw(byte[] b) throws IOException {
return zipEntryInputStream.readRawFully(b);
}
private void cacheRawData(byte[] b, int len) {
if (lastReadRawDataCache != null) {
System.arraycopy(b, 0, lastReadRawDataCache, 0, len);
}
}
private CompressionMethod getCompressionMethod(LocalFileHeader localFileHeader) throws ZipException {
if (localFileHeader.getCompressionMethod() != CompressionMethod.AES_INTERNAL_ONLY) {
return localFileHeader.getCompressionMethod();
}
if (localFileHeader.getAesExtraDataRecord() == null) {
throw new ZipException("AesExtraDataRecord not present in localheader for aes encrypted data");
}
return localFileHeader.getAesExtraDataRecord().getCompressionMethod();
}
public T getDecrypter() {
return decrypter;
}
protected void endOfEntryReached(InputStream inputStream) throws IOException {
// is optional but useful for AES
}
protected long getNumberOfBytesReadForThisEntry() {
return zipEntryInputStream.getNumberOfBytesRead();
}
public LocalFileHeader getLocalFileHeader() {
return localFileHeader;
}
protected abstract T initializeDecrypter(LocalFileHeader localFileHeader, char[] password) throws IOException, ZipException;
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/DecompressedInputStream.java 0000664 0000000 0000000 00000002430 13576501616 0031123 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
abstract class DecompressedInputStream extends InputStream {
private CipherInputStream cipherInputStream;
protected byte[] oneByteBuffer = new byte[1];
public DecompressedInputStream(CipherInputStream cipherInputStream) {
this.cipherInputStream = cipherInputStream;
}
@Override
public int read() throws IOException {
int readLen = read(oneByteBuffer);
if (readLen == -1) {
return -1;
}
return oneByteBuffer[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return cipherInputStream.read(b, off, len);
}
@Override
public void close() throws IOException {
cipherInputStream.close();
}
public void endOfEntryReached(InputStream inputStream) throws IOException {
cipherInputStream.endOfEntryReached(inputStream);
}
public void pushBackInputStreamIfNecessary(PushbackInputStream pushbackInputStream) throws IOException {
// Do nothing by default
}
protected byte[] getLastReadRawDataCache() {
return cipherInputStream.getLastReadRawDataCache();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/InflaterInputStream.java 0000664 0000000 0000000 00000003522 13576501616 0030255 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.EOFException;
import java.io.IOException;
import java.io.PushbackInputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
public class InflaterInputStream extends DecompressedInputStream {
private Inflater inflater;
private byte[] buff;
private byte[] singleByteBuffer = new byte[1];
private int len;
public InflaterInputStream(CipherInputStream cipherInputStream) {
super(cipherInputStream);
this.inflater = new Inflater(true);
buff = new byte[InternalZipConstants.BUFF_SIZE];
}
@Override
public int read() throws IOException {
int readLen = read(singleByteBuffer);
if (readLen == -1) {
return -1;
}
return singleByteBuffer[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
try {
int n;
while ((n = inflater.inflate(b, off, len)) == 0) {
if (inflater.finished() || inflater.needsDictionary()) {
return -1;
}
if (inflater.needsInput()) {
fill();
}
}
return n;
} catch (DataFormatException e) {
throw new IOException(e);
}
}
@Override
public void pushBackInputStreamIfNecessary(PushbackInputStream pushbackInputStream) throws IOException {
int n = inflater.getRemaining();
if (n > 0) {
byte[] rawDataCache = getLastReadRawDataCache();
pushbackInputStream.unread(rawDataCache, len - n, n);
}
}
private void fill() throws IOException {
len = super.read(buff, 0, buff.length);
if (len == -1) {
throw new EOFException("Unexpected end of input stream");
}
inflater.setInput(buff, 0, len);
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/NoCipherInputStream.java 0000664 0000000 0000000 00000001421 13576501616 0030214 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.crypto.Decrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.LocalFileHeader;
import java.io.IOException;
class NoCipherInputStream extends CipherInputStream {
public NoCipherInputStream(ZipEntryInputStream zipEntryInputStream, LocalFileHeader localFileHeader, char[] password) throws IOException, ZipException {
super(zipEntryInputStream, localFileHeader, password);
}
@Override
protected Decrypter initializeDecrypter(LocalFileHeader localFileHeader, char[] password) {
return new NoDecrypter();
}
static class NoDecrypter implements Decrypter {
@Override
public int decryptData(byte[] buff, int start, int len) {
return len;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/SplitInputStream.java 0000664 0000000 0000000 00000006223 13576501616 0027605 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
public class SplitInputStream extends InputStream {
private RandomAccessFile randomAccessFile;
private File zipFile;
private int lastSplitZipFileNumber;
private boolean isSplitZipArchive;
private int currentSplitFileCounter = 0;
private byte[] singleByteArray = new byte[1];
public SplitInputStream(File zipFile, boolean isSplitZipArchive, int lastSplitZipFileNumber) throws FileNotFoundException {
this.randomAccessFile = new RandomAccessFile(zipFile, RandomAccessFileMode.READ.getValue());
this.zipFile = zipFile;
this.isSplitZipArchive = isSplitZipArchive;
this.lastSplitZipFileNumber = lastSplitZipFileNumber;
if (isSplitZipArchive) {
currentSplitFileCounter = lastSplitZipFileNumber;
}
}
@Override
public int read() throws IOException {
int readLen = read(singleByteArray);
if (readLen == -1) {
return -1;
}
return singleByteArray[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int readLen = randomAccessFile.read(b, off, len);
if ((readLen != len || readLen == -1) && isSplitZipArchive) {
openRandomAccessFileForIndex(currentSplitFileCounter + 1);
currentSplitFileCounter++;
if (readLen < 0) readLen = 0;
int newlyRead = randomAccessFile.read(b, readLen, len - readLen);
if (newlyRead > 0) readLen += newlyRead;
}
return readLen;
}
public void prepareExtractionForFileHeader(FileHeader fileHeader) throws IOException {
if (isSplitZipArchive && (currentSplitFileCounter != fileHeader.getDiskNumberStart())) {
openRandomAccessFileForIndex(fileHeader.getDiskNumberStart());
currentSplitFileCounter = fileHeader.getDiskNumberStart();
}
randomAccessFile.seek(fileHeader.getOffsetLocalHeader());
}
private void openRandomAccessFileForIndex(int zipFileIndex) throws IOException {
File nextSplitFile = getNextSplitFileName(zipFileIndex);
if (!nextSplitFile.exists()) {
throw new FileNotFoundException("zip split file does not exist: " + nextSplitFile);
}
randomAccessFile.close();
randomAccessFile = new RandomAccessFile(nextSplitFile, RandomAccessFileMode.READ.getValue());
}
private File getNextSplitFileName(int zipFileIndex) throws IOException {
if (zipFileIndex == lastSplitZipFileNumber) {
return zipFile;
}
String currZipFileNameWithPath = zipFile.getCanonicalPath();
String extensionSubString = ".z0";
if (zipFileIndex >= 9) {
extensionSubString = ".z";
}
return new File(currZipFileNameWithPath.substring(0,
currZipFileNameWithPath.lastIndexOf(".")) + extensionSubString + (zipFileIndex + 1));
}
@Override
public void close() throws IOException {
if (randomAccessFile != null) {
randomAccessFile.close();
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/StoreInputStream.java 0000664 0000000 0000000 00000000312 13576501616 0027577 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
class StoreInputStream extends DecompressedInputStream {
public StoreInputStream(CipherInputStream cipherInputStream) {
super(cipherInputStream);
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/ZipEntryInputStream.java 0000664 0000000 0000000 00000004376 13576501616 0030305 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import java.io.IOException;
import java.io.InputStream;
class ZipEntryInputStream extends InputStream {
private static final int MAX_RAW_READ_FULLY_RETRY_ATTEMPTS = 15;
private InputStream inputStream;
private long numberOfBytesRead = 0;
private byte[] singleByteArray = new byte[1];
private long compressedSize;
public ZipEntryInputStream(InputStream inputStream, long compressedSize) {
this.inputStream = inputStream;
this.compressedSize = compressedSize;
}
@Override
public int read() throws IOException {
int readLen = read(singleByteArray);
if (readLen == -1) {
return -1;
}
return singleByteArray[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (compressedSize != -1) {
if (numberOfBytesRead >= compressedSize) {
return -1;
}
if (len > compressedSize - numberOfBytesRead) {
len = (int) (compressedSize - numberOfBytesRead);
}
}
int readLen = inputStream.read(b, off, len);
if (readLen > 0) {
numberOfBytesRead += readLen;
}
return readLen;
}
public int readRawFully(byte[] b) throws IOException {
int readLen = inputStream.read(b);
if (readLen != b.length) {
readLen = readUntilBufferIsFull(b, readLen);
if (readLen != b.length) {
throw new IOException("Cannot read fully into byte buffer");
}
}
return readLen;
}
private int readUntilBufferIsFull(byte[] b, int readLength) throws IOException {
int remainingLength = b.length - readLength;
int loopReadLength = 0;
int retryAttempt = 0;
while (readLength < b.length && loopReadLength != -1 && retryAttempt < MAX_RAW_READ_FULLY_RETRY_ATTEMPTS) {
loopReadLength += inputStream.read(b, readLength, remainingLength);
if (loopReadLength > 0) {
readLength += loopReadLength;
remainingLength -= loopReadLength;
}
retryAttempt++;
}
return readLength;
}
@Override
public void close() throws IOException {
inputStream.close();
}
public long getNumberOfBytesRead() {
return numberOfBytesRead;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/ZipInputStream.java 0000775 0000000 0000000 00000026370 13576501616 0027264 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.crypto.AESDecrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderReader;
import net.lingala.zip4j.headers.HeaderSignature;
import net.lingala.zip4j.model.DataDescriptor;
import net.lingala.zip4j.model.ExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.DataFormatException;
import static net.lingala.zip4j.util.FileUtils.isZipEntryDirectory;
import static net.lingala.zip4j.util.Zip4jUtil.getCompressionMethod;
public class ZipInputStream extends InputStream {
private PushbackInputStream inputStream;
private DecompressedInputStream decompressedInputStream;
private HeaderReader headerReader = new HeaderReader();
private char[] password;
private LocalFileHeader localFileHeader;
private CRC32 crc32 = new CRC32();
private byte[] endOfEntryBuffer;
private boolean extraDataRecordReadForThisEntry = false;
private boolean canSkipExtendedLocalFileHeader = false;
private Charset charset;
public ZipInputStream(InputStream inputStream) {
this(inputStream, null, InternalZipConstants.CHARSET_UTF_8);
}
public ZipInputStream(InputStream inputStream, Charset charset) {
this(inputStream, null, charset);
}
public ZipInputStream(InputStream inputStream, char[] password) {
this(inputStream, password, InternalZipConstants.CHARSET_UTF_8);
}
public ZipInputStream(InputStream inputStream, char[] password, Charset charset) {
if(charset == null) {
charset = InternalZipConstants.CHARSET_UTF_8;
}
this.inputStream = new PushbackInputStream(inputStream, InternalZipConstants.BUFF_SIZE);
this.password = password;
this.charset = charset;
}
public LocalFileHeader getNextEntry() throws IOException {
return getNextEntry(null);
}
public LocalFileHeader getNextEntry(FileHeader fileHeader) throws IOException {
if (localFileHeader != null) {
readUntilEndOfEntry();
}
localFileHeader = headerReader.readLocalFileHeader(inputStream, charset);
if (localFileHeader == null) {
return null;
}
verifyLocalFileHeader(localFileHeader);
crc32.reset();
if (fileHeader != null) {
localFileHeader.setCrc(fileHeader.getCrc());
localFileHeader.setCompressedSize(fileHeader.getCompressedSize());
localFileHeader.setUncompressedSize(fileHeader.getUncompressedSize());
canSkipExtendedLocalFileHeader = true;
} else {
canSkipExtendedLocalFileHeader = false;
}
if (!isZipEntryDirectory(localFileHeader.getFileName())) {
this.decompressedInputStream = initializeEntryInputStream(localFileHeader);
}
this.extraDataRecordReadForThisEntry = false;
return localFileHeader;
}
@Override
public int read() throws IOException {
byte[] b = new byte[1];
int readLen = read(b);
if (readLen == -1) {
return -1;
}
return b[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (len < 0) {
throw new IllegalArgumentException("Negative read length");
}
if (len == 0) {
return 0;
}
if (localFileHeader == null) {
// localfileheader can be null when end of compressed data is reached. If null check is missing, read method will
// throw a NPE when end of compressed data is reached and read is called again.
return -1;
}
if (localFileHeader.isDirectory()) {
if (!extraDataRecordReadForThisEntry) {
readExtendedLocalFileHeaderIfPresent();
extraDataRecordReadForThisEntry = true;
}
return -1;
}
try {
int readLen = decompressedInputStream.read(b, off, len);
if (readLen == -1) {
endOfCompressedDataReached();
} else {
crc32.update(b, off, readLen);
}
return readLen;
} catch (IOException e) {
if (e.getCause() != null && e.getCause() instanceof DataFormatException
&& isEncryptionMethodZipStandard(localFileHeader)) {
throw new ZipException(e.getMessage(), e.getCause(), ZipException.Type.WRONG_PASSWORD);
}
throw e;
}
}
@Override
public void close() throws IOException {
if (decompressedInputStream != null) {
decompressedInputStream.close();
}
}
public int getAvailableBytesInPushBackInputStream() throws IOException {
return inputStream.available();
}
private void endOfCompressedDataReached() throws IOException {
//With inflater, without knowing the compressed or uncompressed size, we over read necessary data
//In such cases, we have to push back the inputstream to the end of data
decompressedInputStream.pushBackInputStreamIfNecessary(inputStream);
//First signal the end of data for this entry so that ciphers can read any header data if applicable
decompressedInputStream.endOfEntryReached(inputStream);
readExtendedLocalFileHeaderIfPresent();
verifyCrc();
resetFields();
}
private DecompressedInputStream initializeEntryInputStream(LocalFileHeader localFileHeader) throws IOException {
ZipEntryInputStream zipEntryInputStream = new ZipEntryInputStream(inputStream, getCompressedSize(localFileHeader));
CipherInputStream cipherInputStream = initializeCipherInputStream(zipEntryInputStream, localFileHeader);
return initializeDecompressorForThisEntry(cipherInputStream, localFileHeader);
}
private CipherInputStream initializeCipherInputStream(ZipEntryInputStream zipEntryInputStream, LocalFileHeader localFileHeader) throws IOException {
if (!localFileHeader.isEncrypted()) {
return new NoCipherInputStream(zipEntryInputStream, localFileHeader, password);
}
if (localFileHeader.getEncryptionMethod() == EncryptionMethod.AES) {
return new AesCipherInputStream(zipEntryInputStream, localFileHeader, password);
} else {
return new ZipStandardCipherInputStream(zipEntryInputStream, localFileHeader, password);
}
}
private DecompressedInputStream initializeDecompressorForThisEntry(CipherInputStream cipherInputStream, LocalFileHeader localFileHeader) {
CompressionMethod compressionMethod = getCompressionMethod(localFileHeader);
if (compressionMethod == CompressionMethod.DEFLATE) {
return new InflaterInputStream(cipherInputStream);
}
return new StoreInputStream(cipherInputStream);
}
private void readExtendedLocalFileHeaderIfPresent() throws IOException {
if (!localFileHeader.isDataDescriptorExists() || canSkipExtendedLocalFileHeader) {
return;
}
DataDescriptor dataDescriptor = headerReader.readDataDescriptor(inputStream,
checkIfZip64ExtraDataRecordPresentInLFH(localFileHeader.getExtraDataRecords()));
localFileHeader.setCompressedSize(dataDescriptor.getCompressedSize());
localFileHeader.setUncompressedSize(dataDescriptor.getUncompressedSize());
localFileHeader.setCrc(dataDescriptor.getCrc());
}
private void verifyLocalFileHeader(LocalFileHeader localFileHeader) throws IOException {
if (!isEntryDirectory(localFileHeader.getFileName())
&& localFileHeader.getCompressionMethod() == CompressionMethod.STORE
&& localFileHeader.getUncompressedSize() < 0) {
throw new IOException("Invalid local file header for: " + localFileHeader.getFileName()
+ ". Uncompressed size has to be set for entry of compression type store which is not a directory");
}
}
private boolean checkIfZip64ExtraDataRecordPresentInLFH(List extraDataRecords) {
if (extraDataRecords == null) {
return false;
}
for (ExtraDataRecord extraDataRecord : extraDataRecords) {
if (extraDataRecord.getHeader() == HeaderSignature.ZIP64_EXTRA_FIELD_SIGNATURE.getValue()) {
return true;
}
}
return false;
}
private void verifyCrc() throws IOException {
if (localFileHeader.getEncryptionMethod() == EncryptionMethod.AES
&& localFileHeader.getAesExtraDataRecord().getAesVersion().equals(AesVersion.TWO)) {
// Verification will be done in this case by AesCipherInputStream
return;
}
if (localFileHeader.getCrc() != crc32.getValue()) {
ZipException.Type exceptionType = ZipException.Type.CHECKSUM_MISMATCH;
if (isEncryptionMethodZipStandard(localFileHeader)) {
exceptionType = ZipException.Type.WRONG_PASSWORD;
}
throw new ZipException("Reached end of entry, but crc verification failed for " + localFileHeader.getFileName(),
exceptionType);
}
}
private void resetFields() {
localFileHeader = null;
crc32.reset();
}
private boolean isEntryDirectory(String entryName) {
return entryName.endsWith("/") || entryName.endsWith("\\");
}
private long getCompressedSize(LocalFileHeader localFileHeader) {
if (getCompressionMethod(localFileHeader).equals(CompressionMethod.STORE)) {
return localFileHeader.getUncompressedSize();
}
if (localFileHeader.isDataDescriptorExists() && !canSkipExtendedLocalFileHeader) {
return -1;
}
long compressedSize = localFileHeader.getCompressedSize();
if (localFileHeader.getZip64ExtendedInfo() != null) {
compressedSize = localFileHeader.getZip64ExtendedInfo().getCompressedSize();
}
return compressedSize - getEncryptionHeaderSize(localFileHeader);
}
private int getEncryptionHeaderSize(LocalFileHeader localFileHeader) {
if (!localFileHeader.isEncrypted()) {
return 0;
}
if (localFileHeader.getEncryptionMethod().equals(EncryptionMethod.AES)) {
return InternalZipConstants.AES_AUTH_LENGTH + AESDecrypter.PASSWORD_VERIFIER_LENGTH
+ localFileHeader.getAesExtraDataRecord().getAesKeyStrength().getSaltLength();
} else if (localFileHeader.getEncryptionMethod().equals(EncryptionMethod.ZIP_STANDARD)) {
return InternalZipConstants.STD_DEC_HDR_SIZE;
} else {
return 0;
}
}
private void readUntilEndOfEntry() throws IOException {
if (endOfEntryBuffer == null) {
endOfEntryBuffer = new byte[512];
}
while (read(endOfEntryBuffer) != -1);
}
private boolean isEncryptionMethodZipStandard(LocalFileHeader localFileHeader) {
return localFileHeader.isEncrypted() && EncryptionMethod.ZIP_STANDARD.equals(localFileHeader.getEncryptionMethod());
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardCipherInputStream.java 0000664 0000000 0000000 00000002036 13576501616 0032066 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.crypto.StandardDecrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.LocalFileHeader;
import java.io.IOException;
import static net.lingala.zip4j.util.InternalZipConstants.STD_DEC_HDR_SIZE;
class ZipStandardCipherInputStream extends CipherInputStream {
public ZipStandardCipherInputStream(ZipEntryInputStream zipEntryInputStream, LocalFileHeader localFileHeader, char[] password) throws IOException, ZipException {
super(zipEntryInputStream, localFileHeader, password);
}
@Override
protected StandardDecrypter initializeDecrypter(LocalFileHeader localFileHeader, char[] password) throws ZipException, IOException {
return new StandardDecrypter(password, localFileHeader.getCrcRawData(), getStandardDecrypterHeaderBytes());
}
private byte[] getStandardDecrypterHeaderBytes() throws IOException {
byte[] headerBytes = new byte[STD_DEC_HDR_SIZE];
readRaw(headerBytes);
return headerBytes;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/ 0000775 0000000 0000000 00000000000 13576501616 0023651 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/AesCipherOutputStream.java 0000664 0000000 0000000 00000004653 13576501616 0030764 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.crypto.AESEncrpyter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import java.io.IOException;
import java.io.OutputStream;
import static net.lingala.zip4j.util.InternalZipConstants.AES_BLOCK_SIZE;
class AesCipherOutputStream extends CipherOutputStream {
private byte[] pendingBuffer = new byte[AES_BLOCK_SIZE];
private int pendingBufferLength = 0;
public AesCipherOutputStream(ZipEntryOutputStream outputStream, ZipParameters zipParameters, char[] password) throws IOException, ZipException {
super(outputStream, zipParameters, password);
}
@Override
protected AESEncrpyter initializeEncrypter(OutputStream outputStream, ZipParameters zipParameters, char[] password) throws IOException, ZipException {
AESEncrpyter encrypter = new AESEncrpyter(password, zipParameters.getAesKeyStrength());
writeAesEncryptionHeaderData(encrypter);
return encrypter;
}
private void writeAesEncryptionHeaderData(AESEncrpyter encrypter) throws IOException {
writeHeaders(encrypter.getSaltBytes());
writeHeaders(encrypter.getDerivedPasswordVerifier());
}
@Override
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (len >= (AES_BLOCK_SIZE - pendingBufferLength)) {
System.arraycopy(b, off, pendingBuffer, pendingBufferLength, (AES_BLOCK_SIZE - pendingBufferLength));
super.write(pendingBuffer, 0, pendingBuffer.length);
off = (AES_BLOCK_SIZE - pendingBufferLength);
len = len - off;
pendingBufferLength = 0;
} else {
System.arraycopy(b, off, pendingBuffer, pendingBufferLength, len);
pendingBufferLength += len;
return;
}
if (len != 0 && len % 16 != 0) {
System.arraycopy(b, (len + off) - (len % 16), pendingBuffer, 0, len % 16);
pendingBufferLength = len % 16;
len = len - pendingBufferLength;
}
super.write(b, off, len);
}
@Override
public void closeEntry() throws IOException {
if (this.pendingBufferLength != 0) {
super.write(pendingBuffer, 0, pendingBufferLength);
pendingBufferLength = 0;
}
writeHeaders(getEncrypter().getFinalMac());
super.closeEntry();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/CipherOutputStream.java 0000775 0000000 0000000 00000004406 13576501616 0030332 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.crypto.Encrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import java.io.IOException;
import java.io.OutputStream;
abstract class CipherOutputStream extends OutputStream {
private ZipEntryOutputStream zipEntryOutputStream;
private T encrypter;
public CipherOutputStream(ZipEntryOutputStream zipEntryOutputStream, ZipParameters zipParameters, char[] password)
throws IOException, ZipException {
this.zipEntryOutputStream = zipEntryOutputStream;
this.encrypter = initializeEncrypter(zipEntryOutputStream, zipParameters, password);
}
@Override
public void write(int b) throws IOException {
zipEntryOutputStream.write(b);
}
@Override
public void write(byte[] b) throws IOException {
zipEntryOutputStream.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
encrypter.encryptData(b, off, len);
zipEntryOutputStream.write(b, off, len);
}
public void writeHeaders(byte[] b) throws IOException {
zipEntryOutputStream.write(b);
}
public void closeEntry() throws IOException {
zipEntryOutputStream.closeEntry();
}
@Override
public void close() throws IOException {
zipEntryOutputStream.close();
}
public long getNumberOfBytesWrittenForThisEntry() {
return zipEntryOutputStream.getNumberOfBytesWrittenForThisEntry();
}
protected T getEncrypter() {
return encrypter;
}
protected abstract T initializeEncrypter(OutputStream outputStream, ZipParameters zipParameters, char[] password)
throws IOException, ZipException;
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/CompressedOutputStream.java 0000664 0000000 0000000 00000001701 13576501616 0031214 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import java.io.IOException;
import java.io.OutputStream;
abstract class CompressedOutputStream extends OutputStream {
private CipherOutputStream cipherOutputStream;
public CompressedOutputStream(CipherOutputStream cipherOutputStream) {
this.cipherOutputStream = cipherOutputStream;
}
@Override
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
cipherOutputStream.write(b, off, len);
}
protected void closeEntry() throws IOException {
cipherOutputStream.closeEntry();
}
@Override
public void close() throws IOException {
cipherOutputStream.close();
}
public long getCompressedSize() {
return cipherOutputStream.getNumberOfBytesWrittenForThisEntry();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/CountingOutputStream.java 0000664 0000000 0000000 00000004260 13576501616 0030701 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.exception.ZipException;
import java.io.IOException;
import java.io.OutputStream;
public class CountingOutputStream extends OutputStream {
private OutputStream outputStream;
private long numberOfBytesWritten = 0;
public CountingOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
}
@Override
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
outputStream.write(b, off, len);
numberOfBytesWritten += len;
}
public int getCurrentSplitFileCounter() {
if (isSplitZipFile()) {
return ((SplitOutputStream) outputStream).getCurrentSplitFileCounter();
}
return 0;
}
public long getOffsetForNextEntry() throws IOException {
if (outputStream instanceof SplitOutputStream) {
return ((SplitOutputStream) outputStream).getFilePointer();
}
return numberOfBytesWritten;
}
public long getSplitLength() {
if (isSplitZipFile()) {
return ((SplitOutputStream) outputStream).getSplitLength();
}
return 0;
}
public boolean isSplitZipFile() {
return outputStream instanceof SplitOutputStream
&& ((SplitOutputStream)outputStream).isSplitZipFile();
}
public long getNumberOfBytesWritten() throws IOException {
if (outputStream instanceof SplitOutputStream) {
return ((SplitOutputStream) outputStream).getFilePointer();
}
return numberOfBytesWritten;
}
public boolean checkBuffSizeAndStartNextSplitFile(int bufferSize) throws ZipException {
if (!isSplitZipFile()) {
return false;
}
return ((SplitOutputStream)outputStream).checkBufferSizeAndStartNextSplitFile(bufferSize);
}
public long getFilePointer() throws IOException {
if (outputStream instanceof SplitOutputStream) {
return ((SplitOutputStream) outputStream).getFilePointer();
}
return numberOfBytesWritten;
}
@Override
public void close() throws IOException {
outputStream.close();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/DeflaterOutputStream.java 0000775 0000000 0000000 00000003636 13576501616 0030652 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.model.enums.CompressionLevel;
import java.io.IOException;
import java.util.zip.Deflater;
import static net.lingala.zip4j.util.InternalZipConstants.BUFF_SIZE;
class DeflaterOutputStream extends CompressedOutputStream {
private byte[] buff = new byte[BUFF_SIZE];
protected Deflater deflater;
public DeflaterOutputStream(CipherOutputStream cipherOutputStream, CompressionLevel compressionLevel) {
super(cipherOutputStream);
deflater = new Deflater(compressionLevel.getLevel(), true);
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(int bval) throws IOException {
byte[] b = new byte[1];
b[0] = (byte) bval;
write(b, 0, 1);
}
public void write(byte[] buf, int off, int len) throws IOException {
deflater.setInput(buf, off, len);
while (!deflater.needsInput()) {
deflate();
}
}
private void deflate() throws IOException {
int len = deflater.deflate(buff, 0, buff.length);
if (len > 0) {
super.write(buff, 0, len);
}
}
public void closeEntry() throws IOException {
if (!deflater.finished()) {
deflater.finish();
while (!deflater.finished()) {
deflate();
}
}
deflater.end();
super.closeEntry();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/NoCipherOutputStream.java 0000664 0000000 0000000 00000001727 13576501616 0030627 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.crypto.Encrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import java.io.IOException;
import java.io.OutputStream;
class NoCipherOutputStream extends CipherOutputStream {
public NoCipherOutputStream(ZipEntryOutputStream zipEntryOutputStream, ZipParameters zipParameters, char[] password) throws IOException, ZipException {
super(zipEntryOutputStream, zipParameters, password);
}
@Override
protected NoEncrypter initializeEncrypter(OutputStream outputStream, ZipParameters zipParameters, char[] password) {
return new NoEncrypter();
}
static class NoEncrypter implements Encrypter {
@Override
public int encryptData(byte[] buff) {
return encryptData(buff, 0, buff.length);
}
@Override
public int encryptData(byte[] buff, int start, int len) {
return len;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/SplitOutputStream.java 0000775 0000000 0000000 00000014425 13576501616 0030215 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderSignature;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.util.RawIO;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import static net.lingala.zip4j.util.FileUtils.getZipFileNameWithoutExtension;
import static net.lingala.zip4j.util.InternalZipConstants.MIN_SPLIT_LENGTH;
public class SplitOutputStream extends OutputStream {
private RandomAccessFile raf;
private long splitLength;
private File zipFile;
private int currSplitFileCounter;
private long bytesWrittenForThisPart;
private RawIO rawIO = new RawIO();
public SplitOutputStream(File file) throws FileNotFoundException, ZipException {
this(file, -1);
}
public SplitOutputStream(File file, long splitLength) throws FileNotFoundException, ZipException {
if (splitLength >= 0 && splitLength < MIN_SPLIT_LENGTH) {
throw new ZipException("split length less than minimum allowed split length of " + MIN_SPLIT_LENGTH + " Bytes");
}
this.raf = new RandomAccessFile(file, RandomAccessFileMode.WRITE.getValue());
this.splitLength = splitLength;
this.zipFile = file;
this.currSplitFileCounter = 0;
this.bytesWrittenForThisPart = 0;
}
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
if (len <= 0) {
return;
}
if (splitLength == -1) {
raf.write(b, off, len);
bytesWrittenForThisPart += len;
return;
}
if (bytesWrittenForThisPart >= splitLength) {
startNextSplitFile();
raf.write(b, off, len);
bytesWrittenForThisPart = len;
} else if (bytesWrittenForThisPart + len > splitLength) {
if (isHeaderData(b)) {
startNextSplitFile();
raf.write(b, off, len);
bytesWrittenForThisPart = len;
} else {
raf.write(b, off, (int) (splitLength - bytesWrittenForThisPart));
startNextSplitFile();
raf.write(b, off + (int) (splitLength - bytesWrittenForThisPart),
(int) (len - (splitLength - bytesWrittenForThisPart)));
bytesWrittenForThisPart = len - (splitLength - bytesWrittenForThisPart);
}
} else {
raf.write(b, off, len);
bytesWrittenForThisPart += len;
}
}
private void startNextSplitFile() throws IOException {
String zipFileWithoutExt = getZipFileNameWithoutExtension(zipFile.getName());
String zipFileName = zipFile.getAbsolutePath();
String parentPath = (zipFile.getParent() == null) ? "" : zipFile.getParent()
+ System.getProperty("file.separator");
String fileExtension = ".z0" + (currSplitFileCounter + 1);
if (currSplitFileCounter >= 9) {
fileExtension = ".z" + (currSplitFileCounter + 1);
}
File currSplitFile = new File(parentPath + zipFileWithoutExt + fileExtension);
raf.close();
if (currSplitFile.exists()) {
throw new IOException("split file: " + currSplitFile.getName()
+ " already exists in the current directory, cannot rename this file");
}
if (!zipFile.renameTo(currSplitFile)) {
throw new IOException("cannot rename newly created split file");
}
zipFile = new File(zipFileName);
raf = new RandomAccessFile(zipFile, RandomAccessFileMode.WRITE.getValue());
currSplitFileCounter++;
}
private boolean isHeaderData(byte[] buff) {
int signature = rawIO.readIntLittleEndian(buff);
for (HeaderSignature headerSignature : HeaderSignature.values()) {
//Ignore split signature
if (headerSignature != HeaderSignature.SPLIT_ZIP &&
headerSignature.getValue() == signature) {
return true;
}
}
return false;
}
/**
* Checks if the buffer size is sufficient for the current split file. If not
* a new split file will be started.
*
* @param bufferSize
* @return true if a new split file was started else false
* @throws ZipException
*/
public boolean checkBufferSizeAndStartNextSplitFile(int bufferSize) throws ZipException {
if (bufferSize < 0) {
throw new ZipException("negative buffersize for checkBufferSizeAndStartNextSplitFile");
}
if (!isBufferSizeFitForCurrSplitFile(bufferSize)) {
try {
startNextSplitFile();
bytesWrittenForThisPart = 0;
return true;
} catch (IOException e) {
throw new ZipException(e);
}
}
return false;
}
/**
* Checks if the given buffer size will be fit in the current split file.
* If this output stream is a non-split file, then this method always returns true
*
* @param bufferSize
* @return true if the buffer size is fit in the current split file or else false.
*/
private boolean isBufferSizeFitForCurrSplitFile(int bufferSize) {
if (splitLength >= MIN_SPLIT_LENGTH) {
return (bytesWrittenForThisPart + bufferSize <= splitLength);
} else {
//Non split zip -- return true
return true;
}
}
public void seek(long pos) throws IOException {
raf.seek(pos);
}
public int skipBytes(int n) throws IOException {
return raf.skipBytes(n);
}
public void close() throws IOException {
raf.close();
}
public long getFilePointer() throws IOException {
return raf.getFilePointer();
}
public boolean isSplitZipFile() {
return splitLength != -1;
}
public long getSplitLength() {
return splitLength;
}
public int getCurrentSplitFileCounter() {
return currSplitFileCounter;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/StoreOutputStream.java 0000664 0000000 0000000 00000000320 13576501616 0030200 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
class StoreOutputStream extends CompressedOutputStream {
public StoreOutputStream(CipherOutputStream cipherOutputStream) {
super(cipherOutputStream);
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/ZipEntryOutputStream.java 0000664 0000000 0000000 00000002275 13576501616 0030703 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import java.io.IOException;
import java.io.OutputStream;
class ZipEntryOutputStream extends OutputStream {
private long numberOfBytesWrittenForThisEntry = 0;
private OutputStream outputStream;
private boolean entryClosed;
public ZipEntryOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
entryClosed = false;
}
@Override
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (entryClosed) {
throw new IllegalStateException("ZipEntryOutputStream is closed");
}
outputStream.write(b, off, len);
numberOfBytesWrittenForThisEntry += len;
}
public void closeEntry() throws IOException {
entryClosed = true;
}
public long getNumberOfBytesWrittenForThisEntry() {
return numberOfBytesWrittenForThisEntry;
}
@Override
public void close() throws IOException {
// Do nothing
// Do not close the outputstream yet. This will be closed by countingOutputStream
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/ZipOutputStream.java 0000775 0000000 0000000 00000020212 13576501616 0027653 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.FileHeaderFactory;
import net.lingala.zip4j.headers.HeaderSignature;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.RawIO;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.zip.CRC32;
public class ZipOutputStream extends OutputStream {
private CountingOutputStream countingOutputStream;
private char[] password;
private ZipModel zipModel;
private CompressedOutputStream compressedOutputStream;
private FileHeader fileHeader;
private LocalFileHeader localFileHeader;
private FileHeaderFactory fileHeaderFactory = new FileHeaderFactory();
private HeaderWriter headerWriter = new HeaderWriter();
private CRC32 crc32 = new CRC32();
private RawIO rawIO = new RawIO();
private long uncompressedSizeForThisEntry = 0;
private Charset charset;
public ZipOutputStream(OutputStream outputStream) throws IOException {
this(outputStream, null, InternalZipConstants.CHARSET_UTF_8);
}
public ZipOutputStream(OutputStream outputStream, Charset charset) throws IOException {
this(outputStream, null, charset);
}
public ZipOutputStream(OutputStream outputStream, char[] password) throws IOException {
this(outputStream, password, InternalZipConstants.CHARSET_UTF_8);
}
public ZipOutputStream(OutputStream outputStream, char[] password, Charset charset) throws IOException {
this(outputStream, password, charset, new ZipModel());
}
public ZipOutputStream(OutputStream outputStream, char[] password, Charset charset, ZipModel zipModel) throws IOException {
if(charset == null) {
charset = InternalZipConstants.CHARSET_UTF_8;
}
this.countingOutputStream = new CountingOutputStream(outputStream);
this.password = password;
this.charset = charset;
this.zipModel = initializeZipModel(zipModel, countingOutputStream);
writeSplitZipHeaderIfApplicable();
}
public void putNextEntry(ZipParameters zipParameters) throws IOException {
verifyZipParameters(zipParameters);
initializeAndWriteFileHeader(zipParameters);
//Initialisation of below compressedOutputStream should happen after writing local file header
//because local header data should be written first and then the encryption header data
//and below initialisation writes encryption header data
compressedOutputStream = initializeCompressedOutputStream(zipParameters);
}
public void write(int b) throws IOException {
write(new byte[] {(byte)b});
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
crc32.update(b, off, len);
compressedOutputStream.write(b, off, len);
uncompressedSizeForThisEntry += len;
}
public FileHeader closeEntry() throws IOException {
compressedOutputStream.closeEntry();
long compressedSize = compressedOutputStream.getCompressedSize();
fileHeader.setCompressedSize(compressedSize);
localFileHeader.setCompressedSize(compressedSize);
fileHeader.setUncompressedSize(uncompressedSizeForThisEntry);
localFileHeader.setUncompressedSize(uncompressedSizeForThisEntry);
if (writeCrc(fileHeader)) {
fileHeader.setCrc(crc32.getValue());
localFileHeader.setCrc(crc32.getValue());
}
zipModel.getLocalFileHeaders().add(localFileHeader);
zipModel.getCentralDirectory().getFileHeaders().add(fileHeader);
if (localFileHeader.isDataDescriptorExists()) {
headerWriter.writeExtendedLocalHeader(localFileHeader, countingOutputStream);
}
reset();
return fileHeader;
}
@Override
public void close() throws IOException {
zipModel.getEndOfCentralDirectoryRecord().setOffsetOfStartOfCentralDirectory(countingOutputStream.getNumberOfBytesWritten());
headerWriter.finalizeZipFile(zipModel, countingOutputStream, charset);
countingOutputStream.close();
}
private ZipModel initializeZipModel(ZipModel zipModel, CountingOutputStream countingOutputStream) {
if (zipModel == null) {
zipModel = new ZipModel();
}
if (countingOutputStream.isSplitZipFile()) {
zipModel.setSplitArchive(true);
zipModel.setSplitLength(countingOutputStream.getSplitLength());
}
return zipModel;
}
private void initializeAndWriteFileHeader(ZipParameters zipParameters) throws IOException {
fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, countingOutputStream.isSplitZipFile(),
countingOutputStream.getCurrentSplitFileCounter(), charset);
fileHeader.setOffsetLocalHeader(countingOutputStream.getOffsetForNextEntry());
localFileHeader = fileHeaderFactory.generateLocalFileHeader(fileHeader);
headerWriter.writeLocalFileHeader(zipModel, localFileHeader, countingOutputStream, charset);
}
private void reset() throws IOException {
uncompressedSizeForThisEntry = 0;
crc32.reset();
compressedOutputStream.close();
}
private void writeSplitZipHeaderIfApplicable() throws IOException {
if (!countingOutputStream.isSplitZipFile()) {
return;
}
rawIO.writeIntLittleEndian(countingOutputStream, (int) HeaderSignature.SPLIT_ZIP.getValue());
}
private CompressedOutputStream initializeCompressedOutputStream(ZipParameters zipParameters) throws IOException {
ZipEntryOutputStream zipEntryOutputStream = new ZipEntryOutputStream(countingOutputStream);
CipherOutputStream cipherOutputStream = initializeCipherOutputStream(zipEntryOutputStream, zipParameters);
return initializeCompressedOutputStream(cipherOutputStream, zipParameters);
}
private CipherOutputStream initializeCipherOutputStream(ZipEntryOutputStream zipEntryOutputStream,
ZipParameters zipParameters) throws IOException {
if (!zipParameters.isEncryptFiles()) {
return new NoCipherOutputStream(zipEntryOutputStream, zipParameters, null);
}
if (password == null || password.length == 0) {
throw new ZipException("password not set");
}
if (zipParameters.getEncryptionMethod() == EncryptionMethod.AES) {
return new AesCipherOutputStream(zipEntryOutputStream, zipParameters, password);
} else if (zipParameters.getEncryptionMethod() == EncryptionMethod.ZIP_STANDARD) {
return new ZipStandardCipherOutputStream(zipEntryOutputStream, zipParameters, password);
} else {
throw new ZipException("Invalid encryption method");
}
}
private CompressedOutputStream initializeCompressedOutputStream(CipherOutputStream cipherOutputStream,
ZipParameters zipParameters) {
if (zipParameters.getCompressionMethod() == CompressionMethod.DEFLATE) {
return new DeflaterOutputStream(cipherOutputStream, zipParameters.getCompressionLevel());
}
return new StoreOutputStream(cipherOutputStream);
}
private void verifyZipParameters(ZipParameters zipParameters) {
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE
&& zipParameters.getEntrySize() < 0
&& !isEntryDirectory(zipParameters.getFileNameInZip())
&& zipParameters.isWriteExtendedLocalFileHeader()) {
throw new IllegalArgumentException("uncompressed size should be set for zip entries of compression type store");
}
}
private boolean writeCrc(FileHeader fileHeader) {
boolean isAesEncrypted = fileHeader.isEncrypted() && fileHeader.getEncryptionMethod().equals(EncryptionMethod.AES);
if (!isAesEncrypted) {
return true;
}
return fileHeader.getAesExtraDataRecord().getAesVersion().equals(AesVersion.ONE);
}
private boolean isEntryDirectory(String entryName) {
return entryName.endsWith("/") || entryName.endsWith("\\");
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/io/outputstream/ZipStandardCipherOutputStream.java 0000664 0000000 0000000 00000003032 13576501616 0032465 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.crypto.StandardEncrypter;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.IOException;
import java.io.OutputStream;
class ZipStandardCipherOutputStream extends CipherOutputStream {
public ZipStandardCipherOutputStream(ZipEntryOutputStream outputStream, ZipParameters zipParameters, char[] password) throws IOException, ZipException {
super(outputStream, zipParameters, password);
}
@Override
protected StandardEncrypter initializeEncrypter(OutputStream outputStream, ZipParameters zipParameters, char[] password) throws IOException, ZipException {
long key = getEncryptionKey(zipParameters);
StandardEncrypter encrypter = new StandardEncrypter(password, key);
writeHeaders(encrypter.getHeaderBytes());
return encrypter;
}
@Override
public void write(int b) throws IOException {
write(new byte[] {(byte) b});
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len);
}
private long getEncryptionKey(ZipParameters zipParameters) {
if (zipParameters.isWriteExtendedLocalFileHeader()) {
long dosTime = Zip4jUtil.javaToDosTime(zipParameters.getLastModifiedFileTime());
return (dosTime & 0x0000ffff) << 16;
}
return zipParameters.getEntryCRC();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ 0000775 0000000 0000000 00000000000 13576501616 0021566 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/AESExtraDataRecord.java 0000775 0000000 0000000 00000004200 13576501616 0025775 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import net.lingala.zip4j.headers.HeaderSignature;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
public class AESExtraDataRecord extends ZipHeader {
private int dataSize;
private AesVersion aesVersion;
private String vendorID;
private AesKeyStrength aesKeyStrength;
private CompressionMethod compressionMethod;
public AESExtraDataRecord() {
setSignature(HeaderSignature.AES_EXTRA_DATA_RECORD);
dataSize = 7;
aesVersion = AesVersion.TWO;
vendorID = "AE";
aesKeyStrength = AesKeyStrength.KEY_STRENGTH_256;
compressionMethod = CompressionMethod.DEFLATE;
}
public int getDataSize() {
return dataSize;
}
public void setDataSize(int dataSize) {
this.dataSize = dataSize;
}
public AesVersion getAesVersion() {
return aesVersion;
}
public void setAesVersion(AesVersion aesVersion) {
this.aesVersion = aesVersion;
}
public String getVendorID() {
return vendorID;
}
public void setVendorID(String vendorID) {
this.vendorID = vendorID;
}
public AesKeyStrength getAesKeyStrength() {
return aesKeyStrength;
}
public void setAesKeyStrength(AesKeyStrength aesKeyStrength) {
this.aesKeyStrength = aesKeyStrength;
}
public CompressionMethod getCompressionMethod() {
return compressionMethod;
}
public void setCompressionMethod(CompressionMethod compressionMethod) {
this.compressionMethod = compressionMethod;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/AbstractFileHeader.java 0000664 0000000 0000000 00000010507 13576501616 0026110 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import java.util.List;
public abstract class AbstractFileHeader extends ZipHeader {
private int versionNeededToExtract;
private byte[] generalPurposeFlag;
private CompressionMethod compressionMethod;
private long lastModifiedTime;
private long crc = 0;
private byte[] crcRawData;
private long compressedSize = 0;
private long uncompressedSize = 0;
private int fileNameLength;
private int extraFieldLength;
private String fileName;
private boolean isEncrypted;
private EncryptionMethod encryptionMethod = EncryptionMethod.NONE;
private boolean dataDescriptorExists;
private Zip64ExtendedInfo zip64ExtendedInfo;
private AESExtraDataRecord aesExtraDataRecord;
private boolean fileNameUTF8Encoded;
private List extraDataRecords;
private boolean isDirectory;
public int getVersionNeededToExtract() {
return versionNeededToExtract;
}
public void setVersionNeededToExtract(int versionNeededToExtract) {
this.versionNeededToExtract = versionNeededToExtract;
}
public byte[] getGeneralPurposeFlag() {
return generalPurposeFlag;
}
public void setGeneralPurposeFlag(byte[] generalPurposeFlag) {
this.generalPurposeFlag = generalPurposeFlag;
}
public CompressionMethod getCompressionMethod() {
return compressionMethod;
}
public void setCompressionMethod(CompressionMethod compressionMethod) {
this.compressionMethod = compressionMethod;
}
public long getLastModifiedTime() {
return lastModifiedTime;
}
public void setLastModifiedTime(long lastModifiedTime) {
this.lastModifiedTime = lastModifiedTime;
}
public long getCrc() {
return crc;
}
public void setCrc(long crc) {
this.crc = crc;
}
public byte[] getCrcRawData() {
return crcRawData;
}
public void setCrcRawData(byte[] crcRawData) {
this.crcRawData = crcRawData;
}
public long getCompressedSize() {
return compressedSize;
}
public void setCompressedSize(long compressedSize) {
this.compressedSize = compressedSize;
}
public long getUncompressedSize() {
return uncompressedSize;
}
public void setUncompressedSize(long uncompressedSize) {
this.uncompressedSize = uncompressedSize;
}
public int getFileNameLength() {
return fileNameLength;
}
public void setFileNameLength(int fileNameLength) {
this.fileNameLength = fileNameLength;
}
public int getExtraFieldLength() {
return extraFieldLength;
}
public void setExtraFieldLength(int extraFieldLength) {
this.extraFieldLength = extraFieldLength;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public boolean isEncrypted() {
return isEncrypted;
}
public void setEncrypted(boolean encrypted) {
isEncrypted = encrypted;
}
public EncryptionMethod getEncryptionMethod() {
return encryptionMethod;
}
public void setEncryptionMethod(EncryptionMethod encryptionMethod) {
this.encryptionMethod = encryptionMethod;
}
public boolean isDataDescriptorExists() {
return dataDescriptorExists;
}
public void setDataDescriptorExists(boolean dataDescriptorExists) {
this.dataDescriptorExists = dataDescriptorExists;
}
public Zip64ExtendedInfo getZip64ExtendedInfo() {
return zip64ExtendedInfo;
}
public void setZip64ExtendedInfo(Zip64ExtendedInfo zip64ExtendedInfo) {
this.zip64ExtendedInfo = zip64ExtendedInfo;
}
public AESExtraDataRecord getAesExtraDataRecord() {
return aesExtraDataRecord;
}
public void setAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord) {
this.aesExtraDataRecord = aesExtraDataRecord;
}
public boolean isFileNameUTF8Encoded() {
return fileNameUTF8Encoded;
}
public void setFileNameUTF8Encoded(boolean fileNameUTF8Encoded) {
this.fileNameUTF8Encoded = fileNameUTF8Encoded;
}
public List getExtraDataRecords() {
return extraDataRecords;
}
public void setExtraDataRecords(List extraDataRecords) {
this.extraDataRecords = extraDataRecords;
}
public boolean isDirectory() {
return isDirectory;
}
public void setDirectory(boolean directory) {
isDirectory = directory;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ArchiveExtraDataRecord.java 0000775 0000000 0000000 00000002204 13576501616 0026750 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class ArchiveExtraDataRecord extends ZipHeader {
private int extraFieldLength;
private String extraFieldData;
public int getExtraFieldLength() {
return extraFieldLength;
}
public void setExtraFieldLength(int extraFieldLength) {
this.extraFieldLength = extraFieldLength;
}
public String getExtraFieldData() {
return extraFieldData;
}
public void setExtraFieldData(String extraFieldData) {
this.extraFieldData = extraFieldData;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/CentralDirectory.java 0000775 0000000 0000000 00000002402 13576501616 0025707 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import java.util.ArrayList;
import java.util.List;
public class CentralDirectory {
private List fileHeaders = new ArrayList<>();
private DigitalSignature digitalSignature = new DigitalSignature();
public List getFileHeaders() {
return fileHeaders;
}
public void setFileHeaders(List fileHeaders) {
this.fileHeaders = fileHeaders;
}
public DigitalSignature getDigitalSignature() {
return digitalSignature;
}
public void setDigitalSignature(DigitalSignature digitalSignature) {
this.digitalSignature = digitalSignature;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/DataDescriptor.java 0000775 0000000 0000000 00000002315 13576501616 0025345 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class DataDescriptor extends ZipHeader {
private long crc;
private long compressedSize;
private long uncompressedSize;
public long getCrc() {
return crc;
}
public void setCrc(long crc) {
this.crc = crc;
}
public long getCompressedSize() {
return compressedSize;
}
public void setCompressedSize(long compressedSize) {
this.compressedSize = compressedSize;
}
public long getUncompressedSize() {
return uncompressedSize;
}
public void setUncompressedSize(long uncompressedSize) {
this.uncompressedSize = uncompressedSize;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/DigitalSignature.java 0000775 0000000 0000000 00000002116 13576501616 0025673 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class DigitalSignature extends ZipHeader {
private int sizeOfData;
private String signatureData;
public int getSizeOfData() {
return sizeOfData;
}
public void setSizeOfData(int sizeOfData) {
this.sizeOfData = sizeOfData;
}
public String getSignatureData() {
return signatureData;
}
public void setSignatureData(String signatureData) {
this.signatureData = signatureData;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/EndOfCentralDirectoryRecord.java 0000775 0000000 0000000 00000005601 13576501616 0027766 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import net.lingala.zip4j.headers.HeaderSignature;
public class EndOfCentralDirectoryRecord extends ZipHeader {
private int numberOfThisDisk;
private int numberOfThisDiskStartOfCentralDir;
private int totalNumberOfEntriesInCentralDirectoryOnThisDisk;
private int totalNumberOfEntriesInCentralDirectory;
private int sizeOfCentralDirectory;
private long offsetOfStartOfCentralDirectory;
private String comment = "";
public EndOfCentralDirectoryRecord() {
setSignature(HeaderSignature.END_OF_CENTRAL_DIRECTORY);
}
public int getNumberOfThisDisk() {
return numberOfThisDisk;
}
public void setNumberOfThisDisk(int numberOfThisDisk) {
this.numberOfThisDisk = numberOfThisDisk;
}
public int getNumberOfThisDiskStartOfCentralDir() {
return numberOfThisDiskStartOfCentralDir;
}
public void setNumberOfThisDiskStartOfCentralDir(int numberOfThisDiskStartOfCentralDir) {
this.numberOfThisDiskStartOfCentralDir = numberOfThisDiskStartOfCentralDir;
}
public int getTotalNumberOfEntriesInCentralDirectoryOnThisDisk() {
return totalNumberOfEntriesInCentralDirectoryOnThisDisk;
}
public void setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
int totalNumberOfEntriesInCentralDirectoryOnThisDisk) {
this.totalNumberOfEntriesInCentralDirectoryOnThisDisk = totalNumberOfEntriesInCentralDirectoryOnThisDisk;
}
public int getTotalNumberOfEntriesInCentralDirectory() {
return totalNumberOfEntriesInCentralDirectory;
}
public void setTotalNumberOfEntriesInCentralDirectory(int totNoOfEntrisInCentralDir) {
this.totalNumberOfEntriesInCentralDirectory = totNoOfEntrisInCentralDir;
}
public int getSizeOfCentralDirectory() {
return sizeOfCentralDirectory;
}
public void setSizeOfCentralDirectory(int sizeOfCentralDirectory) {
this.sizeOfCentralDirectory = sizeOfCentralDirectory;
}
public long getOffsetOfStartOfCentralDirectory() {
return offsetOfStartOfCentralDirectory;
}
public void setOffsetOfStartOfCentralDirectory(long offSetOfStartOfCentralDir) {
this.offsetOfStartOfCentralDirectory = offSetOfStartOfCentralDir;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
if (comment != null) {
this.comment = comment;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ExtraDataRecord.java 0000775 0000000 0000000 00000002247 13576501616 0025455 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class ExtraDataRecord extends ZipHeader {
private long header;
private int sizeOfData;
private byte[] data;
public long getHeader() {
return header;
}
public void setHeader(long header) {
this.header = header;
}
public int getSizeOfData() {
return sizeOfData;
}
public void setSizeOfData(int sizeOfData) {
this.sizeOfData = sizeOfData;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/FileHeader.java 0000775 0000000 0000000 00000004513 13576501616 0024427 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import net.lingala.zip4j.headers.HeaderSignature;
public class FileHeader extends AbstractFileHeader {
private int versionMadeBy;
private int fileCommentLength = 0;
private int diskNumberStart;
private byte[] internalFileAttributes;
private byte[] externalFileAttributes;
private long offsetLocalHeader;
private String fileComment;
public FileHeader() {
setSignature(HeaderSignature.CENTRAL_DIRECTORY);
}
public int getVersionMadeBy() {
return versionMadeBy;
}
public void setVersionMadeBy(int versionMadeBy) {
this.versionMadeBy = versionMadeBy;
}
public int getFileCommentLength() {
return fileCommentLength;
}
public void setFileCommentLength(int fileCommentLength) {
this.fileCommentLength = fileCommentLength;
}
public int getDiskNumberStart() {
return diskNumberStart;
}
public void setDiskNumberStart(int diskNumberStart) {
this.diskNumberStart = diskNumberStart;
}
public byte[] getInternalFileAttributes() {
return internalFileAttributes;
}
public void setInternalFileAttributes(byte[] internalFileAttributes) {
this.internalFileAttributes = internalFileAttributes;
}
public byte[] getExternalFileAttributes() {
return externalFileAttributes;
}
public void setExternalFileAttributes(byte[] externalFileAttributes) {
this.externalFileAttributes = externalFileAttributes;
}
public long getOffsetLocalHeader() {
return offsetLocalHeader;
}
public void setOffsetLocalHeader(long offsetLocalHeader) {
this.offsetLocalHeader = offsetLocalHeader;
}
public String getFileComment() {
return fileComment;
}
public void setFileComment(String fileComment) {
this.fileComment = fileComment;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/LocalFileHeader.java 0000775 0000000 0000000 00000003107 13576501616 0025400 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import net.lingala.zip4j.headers.HeaderSignature;
public class LocalFileHeader extends AbstractFileHeader {
private byte[] extraField;
private long offsetStartOfData;
private boolean writeCompressedSizeInZip64ExtraRecord;
public LocalFileHeader() {
setSignature(HeaderSignature.LOCAL_FILE_HEADER);
}
public byte[] getExtraField() {
return extraField;
}
public void setExtraField(byte[] extraField) {
this.extraField = extraField;
}
public long getOffsetStartOfData() {
return offsetStartOfData;
}
public void setOffsetStartOfData(long offsetStartOfData) {
this.offsetStartOfData = offsetStartOfData;
}
public boolean isWriteCompressedSizeInZip64ExtraRecord() {
return writeCompressedSizeInZip64ExtraRecord;
}
public void setWriteCompressedSizeInZip64ExtraRecord(boolean writeCompressedSizeInZip64ExtraRecord) {
this.writeCompressedSizeInZip64ExtraRecord = writeCompressedSizeInZip64ExtraRecord;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/Zip64EndOfCentralDirectoryLocator.java 0000775 0000000 0000000 00000003312 13576501616 0031005 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class Zip64EndOfCentralDirectoryLocator extends ZipHeader {
private int numberOfDiskStartOfZip64EndOfCentralDirectoryRecord;
private long offsetZip64EndOfCentralDirectoryRecord;
private int totalNumberOfDiscs;
public int getNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord() {
return numberOfDiskStartOfZip64EndOfCentralDirectoryRecord;
}
public void setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(
int noOfDiskStartOfZip64EndOfCentralDirRec) {
this.numberOfDiskStartOfZip64EndOfCentralDirectoryRecord = noOfDiskStartOfZip64EndOfCentralDirRec;
}
public long getOffsetZip64EndOfCentralDirectoryRecord() {
return offsetZip64EndOfCentralDirectoryRecord;
}
public void setOffsetZip64EndOfCentralDirectoryRecord(long offsetZip64EndOfCentralDirectoryRecord) {
this.offsetZip64EndOfCentralDirectoryRecord = offsetZip64EndOfCentralDirectoryRecord;
}
public int getTotalNumberOfDiscs() {
return totalNumberOfDiscs;
}
public void setTotalNumberOfDiscs(int totNumberOfDiscs) {
this.totalNumberOfDiscs = totNumberOfDiscs;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/Zip64EndOfCentralDirectoryRecord.java 0000775 0000000 0000000 00000007377 13576501616 0030637 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class Zip64EndOfCentralDirectoryRecord extends ZipHeader {
private long sizeOfZip64EndCentralDirectoryRecord;
private int versionMadeBy;
private int versionNeededToExtract;
private int numberOfThisDisk;
private int numberOfThisDiskStartOfCentralDirectory;
private long totalNumberOfEntriesInCentralDirectoryOnThisDisk;
private long totalNumberOfEntriesInCentralDirectory;
private long sizeOfCentralDirectory;
private long offsetStartCentralDirectoryWRTStartDiskNumber;
private byte[] extensibleDataSector;
public long getSizeOfZip64EndCentralDirectoryRecord() {
return sizeOfZip64EndCentralDirectoryRecord;
}
public void setSizeOfZip64EndCentralDirectoryRecord(long sizeOfZip64EndCentralDirectoryRecord) {
this.sizeOfZip64EndCentralDirectoryRecord = sizeOfZip64EndCentralDirectoryRecord;
}
public int getVersionMadeBy() {
return versionMadeBy;
}
public void setVersionMadeBy(int versionMadeBy) {
this.versionMadeBy = versionMadeBy;
}
public int getVersionNeededToExtract() {
return versionNeededToExtract;
}
public void setVersionNeededToExtract(int versionNeededToExtract) {
this.versionNeededToExtract = versionNeededToExtract;
}
public int getNumberOfThisDisk() {
return numberOfThisDisk;
}
public void setNumberOfThisDisk(int numberOfThisDisk) {
this.numberOfThisDisk = numberOfThisDisk;
}
public int getNumberOfThisDiskStartOfCentralDirectory() {
return numberOfThisDiskStartOfCentralDirectory;
}
public void setNumberOfThisDiskStartOfCentralDirectory(int numberOfThisDiskStartOfCentralDirectory) {
this.numberOfThisDiskStartOfCentralDirectory = numberOfThisDiskStartOfCentralDirectory;
}
public long getTotalNumberOfEntriesInCentralDirectoryOnThisDisk() {
return totalNumberOfEntriesInCentralDirectoryOnThisDisk;
}
public void setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
long totalNumberOfEntriesInCentralDirectoryOnThisDisk) {
this.totalNumberOfEntriesInCentralDirectoryOnThisDisk = totalNumberOfEntriesInCentralDirectoryOnThisDisk;
}
public long getTotalNumberOfEntriesInCentralDirectory() {
return totalNumberOfEntriesInCentralDirectory;
}
public void setTotalNumberOfEntriesInCentralDirectory(long totalNumberOfEntriesInCentralDirectory) {
this.totalNumberOfEntriesInCentralDirectory = totalNumberOfEntriesInCentralDirectory;
}
public long getSizeOfCentralDirectory() {
return sizeOfCentralDirectory;
}
public void setSizeOfCentralDirectory(long sizeOfCentralDirectory) {
this.sizeOfCentralDirectory = sizeOfCentralDirectory;
}
public long getOffsetStartCentralDirectoryWRTStartDiskNumber() {
return offsetStartCentralDirectoryWRTStartDiskNumber;
}
public void setOffsetStartCentralDirectoryWRTStartDiskNumber(
long offsetStartCentralDirectoryWRTStartDiskNumber) {
this.offsetStartCentralDirectoryWRTStartDiskNumber = offsetStartCentralDirectoryWRTStartDiskNumber;
}
public byte[] getExtensibleDataSector() {
return extensibleDataSector;
}
public void setExtensibleDataSector(byte[] extensibleDataSector) {
this.extensibleDataSector = extensibleDataSector;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/Zip64ExtendedInfo.java 0000775 0000000 0000000 00000003531 13576501616 0025647 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
public class Zip64ExtendedInfo extends ZipHeader {
private int size;
private long compressedSize;
private long uncompressedSize;
private long offsetLocalHeader;
private int diskNumberStart;
public Zip64ExtendedInfo() {
compressedSize = -1;
uncompressedSize = -1;
offsetLocalHeader = -1;
diskNumberStart = -1;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public long getCompressedSize() {
return compressedSize;
}
public void setCompressedSize(long compressedSize) {
this.compressedSize = compressedSize;
}
public long getUncompressedSize() {
return uncompressedSize;
}
public void setUncompressedSize(long uncompressedSize) {
this.uncompressedSize = uncompressedSize;
}
public long getOffsetLocalHeader() {
return offsetLocalHeader;
}
public void setOffsetLocalHeader(long offsetLocalHeader) {
this.offsetLocalHeader = offsetLocalHeader;
}
public int getDiskNumberStart() {
return diskNumberStart;
}
public void setDiskNumberStart(int diskNumberStart) {
this.diskNumberStart = diskNumberStart;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ZipHeader.java 0000664 0000000 0000000 00000000501 13576501616 0024300 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model;
import net.lingala.zip4j.headers.HeaderSignature;
public abstract class ZipHeader {
private HeaderSignature signature;
public HeaderSignature getSignature() {
return signature;
}
public void setSignature(HeaderSignature signature) {
this.signature = signature;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ZipModel.java 0000775 0000000 0000000 00000011264 13576501616 0024163 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ZipModel implements Cloneable {
private List localFileHeaders = new ArrayList<>();
private List dataDescriptors = new ArrayList<>();
private ArchiveExtraDataRecord archiveExtraDataRecord = new ArchiveExtraDataRecord();
private CentralDirectory centralDirectory = new CentralDirectory();
private EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = new EndOfCentralDirectoryRecord();
private Zip64EndOfCentralDirectoryLocator zip64EndOfCentralDirectoryLocator = new Zip64EndOfCentralDirectoryLocator();
private Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectoryRecord = new Zip64EndOfCentralDirectoryRecord();
private boolean splitArchive;
private long splitLength;
private File zipFile;
private boolean isZip64Format = false;
private boolean isNestedZipFile;
private long start;
private long end;
public ZipModel() {
splitLength = -1;
}
public List getLocalFileHeaders() {
return localFileHeaders;
}
public void setLocalFileHeaders(List localFileHeaderList) {
this.localFileHeaders = localFileHeaderList;
}
public List getDataDescriptors() {
return dataDescriptors;
}
public void setDataDescriptors(List dataDescriptors) {
this.dataDescriptors = dataDescriptors;
}
public CentralDirectory getCentralDirectory() {
return centralDirectory;
}
public void setCentralDirectory(CentralDirectory centralDirectory) {
this.centralDirectory = centralDirectory;
}
public EndOfCentralDirectoryRecord getEndOfCentralDirectoryRecord() {
return endOfCentralDirectoryRecord;
}
public void setEndOfCentralDirectoryRecord(EndOfCentralDirectoryRecord endOfCentralDirectoryRecord) {
this.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord;
}
public ArchiveExtraDataRecord getArchiveExtraDataRecord() {
return archiveExtraDataRecord;
}
public void setArchiveExtraDataRecord(
ArchiveExtraDataRecord archiveExtraDataRecord) {
this.archiveExtraDataRecord = archiveExtraDataRecord;
}
public boolean isSplitArchive() {
return splitArchive;
}
public void setSplitArchive(boolean splitArchive) {
this.splitArchive = splitArchive;
}
public File getZipFile() {
return zipFile;
}
public void setZipFile(File zipFile) {
this.zipFile = zipFile;
}
public Zip64EndOfCentralDirectoryLocator getZip64EndOfCentralDirectoryLocator() {
return zip64EndOfCentralDirectoryLocator;
}
public void setZip64EndOfCentralDirectoryLocator(
Zip64EndOfCentralDirectoryLocator zip64EndOfCentralDirectoryLocator) {
this.zip64EndOfCentralDirectoryLocator = zip64EndOfCentralDirectoryLocator;
}
public Zip64EndOfCentralDirectoryRecord getZip64EndOfCentralDirectoryRecord() {
return zip64EndOfCentralDirectoryRecord;
}
public void setZip64EndOfCentralDirectoryRecord(
Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectoryRecord) {
this.zip64EndOfCentralDirectoryRecord = zip64EndOfCentralDirectoryRecord;
}
public boolean isZip64Format() {
return isZip64Format;
}
public void setZip64Format(boolean isZip64Format) {
this.isZip64Format = isZip64Format;
}
public boolean isNestedZipFile() {
return isNestedZipFile;
}
public void setNestedZipFile(boolean isNestedZipFile) {
this.isNestedZipFile = isNestedZipFile;
}
public long getStart() {
return start;
}
public void setStart(long start) {
this.start = start;
}
public long getEnd() {
return end;
}
public void setEnd(long end) {
this.end = end;
}
public long getSplitLength() {
return splitLength;
}
public void setSplitLength(long splitLength) {
this.splitLength = splitLength;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/ZipParameters.java 0000775 0000000 0000000 00000014355 13576501616 0025232 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.model;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
public class ZipParameters {
private CompressionMethod compressionMethod = CompressionMethod.DEFLATE;
private CompressionLevel compressionLevel = CompressionLevel.NORMAL;
private boolean encryptFiles = false;
private EncryptionMethod encryptionMethod = EncryptionMethod.NONE;
private boolean readHiddenFiles = true;
private boolean readHiddenFolders = true;
private AesKeyStrength aesKeyStrength = AesKeyStrength.KEY_STRENGTH_256;
private AesVersion aesVersion = AesVersion.TWO;
private boolean includeRootFolder = true;
private long entryCRC;
private String defaultFolderPath;
private String fileNameInZip;
private long lastModifiedFileTime = System.currentTimeMillis();
private long entrySize = -1;
private boolean writeExtendedLocalFileHeader = true;
private boolean overrideExistingFilesInZip = true;
private String rootFolderNameInZip;
public ZipParameters() {
}
public ZipParameters(ZipParameters zipParameters) {
this.compressionMethod = zipParameters.getCompressionMethod();
this.compressionLevel = zipParameters.getCompressionLevel();
this.encryptFiles = zipParameters.isEncryptFiles();
this.encryptionMethod = zipParameters.getEncryptionMethod();
this.readHiddenFiles = zipParameters.isReadHiddenFiles();
this.readHiddenFolders = zipParameters.isReadHiddenFolders();
this.aesKeyStrength = zipParameters.getAesKeyStrength();
this.aesVersion = zipParameters.getAesVersion();
this.includeRootFolder = zipParameters.isIncludeRootFolder();
this.entryCRC = zipParameters.getEntryCRC();
this.defaultFolderPath = zipParameters.getDefaultFolderPath();
this.fileNameInZip = zipParameters.getFileNameInZip();
this.lastModifiedFileTime = zipParameters.getLastModifiedFileTime();
this.entrySize = zipParameters.getEntrySize();
this.writeExtendedLocalFileHeader = zipParameters.isWriteExtendedLocalFileHeader();
this.overrideExistingFilesInZip = zipParameters.isOverrideExistingFilesInZip();
this.rootFolderNameInZip = zipParameters.getRootFolderNameInZip();
}
public CompressionMethod getCompressionMethod() {
return compressionMethod;
}
public void setCompressionMethod(CompressionMethod compressionMethod) {
this.compressionMethod = compressionMethod;
}
public boolean isEncryptFiles() {
return encryptFiles;
}
public void setEncryptFiles(boolean encryptFiles) {
this.encryptFiles = encryptFiles;
}
public EncryptionMethod getEncryptionMethod() {
return encryptionMethod;
}
public void setEncryptionMethod(EncryptionMethod encryptionMethod) {
this.encryptionMethod = encryptionMethod;
}
public CompressionLevel getCompressionLevel() {
return compressionLevel;
}
public void setCompressionLevel(CompressionLevel compressionLevel) {
this.compressionLevel = compressionLevel;
}
public boolean isReadHiddenFiles() {
return readHiddenFiles;
}
public void setReadHiddenFiles(boolean readHiddenFiles) {
this.readHiddenFiles = readHiddenFiles;
}
public boolean isReadHiddenFolders() {
return readHiddenFolders;
}
public void setReadHiddenFolders(boolean readHiddenFolders) {
this.readHiddenFolders = readHiddenFolders;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public AesKeyStrength getAesKeyStrength() {
return aesKeyStrength;
}
public void setAesKeyStrength(AesKeyStrength aesKeyStrength) {
this.aesKeyStrength = aesKeyStrength;
}
public AesVersion getAesVersion() {
return aesVersion;
}
public void setAesVersion(AesVersion aesVersion) {
this.aesVersion = aesVersion;
}
public boolean isIncludeRootFolder() {
return includeRootFolder;
}
public void setIncludeRootFolder(boolean includeRootFolder) {
this.includeRootFolder = includeRootFolder;
}
public long getEntryCRC() {
return entryCRC;
}
public void setEntryCRC(long entryCRC) {
this.entryCRC = entryCRC;
}
public String getDefaultFolderPath() {
return defaultFolderPath;
}
public void setDefaultFolderPath(String defaultFolderPath) {
this.defaultFolderPath = defaultFolderPath;
}
public String getFileNameInZip() {
return fileNameInZip;
}
public void setFileNameInZip(String fileNameInZip) {
this.fileNameInZip = fileNameInZip;
}
public long getLastModifiedFileTime() {
return lastModifiedFileTime;
}
public void setLastModifiedFileTime(long lastModifiedFileTime) {
if (lastModifiedFileTime <= 0) {
return;
}
this.lastModifiedFileTime = lastModifiedFileTime;
}
public long getEntrySize() {
return entrySize;
}
public void setEntrySize(long entrySize) {
this.entrySize = entrySize;
}
public boolean isWriteExtendedLocalFileHeader() {
return writeExtendedLocalFileHeader;
}
public void setWriteExtendedLocalFileHeader(boolean writeExtendedLocalFileHeader) {
this.writeExtendedLocalFileHeader = writeExtendedLocalFileHeader;
}
public boolean isOverrideExistingFilesInZip() {
return overrideExistingFilesInZip;
}
public void setOverrideExistingFilesInZip(boolean overrideExistingFilesInZip) {
this.overrideExistingFilesInZip = overrideExistingFilesInZip;
}
public String getRootFolderNameInZip() {
return rootFolderNameInZip;
}
public void setRootFolderNameInZip(String rootFolderNameInZip) {
this.rootFolderNameInZip = rootFolderNameInZip;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/ 0000775 0000000 0000000 00000000000 13576501616 0022715 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/AesKeyStrength.java 0000664 0000000 0000000 00000001671 13576501616 0026465 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
public enum AesKeyStrength {
KEY_STRENGTH_128(1, 8, 16, 16),
KEY_STRENGTH_192(2, 12, 24, 24),
KEY_STRENGTH_256(3, 16, 32, 32);
private int rawCode;
private int saltLength;
private int macLength;
private int keyLength;
AesKeyStrength(int rawCode, int saltLength, int macLength, int keyLength) {
this.rawCode = rawCode;
this.saltLength = saltLength;
this.macLength = macLength;
this.keyLength = keyLength;
}
public int getRawCode() {
return rawCode;
}
public int getSaltLength() {
return saltLength;
}
public int getMacLength() {
return macLength;
}
public int getKeyLength() {
return keyLength;
}
public static AesKeyStrength getAesKeyStrengthFromRawCode(int code) {
for (AesKeyStrength aesKeyStrength : values()) {
if (aesKeyStrength.getRawCode() == code) {
return aesKeyStrength;
}
}
return null;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/AesVersion.java 0000664 0000000 0000000 00000001041 13576501616 0025632 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
public enum AesVersion {
ONE(1),
TWO(2);
private int versionNumber;
AesVersion(int versionNumber) {
this.versionNumber = versionNumber;
}
public int getVersionNumber() {
return versionNumber;
}
public static AesVersion getFromVersionNumber(int versionNumber) {
for (AesVersion aesVersion : values()) {
if (aesVersion.versionNumber == versionNumber) {
return aesVersion;
}
}
throw new IllegalArgumentException("Unsupported Aes version");
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/CompressionLevel.java 0000664 0000000 0000000 00000000402 13576501616 0027045 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
public enum CompressionLevel {
FASTEST(1),
FAST(3),
NORMAL(5),
MAXIMUM(7);
private int level;
CompressionLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/CompressionMethod.java 0000664 0000000 0000000 00000001230 13576501616 0027216 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
import net.lingala.zip4j.exception.ZipException;
public enum CompressionMethod {
STORE(0),
DEFLATE(8),
AES_INTERNAL_ONLY(99);
private int code;
CompressionMethod(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static CompressionMethod getCompressionMethodFromCode(int code) throws ZipException {
for (CompressionMethod compressionMethod : values()) {
if (compressionMethod.getCode() == code) {
return compressionMethod;
}
}
throw new ZipException("Unknown compression method", ZipException.Type.UNKNOWN_COMPRESSION_METHOD);
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/EncryptionMethod.java 0000664 0000000 0000000 00000000210 13576501616 0027044 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
public enum EncryptionMethod {
NONE,
ZIP_STANDARD,
ZIP_STANDARD_VARIANT_STRONG,
AES
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/model/enums/RandomAccessFileMode.java 0000664 0000000 0000000 00000000373 13576501616 0027532 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
public enum RandomAccessFileMode {
READ("r"),
WRITE("rw");
private String value;
RandomAccessFileMode(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/progress/ 0000775 0000000 0000000 00000000000 13576501616 0022332 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/progress/ProgressMonitor.java 0000775 0000000 0000000 00000007073 13576501616 0026363 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.progress;
/**
* If Zip4j is set to run in thread mode, this class helps retrieve current progress
*/
public class ProgressMonitor {
public enum State { READY, BUSY }
public enum Result { SUCCESS, WORK_IN_PROGRESS, ERROR, CANCELLED }
public enum Task { NONE, ADD_ENTRY, REMOVE_ENTRY, CALCULATE_CRC, EXTRACT_ENTRY, MERGE_ZIP_FILES, SET_COMMENT}
private State state;
private long totalWork;
private long workCompleted;
private int percentDone;
private Task currentTask;
private String fileName;
private Result result;
private Exception exception;
private boolean cancelAllTasks;
private boolean pause;
public ProgressMonitor() {
reset();
}
public void updateWorkCompleted(long workCompleted) {
this.workCompleted += workCompleted;
if (totalWork > 0) {
percentDone = (int) ((this.workCompleted * 100 / totalWork));
if (percentDone > 100) {
percentDone = 100;
}
}
while (pause) {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
//Do nothing
}
}
}
public void endProgressMonitor() {
result = Result.SUCCESS;
percentDone = 100;
reset();
}
public void endProgressMonitor(Exception e) {
result = Result.ERROR;
exception = e;
reset();
}
public void fullReset() {
reset();
fileName = null;
totalWork = 0;
workCompleted = 0;
percentDone = 0;
}
private void reset() {
currentTask = Task.NONE;
state = State.READY;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public long getTotalWork() {
return totalWork;
}
public void setTotalWork(long totalWork) {
this.totalWork = totalWork;
}
public long getWorkCompleted() {
return workCompleted;
}
public int getPercentDone() {
return percentDone;
}
public void setPercentDone(int percentDone) {
this.percentDone = percentDone;
}
public Task getCurrentTask() {
return currentTask;
}
public void setCurrentTask(Task currentTask) {
this.currentTask = currentTask;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public Exception getException() {
return exception;
}
public void setException(Exception exception) {
this.exception = exception;
}
public boolean isCancelAllTasks() {
return cancelAllTasks;
}
public void setCancelAllTasks(boolean cancelAllTasks) {
this.cancelAllTasks = cancelAllTasks;
}
public boolean isPause() {
return pause;
}
public void setPause(boolean pause) {
this.pause = pause;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/ 0000775 0000000 0000000 00000000000 13576501616 0021613 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AbstractAddFileToZipTask.java 0000664 0000000 0000000 00000022343 13576501616 0027247 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.RemoveEntryFromZipFileTask.RemoveEntryFromZipFileTaskParameters;
import net.lingala.zip4j.util.FileUtils;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static net.lingala.zip4j.headers.HeaderUtil.getFileHeader;
import static net.lingala.zip4j.model.enums.CompressionMethod.DEFLATE;
import static net.lingala.zip4j.model.enums.CompressionMethod.STORE;
import static net.lingala.zip4j.model.enums.EncryptionMethod.NONE;
import static net.lingala.zip4j.model.enums.EncryptionMethod.ZIP_STANDARD;
import static net.lingala.zip4j.progress.ProgressMonitor.Task.ADD_ENTRY;
import static net.lingala.zip4j.progress.ProgressMonitor.Task.CALCULATE_CRC;
import static net.lingala.zip4j.progress.ProgressMonitor.Task.REMOVE_ENTRY;
import static net.lingala.zip4j.util.CrcUtil.computeFileCrc;
import static net.lingala.zip4j.util.FileUtils.getRelativeFileName;
import static net.lingala.zip4j.util.InternalZipConstants.BUFF_SIZE;
import static net.lingala.zip4j.util.Zip4jUtil.javaToDosTime;
public abstract class AbstractAddFileToZipTask extends AsyncZipTask {
private ZipModel zipModel;
private char[] password;
private HeaderWriter headerWriter;
AbstractAddFileToZipTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel,
char[] password, HeaderWriter headerWriter) {
super(progressMonitor, runInThread);
this.zipModel = zipModel;
this.password = password;
this.headerWriter = headerWriter;
}
void addFilesToZip(List filesToAdd, ProgressMonitor progressMonitor, ZipParameters zipParameters, Charset charset)
throws IOException {
List updatedFilesToAdd = removeFilesIfExists(filesToAdd, zipParameters, progressMonitor, charset);
try (SplitOutputStream splitOutputStream = new SplitOutputStream(zipModel.getZipFile(), zipModel.getSplitLength());
ZipOutputStream zipOutputStream = initializeOutputStream(splitOutputStream, charset)) {
byte[] readBuff = new byte[BUFF_SIZE];
int readLen = -1;
for (File fileToAdd : updatedFilesToAdd) {
verifyIfTaskIsCancelled();
ZipParameters clonedZipParameters = cloneAndAdjustZipParameters(zipParameters, fileToAdd, progressMonitor);
progressMonitor.setFileName(fileToAdd.getAbsolutePath());
zipOutputStream.putNextEntry(clonedZipParameters);
if (fileToAdd.isDirectory()) {
zipOutputStream.closeEntry();
continue;
}
try (InputStream inputStream = new FileInputStream(fileToAdd)) {
while ((readLen = inputStream.read(readBuff)) != -1) {
zipOutputStream.write(readBuff, 0, readLen);
progressMonitor.updateWorkCompleted(readLen);
verifyIfTaskIsCancelled();
}
}
FileHeader fileHeader = zipOutputStream.closeEntry();
fileHeader.setExternalFileAttributes(FileUtils.getFileAttributes(fileToAdd));
updateLocalFileHeader(fileHeader, splitOutputStream);
}
}
}
long calculateWorkForFiles(List filesToAdd, ZipParameters zipParameters) throws ZipException {
long totalWork = 0;
for (File fileToAdd : filesToAdd) {
if (!fileToAdd.exists()) {
continue;
}
if (zipParameters.isEncryptFiles() && zipParameters.getEncryptionMethod() == EncryptionMethod.ZIP_STANDARD) {
totalWork += (fileToAdd.length() * 2); // for CRC calculation
} else {
totalWork += fileToAdd.length();
}
//If an entry already exists, we have to remove that entry first and then add content again.
//In this case, add corresponding work
String relativeFileName = getRelativeFileName(fileToAdd.getAbsolutePath(), zipParameters.getDefaultFolderPath(),
zipParameters.getRootFolderNameInZip());
FileHeader fileHeader = getFileHeader(getZipModel(), relativeFileName);
if (fileHeader != null) {
totalWork += (getZipModel().getZipFile().length() - fileHeader.getCompressedSize());
}
}
return totalWork;
}
ZipOutputStream initializeOutputStream(SplitOutputStream splitOutputStream, Charset charset) throws IOException {
if (zipModel.getZipFile().exists()) {
if (zipModel.getEndOfCentralDirectoryRecord() == null) {
throw new ZipException("invalid end of central directory record");
}
splitOutputStream.seek(zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory());
}
return new ZipOutputStream(splitOutputStream, password, charset, zipModel);
}
void verifyZipParameters(ZipParameters parameters) throws ZipException {
if (parameters == null) {
throw new ZipException("cannot validate zip parameters");
}
if (parameters.getCompressionMethod() != STORE && parameters.getCompressionMethod() != DEFLATE) {
throw new ZipException("unsupported compression type");
}
if (parameters.isEncryptFiles()) {
if (parameters.getEncryptionMethod() == NONE) {
throw new ZipException("Encryption method has to be set, when encrypt files flag is set");
}
if (password == null || password.length <= 0) {
throw new ZipException("input password is empty or null");
}
} else {
parameters.setEncryptionMethod(NONE);
}
}
void updateLocalFileHeader(FileHeader fileHeader, SplitOutputStream splitOutputStream) throws IOException {
headerWriter.updateLocalFileHeader(fileHeader, getZipModel(), splitOutputStream);
}
private ZipParameters cloneAndAdjustZipParameters(ZipParameters zipParameters, File fileToAdd,
ProgressMonitor progressMonitor) throws IOException {
ZipParameters clonedZipParameters = new ZipParameters(zipParameters);
clonedZipParameters.setLastModifiedFileTime(javaToDosTime((fileToAdd.lastModified())));
if (fileToAdd.isDirectory()) {
clonedZipParameters.setEntrySize(0);
} else {
clonedZipParameters.setEntrySize(fileToAdd.length());
}
clonedZipParameters.setWriteExtendedLocalFileHeader(false);
clonedZipParameters.setLastModifiedFileTime(fileToAdd.lastModified());
if (!Zip4jUtil.isStringNotNullAndNotEmpty(zipParameters.getFileNameInZip())) {
String relativeFileName = getRelativeFileName(fileToAdd.getAbsolutePath(), zipParameters.getDefaultFolderPath(),
zipParameters.getRootFolderNameInZip());
clonedZipParameters.setFileNameInZip(relativeFileName);
}
if (fileToAdd.isDirectory()) {
clonedZipParameters.setCompressionMethod(CompressionMethod.STORE);
clonedZipParameters.setEncryptionMethod(EncryptionMethod.NONE);
clonedZipParameters.setEncryptFiles(false);
} else {
if (clonedZipParameters.isEncryptFiles() && clonedZipParameters.getEncryptionMethod() == ZIP_STANDARD) {
progressMonitor.setCurrentTask(CALCULATE_CRC);
clonedZipParameters.setEntryCRC(computeFileCrc(fileToAdd, progressMonitor));
progressMonitor.setCurrentTask(ADD_ENTRY);
}
if (fileToAdd.length() == 0) {
clonedZipParameters.setCompressionMethod(CompressionMethod.STORE);
}
}
return clonedZipParameters;
}
private List removeFilesIfExists(List files, ZipParameters zipParameters, ProgressMonitor progressMonitor, Charset charset)
throws ZipException {
List filesToAdd = new ArrayList<>(files);
if (!zipModel.getZipFile().exists()) {
return filesToAdd;
}
for (File file : files) {
String fileName = getRelativeFileName(file.getAbsolutePath(), zipParameters.getDefaultFolderPath(),
zipParameters.getRootFolderNameInZip());
FileHeader fileHeader = getFileHeader(zipModel, fileName);
if (fileHeader != null) {
if (zipParameters.isOverrideExistingFilesInZip()) {
progressMonitor.setCurrentTask(REMOVE_ENTRY);
removeFile(fileHeader, progressMonitor, charset);
verifyIfTaskIsCancelled();
progressMonitor.setCurrentTask(ADD_ENTRY);
} else {
filesToAdd.remove(file);
}
}
}
return filesToAdd;
}
private void removeFile(FileHeader fileHeader, ProgressMonitor progressMonitor, Charset charset) throws ZipException {
RemoveEntryFromZipFileTask removeEntryFromZipFileTask = new RemoveEntryFromZipFileTask(progressMonitor, false,
zipModel);
removeEntryFromZipFileTask.execute(new RemoveEntryFromZipFileTaskParameters(fileHeader, charset));
}
@Override
protected ProgressMonitor.Task getTask() {
return ProgressMonitor.Task.ADD_ENTRY;
}
protected ZipModel getZipModel() {
return zipModel;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AbstractExtractFileTask.java 0000664 0000000 0000000 00000010540 13576501616 0027177 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.util.UnzipUtil;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.regex.Matcher;
import static net.lingala.zip4j.util.InternalZipConstants.BUFF_SIZE;
import static net.lingala.zip4j.util.InternalZipConstants.FILE_SEPARATOR;
public abstract class AbstractExtractFileTask extends AsyncZipTask {
private ZipModel zipModel;
private byte[] buff = new byte[BUFF_SIZE];
public AbstractExtractFileTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel) {
super(progressMonitor, runInThread);
this.zipModel = zipModel;
}
protected void extractFile(ZipInputStream zipInputStream, FileHeader fileHeader, String outputPath,
String newFileName, ProgressMonitor progressMonitor) throws IOException {
if (!outputPath.endsWith(FILE_SEPARATOR)) {
outputPath += FILE_SEPARATOR;
}
File outputFile = determineOutputFile(fileHeader, outputPath, newFileName);
progressMonitor.setFileName(outputFile.getAbsolutePath());
// make sure no file is extracted outside of the target directory (a.k.a zip slip)
if (!outputFile.getCanonicalPath().startsWith(new File(outputPath).getCanonicalPath())) {
throw new ZipException("illegal file name that breaks out of the target directory: "
+ fileHeader.getFileName());
}
verifyNextEntry(zipInputStream, fileHeader);
if (fileHeader.isDirectory()) {
if (!outputFile.exists()) {
if (!outputFile.mkdirs()) {
throw new ZipException("Could not create directory: " + outputFile);
}
}
} else {
checkOutputDirectoryStructure(outputFile);
unzipFile(zipInputStream, fileHeader, outputFile, progressMonitor);
}
}
private void unzipFile(ZipInputStream inputStream, FileHeader fileHeader, File outputFile,
ProgressMonitor progressMonitor) throws IOException {
int readLength;
try (OutputStream outputStream = new FileOutputStream(outputFile)) {
while ((readLength = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, readLength);
progressMonitor.updateWorkCompleted(readLength);
verifyIfTaskIsCancelled();
}
} catch (Exception e) {
if (outputFile.exists()) {
outputFile.delete();
}
throw e;
}
UnzipUtil.applyFileAttributes(fileHeader, outputFile);
}
private void verifyNextEntry(ZipInputStream zipInputStream, FileHeader fileHeader) throws IOException {
LocalFileHeader localFileHeader = zipInputStream.getNextEntry(fileHeader);
if (localFileHeader == null) {
throw new ZipException("Could not read corresponding local file header for file header: "
+ fileHeader.getFileName());
}
if (!fileHeader.getFileName().equals(localFileHeader.getFileName())) {
throw new ZipException("File header and local file header mismatch");
}
}
private void checkOutputDirectoryStructure(File outputFile) throws ZipException {
if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
throw new ZipException("Unable to create parent directories: " + outputFile.getParentFile());
}
}
private File determineOutputFile(FileHeader fileHeader, String outputPath, String newFileName) {
String outputFileName;
if (Zip4jUtil.isStringNotNullAndNotEmpty(newFileName)) {
outputFileName = newFileName;
} else {
outputFileName = getFileNameWithSystemFileSeparators(fileHeader.getFileName()); // replace all slashes with file separator
}
return new File(outputPath + FILE_SEPARATOR + outputFileName);
}
private String getFileNameWithSystemFileSeparators(String fileNameToReplace) {
return fileNameToReplace.replaceAll("[/\\\\]", Matcher.quoteReplacement(FILE_SEPARATOR));
}
@Override
protected ProgressMonitor.Task getTask() {
return ProgressMonitor.Task.EXTRACT_ENTRY;
}
public ZipModel getZipModel() {
return zipModel;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AbstractZipTaskParameters.java 0000664 0000000 0000000 00000000360 13576501616 0027552 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import java.nio.charset.Charset;
public abstract class AbstractZipTaskParameters {
protected Charset charset;
protected AbstractZipTaskParameters(Charset charset) {
this.charset = charset;
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AddFilesToZipTask.java 0000664 0000000 0000000 00000003422 13576501616 0025743 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.AddFilesToZipTask.AddFilesToZipTaskParameters;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
public class AddFilesToZipTask extends AbstractAddFileToZipTask {
public AddFilesToZipTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel, char[] password,
HeaderWriter headerWriter) {
super(progressMonitor, runInThread, zipModel, password, headerWriter);
}
@Override
protected void executeTask(AddFilesToZipTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
verifyZipParameters(taskParameters.zipParameters);
addFilesToZip(taskParameters.filesToAdd, progressMonitor, taskParameters.zipParameters, taskParameters.charset);
}
@Override
protected long calculateTotalWork(AddFilesToZipTaskParameters taskParameters) throws ZipException {
return calculateWorkForFiles(taskParameters.filesToAdd, taskParameters.zipParameters);
}
@Override
protected ProgressMonitor.Task getTask() {
return super.getTask();
}
public static class AddFilesToZipTaskParameters extends AbstractZipTaskParameters {
private List filesToAdd;
private ZipParameters zipParameters;
public AddFilesToZipTaskParameters(List filesToAdd, ZipParameters zipParameters, Charset charset) {
super(charset);
this.filesToAdd = filesToAdd;
this.zipParameters = zipParameters;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AddFolderToZipTask.java 0000664 0000000 0000000 00000006277 13576501616 0026127 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.AddFolderToZipTask.AddFolderToZipTaskParameters;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import static net.lingala.zip4j.util.FileUtils.getFilesInDirectoryRecursive;
public class AddFolderToZipTask extends AbstractAddFileToZipTask {
public AddFolderToZipTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel, char[] password,
HeaderWriter headerWriter) {
super(progressMonitor, runInThread, zipModel, password, headerWriter);
}
@Override
protected void executeTask(AddFolderToZipTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
List filesToAdd = getFilesToAdd(taskParameters);
setDefaultFolderPath(taskParameters);
addFilesToZip(filesToAdd, progressMonitor, taskParameters.zipParameters, taskParameters.charset);
}
@Override
protected long calculateTotalWork(AddFolderToZipTaskParameters taskParameters) throws ZipException {
List filesToAdd = getFilesInDirectoryRecursive(taskParameters.folderToAdd,
taskParameters.zipParameters.isReadHiddenFiles(),
taskParameters.zipParameters.isReadHiddenFolders());
if (taskParameters.zipParameters.isIncludeRootFolder()) {
filesToAdd.add(taskParameters.folderToAdd);
}
return calculateWorkForFiles(filesToAdd, taskParameters.zipParameters);
}
private void setDefaultFolderPath(AddFolderToZipTaskParameters taskParameters) throws IOException {
String rootFolderPath;
File folderToAdd = taskParameters.folderToAdd;
if (taskParameters.zipParameters.isIncludeRootFolder()) {
File parentFile = folderToAdd.getCanonicalFile().getParentFile();
if (parentFile == null) {
rootFolderPath = folderToAdd.getCanonicalPath();
} else {
rootFolderPath = folderToAdd.getCanonicalFile().getParentFile().getCanonicalPath();
}
} else {
rootFolderPath = folderToAdd.getCanonicalPath();
}
taskParameters.zipParameters.setDefaultFolderPath(rootFolderPath);
}
private List getFilesToAdd(AddFolderToZipTaskParameters taskParameters) throws ZipException {
List filesToAdd = getFilesInDirectoryRecursive(taskParameters.folderToAdd,
taskParameters.zipParameters.isReadHiddenFiles(),
taskParameters.zipParameters.isReadHiddenFolders());
if (taskParameters.zipParameters.isIncludeRootFolder()) {
filesToAdd.add(taskParameters.folderToAdd);
}
return filesToAdd;
}
public static class AddFolderToZipTaskParameters extends AbstractZipTaskParameters {
private File folderToAdd;
private ZipParameters zipParameters;
public AddFolderToZipTaskParameters(File folderToAdd, ZipParameters zipParameters, Charset charset) {
super(charset);
this.folderToAdd = folderToAdd;
this.zipParameters = zipParameters;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AddStreamToZipTask.java 0000664 0000000 0000000 00000010553 13576501616 0026137 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderUtil;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.AddStreamToZipTask.AddStreamToZipTaskParameters;
import net.lingala.zip4j.tasks.RemoveEntryFromZipFileTask.RemoveEntryFromZipFileTaskParameters;
import net.lingala.zip4j.util.Zip4jUtil;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import static net.lingala.zip4j.util.InternalZipConstants.BUFF_SIZE;
public class AddStreamToZipTask extends AbstractAddFileToZipTask {
public AddStreamToZipTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel, char[] password,
HeaderWriter headerWriter) {
super(progressMonitor, runInThread, zipModel, password, headerWriter);
}
@Override
protected void executeTask(AddStreamToZipTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
verifyZipParameters(taskParameters.zipParameters);
if (!Zip4jUtil.isStringNotNullAndNotEmpty(taskParameters.zipParameters.getFileNameInZip())) {
throw new ZipException("fileNameInZip has to be set in zipParameters when adding stream");
}
removeFileIfExists(getZipModel(), taskParameters.charset, taskParameters.zipParameters.getFileNameInZip(), progressMonitor);
// For streams, it is necessary to write extended local file header because of Zip standard encryption.
// If we do not write extended local file header, zip standard encryption needs a crc upfront for key,
// which cannot be calculated until we read the complete stream. If we use extended local file header,
// last modified file time is used, or current system time if not available.
taskParameters.zipParameters.setWriteExtendedLocalFileHeader(true);
if (taskParameters.zipParameters.getCompressionMethod().equals(CompressionMethod.STORE)) {
// Set some random value here. This will be updated again when closing entry
taskParameters.zipParameters.setEntrySize(0);
}
try(SplitOutputStream splitOutputStream = new SplitOutputStream(getZipModel().getZipFile(), getZipModel().getSplitLength());
ZipOutputStream zipOutputStream = initializeOutputStream(splitOutputStream, taskParameters.charset)) {
byte[] readBuff = new byte[BUFF_SIZE];
int readLen = -1;
ZipParameters zipParameters = taskParameters.zipParameters;
zipOutputStream.putNextEntry(zipParameters);
if (!zipParameters.getFileNameInZip().endsWith("/") &&
!zipParameters.getFileNameInZip().endsWith("\\")) {
while ((readLen = taskParameters.inputStream.read(readBuff)) != -1) {
zipOutputStream.write(readBuff, 0, readLen);
}
}
FileHeader fileHeader = zipOutputStream.closeEntry();
if (fileHeader.getCompressionMethod().equals(CompressionMethod.STORE)) {
updateLocalFileHeader(fileHeader, splitOutputStream);
}
}
}
@Override
protected long calculateTotalWork(AddStreamToZipTaskParameters taskParameters) {
return 0;
}
private void removeFileIfExists(ZipModel zipModel, Charset charset, String fileNameInZip, ProgressMonitor progressMonitor)
throws ZipException {
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, fileNameInZip);
if (fileHeader != null) {
RemoveEntryFromZipFileTask removeEntryFromZipFileTask = new RemoveEntryFromZipFileTask(progressMonitor, false,
zipModel);
removeEntryFromZipFileTask.execute(new RemoveEntryFromZipFileTaskParameters(fileHeader, charset));
}
}
public static class AddStreamToZipTaskParameters extends AbstractZipTaskParameters {
private InputStream inputStream;
private ZipParameters zipParameters;
public AddStreamToZipTaskParameters(InputStream inputStream, ZipParameters zipParameters, Charset charset) {
super(charset);
this.inputStream = inputStream;
this.zipParameters = zipParameters;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/AsyncZipTask.java 0000664 0000000 0000000 00000004265 13576501616 0025050 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.progress.ProgressMonitor;
import java.io.IOException;
import java.util.concurrent.Executors;
public abstract class AsyncZipTask {
private ProgressMonitor progressMonitor;
private boolean runInThread;
public AsyncZipTask(ProgressMonitor progressMonitor, boolean runInThread) {
this.progressMonitor = progressMonitor;
this.runInThread = runInThread;
}
public void execute(T taskParameters) throws ZipException {
progressMonitor.fullReset();
progressMonitor.setState(ProgressMonitor.State.BUSY);
progressMonitor.setCurrentTask(getTask());
if (runInThread) {
long totalWorkToBeDone = calculateTotalWork(taskParameters);
progressMonitor.setTotalWork(totalWorkToBeDone);
Executors.newSingleThreadExecutor().execute(() -> {
try {
performTaskWithErrorHandling(taskParameters, progressMonitor);
} catch (ZipException e) {
//Do nothing. Exception will be passed through progress monitor
}
});
} else {
performTaskWithErrorHandling(taskParameters, progressMonitor);
}
}
private void performTaskWithErrorHandling(T taskParameters, ProgressMonitor progressMonitor) throws ZipException {
try {
executeTask(taskParameters, progressMonitor);
progressMonitor.endProgressMonitor();
} catch (ZipException e) {
progressMonitor.endProgressMonitor(e);
throw e;
} catch (Exception e) {
progressMonitor.endProgressMonitor(e);
throw new ZipException(e);
}
}
protected void verifyIfTaskIsCancelled() throws ZipException {
if (!progressMonitor.isCancelAllTasks()) {
return;
}
progressMonitor.setResult(ProgressMonitor.Result.CANCELLED);
progressMonitor.setState(ProgressMonitor.State.READY);
throw new ZipException("Task cancelled", ZipException.Type.TASK_CANCELLED_EXCEPTION);
}
protected abstract void executeTask(T taskParameters, ProgressMonitor progressMonitor) throws IOException;
protected abstract long calculateTotalWork(T taskParameters) throws ZipException;
protected abstract ProgressMonitor.Task getTask();
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/ExtractAllFilesTask.java 0000664 0000000 0000000 00000006323 13576501616 0026333 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.io.inputstream.SplitInputStream;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.ExtractAllFilesTask.ExtractAllFilesTaskParameters;
import java.io.IOException;
import java.nio.charset.Charset;
public class ExtractAllFilesTask extends AbstractExtractFileTask {
private char[] password;
private SplitInputStream splitInputStream;
public ExtractAllFilesTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel, char[] password) {
super(progressMonitor, runInThread, zipModel);
this.password = password;
}
@Override
protected void executeTask(ExtractAllFilesTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
try (ZipInputStream zipInputStream = prepareZipInputStream(taskParameters.charset)) {
for (FileHeader fileHeader : getZipModel().getCentralDirectory().getFileHeaders()) {
if (fileHeader.getFileName().startsWith("__MACOSX")) {
progressMonitor.updateWorkCompleted(fileHeader.getUncompressedSize());
continue;
}
splitInputStream.prepareExtractionForFileHeader(fileHeader);
extractFile(zipInputStream, fileHeader, taskParameters.outputPath, null, progressMonitor);
verifyIfTaskIsCancelled();
}
} finally {
if (splitInputStream != null) {
splitInputStream.close();
}
}
}
@Override
protected long calculateTotalWork(ExtractAllFilesTaskParameters taskParameters) {
long totalWork = 0;
for (FileHeader fileHeader : getZipModel().getCentralDirectory().getFileHeaders()) {
if (fileHeader.getZip64ExtendedInfo() != null &&
fileHeader.getZip64ExtendedInfo().getUncompressedSize() > 0) {
totalWork += fileHeader.getZip64ExtendedInfo().getUncompressedSize();
} else {
totalWork += fileHeader.getUncompressedSize();
}
}
return totalWork;
}
private ZipInputStream prepareZipInputStream(Charset charset) throws IOException {
splitInputStream = new SplitInputStream(getZipModel().getZipFile(),
getZipModel().isSplitArchive(), getZipModel().getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
FileHeader fileHeader = getFirstFileHeader(getZipModel());
if (fileHeader != null) {
splitInputStream.prepareExtractionForFileHeader(fileHeader);
}
return new ZipInputStream(splitInputStream, password, charset);
}
private FileHeader getFirstFileHeader(ZipModel zipModel) {
if (zipModel.getCentralDirectory() == null
|| zipModel.getCentralDirectory().getFileHeaders() == null
|| zipModel.getCentralDirectory().getFileHeaders().size() == 0) {
return null;
}
return zipModel.getCentralDirectory().getFileHeaders().get(0);
}
public static class ExtractAllFilesTaskParameters extends AbstractZipTaskParameters {
private String outputPath;
public ExtractAllFilesTaskParameters(String outputPath, Charset charset) {
super(charset);
this.outputPath = outputPath;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/ExtractFileTask.java 0000664 0000000 0000000 00000004430 13576501616 0025514 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.io.inputstream.SplitInputStream;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.ExtractFileTask.ExtractFileTaskParameters;
import java.io.IOException;
import java.nio.charset.Charset;
public class ExtractFileTask extends AbstractExtractFileTask {
private char[] password;
private SplitInputStream splitInputStream;
public ExtractFileTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel, char[] password) {
super(progressMonitor, runInThread, zipModel);
this.password = password;
}
@Override
protected void executeTask(ExtractFileTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
try(ZipInputStream zipInputStream = createZipInputStream(taskParameters.fileHeader, taskParameters.charset)) {
extractFile(zipInputStream, taskParameters.fileHeader, taskParameters.outputPath, taskParameters.newFileName,
progressMonitor);
} finally {
if (splitInputStream != null) {
splitInputStream.close();
}
}
}
@Override
protected long calculateTotalWork(ExtractFileTaskParameters taskParameters) {
return taskParameters.fileHeader.getUncompressedSize();
}
protected ZipInputStream createZipInputStream(FileHeader fileHeader, Charset charset) throws IOException {
splitInputStream = new SplitInputStream(getZipModel().getZipFile(),
getZipModel().isSplitArchive(), getZipModel().getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
splitInputStream.prepareExtractionForFileHeader(fileHeader);
return new ZipInputStream(splitInputStream, password, charset);
}
public static class ExtractFileTaskParameters extends AbstractZipTaskParameters {
private String outputPath;
private FileHeader fileHeader;
private String newFileName;
public ExtractFileTaskParameters(String outputPath, FileHeader fileHeader, String newFileName, Charset charset) {
super(charset);
this.outputPath = outputPath;
this.fileHeader = fileHeader;
this.newFileName = newFileName;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/MergeSplitZipFileTask.java 0000664 0000000 0000000 00000020307 13576501616 0026641 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderSignature;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.model.EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryLocator;
import net.lingala.zip4j.model.Zip64EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.MergeSplitZipFileTask.MergeSplitZipFileTaskParameters;
import net.lingala.zip4j.util.RawIO;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.List;
import static net.lingala.zip4j.util.FileUtils.copyFile;
public class MergeSplitZipFileTask extends AsyncZipTask {
private ZipModel zipModel;
private RawIO rawIO = new RawIO();
public MergeSplitZipFileTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel) {
super(progressMonitor, runInThread);
this.zipModel = zipModel;
}
@Override
protected void executeTask(MergeSplitZipFileTaskParameters taskParameters, ProgressMonitor progressMonitor) throws IOException {
if (!zipModel.isSplitArchive()) {
ZipException e = new ZipException("archive not a split zip file");
progressMonitor.endProgressMonitor(e);
throw e;
}
try (OutputStream outputStream = new FileOutputStream(taskParameters.outputZipFile)) {
long totalBytesWritten = 0;
int totalNumberOfSplitFiles = zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk();
if (totalNumberOfSplitFiles <= 0) {
throw new ZipException("zip archive not a split zip file");
}
int splitSignatureOverhead = 0;
for (int i = 0; i <= totalNumberOfSplitFiles; i++) {
try (RandomAccessFile randomAccessFile = createSplitZipFileStream(zipModel, i)) {
int start = 0;
long end = randomAccessFile.length();
if (i == 0) {
if (rawIO.readIntLittleEndian(randomAccessFile) == HeaderSignature.SPLIT_ZIP.getValue()) {
splitSignatureOverhead = 4;
start = 4;
} else {
randomAccessFile.seek(0);
}
}
if (i == totalNumberOfSplitFiles) {
end = zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory();
}
copyFile(randomAccessFile, outputStream, start, end, progressMonitor);
totalBytesWritten += (end - start);
updateFileHeaderOffsetsForIndex(zipModel.getCentralDirectory().getFileHeaders(),
i == 0 ? 0 : totalBytesWritten, i, splitSignatureOverhead);
verifyIfTaskIsCancelled();
}
}
updateHeadersForMergeSplitFileAction(zipModel, totalBytesWritten, outputStream, taskParameters.charset);
progressMonitor.endProgressMonitor();
} catch (CloneNotSupportedException e) {
throw new ZipException(e);
}
}
@Override
protected long calculateTotalWork(MergeSplitZipFileTaskParameters taskParameters) {
if (!zipModel.isSplitArchive()) {
return 0;
}
long totalSize = 0;
for (int i = 0; i <= zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk(); i++) {
totalSize += getNextSplitZipFile(zipModel, i).length();
}
return totalSize;
}
private void updateFileHeaderOffsetsForIndex(List fileHeaders, long offsetToAdd, int index,
int splitSignatureOverhead) {
for (FileHeader fileHeader : fileHeaders) {
if (fileHeader.getDiskNumberStart() == index) {
fileHeader.setOffsetLocalHeader(fileHeader.getOffsetLocalHeader() + offsetToAdd - splitSignatureOverhead);
fileHeader.setDiskNumberStart(0);
}
}
}
private File getNextSplitZipFile(ZipModel zipModel, int partNumber) {
if (partNumber == zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk()) {
return zipModel.getZipFile();
}
String splitZipExtension = ".z0";
if (partNumber >= 9) {
splitZipExtension = ".z";
}
String rootZipFile = zipModel.getZipFile().getPath();
String nextSplitZipFileName = zipModel.getZipFile().getPath().substring(0, rootZipFile.lastIndexOf("."))
+ splitZipExtension + (partNumber + 1);
return new File(nextSplitZipFileName);
}
private RandomAccessFile createSplitZipFileStream(ZipModel zipModel, int partNumber) throws FileNotFoundException {
File splitFile = getNextSplitZipFile(zipModel, partNumber);
return new RandomAccessFile(splitFile, RandomAccessFileMode.READ.getValue());
}
private void updateHeadersForMergeSplitFileAction(ZipModel zipModel, long totalBytesWritten,
OutputStream outputStream, Charset charset)
throws IOException, CloneNotSupportedException {
ZipModel newZipModel = (ZipModel) zipModel.clone();
newZipModel.getEndOfCentralDirectoryRecord().setOffsetOfStartOfCentralDirectory(totalBytesWritten);
updateSplitZipModel(newZipModel, totalBytesWritten);
HeaderWriter headerWriter = new HeaderWriter();
headerWriter.finalizeZipFileWithoutValidations(newZipModel, outputStream, charset);
}
private void updateSplitZipModel(ZipModel zipModel, long totalFileSize) {
zipModel.setSplitArchive(false);
updateSplitEndCentralDirectory(zipModel);
if (zipModel.isZip64Format()) {
updateSplitZip64EndCentralDirLocator(zipModel, totalFileSize);
updateSplitZip64EndCentralDirRec(zipModel, totalFileSize);
}
}
private void updateSplitEndCentralDirectory(ZipModel zipModel) {
int numberOfFileHeaders = zipModel.getCentralDirectory().getFileHeaders().size();
EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = zipModel.getEndOfCentralDirectoryRecord();
endOfCentralDirectoryRecord.setNumberOfThisDisk(0);
endOfCentralDirectoryRecord.setNumberOfThisDiskStartOfCentralDir(0);
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectory(numberOfFileHeaders);
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(numberOfFileHeaders);
}
private void updateSplitZip64EndCentralDirLocator(ZipModel zipModel, long totalFileSize) {
if (zipModel.getZip64EndOfCentralDirectoryLocator() == null) {
return;
}
Zip64EndOfCentralDirectoryLocator zip64EndOfCentralDirectoryLocator = zipModel
.getZip64EndOfCentralDirectoryLocator();
zip64EndOfCentralDirectoryLocator.setNumberOfDiskStartOfZip64EndOfCentralDirectoryRecord(0);
zip64EndOfCentralDirectoryLocator.setOffsetZip64EndOfCentralDirectoryRecord(
zip64EndOfCentralDirectoryLocator.getOffsetZip64EndOfCentralDirectoryRecord() + totalFileSize);
zip64EndOfCentralDirectoryLocator.setTotalNumberOfDiscs(1);
}
private void updateSplitZip64EndCentralDirRec(ZipModel zipModel, long totalFileSize) {
if (zipModel.getZip64EndOfCentralDirectoryRecord() == null) {
return;
}
Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectoryRecord = zipModel.getZip64EndOfCentralDirectoryRecord();
zip64EndOfCentralDirectoryRecord.setNumberOfThisDisk(0);
zip64EndOfCentralDirectoryRecord.setNumberOfThisDiskStartOfCentralDirectory(0);
zip64EndOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
zipModel.getEndOfCentralDirectoryRecord().getTotalNumberOfEntriesInCentralDirectory());
zip64EndOfCentralDirectoryRecord.setOffsetStartCentralDirectoryWRTStartDiskNumber(
zip64EndOfCentralDirectoryRecord.getOffsetStartCentralDirectoryWRTStartDiskNumber() + totalFileSize);
}
@Override
protected ProgressMonitor.Task getTask() {
return ProgressMonitor.Task.MERGE_ZIP_FILES;
}
public static class MergeSplitZipFileTaskParameters extends AbstractZipTaskParameters {
private File outputZipFile;
public MergeSplitZipFileTaskParameters(File outputZipFile, Charset charset) {
super(charset);
this.outputZipFile = outputZipFile;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/RemoveEntryFromZipFileTask.java 0000664 0000000 0000000 00000020536 13576501616 0027675 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.model.EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.RemoveEntryFromZipFileTask.RemoveEntryFromZipFileTaskParameters;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Random;
import static net.lingala.zip4j.headers.HeaderUtil.getIndexOfFileHeader;
import static net.lingala.zip4j.util.FileUtils.copyFile;
public class RemoveEntryFromZipFileTask extends AsyncZipTask {
private ZipModel zipModel;
public RemoveEntryFromZipFileTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel) {
super(progressMonitor, runInThread);
this.zipModel = zipModel;
}
@Override
protected void executeTask(RemoveEntryFromZipFileTaskParameters taskParameters, ProgressMonitor progressMonitor)
throws IOException {
if (zipModel.isSplitArchive()) {
throw new ZipException("This is a split archive. Zip file format does not allow updating split/spanned files");
}
File temporaryZipFile = getTemporaryFile(zipModel.getZipFile().getPath());
boolean successFlag = false;
try (SplitOutputStream outputStream = new SplitOutputStream(temporaryZipFile);
RandomAccessFile inputStream = new RandomAccessFile(zipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())){
int indexOfFileHeader = getIndexOfFileHeader(zipModel, taskParameters.fileHeader);
long offsetLocalFileHeader = getOffsetLocalFileHeader(taskParameters.fileHeader);
long offsetStartOfCentralDirectory = getOffsetOfStartOfCentralDirectory(zipModel);
List fileHeaders = zipModel.getCentralDirectory().getFileHeaders();
long offsetEndOfCompressedData = getOffsetEndOfCompressedData(indexOfFileHeader,
offsetStartOfCentralDirectory, fileHeaders);
if (indexOfFileHeader == 0) {
if (zipModel.getCentralDirectory().getFileHeaders().size() > 1) {
// if this is the only file and it is deleted then no need to do this
copyFile(inputStream, outputStream, offsetEndOfCompressedData + 1,
offsetStartOfCentralDirectory, progressMonitor);
}
} else if (indexOfFileHeader == fileHeaders.size() - 1) {
copyFile(inputStream, outputStream, 0, offsetLocalFileHeader, progressMonitor);
} else {
copyFile(inputStream, outputStream, 0, offsetLocalFileHeader, progressMonitor);
copyFile(inputStream, outputStream, offsetEndOfCompressedData + 1,
offsetStartOfCentralDirectory, progressMonitor);
}
verifyIfTaskIsCancelled();
updateHeaders(zipModel, outputStream, indexOfFileHeader, offsetEndOfCompressedData, offsetLocalFileHeader, taskParameters.charset);
successFlag = true;
} finally {
cleanupFile(successFlag, zipModel.getZipFile(), temporaryZipFile);
}
}
private long getOffsetOfStartOfCentralDirectory(ZipModel zipModel) {
long offsetStartCentralDir = zipModel.getEndOfCentralDirectoryRecord().getOffsetOfStartOfCentralDirectory();
if (zipModel.isZip64Format() && zipModel.getZip64EndOfCentralDirectoryRecord() != null) {
offsetStartCentralDir = zipModel.getZip64EndOfCentralDirectoryRecord()
.getOffsetStartCentralDirectoryWRTStartDiskNumber();
}
return offsetStartCentralDir;
}
private long getOffsetEndOfCompressedData(int indexOfFileHeader, long offsetStartOfCentralDirectory,
List fileHeaders) {
if (indexOfFileHeader == fileHeaders.size() - 1) {
return offsetStartOfCentralDirectory - 1;
}
FileHeader nextFileHeader = fileHeaders.get(indexOfFileHeader + 1);
long offsetEndOfCompressedFile = nextFileHeader.getOffsetLocalHeader() - 1;
if (nextFileHeader.getZip64ExtendedInfo() != null
&& nextFileHeader.getZip64ExtendedInfo().getOffsetLocalHeader() != -1) {
offsetEndOfCompressedFile = nextFileHeader.getZip64ExtendedInfo().getOffsetLocalHeader() - 1;
}
return offsetEndOfCompressedFile;
}
private File getTemporaryFile(String zipPathWithName) {
Random random = new Random();
File tmpFile = new File(zipPathWithName + random.nextInt(10000));
while (tmpFile.exists()) {
tmpFile = new File(zipPathWithName + random.nextInt(10000));
}
return tmpFile;
}
private long getOffsetLocalFileHeader(FileHeader fileHeader) {
long offsetLocalFileHeader = fileHeader.getOffsetLocalHeader();
if (fileHeader.getZip64ExtendedInfo() != null && fileHeader.getZip64ExtendedInfo().getOffsetLocalHeader() != -1) {
offsetLocalFileHeader = fileHeader.getZip64ExtendedInfo().getOffsetLocalHeader();
}
return offsetLocalFileHeader;
}
private void updateHeaders(ZipModel zipModel, SplitOutputStream splitOutputStream, int indexOfFileHeader, long
offsetEndOfCompressedFile, long offsetLocalFileHeader, Charset charset) throws IOException {
updateEndOfCentralDirectoryRecord(zipModel, splitOutputStream);
zipModel.getCentralDirectory().getFileHeaders().remove(indexOfFileHeader);
updateFileHeadersWithLocalHeaderOffsets(zipModel.getCentralDirectory().getFileHeaders(), offsetEndOfCompressedFile,
offsetLocalFileHeader);
HeaderWriter headerWriter = new HeaderWriter();
headerWriter.finalizeZipFile(zipModel, splitOutputStream, charset);
}
private void updateEndOfCentralDirectoryRecord(ZipModel zipModel, SplitOutputStream splitOutputStream)
throws IOException {
EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = zipModel.getEndOfCentralDirectoryRecord();
endOfCentralDirectoryRecord.setOffsetOfStartOfCentralDirectory(splitOutputStream.getFilePointer());
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectory(
endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectory() - 1);
endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk(
endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectoryOnThisDisk() - 1);
zipModel.setEndOfCentralDirectoryRecord(endOfCentralDirectoryRecord);
}
private void updateFileHeadersWithLocalHeaderOffsets(List fileHeaders, long offsetEndOfCompressedFile,
long offsetLocalFileHeader) {
for (int i = 0; i < fileHeaders.size(); i ++) {
FileHeader fileHeader = fileHeaders.get(i);
long offsetLocalHdr = fileHeader.getOffsetLocalHeader();
if (fileHeader.getZip64ExtendedInfo() != null && fileHeader.getZip64ExtendedInfo().getOffsetLocalHeader() != -1) {
offsetLocalHdr = fileHeader.getZip64ExtendedInfo().getOffsetLocalHeader();
}
if (offsetLocalHdr > offsetLocalFileHeader) {
fileHeader.setOffsetLocalHeader(offsetLocalHdr - (offsetEndOfCompressedFile - offsetLocalFileHeader) - 1);
}
}
}
private void cleanupFile(boolean successFlag, File zipFile, File temporaryZipFile) throws ZipException {
if (successFlag) {
restoreFileName(zipFile, temporaryZipFile);
} else {
temporaryZipFile.delete();
}
}
private void restoreFileName(File zipFile, File temporaryZipFile) throws ZipException {
if (zipFile.delete()) {
if (!temporaryZipFile.renameTo(zipFile)) {
throw new ZipException("cannot rename modified zip file");
}
} else {
throw new ZipException("cannot delete old zip file");
}
}
@Override
protected long calculateTotalWork(RemoveEntryFromZipFileTaskParameters taskParameters) {
return zipModel.getZipFile().length() - taskParameters.fileHeader.getCompressedSize();
}
@Override
protected ProgressMonitor.Task getTask() {
return ProgressMonitor.Task.REMOVE_ENTRY;
}
public static class RemoveEntryFromZipFileTaskParameters extends AbstractZipTaskParameters {
private FileHeader fileHeader;
public RemoveEntryFromZipFileTaskParameters(FileHeader fileHeader, Charset charset) {
super(charset);
this.fileHeader = fileHeader;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/tasks/SetCommentTask.java 0000664 0000000 0000000 00000004304 13576501616 0025360 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.tasks;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderWriter;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.model.EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.tasks.SetCommentTask.SetCommentTaskTaskParameters;
import java.io.IOException;
import java.nio.charset.Charset;
public class SetCommentTask extends AsyncZipTask {
private ZipModel zipModel;
public SetCommentTask(ProgressMonitor progressMonitor, boolean runInThread, ZipModel zipModel) {
super(progressMonitor, runInThread);
this.zipModel = zipModel;
}
@Override
protected void executeTask(SetCommentTaskTaskParameters taskParameters, ProgressMonitor progressMonitor) throws IOException {
if (taskParameters.comment == null) {
throw new ZipException("comment is null, cannot update Zip file with comment");
}
EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = zipModel.getEndOfCentralDirectoryRecord();
endOfCentralDirectoryRecord.setComment(taskParameters.comment);
try (SplitOutputStream outputStream = new SplitOutputStream(zipModel.getZipFile())) {
if (zipModel.isZip64Format()) {
outputStream.seek(zipModel.getZip64EndOfCentralDirectoryRecord()
.getOffsetStartCentralDirectoryWRTStartDiskNumber());
} else {
outputStream.seek(endOfCentralDirectoryRecord.getOffsetOfStartOfCentralDirectory());
}
HeaderWriter headerWriter = new HeaderWriter();
headerWriter.finalizeZipFileWithoutValidations(zipModel, outputStream, taskParameters.charset);
}
}
@Override
protected long calculateTotalWork(SetCommentTaskTaskParameters taskParameters) {
return 0;
}
@Override
protected ProgressMonitor.Task getTask() {
return ProgressMonitor.Task.SET_COMMENT;
}
public static class SetCommentTaskTaskParameters extends AbstractZipTaskParameters {
private String comment;
public SetCommentTaskTaskParameters(String comment, Charset charset) {
super(charset);
this.comment = comment;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/ 0000775 0000000 0000000 00000000000 13576501616 0021443 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/BitUtils.java 0000664 0000000 0000000 00000000510 13576501616 0024041 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
public class BitUtils {
public static boolean isBitSet(byte b, int pos) {
return (b & (1L << pos)) != 0;
}
public static byte setBit(byte b, int pos) {
return (byte) (b | 1 << pos);
}
public static byte unsetBit(byte b, int pos) {
return (byte) (b & ~(1 << pos));
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/CrcUtil.java 0000775 0000000 0000000 00000003576 13576501616 0023671 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.progress.ProgressMonitor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
public class CrcUtil {
private static final int BUF_SIZE = 1 << 14; //16384
public static long computeFileCrc(File inputFile, ProgressMonitor progressMonitor) throws IOException {
if (inputFile == null || !inputFile.exists() || !inputFile.canRead()) {
throw new ZipException("input file is null or does not exist or cannot read. " +
"Cannot calculate CRC for the file");
}
byte[] buff = new byte[BUF_SIZE];
CRC32 crc32 = new CRC32();
try(InputStream inputStream = new FileInputStream(inputFile)) {
int readLen;
while ((readLen = inputStream.read(buff)) != -1) {
crc32.update(buff, 0, readLen);
if (progressMonitor != null) {
progressMonitor.updateWorkCompleted(readLen);
if (progressMonitor.isCancelAllTasks()) {
progressMonitor.setResult(ProgressMonitor.Result.CANCELLED);
progressMonitor.setState(ProgressMonitor.State.READY);
return 0;
}
}
}
return crc32.getValue();
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/FileUtils.java 0000664 0000000 0000000 00000034562 13576501616 0024220 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.progress.ProgressMonitor;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.DosFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.GROUP_READ;
import static java.nio.file.attribute.PosixFilePermission.GROUP_WRITE;
import static java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ;
import static java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
import static net.lingala.zip4j.util.BitUtils.isBitSet;
import static net.lingala.zip4j.util.InternalZipConstants.BUFF_SIZE;
import static net.lingala.zip4j.util.InternalZipConstants.FILE_SEPARATOR;
import static net.lingala.zip4j.util.InternalZipConstants.ZIP_FILE_SEPARATOR;
import static net.lingala.zip4j.util.Zip4jUtil.isStringNotNullAndNotEmpty;
public class FileUtils {
public static void setFileAttributes(Path file, byte[] fileAttributes) {
if (fileAttributes == null || fileAttributes.length == 0) {
return;
}
String os = System.getProperty("os.name").toLowerCase();
if (isWindows(os)) {
applyWindowsFileAttributes(file, fileAttributes);
} else if (isMac(os) || isUnix(os)) {
applyPosixFileAttributes(file, fileAttributes);
}
}
public static void setFileLastModifiedTime(Path file, long lastModifiedTime) {
if (lastModifiedTime <= 0 || !Files.exists(file)) {
return;
}
try {
Files.setLastModifiedTime(file, FileTime.fromMillis(Zip4jUtil.dosToJavaTme(lastModifiedTime)));
} catch (Exception e) {
// Ignore
}
}
public static void setFileLastModifiedTimeWithoutNio(File file, long lastModifiedTime) {
file.setLastModified(Zip4jUtil.dosToJavaTme(lastModifiedTime));
}
public static byte[] getFileAttributes(File file) {
try {
if (file == null || !file.exists()) {
return new byte[4];
}
Path path = file.toPath();
String os = System.getProperty("os.name").toLowerCase();
if (isWindows(os)) {
return getWindowsFileAttributes(path);
} else if (isMac(os) || isUnix(os)) {
return getPosixFileAttributes(path);
} else {
return new byte[4];
}
} catch (NoSuchMethodError e) {
return new byte[4];
}
}
public static List getFilesInDirectoryRecursive(File path, boolean readHiddenFiles, boolean readHiddenFolders)
throws ZipException {
if (path == null) {
throw new ZipException("input path is null, cannot read files in the directory");
}
List result = new ArrayList<>();
File[] filesAndDirs = path.listFiles();
if (!path.isDirectory() || !path.canRead() || filesAndDirs == null) {
return result;
}
for (File file : filesAndDirs) {
if (file.isHidden()) {
if (file.isDirectory()) {
if (!readHiddenFolders) {
continue;
}
} else if (!readHiddenFiles) {
continue;
}
}
result.add(file);
if (file.isDirectory()) {
result.addAll(getFilesInDirectoryRecursive(file, readHiddenFiles, readHiddenFolders));
}
}
return result;
}
public static String getZipFileNameWithoutExtension(String zipFile) throws ZipException {
if (!isStringNotNullAndNotEmpty(zipFile)) {
throw new ZipException("zip file name is empty or null, cannot determine zip file name");
}
String tmpFileName = zipFile;
if (zipFile.contains(System.getProperty("file.separator"))) {
tmpFileName = zipFile.substring(zipFile.lastIndexOf(System.getProperty("file.separator")) + 1);
}
if (tmpFileName.endsWith(".zip")) {
tmpFileName = tmpFileName.substring(0, tmpFileName.lastIndexOf("."));
}
return tmpFileName;
}
public static List getSplitZipFiles(ZipModel zipModel) throws ZipException {
if (zipModel == null) {
throw new ZipException("cannot get split zip files: zipmodel is null");
}
if (zipModel.getEndOfCentralDirectoryRecord() == null) {
return null;
}
if (!zipModel.getZipFile().exists()) {
throw new ZipException("zip file does not exist");
}
List splitZipFiles = new ArrayList<>();
File currZipFile = zipModel.getZipFile();
String partFile;
if (!zipModel.isSplitArchive()) {
splitZipFiles.add(currZipFile);
return splitZipFiles;
}
int numberOfThisDisk = zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk();
if (numberOfThisDisk == 0) {
splitZipFiles.add(currZipFile);
return splitZipFiles;
} else {
for (int i = 0; i <= numberOfThisDisk; i++) {
if (i == numberOfThisDisk) {
splitZipFiles.add(zipModel.getZipFile());
} else {
String fileExt = ".z0";
if (i >= 9) {
fileExt = ".z";
}
partFile = (currZipFile.getName().contains("."))
? currZipFile.getPath().substring(0, currZipFile.getPath().lastIndexOf(".")) : currZipFile.getPath();
partFile = partFile + fileExt + (i + 1);
splitZipFiles.add(new File(partFile));
}
}
}
return splitZipFiles;
}
public static String getRelativeFileName(String file, String rootFolderPath, String rootFolderNameInZip)
throws ZipException {
String fileName;
try {
String fileCanonicalPath = new File(file).getCanonicalPath();
if (isStringNotNullAndNotEmpty(rootFolderPath)) {
File rootFolderFile = new File(rootFolderPath);
String rootFolderFileRef = rootFolderFile.getCanonicalPath();
if (!rootFolderFileRef.endsWith(FILE_SEPARATOR)) {
rootFolderFileRef += FILE_SEPARATOR;
}
String tmpFileName = fileCanonicalPath.substring(rootFolderFileRef.length());
if (tmpFileName.startsWith(System.getProperty("file.separator"))) {
tmpFileName = tmpFileName.substring(1);
}
File tmpFile = new File(fileCanonicalPath);
if (tmpFile.isDirectory()) {
tmpFileName = tmpFileName.replaceAll("\\\\", "/");
tmpFileName += ZIP_FILE_SEPARATOR;
} else {
String bkFileName = tmpFileName.substring(0, tmpFileName.lastIndexOf(tmpFile.getName()));
bkFileName = bkFileName.replaceAll("\\\\", "/");
tmpFileName = bkFileName + tmpFile.getName();
}
fileName = tmpFileName;
} else {
File relFile = new File(fileCanonicalPath);
if (relFile.isDirectory()) {
fileName = relFile.getName() + ZIP_FILE_SEPARATOR;
} else {
fileName = relFile.getName();
}
}
} catch (IOException e) {
throw new ZipException(e);
}
if (Zip4jUtil.isStringNotNullAndNotEmpty(rootFolderNameInZip)) {
if (!rootFolderNameInZip.endsWith("\\") && !rootFolderNameInZip.endsWith("/")) {
rootFolderNameInZip = rootFolderNameInZip + InternalZipConstants.FILE_SEPARATOR;
}
rootFolderNameInZip = rootFolderNameInZip.replaceAll("\\\\", "/");
fileName = rootFolderNameInZip + fileName;
}
return fileName;
}
public static boolean isZipEntryDirectory(String fileNameInZip) {
return fileNameInZip.endsWith("/") || fileNameInZip.endsWith("\\");
}
public static void copyFile(RandomAccessFile randomAccessFile, OutputStream outputStream, long start, long end,
ProgressMonitor progressMonitor) throws ZipException {
if (start < 0 || end < 0 || start > end) {
throw new ZipException("invalid offsets");
}
if (start == end) {
return;
}
try {
randomAccessFile.seek(start);
int readLen;
byte[] buff;
long bytesRead = 0;
long bytesToRead = end - start;
if ((end - start) < BUFF_SIZE) {
buff = new byte[(int) bytesToRead];
} else {
buff = new byte[BUFF_SIZE];
}
while ((readLen = randomAccessFile.read(buff)) != -1) {
outputStream.write(buff, 0, readLen);
progressMonitor.updateWorkCompleted(readLen);
if (progressMonitor.isCancelAllTasks()) {
progressMonitor.setResult(ProgressMonitor.Result.CANCELLED);
return;
}
bytesRead += readLen;
if (bytesRead == bytesToRead) {
break;
} else if (bytesRead + buff.length > bytesToRead) {
buff = new byte[(int) (bytesToRead - bytesRead)];
}
}
} catch (IOException e) {
throw new ZipException(e);
}
}
public static void assertFilesExist(List files) throws ZipException {
for (File file : files) {
if (!file.exists()) {
throw new ZipException("File does not exist: " + file);
}
}
}
private static void applyWindowsFileAttributes(Path file, byte[] fileAttributes) {
if (fileAttributes[0] == 0) {
// No file attributes defined in the archive
return;
}
DosFileAttributeView fileAttributeView = Files.getFileAttributeView(file, DosFileAttributeView.class);
try {
fileAttributeView.setReadOnly(isBitSet(fileAttributes[0], 0));
fileAttributeView.setHidden(isBitSet(fileAttributes[0], 1));
fileAttributeView.setSystem(isBitSet(fileAttributes[0], 2));
fileAttributeView.setArchive(isBitSet(fileAttributes[0], 5));
} catch (IOException e) {
//Ignore
}
}
private static void applyPosixFileAttributes(Path file, byte[] fileAttributes) {
if (fileAttributes[2] == 0 && fileAttributes[3] == 0) {
// No file attributes defined
return;
}
try {
Set posixFilePermissions = new HashSet<>();
addIfBitSet(fileAttributes[3], 0, posixFilePermissions, PosixFilePermission.OWNER_READ);
addIfBitSet(fileAttributes[2], 7, posixFilePermissions, PosixFilePermission.OWNER_WRITE);
addIfBitSet(fileAttributes[2], 6, posixFilePermissions, PosixFilePermission.OWNER_EXECUTE);
addIfBitSet(fileAttributes[2], 5, posixFilePermissions, PosixFilePermission.GROUP_READ);
addIfBitSet(fileAttributes[2], 4, posixFilePermissions, PosixFilePermission.GROUP_WRITE);
addIfBitSet(fileAttributes[2], 3, posixFilePermissions, PosixFilePermission.GROUP_EXECUTE);
addIfBitSet(fileAttributes[2], 2, posixFilePermissions, PosixFilePermission.OTHERS_READ);
addIfBitSet(fileAttributes[2], 1, posixFilePermissions, PosixFilePermission.OTHERS_WRITE);
addIfBitSet(fileAttributes[2], 0, posixFilePermissions, PosixFilePermission.OTHERS_EXECUTE);
Files.setPosixFilePermissions(file, posixFilePermissions);
} catch (IOException e) {
// Ignore
}
}
private static byte[] getWindowsFileAttributes(Path file) {
byte[] fileAttributes = new byte[4];
try {
DosFileAttributeView dosFileAttributeView = Files.getFileAttributeView(file, DosFileAttributeView.class);
DosFileAttributes dosFileAttributes = dosFileAttributeView.readAttributes();
byte windowsAttribute = 0;
windowsAttribute = setBitIfApplicable(dosFileAttributes.isReadOnly(), windowsAttribute, 0);
windowsAttribute = setBitIfApplicable(dosFileAttributes.isHidden(), windowsAttribute, 1);
windowsAttribute = setBitIfApplicable(dosFileAttributes.isSystem(), windowsAttribute, 2);
windowsAttribute = setBitIfApplicable(dosFileAttributes.isArchive(), windowsAttribute, 5);
fileAttributes[0] = windowsAttribute;
} catch (IOException e) {
// ignore
}
return fileAttributes;
}
private static byte[] getPosixFileAttributes(Path file) {
byte[] fileAttributes = new byte[4];
try {
PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(file, PosixFileAttributeView.class);
Set posixFilePermissions = posixFileAttributeView.readAttributes().permissions();
fileAttributes[3] = setBitIfApplicable(Files.isRegularFile(file), fileAttributes[3], 7);
fileAttributes[3] = setBitIfApplicable(Files.isDirectory(file), fileAttributes[3], 6);
fileAttributes[3] = setBitIfApplicable(posixFilePermissions.contains(OWNER_READ), fileAttributes[3], 0);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(OWNER_WRITE), fileAttributes[2], 7);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(OWNER_EXECUTE), fileAttributes[2], 6);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(GROUP_READ), fileAttributes[2], 5);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(GROUP_WRITE), fileAttributes[2], 4);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(GROUP_EXECUTE), fileAttributes[2], 3);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(OTHERS_READ), fileAttributes[2], 2);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(OTHERS_WRITE), fileAttributes[2], 1);
fileAttributes[2] = setBitIfApplicable(posixFilePermissions.contains(OTHERS_EXECUTE), fileAttributes[2], 0);
} catch (IOException e) {
// Ignore
}
return fileAttributes;
}
private static byte setBitIfApplicable(boolean applicable, byte b, int pos) {
if (applicable) {
b = BitUtils.setBit(b, pos);
}
return b;
}
private static void addIfBitSet(byte b, int pos, Set posixFilePermissions,
PosixFilePermission posixFilePermissionToAdd) {
if (isBitSet(b, pos)) {
posixFilePermissions.add(posixFilePermissionToAdd);
}
}
private static boolean isWindows(String os) {
return (os.contains("win"));
}
private static boolean isMac(String os) {
return (os.contains("mac"));
}
private static boolean isUnix(String os) {
return (os.contains("nux"));
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/InternalZipConstants.java 0000775 0000000 0000000 00000003555 13576501616 0026455 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.util;
import java.nio.charset.Charset;
public final class InternalZipConstants {
private InternalZipConstants() {
}
public static final int ENDHDR = 22; // END header size
public static final int STD_DEC_HDR_SIZE = 12;
//AES Constants
public static final int AES_AUTH_LENGTH = 10;
public static final int AES_BLOCK_SIZE = 16;
public static final int MIN_SPLIT_LENGTH = 65536;
public static final long ZIP_64_SIZE_LIMIT = 4294967295L;
public static final int ZIP_64_NUMBER_OF_ENTRIES_LIMIT = 65535;
public static final int BUFF_SIZE = 1024 * 4;
// Update local file header constants
// This value holds the number of bytes to skip from
// the offset of start of local header
public static final int UPDATE_LFH_CRC = 14;
public static final int UPDATE_LFH_COMP_SIZE = 18;
public static final int UPDATE_LFH_UNCOMP_SIZE = 22;
public static final String ZIP_STANDARD_CHARSET = "Cp437";
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
public static final String ZIP_FILE_SEPARATOR = "/";
public static final int MAX_ALLOWED_ZIP_COMMENT_LENGTH = 0xFFFF;
public static final Charset CHARSET_UTF_8 = Charset.forName("UTF-8");
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/RawIO.java 0000775 0000000 0000000 00000012245 13576501616 0023276 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class RawIO {
private byte[] shortBuff = new byte[2];
private byte[] intBuff = new byte[4];
private byte[] longBuff = new byte[8];
public long readLongLittleEndian(RandomAccessFile randomAccessFile) throws IOException {
randomAccessFile.readFully(longBuff);
return readLongLittleEndian(longBuff, 0);
}
public long readLongLittleEndian(RandomAccessFile randomAccessFile, int readLen) throws IOException {
resetBytes(longBuff);
randomAccessFile.readFully(longBuff, 0, readLen);
return readLongLittleEndian(longBuff, 0);
}
public long readLongLittleEndian(InputStream inputStream) throws IOException {
readFully(inputStream, longBuff, longBuff.length);
return readLongLittleEndian(longBuff, 0);
}
public long readLongLittleEndian(InputStream inputStream, int readLen) throws IOException {
resetBytes(longBuff);
readFully(inputStream, longBuff, readLen);
return readLongLittleEndian(longBuff, 0);
}
public long readLongLittleEndian(byte[] array, int pos) {
if (array.length < 8) {
resetBytes(longBuff);
}
System.arraycopy(array, pos, longBuff, 0, array.length < 8 ? array.length : 8);
long temp = 0;
temp |= longBuff[7] & 0xff;
temp <<= 8;
temp |= longBuff[6] & 0xff;
temp <<= 8;
temp |= longBuff[5] & 0xff;
temp <<= 8;
temp |= longBuff[4] & 0xff;
temp <<= 8;
temp |= longBuff[3] & 0xff;
temp <<= 8;
temp |= longBuff[2] & 0xff;
temp <<= 8;
temp |= longBuff[1] & 0xff;
temp <<= 8;
temp |= longBuff[0] & 0xff;
return temp;
}
public int readIntLittleEndian(RandomAccessFile randomAccessFile) throws IOException {
randomAccessFile.readFully(intBuff);
return readIntLittleEndian(intBuff);
}
public int readIntLittleEndian(InputStream inputStream) throws IOException {
readFully(inputStream, intBuff, 4);
return readIntLittleEndian(intBuff);
}
public int readIntLittleEndian(byte[] b) {
return readIntLittleEndian(b, 0);
}
public int readIntLittleEndian(byte[] b, int pos) {
return ((b[pos] & 0xff) | (b[1 + pos] & 0xff) << 8)
| ((b[2 + pos] & 0xff) | (b[3 + pos] & 0xff) << 8) << 16;
}
public int readShortLittleEndian(RandomAccessFile randomAccessFile) throws IOException {
randomAccessFile.readFully(shortBuff);
return readShortLittleEndian(shortBuff, 0);
}
public int readShortLittleEndian(InputStream inputStream) throws IOException {
readFully(inputStream, shortBuff, shortBuff.length);
return readShortLittleEndian(shortBuff, 0);
}
public int readShortLittleEndian(byte[] buff, int position) {
return (buff[position] & 0xff) | (buff[1 + position] & 0xff) << 8;
}
public void writeShortLittleEndian(OutputStream outputStream, int value) throws IOException {
writeShortLittleEndian(shortBuff, 0, value);
outputStream.write(shortBuff);
}
public void writeShortLittleEndian(byte[] array, int pos, int value) {
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
public void writeIntLittleEndian(OutputStream outputStream, int value) throws IOException {
writeIntLittleEndian(intBuff, 0, value);
outputStream.write(intBuff);
}
public void writeIntLittleEndian(byte[] array, int pos, int value) {
array[pos + 3] = (byte) (value >>> 24);
array[pos + 2] = (byte) (value >>> 16);
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
public void writeLongLittleEndian(OutputStream outputStream, long value) throws IOException {
writeLongLittleEndian(longBuff, 0, value);
outputStream.write(longBuff);
}
public void writeLongLittleEndian(byte[] array, int pos, long value) {
array[pos + 7] = (byte) (value >>> 56);
array[pos + 6] = (byte) (value >>> 48);
array[pos + 5] = (byte) (value >>> 40);
array[pos + 4] = (byte) (value >>> 32);
array[pos + 3] = (byte) (value >>> 24);
array[pos + 2] = (byte) (value >>> 16);
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
private void readFully(InputStream inputStream, byte[] buff, int readLen) throws IOException {
int actualReadLength = Zip4jUtil.readFully(inputStream, buff, 0, readLen);
if (actualReadLength != readLen) {
throw new ZipException("Could not fill buffer");
}
}
private void resetBytes(byte[] b) {
for(int i = 0; i < b.length; i++) {
b[i] = 0;
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/UnzipUtil.java 0000775 0000000 0000000 00000003476 13576501616 0024266 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.SplitInputStream;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import static net.lingala.zip4j.util.FileUtils.setFileAttributes;
import static net.lingala.zip4j.util.FileUtils.setFileLastModifiedTime;
import static net.lingala.zip4j.util.FileUtils.setFileLastModifiedTimeWithoutNio;
public class UnzipUtil {
public static ZipInputStream createZipInputStream(ZipModel zipModel, FileHeader fileHeader, char[] password)
throws IOException {
SplitInputStream splitInputStream = null;
try {
splitInputStream = new SplitInputStream(zipModel.getZipFile(), zipModel.isSplitArchive(),
zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk());
splitInputStream.prepareExtractionForFileHeader(fileHeader);
ZipInputStream zipInputStream = new ZipInputStream(splitInputStream, password);
if (zipInputStream.getNextEntry(fileHeader) == null) {
throw new ZipException("Could not locate local file header for corresponding file header");
}
return zipInputStream;
} catch (IOException e) {
if (splitInputStream != null) {
splitInputStream.close();
}
throw e;
}
}
public static void applyFileAttributes(FileHeader fileHeader, File file) {
try {
Path path = file.toPath();
setFileAttributes(path, fileHeader.getExternalFileAttributes());
setFileLastModifiedTime(path, fileHeader.getLastModifiedTime());
} catch (NoSuchMethodError e) {
setFileLastModifiedTimeWithoutNio(file, fileHeader.getLastModifiedTime());
}
}
}
zip4j-2.2.8/src/main/java/net/lingala/zip4j/util/Zip4jUtil.java 0000775 0000000 0000000 00000012246 13576501616 0024154 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 Srikanth Reddy Lingala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.enums.CompressionMethod;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
public class Zip4jUtil {
private static final int MAX_RAW_READ_FULLY_RETRY_ATTEMPTS = 15;
public static boolean isStringNotNullAndNotEmpty(String str) {
return str != null && str.trim().length() > 0;
}
public static boolean createDirectoryIfNotExists(File file) throws ZipException {
if (file == null) {
throw new ZipException("output path is null");
}
if (file.exists()) {
if (!file.isDirectory()) {
throw new ZipException("output directory is not valid");
}
} else {
if (!file.mkdirs()) {
throw new ZipException("Cannot create output directories");
}
}
return true;
}
public static long javaToDosTime(long time) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(time);
int year = cal.get(Calendar.YEAR);
if (year < 1980) {
return (1 << 21) | (1 << 16);
}
return (year - 1980) << 25 | (cal.get(Calendar.MONTH) + 1) << 21 |
cal.get(Calendar.DATE) << 16 | cal.get(Calendar.HOUR_OF_DAY) << 11 | cal.get(Calendar.MINUTE) << 5 |
cal.get(Calendar.SECOND) >> 1;
}
public static long dosToJavaTme(long dosTime) {
int sec = (int) (2 * (dosTime & 0x1f));
int min = (int) ((dosTime >> 5) & 0x3f);
int hrs = (int) ((dosTime >> 11) & 0x1f);
int day = (int) ((dosTime >> 16) & 0x1f);
int mon = (int) (((dosTime >> 21) & 0xf) - 1);
int year = (int) (((dosTime >> 25) & 0x7f) + 1980);
Calendar cal = Calendar.getInstance();
cal.set(year, mon, day, hrs, min, sec);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime().getTime();
}
public static byte[] convertCharArrayToByteArray(char[] charArray) {
byte[] bytes = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) {
bytes[i] = (byte) charArray[i];
}
return bytes;
}
public static CompressionMethod getCompressionMethod(LocalFileHeader localFileHeader) {
if (localFileHeader.getCompressionMethod() != CompressionMethod.AES_INTERNAL_ONLY) {
return localFileHeader.getCompressionMethod();
}
if (localFileHeader.getAesExtraDataRecord() == null) {
throw new RuntimeException("AesExtraDataRecord not present in local header for aes encrypted data");
}
return localFileHeader.getAesExtraDataRecord().getCompressionMethod();
}
public static int readFully(InputStream inputStream, byte[] bufferToReadInto) throws IOException {
int readLen = inputStream.read(bufferToReadInto);
if (readLen != bufferToReadInto.length) {
readLen = readUntilBufferIsFull(inputStream, bufferToReadInto, readLen);
if (readLen != bufferToReadInto.length) {
throw new IOException("Cannot read fully into byte buffer");
}
}
return readLen;
}
public static int readFully(InputStream inputStream, byte[] b, int offset, int length) throws IOException {
int numberOfBytesRead = 0;
if (offset < 0) {
throw new IllegalArgumentException("Negative offset");
}
if (length < 0) {
throw new IllegalArgumentException("Negative length");
}
if (length == 0) {
return 0;
}
if (offset + length > b.length) {
throw new IllegalArgumentException("Length greater than buffer size");
}
while (numberOfBytesRead != length) {
int currentReadLength = inputStream.read(b, offset + numberOfBytesRead, length - numberOfBytesRead);
if (currentReadLength == -1) {
if (numberOfBytesRead == 0) {
return -1;
}
return numberOfBytesRead;
}
numberOfBytesRead += currentReadLength;
}
return numberOfBytesRead;
}
private static int readUntilBufferIsFull(InputStream inputStream, byte[] bufferToReadInto, int readLength)
throws IOException {
int remainingLength = bufferToReadInto.length - readLength;
int loopReadLength = 0;
int retryAttempt = 1; // first attempt is already done before this method is called
while (readLength < bufferToReadInto.length
&& loopReadLength != -1
&& retryAttempt < MAX_RAW_READ_FULLY_RETRY_ATTEMPTS) {
loopReadLength = inputStream.read(bufferToReadInto, readLength, remainingLength);
if (loopReadLength > 0) {
readLength += loopReadLength;
remainingLength -= loopReadLength;
}
retryAttempt++;
}
return readLength;
}
}
zip4j-2.2.8/src/test/ 0000775 0000000 0000000 00000000000 13576501616 0014343 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/ 0000775 0000000 0000000 00000000000 13576501616 0015264 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/ 0000775 0000000 0000000 00000000000 13576501616 0016052 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/ 0000775 0000000 0000000 00000000000 13576501616 0017461 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/ 0000775 0000000 0000000 00000000000 13576501616 0020521 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/AbstractIT.java 0000664 0000000 0000000 00000005001 13576501616 0023360 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.testutils.TestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import static net.lingala.zip4j.testutils.TestUtils.getTestFileFromResources;
import static org.assertj.core.api.Assertions.assertThat;
public abstract class AbstractIT {
protected static final char[] PASSWORD = "test123!".toCharArray();
protected static final List FILES_TO_ADD = Arrays.asList(
getTestFileFromResources("sample_text1.txt"),
getTestFileFromResources("sample_text_large.txt"),
getTestFileFromResources("sample.pdf")
);
protected static final Charset CHARSET_MS_932 = Charset.forName("Ms932");
protected static final Charset CHARSET_GBK = Charset.forName("GBK");
protected static final Charset CHARSET_CP_949 = Charset.forName("Cp949");
protected File generatedZipFile;
protected File outputFolder;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Before
public void before() throws IOException {
generatedZipFile = temporaryFolder.newFile("output.zip");
outputFolder = temporaryFolder.newFolder("output");
File[] allTempFiles = temporaryFolder.getRoot().listFiles();
Arrays.stream(allTempFiles).forEach(File::delete);
}
protected ZipParameters createZipParameters(EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(encryptionMethod);
zipParameters.setAesKeyStrength(aesKeyStrength);
return zipParameters;
}
protected void verifyFileHeadersContainsFiles(List fileHeaders, List fileNames) {
for (String fileName : fileNames) {
boolean fileFound = false;
for (FileHeader fileHeader : fileHeaders) {
if (fileHeader.getFileName().equals(fileName)) {
fileFound = true;
break;
}
}
assertThat(fileFound).as("File with name %s not found in zip file", fileName).isTrue();
}
}
protected File getTestArchiveFromResources(String archiveName) {
return TestUtils.getTestArchiveFromResources(archiveName);
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/AddFilesToZipIT.java 0000664 0000000 0000000 00000130307 13576501616 0024266 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.AbstractFileHeader;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.testutils.HeaderVerifier;
import net.lingala.zip4j.testutils.TestUtils;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.BitUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
public class AddFilesToZipIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private HeaderVerifier headerVerifier = new HeaderVerifier();
@Test
public void testAddFileAsStringParameterThrowsExceptionWhenFileDoesNotExist() throws ZipException {
expectedException.expectMessage("File does not exist: somefile.txt");
expectedException.expect(ZipException.class);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile("somefile.txt");
}
@Test
public void testAddFileAsStringParameterWithoutZipParameterAddsAsDeflate() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(TestUtils.getTestFileFromResources("sample.pdf").getPath());
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample.pdf"), CompressionMethod.DEFLATE, null, null);
}
@Test
public void testAddFileAsStringWithZipParametersStoreAndStandardEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt").getPath(), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
EncryptionMethod.ZIP_STANDARD, null);
}
@Test
public void testAddFileAsStringWithZipParametersStoreAndStandardEncryptionAndCharsetCp949() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.setCharset(CHARSET_CP_949);
String koreanFileName = "가나다.abc";
zipFile.addFile(TestUtils.getTestFileFromResources(koreanFileName).getPath(), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1, true, CHARSET_CP_949);
assertThat(zipFile.getFileHeaders().get(0).getFileName()).isEqualTo(koreanFileName);
}
@Test
public void testAddFileThrowsExceptionWhenFileDoesNotExist() throws ZipException {
expectedException.expectMessage("File does not exist: somefile.txt");
expectedException.expect(ZipException.class);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(new File("somefile.txt"));
}
@Test
public void testAddFileThrowsExceptionWhenPasswordNotSet() throws ZipException {
expectedException.expectMessage("input password is empty or null");
expectedException.expect(ZipException.class);
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"), zipParameters);
}
@Test
public void testAddFileWithoutZipParameterAddsAsDeflate() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("file_PDF_1MB.pdf"), CompressionMethod.DEFLATE, null,
null);
}
@Test
public void testAddFileWithZipParametersStoreAndStandardZip() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
EncryptionMethod.ZIP_STANDARD, null);
}
@Test
public void testAddFileWithZipParametersStoreAndAes128Encryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
}
@Test
public void testAddFileWithZipParametersStoreAndAes256Encryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
}
@Test
public void testAddFileRemovesExistingFileNoEncryption() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"));
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 3);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.DEFLATE,
null, null);
}
@Test
public void testAddFileDoesNotOverrideFileIfFlagIsDisabled() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setOverrideExistingFilesInZip(false);
zipFile.setPassword(PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 3);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.DEFLATE,
null, null);
}
@Test
public void testAddFileRemovesExistingFileNoEncryptionSingleFileInZip() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"));
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
null, null);
}
@Test
public void testAddFileWithDifferentFileNameSetsTheNewFileName() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip("/data/newfile.txt");
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getFileHeaders()).hasSize(1);
assertThat(zipFile.getFileHeader("/data/newfile.txt")).isNotNull();
assertThat(zipFile.getFileHeader("sample_text_large.txt")).isNull();
zipFile.extractAll(outputFolder.getPath());
}
@Test
public void testAddFileRemovesExistingFileWithAesEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(1, TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.addFiles(filesToAdd, zipParameters);
zipFile.addFile(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size()
+ 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("file_PDF_1MB.pdf"), CompressionMethod.DEFLATE,
EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
}
@Test
public void testAddFileWithAfterDeflateRemainingBytesTestFile() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setAesVersion(AesVersion.TWO);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("after_deflate_remaining_bytes.bin"), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("after_deflate_remaining_bytes.bin"),
CompressionMethod.DEFLATE, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
}
@Test
public void testAddFileProgressMonitorThrowsExceptionWhenPerformingActionInBusyState() throws ZipException {
expectedException.expectMessage("invalid operation - Zip4j is in busy state");
expectedException.expect(ZipException.class);
ZipFile zipFile = new ZipFile(generatedZipFile);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
progressMonitor.setState(ProgressMonitor.State.BUSY);
zipFile.addFile(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
}
@Test
public void testAddFileWithProgressMonitor() throws IOException, InterruptedException {
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
boolean percentBetweenZeroAndHundred = false;
boolean fileNameSet = false;
boolean taskNameSet = false;
zipFile.setRunInThread(true);
zipFile.addFile(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"),
createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256));
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
int percentDone = progressMonitor.getPercentDone();
String fileName = progressMonitor.getFileName();
if (percentDone > 0 && percentDone < 100) {
percentBetweenZeroAndHundred = true;
}
if (fileName != null) {
assertThat(fileName).contains("file_PDF_1MB.pdf");
fileNameSet = true;
}
Thread.sleep(10);
if (!progressMonitor.getCurrentTask().equals(ProgressMonitor.Task.NONE)) {
assertThat(progressMonitor.getCurrentTask()).isEqualTo(ProgressMonitor.Task.ADD_ENTRY);
taskNameSet = true;
}
}
assertThat(progressMonitor.getResult()).isEqualTo(ProgressMonitor.Result.SUCCESS);
assertThat(progressMonitor.getState().equals(ProgressMonitor.State.READY));
assertThat(progressMonitor.getException()).isNull();
assertThat(percentBetweenZeroAndHundred).isTrue();
assertThat(fileNameSet).isTrue();
assertThat(taskNameSet).isTrue();
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
}
@Test
public void testAddFilesWithoutParametersWhenZipFileDoesNotExistCreatesSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(asList(
TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"),
TestUtils.getTestFileFromResources("zero_byte_file.txt")
));
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 2);
verifyZipFileContainsFiles(generatedZipFile, asList("file_PDF_1MB.pdf", "zero_byte_file.txt"),
CompressionMethod.DEFLATE, null, null);
}
@Test
public void testAddFilesWhenZipFileDoesNotExistCreatesSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(asList(
TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"),
TestUtils.getTestFileFromResources("sample_text1.txt")
), new ZipParameters());
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 2);
verifyZipFileContainsFiles(generatedZipFile, asList("file_PDF_1MB.pdf", "sample_text1.txt"),
CompressionMethod.DEFLATE, null, null);
}
@Test
public void testAddFilesWithZeroByteFileWithAes128Encryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(singletonList(TestUtils.getTestFileFromResources("zero_byte_file.txt")), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("zero_byte_file.txt"),
CompressionMethod.DEFLATE, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
}
@Test
public void testAddFilesWithAes256EncryptionV1() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setAesVersion(AesVersion.ONE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
verifyZipFileContainsFiles(generatedZipFile, fileNames, CompressionMethod.DEFLATE, EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256, AesVersion.ONE);
}
@Test
public void testAddFilesWithAes256EncryptionV2() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
verifyZipFileContainsFiles(generatedZipFile, fileNames, CompressionMethod.DEFLATE, EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256);
}
@Test
public void testAddFilesWithZipStandardEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
verifyZipFileContainsFiles(generatedZipFile, fileNames, CompressionMethod.DEFLATE, EncryptionMethod.ZIP_STANDARD,
null);
}
@Test
public void testAddFilesWhenFilesAlreadyExistsRemovesFiles() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
char[] newPassword = "SOME_OTHER_PASSWORD".toCharArray();
zipFile = new ZipFile(generatedZipFile, newPassword);
zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, newPassword, outputFolder, FILES_TO_ADD.size());
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
verifyZipFileContainsFiles(generatedZipFile, fileNames, CompressionMethod.DEFLATE, EncryptionMethod.ZIP_STANDARD,
null);
}
@Test
public void testAddFilesThrowsExceptionForAES192() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("Invalid AES key strength");
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_192);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
}
@Test
public void testAddFilesToSplitZipThrowsException() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.createSplitZipFile(singletonList(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf")), new ZipParameters(),
true, InternalZipConstants.MIN_SPLIT_LENGTH);
expectedException.expect(ZipException.class);
expectedException.expectMessage("Zip file already exists. " +
"Zip file format does not allow updating split/spanned files");
zipFile.addFiles(singletonList(TestUtils.getTestFileFromResources("sample.pdf")));
}
@Test
public void testAddFilesWithDifferentEncryptionType() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(singletonList(TestUtils.getTestFileFromResources("sample.pdf")), zipParameters);
zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
zipFile.addFiles(singletonList(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf")), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 2);
}
@Test
public void testAddFilesWithUtf8Characters() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(asList(
TestUtils.getTestFileFromResources("sample.pdf"),
TestUtils.getTestFileFromResources("бореиская.txt"),
TestUtils.getTestFileFromResources("zero_byte_file.txt"),
TestUtils.getTestFileFromResources("sample_text1.txt"),
TestUtils.getTestFileFromResources("가나다.abc")
), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 5);
List fileNamesThatShouldExistInZip = asList(
"sample.pdf",
"бореиская.txt",
"zero_byte_file.txt",
"sample_text1.txt",
"가나다.abc"
);
verifyZipFileContainsFiles(generatedZipFile, fileNamesThatShouldExistInZip, CompressionMethod.DEFLATE,
EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
}
@Test
public void testAddFilesWithProgressMonitor() throws IOException, InterruptedException {
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
boolean percentBetweenZeroAndHundred = false;
boolean fileNameSet = false;
boolean taskNameSet = false;
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.setRunInThread(true);
zipFile.addFiles(filesToAdd, createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256));
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
int percentDone = progressMonitor.getPercentDone();
String fileName = progressMonitor.getFileName();
if (percentDone > 0 && percentDone < 100) {
percentBetweenZeroAndHundred = true;
}
if (fileName != null) {
fileNameSet = true;
}
Thread.sleep(10);
if (!progressMonitor.getCurrentTask().equals(ProgressMonitor.Task.NONE)) {
assertThat(progressMonitor.getCurrentTask()).isEqualTo(ProgressMonitor.Task.ADD_ENTRY);
taskNameSet = true;
}
}
assertThat(progressMonitor.getResult()).isEqualTo(ProgressMonitor.Result.SUCCESS);
assertThat(progressMonitor.getState().equals(ProgressMonitor.State.READY));
assertThat(progressMonitor.getException()).isNull();
assertThat(percentBetweenZeroAndHundred).isTrue();
assertThat(fileNameSet).isTrue();
assertThat(taskNameSet).isTrue();
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 4);
}
@Test
public void testAddFolderWithoutZipParameters() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFolder(TestUtils.getTestFileFromResources(""));
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 13);
List fileHeaders = getFileHeaders(generatedZipFile);
verifyAllFilesInZipContainsPath(fileHeaders, "test-files/");
verifyFoldersInZip(fileHeaders, generatedZipFile, null);
}
@Test
public void testAddFolderWithStoreAndAes128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 13);
List fileHeaders = getFileHeaders(generatedZipFile);
verifyAllFilesInZipContainsPath(fileHeaders, "test-files/");
verifyFoldersInZip(fileHeaders, generatedZipFile, PASSWORD);
}
@Test
public void testAddFolderWithDeflateAndAes256AndWithoutRootFolder() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setIncludeRootFolder(false);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 12);
List fileHeaders = getFileHeaders(generatedZipFile);
verifyAllFilesInZipDoesNotContainPath(fileHeaders, "test-files/");
verifyFoldersInZip(fileHeaders, generatedZipFile, PASSWORD);
}
@Test
public void testAddFolderWithRootFolderNameInZipAndWithoutRootFolder() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setIncludeRootFolder(false);
zipParameters.setRootFolderNameInZip("root_folder_name");
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
List fileHeaders = getFileHeaders(generatedZipFile);
verifyAllFilesInZipContainsPath(fileHeaders, "root_folder_name/");
verifyAllFilesInZipDoesNotContainPath(fileHeaders, "root_folder_name/test-files/");
verifyFoldersInZip(fileHeaders, generatedZipFile, PASSWORD);
}
@Test
public void testAddFolderWithRootFolderNameInZipAndWithRootFolder() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setIncludeRootFolder(true);
zipParameters.setRootFolderNameInZip("root_folder_name");
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
List fileHeaders = getFileHeaders(generatedZipFile);
verifyAllFilesInZipContainsPath(fileHeaders, "root_folder_name/");
verifyAllFilesInZipContainsPath(fileHeaders, "root_folder_name/test-files/");
verifyFoldersInZip(fileHeaders, generatedZipFile, PASSWORD);
}
@Test
public void testAddFolderWithProgressMonitor() throws IOException, InterruptedException {
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
boolean percentBetweenZeroAndHundred = false;
boolean fileNameSet = false;
zipFile.setRunInThread(true);
zipFile.addFolder(TestUtils.getTestFileFromResources(""),
createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256));
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
int percentDone = progressMonitor.getPercentDone();
String fileName = progressMonitor.getFileName();
if (percentDone > 0 && percentDone < 100) {
percentBetweenZeroAndHundred = true;
}
if (fileName != null) {
fileNameSet = true;
}
Thread.sleep(10);
}
assertThat(progressMonitor.getResult()).isEqualTo(ProgressMonitor.Result.SUCCESS);
assertThat(progressMonitor.getState().equals(ProgressMonitor.State.READY));
assertThat(progressMonitor.getException()).isNull();
assertThat(percentBetweenZeroAndHundred).isTrue();
assertThat(fileNameSet).isTrue();
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 13);
}
@Test
public void testAddFolderWithNotNormalizedPath() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
ZipParameters parameters = new ZipParameters();
String folderToAddPath = TestUtils.getTestFileFromResources("").getPath()
+ InternalZipConstants.FILE_SEPARATOR + ".."
+ InternalZipConstants.FILE_SEPARATOR
+ TestUtils.getTestFileFromResources("").getName();
File folderToAdd = new File(folderToAddPath);
zipFile.addFolder(folderToAdd, parameters);
File fileToAdd = TestUtils.getTestFileFromResources("file_PDF_1MB.pdf");
zipFile.addFile(fileToAdd, parameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 13);
}
@Test
public void testAddStreamToZipThrowsExceptionWhenFileNameIsNull() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(TestUtils.getTestFileFromResources("бореиская.txt"));
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(null);
expectedException.expectMessage("fileNameInZip has to be set in zipParameters when adding stream");
expectedException.expect(ZipException.class);
zipFile.addStream(inputStream, zipParameters);
}
@Test
public void testAddStreamToZipThrowsExceptionWhenFileNameIsEmpty() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(TestUtils.getTestFileFromResources("бореиская.txt"));
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip("");
expectedException.expectMessage("fileNameInZip has to be set in zipParameters when adding stream");
expectedException.expect(ZipException.class);
zipFile.addStream(inputStream, zipParameters);
}
@Test
public void testAddStreamToZipWithoutEncryptionForNewZipAddsSuccessfully() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("бореиская.txt");
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("бореиская.txt"), CompressionMethod.DEFLATE, null, null);
}
@Test
public void testAddStreamToWithStoreCompressionAndWithoutEncryption() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("бореиская.txt");
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("бореиская.txt"), CompressionMethod.STORE, null, null);
zipFile = new ZipFile(generatedZipFile);
byte[] generalPurposeBytes = zipFile.getFileHeaders().get(0).getGeneralPurposeFlag();
// assert that extra data record is not present
assertThat(BitUtils.isBitSet(generalPurposeBytes[0], 3)).isTrue();
}
@Test
public void testAddStreamToWithStoreCompressionAndZipStandardEncryption() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("sample_text_large.txt");
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("sample_text_large.txt"), CompressionMethod.STORE,
EncryptionMethod.ZIP_STANDARD, null);
zipFile = new ZipFile(generatedZipFile, PASSWORD);
byte[] generalPurposeBytes = zipFile.getFileHeaders().get(0).getGeneralPurposeFlag();
// assert that extra data record is not present
assertThat(BitUtils.isBitSet(generalPurposeBytes[0], 3)).isTrue();
}
@Test
public void testAddStreamWithStoreCompressionAndCharset() throws IOException {
String koreanFileName = "가나다.abc";
File fileToAdd = TestUtils.getTestFileFromResources(koreanFileName);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.setCharset(CHARSET_CP_949);
zipFile.addStream(inputStream, zipParameters);
byte[] generalPurposeBytes = zipFile.getFileHeaders().get(0).getGeneralPurposeFlag();
// assert that extra data record is not present
assertThat(BitUtils.isBitSet(generalPurposeBytes[1], 3)).isFalse();
assertThat(zipFile.getFileHeaders().get(0).getFileName()).isEqualTo(koreanFileName);
}
@Test
public void testAddStreamWithStoreCompressionAndDefaultCharset() throws IOException {
String koreanFileName = "가나다.abc";
File fileToAdd = TestUtils.getTestFileFromResources(koreanFileName);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
byte[] generalPurposeBytes = zipFile.getFileHeaders().get(0).getGeneralPurposeFlag();
// assert that extra data record is not present
assertThat(BitUtils.isBitSet(generalPurposeBytes[1], 3)).isTrue();
assertThat(zipFile.getFileHeaders().get(0).getFileName()).isEqualTo(koreanFileName);
}
@Test
public void testAddStreamToZipWithAesEncryptionForNewZipAddsSuccessfully() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("бореиская.txt");
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 1);
verifyZipFileContainsFiles(generatedZipFile, singletonList("бореиская.txt"), CompressionMethod.DEFLATE,
EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
headerVerifier.verifyLocalFileHeaderUncompressedSize(generatedZipFile, "бореиская.txt", 0);
}
@Test
public void testAddStreamToZipWithoutEncryptionForExistingZipAddsSuccessfully() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("가나다.abc");
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 4);
verifyFileIsOf(generatedZipFile, "가나다.abc", CompressionMethod.DEFLATE, EncryptionMethod.NONE, null, null);
}
@Test
public void testAddStreamToZipWithAesEncryptionV2ForExistingZipAddsSuccessfully() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("가나다.abc");
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 4);
verifyFileIsOf(generatedZipFile, "가나다.abc", CompressionMethod.DEFLATE, EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_128, AesVersion.TWO);
}
@Test
public void testAddStreamToZipWithAesEncryptionV1ForExistingZipAddsSuccessfully() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("가나다.abc");
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setAesVersion(AesVersion.ONE);
zipParameters.setFileNameInZip(fileToAdd.getName());
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
InputStream inputStream = new FileInputStream(fileToAdd);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 4);
verifyFileIsOf(generatedZipFile, "가나다.abc", CompressionMethod.DEFLATE, EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256, AesVersion.ONE);
}
@Test
public void testAddStreamToZipWithCharsetCp949() throws IOException {
String koreanFileName = "가나다.abc";
ZipFile zipFile = new ZipFile(generatedZipFile);
File fileToAdd = TestUtils.getTestFileFromResources(koreanFileName);
InputStream inputStream = new FileInputStream(fileToAdd);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(fileToAdd.getName());
zipFile.setCharset(CHARSET_CP_949);
zipFile.addStream(inputStream, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, null, outputFolder, 1, true, CHARSET_CP_949);
assertThat(zipFile.getFileHeaders().get(0).getFileName()).isEqualTo(koreanFileName);
}
@Test
public void testAddStreamToZipWithSameEntryNameRemovesOldEntry() throws IOException {
File fileToAdd = TestUtils.getTestFileFromResources("sample.pdf");
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFile(fileToAdd);
try(InputStream inputStream = new FileInputStream(fileToAdd)) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip("sample.pdf");
zipFile.addStream(inputStream, zipParameters);
}
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 1);
}
private void verifyZipFileContainsFiles(File generatedZipFile, List fileNames,
CompressionMethod compressionMethod, EncryptionMethod encryptionMethod,
AesKeyStrength aesKeyStrength) throws ZipException {
verifyZipFileContainsFiles(generatedZipFile, fileNames, compressionMethod, encryptionMethod, aesKeyStrength,
AesVersion.TWO);
}
private void verifyZipFileContainsFiles(File generatedZipFile, List fileNames,
CompressionMethod compressionMethod, EncryptionMethod encryptionMethod,
AesKeyStrength aesKeyStrength, AesVersion aesVersion) throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List fileHeaders = zipFile.getFileHeaders();
verifyFileHeadersContainsFiles(fileHeaders, fileNames);
verifyAllFilesAreOf(fileHeaders, compressionMethod, encryptionMethod, aesKeyStrength, aesVersion);
}
private void verifyFoldersInZip(List fileHeaders, File generatedZipFile, char[] password)
throws IOException {
verifyFoldersInFileHeaders(fileHeaders);
verifyFoldersInLocalFileHeaders(generatedZipFile, password);
}
private void verifyFoldersInFileHeaders(List fileHeaders) {
fileHeaders.stream().filter(FileHeader::isDirectory).forEach(this::verifyFolderEntryInZip);
}
private void verifyFoldersInLocalFileHeaders(File generatedZipFile, char[] password) throws IOException {
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(generatedZipFile), password)) {
LocalFileHeader localFileHeader;
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
if (localFileHeader.isDirectory()) {
verifyFolderEntryInZip(localFileHeader);
}
}
}
}
private void verifyFolderEntryInZip(AbstractFileHeader fileHeader) {
assertThat(fileHeader.getCrc()).isZero();
assertThat(fileHeader.getCompressedSize()).isZero();
assertThat(fileHeader.getUncompressedSize()).isZero();
assertThat(fileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.STORE);
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.NONE);
}
private void verifyAllFilesInZipContainsPath(List fileHeaders, String pathToBeChecked) {
fileHeaders.forEach(e -> assertThat(e.getFileName()).startsWith(pathToBeChecked));
}
private void verifyAllFilesInZipDoesNotContainPath(List fileHeaders, String pathToBeChecked) {
fileHeaders.forEach(e -> assertThat(e.getFileName()).doesNotStartWith(pathToBeChecked));
}
private void verifyAllFilesAreOf(List fileHeaders, CompressionMethod compressionMethod,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength,
AesVersion aesVersion) {
for (FileHeader fileHeader : fileHeaders) {
if (fileHeader.isDirectory()) {
assertThat(fileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.STORE);
assertThat(fileHeader.isEncrypted()).isFalse();
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
assertThat(fileHeader.getCrc()).isZero();
} else {
CompressionMethod shouldBeCompressionMethod = getShouldBeCompressionMethod(
encryptionMethod == EncryptionMethod.AES, compressionMethod, fileHeader.getUncompressedSize());
assertThat(fileHeader.getCompressionMethod()).isEqualTo(shouldBeCompressionMethod);
if (encryptionMethod == null) {
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.NONE);
} else {
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(encryptionMethod);
}
if (encryptionMethod == EncryptionMethod.AES) {
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), aesKeyStrength, aesVersion);
if (fileHeader.getAesExtraDataRecord().getAesVersion().equals(AesVersion.TWO)) {
assertThat(fileHeader.getCrc()).isZero();
} else {
if (fileHeader.getCompressedSize() != 0) {
assertThat(fileHeader.getCrc()).isNotZero();
}
}
} else {
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
}
private void verifyFileIsOf(File generatedZipFile, String fileName, CompressionMethod compressionMethod,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength, AesVersion aesVersion)
throws ZipException {
List fileHeaders = getFileHeaders(generatedZipFile);
FileHeader fileHeader = getFileHeaderFrom(fileHeaders, fileName);
if (encryptionMethod == null || encryptionMethod == EncryptionMethod.NONE) {
assertThat(fileHeader.isEncrypted()).isFalse();
assertThat(fileHeader.getEncryptionMethod()).isIn(null, EncryptionMethod.NONE);
} else {
verifyAllFilesAreOf(singletonList(fileHeader), compressionMethod, encryptionMethod, aesKeyStrength, aesVersion);
}
}
private FileHeader getFileHeaderFrom(List fileHeaders, String fileName) {
Optional fileHeader = fileHeaders.stream().filter(e -> e.getFileName().equals(fileName)).findFirst();
assertThat(fileHeader).isPresent();
return fileHeader.get();
}
private List getFileHeaders(File generatedZipFile) throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List fileHeaders = zipFile.getFileHeaders();
assertThat(fileHeaders.size()).isNotZero();
return fileHeaders;
}
private void verifyAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord, AesKeyStrength aesKeyStrength,
AesVersion aesVersion) {
assertThat(aesExtraDataRecord).isNotNull();
assertThat(aesExtraDataRecord.getAesKeyStrength()).isEqualTo(aesKeyStrength);
assertThat(aesExtraDataRecord.getAesVersion()).isEqualTo(aesVersion);
}
private CompressionMethod getShouldBeCompressionMethod(boolean isAesEncrypted, CompressionMethod compressionMethod,
long uncompressedSize) {
if (isAesEncrypted) {
return CompressionMethod.AES_INTERNAL_ONLY;
}
if (uncompressedSize == 0) {
return CompressionMethod.STORE;
}
return compressionMethod;
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/CreateZipFileIT.java 0000664 0000000 0000000 00000035131 13576501616 0024312 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.testutils.TestUtils;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.FileUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import org.assertj.core.data.Offset;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static net.lingala.zip4j.testutils.TestUtils.getTestFileFromResources;
import static net.lingala.zip4j.testutils.ZipFileVerifier.verifyZipFileByExtractingAllFiles;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Contains Integration tests for create operations of ZipFile
*/
public class CreateZipFileIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testCreateSplitZipFileNotSplitArchiveWithZipNameAsString() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile.getPath());
zipFile.createSplitZipFile(FILES_TO_ADD, new ZipParameters(), false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, FILES_TO_ADD.size());
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithZipNameAsStringAndCharsetCp949() throws IOException {
String koreanFileName = "가나다.abc";
ZipFile zipFile = new ZipFile(generatedZipFile.getPath());
List filesToAdd = new ArrayList<>();
filesToAdd.add(getTestFileFromResources(koreanFileName));
zipFile.setCharset(CHARSET_CP_949);
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, null, outputFolder, filesToAdd.size(), true, CHARSET_CP_949);
assertThat(zipFile.getFileHeaders().get(0).getFileName()).isEqualTo(koreanFileName);
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithZipNameAsStringWithAESEncryption256() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile.getPath(), PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifyFileHeadersEncrypted(zipFile.getFileHeaders(), EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE);
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithZipNameAsStringWithAESEncryption128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile.getPath(), PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifyFileHeadersEncrypted(zipFile.getFileHeaders(), EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128,
CompressionMethod.DEFLATE);
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithFile() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.createSplitZipFile(FILES_TO_ADD, new ZipParameters(), false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, FILES_TO_ADD.size());
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithFileAndWithAESEncryption256() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile.getPath(), PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifyFileHeadersEncrypted(zipFile.getFileHeaders(), EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE);
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithFileAndWithAESEncryption128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile.getPath(), PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifyFileHeadersEncrypted(zipFile.getFileHeaders(), EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128,
CompressionMethod.DEFLATE);
}
@Test
public void testCreateSplitZipFileNotSplitArchiveWithFileAndWithStandardEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD,
AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile.getPath(), PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, false, -1);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifyFileHeadersEncrypted(zipFile.getFileHeaders(), EncryptionMethod.ZIP_STANDARD, AesKeyStrength.KEY_STRENGTH_128,
CompressionMethod.DEFLATE);
}
@Test
public void testCreateSplitZipFileThrowsExceptionWhenSplitSizeLessThanMinimumAllowed() throws ZipException {
expectedException.expectMessage("split length less than minimum allowed split length of "
+ InternalZipConstants.MIN_SPLIT_LENGTH + " Bytes");
expectedException.expect(ZipException.class);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.createSplitZipFile(FILES_TO_ADD, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH - 1);
}
@Test
public void testCreateSplitZipFileStoreAndWithoutEncryption() throws IOException {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, FILES_TO_ADD.size());
verifySplitZip(generatedZipFile, 2, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileStoreAndStandardZipEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifySplitZip(generatedZipFile, 2, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileStoreAndWithAesEncryptionKeyStrength256() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.createSplitZipFile(FILES_TO_ADD, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
verifySplitZip(generatedZipFile, 2, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileStoreAndWithAesEncryptionKeyStrength128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_128);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size() + 1);
verifySplitZip(generatedZipFile, 18, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileDeflateAndWithoutEncryption() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, 716800);
verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, FILES_TO_ADD.size() + 1);
verifySplitZip(generatedZipFile, 2, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileDeflateAndStandardZipEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.DEFLATE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, 512000);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size() + 1);
verifySplitZip(generatedZipFile, 2, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileDeflateAndWithAesEncryptionKeyStrength256() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size() + 1);
verifySplitZip(generatedZipFile, 15, InternalZipConstants.MIN_SPLIT_LENGTH);
}
@Test
public void testCreateSplitZipFileDeflateAndWithAesEncryptionKeyStrength128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES,
AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH + 2000);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size() + 1);
verifySplitZip(generatedZipFile, 15, InternalZipConstants.MIN_SPLIT_LENGTH + 2000);
}
@Test
public void testCreateZipFileWithSetPasswordSetter() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.setPassword(PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, FILES_TO_ADD.size());
}
private void verifySplitZip(File zipFile, int numberOfExpectedSplitFiles, long splitLength) throws ZipException {
assertNumberOfSplitFile(zipFile, numberOfExpectedSplitFiles);
assertSplitFileSizes(zipFile, numberOfExpectedSplitFiles, splitLength);
}
private void assertSplitFileSizes(File zipFile, int numberOfExpectedSplitFiles, long splitLength) {
for (int i = 0; i < numberOfExpectedSplitFiles - 2; i++) {
String zipExtension = ".z0";
if (i >= 9) {
zipExtension = ".z";
}
String fileNameWithoutExtension = zipFile.getPath().substring(0, zipFile.getPath().lastIndexOf(".zip"));
File splitZip = new File(fileNameWithoutExtension + zipExtension + (i + 1));
assertThat(splitZip).exists();
assertThat(splitZip.length()).isCloseTo(splitLength, Offset.offset(1000L));
}
}
private void assertNumberOfSplitFile(File zipFile, int numberOfExpectedSplitFiles) throws ZipException {
File[] allSplitFiles = getAllSplitZipFilesInFolder(zipFile.getParentFile(),
FileUtils.getZipFileNameWithoutExtension(zipFile.getName()));
assertThat(allSplitFiles.length).as("Number of split files").isEqualTo(numberOfExpectedSplitFiles);
}
private void verifyFileHeadersEncrypted(List fileHeaders, EncryptionMethod encryptionMethod,
AesKeyStrength aesKeyStrength, CompressionMethod compressionMethod) {
for (FileHeader fileHeader : fileHeaders) {
if (fileHeader.isDirectory()) {
assertThat(fileHeader.isEncrypted()).isFalse();
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
} else {
assertThat(fileHeader.isEncrypted()).isTrue();
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(encryptionMethod);
if (encryptionMethod == EncryptionMethod.AES) {
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), compressionMethod, aesKeyStrength);
} else {
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
}
private void verifyAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord, CompressionMethod compressionMethod,
AesKeyStrength aesKeyStrength) {
assertThat(aesExtraDataRecord).isNotNull();
assertThat(aesExtraDataRecord.getCompressionMethod()).isEqualTo(compressionMethod);
assertThat(aesExtraDataRecord.getAesKeyStrength()).isEqualTo(aesKeyStrength);
}
private File[] getAllSplitZipFilesInFolder(File folder, String fileNameWithoutExtension) {
FilenameFilter filenameFilter = (dir, name) -> name.contains(fileNameWithoutExtension + ".");
return folder.listFiles(filenameFilter);
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/ExtractZipFileIT.java 0000664 0000000 0000000 00000044765 13576501616 0024536 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.testutils.TestUtils;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class ExtractZipFileIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testExtractAllStoreAndNoEncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllStoreAndZipStandardEncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllStoreAndAes128EncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllStoreAndAes256EncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllDeflateAndNoEncryptionExtractsSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllDeflateAndZipStandardEncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllDeflateAndAes128EncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractAllDeflateAndAes256EncryptionExtractsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile.extractAll(outputFolder.getPath());
ZipFileVerifier.verifyFolderContentsSameAsSourceFiles(outputFolder);
verifyNumberOfFilesInOutputFolder(outputFolder, 3);
}
@Test
public void testExtractFileWithFileHeaderWithAes128() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
FileHeader fileHeader = zipFile.getFileHeader("sample_text_large.txt");
zipFile.extractFile(fileHeader, outputFolder.getPath());
File[] outputFiles = outputFolder.listFiles();
assertThat(outputFiles).hasSize(1);
ZipFileVerifier.verifyFileContent(TestUtils.getTestFileFromResources("sample_text_large.txt"), outputFiles[0]);
}
@Test
public void testExtractFileWithFileHeaderWithAes128AndInDirectory() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
FileHeader fileHeader = zipFile.getFileHeader("test-files/öüäöäö/asöäööl");
zipFile.extractFile(fileHeader, outputFolder.getPath());
File outputFile = getFileWithNameFrom(outputFolder, "asöäööl");
ZipFileVerifier.verifyFileContent(TestUtils.getTestFileFromResources("öüäöäö/asöäööl"), outputFile);
}
@Test
public void testExtractFileWithFileHeaderWithAes256AndWithANewFileName() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
String newFileName = "newFileName";
FileHeader fileHeader = zipFile.getFileHeader("sample_text_large.txt");
zipFile.extractFile(fileHeader, outputFolder.getPath(), newFileName);
File outputFile = getFileWithNameFrom(outputFolder, newFileName);
ZipFileVerifier.verifyFileContent(TestUtils.getTestFileFromResources("sample_text_large.txt"), outputFile);
}
@Test
public void testExtractFileWithFileNameThrowsExceptionWhenFileNotFound() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
expectedException.expect(ZipException.class);
expectedException.expectMessage("No file found with name NOT_EXISTING in zip file");
zipFile.extractFile("NOT_EXISTING", outputFolder.getPath());
}
@Test
public void testExtractFileWithFileNameWithZipStandardEncryption() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
zipFile.extractFile("test-files/sample_directory/favicon.ico", outputFolder.getPath());
File outputFile = getFileWithNameFrom(outputFolder, "favicon.ico");
ZipFileVerifier.verifyFileContent(TestUtils.getTestFileFromResources("sample_directory/favicon.ico"), outputFile);
}
@Test
public void testExtractFileWithFileNameWithZipStandardEncryptionAndNewFileName() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
String newFileName = "newFileName";
zipFile.extractFile("test-files/sample_directory/favicon.ico", outputFolder.getPath(), newFileName);
File outputFile = getFileWithNameFrom(outputFolder, newFileName);
ZipFileVerifier.verifyFileContent(TestUtils.getTestFileFromResources("sample_directory/favicon.ico"), outputFile);
}
@Test
public void testExtractFilesThrowsExceptionForWrongPasswordForAes() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
try {
zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.extractAll(outputFolder.getPath());
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e).isNotNull();
assertThat(e.getType()).isEqualTo(ZipException.Type.WRONG_PASSWORD);
}
}
@Test
public void testExtractFilesThrowsExceptionForWrongPasswordForZipStandardAndDeflate() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
try {
zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.extractAll(outputFolder.getPath());
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e).isNotNull();
assertThat(e.getType()).isEqualTo(ZipException.Type.WRONG_PASSWORD);
}
}
@Test
public void testExtractFilesThrowsExceptionForWrongPasswordForZipStandardAndStore() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
zipParameters.setCompressionMethod(CompressionMethod.STORE);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
try {
zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.extractAll(outputFolder.getPath());
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e).isNotNull();
assertThat(e.getType()).isEqualTo(ZipException.Type.WRONG_PASSWORD);
}
}
@Test
public void testExtractFilesForAZipMadeWithZip4jv1AndStoreCompressionWithAES() throws IOException {
File zipArchiveToTest = getTestArchiveFromResources("store_compression_made_with_v1.3.3.zip");
ZipFileVerifier.verifyZipFileByExtractingAllFiles(zipArchiveToTest, "aaaaaaaa".toCharArray(), outputFolder, 5,
false);
}
@Test
public void testExtractFilesForZipFileWhileWithCorruptExtraDataRecordLength() throws IOException {
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("corrupt_extra_data_record_length.zip"));
zipFile.extractAll(outputFolder.getPath());
assertThat(zipFile.getFileHeaders()).hasSize(44);
assertThat(Files.walk(outputFolder.toPath()).filter(Files::isRegularFile)).hasSize(44);
}
@Test
public void testExtractFilesWithSetPasswordSetter() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.setPassword(PASSWORD);
zipFile.extractAll(outputFolder.getCanonicalPath());
}
@Test
public void testExtractZipFileWithMissingExtendedLocalFileHeader() throws IOException {
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("missing_exended_local_file_header.zip"));
zipFile.extractAll(outputFolder.getPath());
assertThat(zipFile.getFileHeaders()).hasSize(3);
assertThat(Files.walk(outputFolder.toPath()).filter(Files::isRegularFile)).hasSize(3);
}
@Test
public void testExtractZipFileWithZip64ExtraDataRecordWithOnlyFileSizesInIt() throws IOException {
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("zip64_with_only_file_sizes.zip"),
"Shu1an@2019GTS".toCharArray());
zipFile.extractAll(outputFolder.getPath());
assertThat(zipFile.getFileHeaders()).hasSize(1);
assertThat(Files.walk(outputFolder.toPath()).filter(Files::isRegularFile)).hasSize(1);
}
@Test
public void testExtractZipFileWithChineseCharsetGBK() throws IOException {
String expactedFileName = "fff - 副本.txt";
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("testfile_with_chinese_filename_by_7zip.zip"));
zipFile.setCharset(CHARSET_GBK);
zipFile.extractAll(outputFolder.getPath());
assertThat(zipFile.getFileHeaders()).hasSize(2);
Set filenameSet = new HashSet<>();
Files.walk(outputFolder.toPath()).forEach(file -> filenameSet.add(file.getFileName().toString()));
assertThat(filenameSet.contains(expactedFileName)).isTrue();
}
@Test
public void testExtractZipFileWithCheckoutMismatchThrowsExceptionWithType() {
try {
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("entry_with_checksum_mismatch.zip"));
zipFile.extractAll(outputFolder.getPath());
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e.getType()).isEqualTo(ZipException.Type.CHECKSUM_MISMATCH);
assertThat(e.getMessage()).isEqualTo("Reached end of entry, but crc verification failed for sample_text1.txt");
}
}
@Test
public void testExtractNestedZipFileWithNoEncryptionOnInnerAndOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.NONE, EncryptionMethod.NONE);
}
@Test
public void testExtractNestedZipFileWithNoEncryptionOnInnerAndZipStandardOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.NONE, EncryptionMethod.ZIP_STANDARD);
}
@Test
public void testExtractNestedZipFileWithNoEncryptionOnInnerAndAesdOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.NONE, EncryptionMethod.AES);
}
@Test
public void testExtractNestedZipFileWithZipStandardEncryptionOnInnerAndNoneOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.ZIP_STANDARD, EncryptionMethod.NONE);
}
@Test
public void testExtractNestedZipFileWitAesOnInnerAndNoneOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.AES, EncryptionMethod.NONE);
}
@Test
public void testExtractNestedZipFileWithZipStandardEncryptionOnInnerAndAesOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.ZIP_STANDARD, EncryptionMethod.AES);
}
@Test
public void testExtractNestedZipFileWithAesOnInnerAndZipStandardOuter() throws IOException {
testExtractNestedZipFileWithEncrpytion(EncryptionMethod.AES, EncryptionMethod.ZIP_STANDARD);
}
@Test
public void testExtractZipFileLessThanMinimumExpectedZipFileSizeThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("Zip file size less than minimum expected zip file size. " +
"Probably not a zip file or a corrupted zip file");
ZipFile zipFile = new ZipFile(getTestArchiveFromResources("invalid_zip_file_size_less_than_22kb.zip"));
zipFile.extractAll(temporaryFolder.toString());
}
private void testExtractNestedZipFileWithEncrpytion(EncryptionMethod innerZipEncryption,
EncryptionMethod outerZipEncryption) throws IOException {
File innerZipFile = temporaryFolder.newFile("inner.zip");
File outerZipFile = temporaryFolder.newFile("outer.zip");
innerZipFile.delete();
outerZipFile.delete();
createNestedZip(innerZipFile, outerZipFile, innerZipEncryption, outerZipEncryption);
verifyNestedZipFile(outerZipFile, FILES_TO_ADD.size());
}
private void createNestedZip(File innerSourceZipFile, File outerSourceZipFile, EncryptionMethod innerEncryption,
EncryptionMethod outerEncryption) throws ZipException {
ZipFile innerZipFile = new ZipFile(innerSourceZipFile, PASSWORD);
ZipParameters innerZipParameters = createZipParametersForNestedZip(innerEncryption);
innerZipFile.addFiles(FILES_TO_ADD, innerZipParameters);
ZipFile outerZipFile = new ZipFile(outerSourceZipFile, PASSWORD);
ZipParameters outerZipParameters = createZipParametersForNestedZip(outerEncryption);
outerZipFile.addFile(innerSourceZipFile, outerZipParameters);
}
private void verifyNestedZipFile(File outerZipFileToVerify, int numberOfFilesInNestedZip) throws IOException {
ZipFile zipFile = new ZipFile(outerZipFileToVerify, PASSWORD);
FileHeader fileHeader = zipFile.getFileHeader("inner.zip");
assertThat(fileHeader).isNotNull();
int actualNumberOfFilesInNestedZip = 0;
try(InputStream inputStream = zipFile.getInputStream(fileHeader)) {
try(ZipInputStream zipInputStream = new ZipInputStream(inputStream, PASSWORD)) {
while (zipInputStream.getNextEntry() != null) {
actualNumberOfFilesInNestedZip++;
}
}
}
assertThat(actualNumberOfFilesInNestedZip).isEqualTo(numberOfFilesInNestedZip);
}
private ZipParameters createZipParametersForNestedZip(EncryptionMethod encryptionMethod) {
ZipParameters zipParameters = new ZipParameters();
if (encryptionMethod != null && !encryptionMethod.equals(EncryptionMethod.NONE)) {
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(encryptionMethod);
}
return zipParameters;
}
private void verifyNumberOfFilesInOutputFolder(File outputFolder, int numberOfExpectedFiles) {
assertThat(outputFolder.listFiles()).hasSize(numberOfExpectedFiles);
}
private File getFileWithNameFrom(File outputFolder, String fileName) throws ZipException {
List filesInFolder = FileUtils.getFilesInDirectoryRecursive(outputFolder, true, true);
Optional file = filesInFolder.stream().filter(e -> e.getName().equals(fileName)).findFirst();
assertThat(file).isPresent();
return file.get();
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/MiscZipFileIT.java 0000664 0000000 0000000 00000045042 13576501616 0024004 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.testutils.TestUtils;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.FileUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class MiscZipFileIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testMergeSplitZipFilesMergesSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
File mergedZipFile = new File(temporaryFolder.getRoot().getPath() + InternalZipConstants.FILE_SEPARATOR
+ "merged_zip_file.zip");
zipFile.mergeSplitFiles(mergedZipFile);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(mergedZipFile, outputFolder, 4);
}
@Test
public void testMergeSplitZipFilesWithAesEncryptionMergesSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
File mergedZipFile = new File(temporaryFolder.getRoot().getPath() + InternalZipConstants.FILE_SEPARATOR
+ "merged_zip_file.zip");
zipFile.mergeSplitFiles(mergedZipFile);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(mergedZipFile, PASSWORD, outputFolder, 4);
}
@Test
public void testGetFileHeadersReturnsEmptyListForNewZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getFileHeaders()).isEmpty();
}
@Test
public void testGetFileHeadersReturnsAllHeaders() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
List fileHeaders = zipFile.getFileHeaders();
assertThat(fileHeaders).isNotNull();
assertThat(fileHeaders).hasSize(FILES_TO_ADD.size());
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
verifyFileHeadersContainsFiles(fileHeaders, fileNames);
}
@Test
public void testGetFileHeadersReturnsAllHeadersAfterAddingAnotherFile() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.addFile(TestUtils.getTestFileFromResources("бореиская.txt"));
List fileHeaders = zipFile.getFileHeaders();
assertThat(fileHeaders).isNotNull();
assertThat(fileHeaders).hasSize(FILES_TO_ADD.size() + 1);
List fileNames = FILES_TO_ADD.stream().map(File::getName).collect(Collectors.toList());
fileNames.add("бореиская.txt");
verifyFileHeadersContainsFiles(fileHeaders, fileNames);
}
@Test
public void testGetFileHeaderReturnsNullForNewZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getFileHeader("SOME_NAME")).isNull();
}
@Test
public void testGetFileHeaderReturnsNullWhenFileDoesNotExist() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
assertThat(zipFile.getFileHeader("SOME_NAME")).isNull();
}
@Test
public void testGetFileHeaderReturnsFileHeaderSuccessfully() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
FileHeader fileHeader = zipFile.getFileHeader("sample_text_large.txt");
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getFileName()).isEqualTo("sample_text_large.txt");
}
@Test
public void testGetFileHeaderReturnsFileHeaderSuccessfullyAfterAddingNewFile() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
String fileToAdd = "file_PDF_1MB.pdf";
zipFile.addFile(TestUtils.getTestFileFromResources(fileToAdd));
FileHeader fileHeader = zipFile.getFileHeader(fileToAdd);
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getFileName()).isEqualTo(fileToAdd);
}
@Test
public void testIsEncryptedReturnsFalseForNewZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.isEncrypted()).isFalse();
}
@Test
public void testIsEncryptedReturnsFalseForNonEncryptedZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
assertThat(zipFile.isEncrypted()).isFalse();
}
@Test
public void testIsEncryptedReturnsTrueForStandardZipEncryption() throws ZipException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, null);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
assertThat(zipFile.isEncrypted()).isTrue();
}
@Test
public void testIsEncryptedReturnsTrueForAesEncryption() throws ZipException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
assertThat(zipFile.isEncrypted()).isTrue();
}
@Test
public void testIsEncryptedReturnsTrueAfterAddingAnEncryptedFile() throws ZipException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
assertThat(zipFile.isEncrypted()).isTrue();
}
@Test
public void testIsEncryptedReturnsFalseAfterRemovingAllEncryptedFiles() throws ZipException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text_large.txt"), zipParameters);
zipFile.removeFile("sample_text_large.txt");
assertThat(zipFile.isEncrypted()).isFalse();
}
@Test
public void testIsSplitArchiveReturnsFalseForNewlyCreatedZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.isSplitArchive()).isFalse();
}
@Test
public void testIsSplitArchiveReturnsFalseForNonSplitZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
assertThat(zipFile.isSplitArchive()).isFalse();
}
@Test
public void testIsSplitArchiveReturnsTrueForSplitZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
assertThat(zipFile.isSplitArchive()).isTrue();
}
@Test
public void testIsSplitArchiveReturnsFalseWhenCreatedAsSplitZipButNotSplit() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.createSplitZipFile(FILES_TO_ADD, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.isSplitArchive()).isFalse();
}
@Test
public void testIsSplitArchiveReturnsFalseForMergedZipFile() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
File mergedZipFile = new File(temporaryFolder.getRoot().getPath() + InternalZipConstants.FILE_SEPARATOR
+ "merged.zip");
zipFile.mergeSplitFiles(mergedZipFile);
zipFile = new ZipFile(mergedZipFile);
assertThat(zipFile.isSplitArchive()).isFalse();
}
@Test
public void testSetComment() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.setComment("SOME_COMMENT");
zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getComment()).isEqualTo("SOME_COMMENT");
}
@Test
public void testSetCommentWithChineseCharacters() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.setCharset(Charset.forName("GBK"));
zipFile.addFiles(FILES_TO_ADD);
zipFile.setComment("测试中文");
zipFile = new ZipFile(generatedZipFile);
zipFile.setCharset(Charset.forName("GBK"));
assertThat(zipFile.getComment()).isEqualTo("测试中文");
}
@Test
public void testSetCommentWithGermanCharacters() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.setComment("ÄÜÖÖÜSDSDS");
zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getComment()).isEqualTo("ÄÜÖÖÜSDSDS");
}
@Test
public void testSetCommentForMergedZipRetainsComment() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
String comment = "SOME_COMMENT";
zipFile.setComment(comment);
assertThat(zipFile.getComment()).isEqualTo(comment);
File mergedZipFile = new File(temporaryFolder.getRoot().getPath() + InternalZipConstants.FILE_SEPARATOR
+ "merged.zip");
zipFile.mergeSplitFiles(mergedZipFile);
zipFile = new ZipFile(mergedZipFile);
assertThat(zipFile.getComment()).isEqualTo(comment);
}
@Test
public void testSetCommentWithEmptyStringRemovesComment() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
String comment = "SOME_COMMENT";
zipFile.setComment(comment);
assertThat(zipFile.getComment()).isEqualTo(comment);
zipFile.setComment("");
assertThat(zipFile.getComment()).isEqualTo("");
//Make sure comment is empty and not null also when a new instance is now created
zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getComment()).isEqualTo("");
}
@Test
public void testGetInputStreamWithoutEncryptionReturnsSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
try (InputStream inputStream = zipFile.getInputStream(zipFile.getFileHeader("sample_text_large.txt"))) {
assertThat(inputStream).isNotNull();
verifyInputStream(inputStream, TestUtils.getTestFileFromResources("sample_text_large.txt"));
}
}
@Test
public void testGetInputStreamWithAesEncryptionReturnsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD, zipParameters);
try (InputStream inputStream = zipFile.getInputStream(zipFile.getFileHeader("sample_text_large.txt"))) {
assertThat(inputStream).isNotNull();
verifyInputStream(inputStream, TestUtils.getTestFileFromResources("sample_text_large.txt"));
}
}
@Test
public void testGetInputStreamWithAesEncryptionAndSplitFileReturnsSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, InternalZipConstants.MIN_SPLIT_LENGTH);
try (InputStream inputStream = zipFile.getInputStream(zipFile.getFileHeader("file_PDF_1MB.pdf"))) {
assertThat(inputStream).isNotNull();
verifyInputStream(inputStream, TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
}
//Check also with a new instance
zipFile = new ZipFile(generatedZipFile, PASSWORD);
try (InputStream inputStream = zipFile.getInputStream(zipFile.getFileHeader("file_PDF_1MB.pdf"))) {
verifyInputStream(inputStream, TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
}
}
@Test
public void testIsValidZipFileReturnsFalseForNonZipFile() {
assertThat(new ZipFile(TestUtils.getTestFileFromResources("sample_text_large.txt")).isValidZipFile()).isFalse();
}
@Test
public void testIsValidZipFileReturnsFalseForNonExistingZip() {
assertThat(new ZipFile("DoesNoExist").isValidZipFile()).isFalse();
}
@Test
public void testIsValidZipFileReturnsTrueForAValidZip() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
assertThat(zipFile.isValidZipFile()).isTrue();
}
@Test
public void testGetSplitZipFilesReturnsJustZipFileForNonSplit() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
List splitZipFiles = zipFile.getSplitZipFiles();
assertThat(splitZipFiles).hasSize(1);
assertThat(splitZipFiles.get(0)).hasName(generatedZipFile.getName());
}
@Test
public void testGetSplitZipFilesReturnsAllSplitZipFiles() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
List splitZipFiles = zipFile.getSplitZipFiles();
assertThat(splitZipFiles).hasSize(15);
verifySplitZipFileNames(splitZipFiles, 15, FileUtils.getZipFileNameWithoutExtension(generatedZipFile.getName()));
}
@Test
public void testRenameZipFileAfterExtractionWithInputStreamSucceeds() throws IOException {
new ZipFile(generatedZipFile).addFiles(FILES_TO_ADD);
ZipFile zipFile = new ZipFile(generatedZipFile);
FileHeader fileHeader = zipFile.getFileHeader("sample_text1.txt");
assertThat(fileHeader).isNotNull();
try(InputStream inputStream = zipFile.getInputStream(fileHeader)) {
inputStream.read(new byte[100]);
}
File newFile = temporaryFolder.newFile("NEW_FILE_NAME.ZIP");
String oldFile = generatedZipFile.getPath();
if(TestUtils.isWindows())
{
newFile.delete();
}
assertThat(generatedZipFile.renameTo(newFile)).isTrue();
assertThat(new File(oldFile)).doesNotExist();
}
@Test
public void testZipSlipFix() throws Exception {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip("../../bad.txt");
ZipFile zip = new ZipFile(generatedZipFile);
zip.addFile(TestUtils.getTestFileFromResources("sample_text1.txt"), zipParameters);
try {
zip.extractAll(outputFolder.getAbsolutePath());
fail("zip4j is vulnerable for slip zip");
} catch (ZipException e) {
assertThat(e).hasMessageStartingWith("illegal file name that breaks out of the target directory: ");
}
}
@Test
public void testUnzipFileZipSlipWithNotNormalizedTarget() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFiles(FILES_TO_ADD);
zipFile.extractAll(new File(outputFolder.getPath(),
".." + InternalZipConstants.FILE_SEPARATOR + outputFolder.getName()).getAbsolutePath());
}
@Test
public void testExtractFileDeletesOutputFileWhenWrongPassword() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.ZIP_STANDARD, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFile(TestUtils.getTestFileFromResources("sample_text1.txt"), zipParameters);
try {
zipFile = new ZipFile(generatedZipFile, "WRONG_PASSWORD".toCharArray());
zipFile.extractAll(outputFolder.getCanonicalPath());
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(new File(outputFolder.getCanonicalPath() + "sample_text1.txt")).doesNotExist();
assertThat(e.getType()).isEqualTo(ZipException.Type.WRONG_PASSWORD);
}
}
private void verifyInputStream(InputStream inputStream, File fileToCompareAgainst) throws IOException {
File outputFile = temporaryFolder.newFile();
try (OutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] b = new byte[InternalZipConstants.BUFF_SIZE];
int readLen = -1;
while ((readLen = inputStream.read(b)) != -1) {
outputStream.write(b, 0, readLen);
}
}
ZipFileVerifier.verifyFileContent(fileToCompareAgainst, outputFile);
}
private void verifySplitZipFileNames(List files, int expectedNumberOfZipFiles,
String fileNameWithoutExtension) {
assertThat(files).hasSize(expectedNumberOfZipFiles);
for (int i = 0; i < expectedNumberOfZipFiles; i++) {
File file = files.get(i);
String fileExtensionPrefix = ".z0";
if (i >= 9) {
fileExtensionPrefix = ".z";
}
String expectedFileName = fileNameWithoutExtension + fileExtensionPrefix + (i + 1);
if (i == expectedNumberOfZipFiles - 1) {
expectedFileName = fileNameWithoutExtension + ".zip";
}
assertThat(file).hasName(expectedFileName);
}
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/RemoveFilesFromZipIT.java 0000664 0000000 0000000 00000012662 13576501616 0025357 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.testutils.TestUtils;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
public class RemoveFilesFromZipIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testRemoveFileAsFileNameThrowsExceptionWhenZipFileDoesNotExist() throws ZipException {
String fileNameToRemove = "SOME_NAME";
expectedException.expect(ZipException.class);
expectedException.expectMessage("could not find file header for file: " + fileNameToRemove);
new ZipFile(generatedZipFile).removeFile(fileNameToRemove);
}
@Test
public void testRemoveFileAsFileNameThrowsExceptionWhenFileDoesNotExistInZip() throws ZipException {
String fileNameToRemove = "SOME_NAME";
expectedException.expect(ZipException.class);
expectedException.expectMessage("could not find file header for file: " + fileNameToRemove);
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.removeFile(fileNameToRemove);
}
@Test
public void testRemoveFileAsFileNameThrowsExceptionForSplitArchive() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
expectedException.expect(ZipException.class);
expectedException.expectMessage("Zip file format does not allow updating split/spanned files");
zipFile.removeFile("file_PDF_1MB.pdf");
}
@Test
public void testRemoveFileAsFileNameRemovesSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
zipFile.addFiles(FILES_TO_ADD);
zipFile.removeFile("sample_text1.txt");
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 2);
verifyZipFileDoesNotContainFile(generatedZipFile, "sample_text1.txt");
}
@Test
public void testRemoveFileAsFileNameWithCharsetCp949RemovesSuccessfully() throws IOException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>();
filesToAdd.add(TestUtils.getTestFileFromResources("가나다.abc"));
filesToAdd.add(TestUtils.getTestFileFromResources("sample_text1.txt"));
zipFile.setCharset(CHARSET_CP_949);
zipFile.addFiles(filesToAdd);
zipFile.removeFile("sample_text1.txt");
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, null, outputFolder, 1, true, CHARSET_CP_949);
verifyZipFileDoesNotContainFile(generatedZipFile, "sample_text1.txt");
}
@Test
public void testRemoveFileAsFileNameRemovesSuccessfullyWithFolderNameInPath() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
zipFile.removeFile("test-files/öüäöäö/asöäööl");
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 12);
verifyZipFileDoesNotContainFile(generatedZipFile, "test-files/öüäöäö/asöäööl");
}
@Test
public void testRemoveFileAsFileHeaderThrowsExceptionForSplitArchive() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
List filesToAdd = new ArrayList<>(FILES_TO_ADD);
filesToAdd.add(TestUtils.getTestFileFromResources("file_PDF_1MB.pdf"));
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, InternalZipConstants.MIN_SPLIT_LENGTH);
expectedException.expect(ZipException.class);
expectedException.expectMessage("Zip file format does not allow updating split/spanned files");
zipFile.removeFile(zipFile.getFileHeader("file_PDF_1MB.pdf"));
}
@Test
public void testRemoveFileAsFileHeaderRemovesSuccessfully() throws IOException {
ZipParameters zipParameters = createZipParameters(EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256);
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
zipFile.addFolder(TestUtils.getTestFileFromResources(""), zipParameters);
zipFile.removeFile(zipFile.getFileHeader("test-files/sample_directory/favicon.ico"));
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, 12);
verifyZipFileDoesNotContainFile(generatedZipFile, "sample_directory/favicon.ico");
}
private void verifyZipFileDoesNotContainFile(File generatedZipFile, String fileNameToCheck) throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
Optional fileHeader = zipFile.getFileHeaders().stream()
.filter(e -> e.getFileName().equals(fileNameToCheck)).findFirst();
assertThat(fileHeader).isNotPresent();
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/ZipFileTest.java 0000664 0000000 0000000 00000043545 13576501616 0023601 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.progress.ProgressMonitor;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
// Tests only failure scenarios. All other tests are covered in the corresponding Integration test
public class ZipFileTest {
private File sourceZipFile;
private ZipFile zipFile;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
public void setup() {
sourceZipFile = mockFile(false);
zipFile = new ZipFile(sourceZipFile);
}
@Test
public void testCreateZipFileThrowsExceptionWhenZipFileExists() throws ZipException {
reset(sourceZipFile);
when(sourceZipFile.exists()).thenReturn(true);
expectedException.expect(ZipException.class);
expectedException.expectMessage("zip file: " + sourceZipFile + " already exists. " +
"To add files to existing zip file use addFile method");
zipFile.createSplitZipFile(Collections.emptyList(), new ZipParameters(), true, 10000);
}
@Test
public void testCreateZipFileThrowsExceptionWhenFileListIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null, cannot create zip file");
zipFile.createSplitZipFile(null, new ZipParameters(), true, 10000);
}
@Test
public void testCreateZipFileThrowsExceptionWhenFileListIsEmpty() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null, cannot create zip file");
zipFile.createSplitZipFile(Collections.emptyList(), new ZipParameters(), true, 10000);
}
@Test
public void testCreateZipFileFromFolderThrowsExceptionWheFolderIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("folderToAdd is null, cannot create zip file from folder");
zipFile.createSplitZipFileFromFolder(null, new ZipParameters(), true, 10000);
}
@Test
public void testCreateZipFileFromFolderThrowsExceptionWhenParametersAreNull() throws ZipException {
File folderToAdd = mockFile(true);
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters are null, cannot create zip file from folder");
zipFile.createSplitZipFileFromFolder(folderToAdd, null, true, 10000);
}
@Test
public void testCreateZipFileFromFolderThrowsExceptionWhenZipFileExists() throws ZipException {
reset(sourceZipFile);
when(sourceZipFile.exists()).thenReturn(true);
File folderToAdd = mockFile(true);
expectedException.expect(ZipException.class);
expectedException.expectMessage("zip file: " + sourceZipFile
+ " already exists. To add files to existing zip file use addFolder method");
zipFile.createSplitZipFileFromFolder(folderToAdd, new ZipParameters(), true, 10000);
}
@Test
public void testAddFileAsStringThrowsExceptionWhenFileIsNull() throws ZipException {
expectedException.expectMessage("file to add is null or empty");
expectedException.expect(ZipException.class);
zipFile.addFile((String) null);
}
@Test
public void testAddFileAsStringThrowsExceptionWhenFileIsEmpty() throws ZipException {
expectedException.expectMessage("file to add is null or empty");
expectedException.expect(ZipException.class);
zipFile.addFile(" ");
}
@Test
public void testAddFileAsStringWithParametersThrowsExceptionWhenFileIsNull() throws ZipException {
expectedException.expectMessage("file to add is null or empty");
expectedException.expect(ZipException.class);
zipFile.addFile((String) null, new ZipParameters());
}
@Test
public void testAddFileAsStringWithParametersThrowsExceptionWhenFileIsEmpty() throws ZipException {
expectedException.expectMessage("file to add is null or empty");
expectedException.expect(ZipException.class);
zipFile.addFile("", new ZipParameters());
}
@Test
public void testAddFileAsFileThrowsExceptionWhenParametersIsNull() throws ZipException {
File fileToAdd = mockFile(true);
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters are null");
zipFile.addFile(fileToAdd, null);
}
@Test
public void testAddFileAsFileThrowsExceptionWhenProgressMonitorStateIsBusy() throws ZipException {
File fileToAdd = mockFile(true);
zipFile.getProgressMonitor().setState(ProgressMonitor.State.BUSY);
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid operation - Zip4j is in busy state");
zipFile.addFile(fileToAdd, new ZipParameters());
}
@Test
public void testAddFilesThrowsExceptionWhenInputFilesIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null or empty");
zipFile.addFiles(null);
}
@Test
public void testAddFilesThrowsExceptionWhenInputFilesIsEmpty() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null or empty");
zipFile.addFiles(Collections.emptyList());
}
@Test
public void testAddFilesThrowsExceptionWhenProgressMonitorStateIsBusy() throws ZipException {
zipFile.getProgressMonitor().setState(ProgressMonitor.State.BUSY);
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid operation - Zip4j is in busy state");
zipFile.addFiles(Collections.singletonList(new File("Some_File")));
}
@Test
public void testAddFilesWithParametersThrowsExceptionWhenInputFilesIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null or empty");
zipFile.addFiles(null, new ZipParameters());
}
@Test
public void testAddFilesWithParametersThrowsExceptionWhenInputFilesIsEmpty() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input file List is null or empty");
zipFile.addFiles(Collections.emptyList(), new ZipParameters());
}
@Test
public void testAddFilesWithParametersThrowsExceptionWhenParametersAreNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters are null");
zipFile.addFiles(Collections.singletonList(new File("Some_File")), null);
}
@Test
public void testAddFilesWithParametersThrowsExceptionWhenProgressMonitorStateIsBusy() throws ZipException {
zipFile.getProgressMonitor().setState(ProgressMonitor.State.BUSY);
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid operation - Zip4j is in busy state");
zipFile.addFiles(Collections.singletonList(new File("Some_File")), new ZipParameters());
}
@Test
public void testAddFolderThrowsExceptionWhenFolderIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input path is null, cannot add folder to zip file");
zipFile.addFolder(null);
}
@Test
public void testAddFolderThrowsExceptionWhenFolderDoesNotExist() throws ZipException {
File folderToAdd = mockFile(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("folder does not exist");
zipFile.addFolder(folderToAdd);
}
@Test
public void testAddFolderThrowsExceptionWhenFolderNotADirectory() throws ZipException {
File folderToAdd = mockFile(true);
when(folderToAdd.isDirectory()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("input folder is not a directory");
zipFile.addFolder(folderToAdd);
}
@Test
public void testAddFolderThrowsExceptionWhenCannotReadFolder() throws ZipException {
File folderToAdd = mockFile(true);
when(folderToAdd.isDirectory()).thenReturn(true);
when(folderToAdd.canRead()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("cannot read input folder");
zipFile.addFolder(folderToAdd);
}
@Test
public void testAddFolderWithParametersThrowsExceptionWhenFolderIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input path is null, cannot add folder to zip file");
zipFile.addFolder(null, new ZipParameters());
}
@Test
public void testAddFolderWithParametersThrowsExceptionWhenFolderDoesNotExist() throws ZipException {
File folderToAdd = mockFile(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("folder does not exist");
zipFile.addFolder(folderToAdd, new ZipParameters());
}
@Test
public void testAddFolderWithParametersThrowsExceptionWhenFolderNotADirectory() throws ZipException {
File folderToAdd = mockFile(true);
when(folderToAdd.isDirectory()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("input folder is not a directory");
zipFile.addFolder(folderToAdd, new ZipParameters());
}
@Test
public void testAddFolderWithParametersThrowsExceptionWhenCannotReadFolder() throws ZipException {
File folderToAdd = mockFile(true);
when(folderToAdd.isDirectory()).thenReturn(true);
when(folderToAdd.canRead()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("cannot read input folder");
zipFile.addFolder(folderToAdd, new ZipParameters());
}
@Test
public void testAddFolderWithParametersThrowsExceptionWhenInputParametersAreNull() throws ZipException {
File folderToAdd = mockFile(true);
when(folderToAdd.isDirectory()).thenReturn(true);
when(folderToAdd.canRead()).thenReturn(true);
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters are null, cannot add folder to zip file");
zipFile.addFolder(folderToAdd, null);
}
@Test
public void testAddStreamThrowsExceptionWhenInputStreamIsNull() throws ZipException {
expectedException.expectMessage("inputstream is null, cannot add file to zip");
expectedException.expect(ZipException.class);
zipFile.addStream(null, new ZipParameters());
}
@Test
public void testAddStreamThrowsExceptionWhenParametersIsNull() throws ZipException {
expectedException.expectMessage("zip parameters are null");
expectedException.expect(ZipException.class);
zipFile.addStream(new ByteArrayInputStream(new byte[2]), null);
}
@Test
public void testExtractAllThrowsExceptionWhenDestinationIsNull() throws ZipException {
expectedException.expectMessage("output path is null or invalid");
expectedException.expect(ZipException.class);
zipFile.extractAll(null);
}
@Test
public void testExtractAllThrowsExceptionWhenDestinationIsEmpty() throws ZipException {
expectedException.expectMessage("output path is null or invalid");
expectedException.expect(ZipException.class);
zipFile.extractAll(" ");
}
@Test
public void testExtractFileWithFileHeaderWhenFileHeaderIsNullThrowsException() throws ZipException {
expectedException.expectMessage("input file header is null, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile((FileHeader) null, "SOME_DESTINATION");
}
@Test
public void testExtractFileWithFileHeaderWhenDestinationIsNullThrowsException() throws ZipException {
expectedException.expectMessage("destination path is empty or null, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile(new FileHeader(), null);
}
@Test
public void testExtractFileWithFileHeaderWhenDestinationIsEmptyThrowsException() throws ZipException {
expectedException.expectMessage("destination path is empty or null, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile(new FileHeader(), "");
}
@Test
public void testExtractFileWithFileHeaderWhenBusyStateThrowsException() throws ZipException {
zipFile.getProgressMonitor().setState(ProgressMonitor.State.BUSY);
expectedException.expectMessage("invalid operation - Zip4j is in busy state");
expectedException.expect(ZipException.class);
zipFile.extractFile(new FileHeader(), "SOME_DESTINATION");
}
@Test
public void testExtractFileWithFileNameThrowsExceptionWhenNameIsNull() throws ZipException {
expectedException.expectMessage("file to extract is null or empty, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile((String) null, "SOME_DESTINATION");
}
@Test
public void testExtractFileWithFileNameThrowsExceptionWhenNameIsEmpty() throws ZipException {
expectedException.expectMessage("file to extract is null or empty, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile("", "SOME_DESTINATION");
}
@Test
public void testExtractFileWithNewFileNameThrowsExceptionWhenNameIsNull() throws ZipException {
expectedException.expectMessage("file to extract is null or empty, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile((String) null, "SOME_DESTINATION", "NEW_FILE_NAME");
}
@Test
public void testExtractFileWithNewFileNameThrowsExceptionWhenNameIsEmpty() throws ZipException {
expectedException.expectMessage("file to extract is null or empty, cannot extract file");
expectedException.expect(ZipException.class);
zipFile.extractFile("", "SOME_DESTINATION");
}
@Test
public void testGetFileHeadersReturnsEmptyListWhenZipFileDoesNotExist() throws ZipException {
File mockFile = mockFile(false);
ZipFile zipFile = new ZipFile(mockFile);
assertThat(zipFile.getFileHeaders()).isEmpty();
}
@Test
public void testGetFileHeaderThrowsExceptionWhenFileNameIsNull() throws ZipException {
expectedException.expectMessage("input file name is emtpy or null, cannot get FileHeader");
expectedException.expect(ZipException.class);
zipFile.getFileHeader(null);
}
@Test
public void testGetFileHeaderThrowsExceptionWhenFileNameIsEmpty() throws ZipException {
expectedException.expectMessage("input file name is emtpy or null, cannot get FileHeader");
expectedException.expect(ZipException.class);
zipFile.getFileHeader("");
}
@Test
public void testRemoveFileWithFileNameThrowsExceptionWhenFileNameIsNull() throws ZipException {
expectedException.expectMessage("file name is empty or null, cannot remove file");
expectedException.expect(ZipException.class);
zipFile.removeFile((String) null);
}
@Test
public void testRemoveFileWithFileNameThrowsExceptionWhenFileNameIsEmpty() throws ZipException {
expectedException.expectMessage("file name is empty or null, cannot remove file");
expectedException.expect(ZipException.class);
zipFile.removeFile("");
}
@Test
public void testRemoveFileWithFileHeaderThrowsExceptionWhenFileNameIsNull() throws ZipException {
expectedException.expectMessage("input file header is null, cannot remove file");
expectedException.expect(ZipException.class);
zipFile.removeFile((FileHeader) null);
}
@Test
public void testMergeSplitFilesWhenOutputFileIsNullThrowsException() throws ZipException {
expectedException.expectMessage("outputZipFile is null, cannot merge split files");
expectedException.expect(ZipException.class);
zipFile.mergeSplitFiles(null);
}
@Test
public void testMergeSplitFilesWhenOutputFileDoesAlreadyExistsThrowsException() throws ZipException {
expectedException.expectMessage("output Zip File already exists");
expectedException.expect(ZipException.class);
File mergedZipFile = mockFile(true);
zipFile.mergeSplitFiles(mergedZipFile);
}
@Test
public void testSetCommentWhenCommentIsNullThrowsException() throws ZipException {
expectedException.expectMessage("input comment is null, cannot update zip file");
expectedException.expect(ZipException.class);
zipFile.setComment(null);
}
@Test
public void testSetCommentWhenZipFileDoesNotExistsThrowsException() throws ZipException {
expectedException.expectMessage("zip file does not exist, cannot set comment for zip file");
expectedException.expect(ZipException.class);
zipFile.setComment("Some comment");
}
@Test
public void testGetCommentWhenZipFileDoesNotExistThrowsException() throws ZipException {
expectedException.expectMessage("zip file does not exist, cannot read comment");
expectedException.expect(ZipException.class);
zipFile.getComment();
}
@Test
public void testGetInputStreamWhenFileHeaderIsNullThrowsException() throws IOException {
expectedException.expectMessage("FileHeader is null, cannot get InputStream");
expectedException.expect(ZipException.class);
zipFile.getInputStream(null);
}
@Test
public void testSetRunInThreadSetsFlag() {
zipFile.setRunInThread(true);
assertThat(zipFile.isRunInThread()).isTrue();
zipFile.setRunInThread(false);
assertThat(zipFile.isRunInThread()).isFalse();
}
@Test
public void testGetFileReturnsValidFile() {
assertThat(zipFile.getFile()).isSameAs(sourceZipFile);
}
@Test
public void testToString() {
assertThat(zipFile.toString()).isEqualTo("SOME_PATH");
}
private File mockFile(boolean fileExists) {
File file = mock(File.class);
when(file.exists()).thenReturn(fileExists);
when(file.toString()).thenReturn("SOME_PATH");
return file;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/ZipFileZip64IT.java 0000664 0000000 0000000 00000006754 13576501616 0024034 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j;
import net.lingala.zip4j.headers.HeaderReader;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.testutils.RandomInputStream;
import net.lingala.zip4j.testutils.SlowTests;
import net.lingala.zip4j.testutils.ZipFileVerifier;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import static org.assertj.core.api.Assertions.assertThat;
@Category(SlowTests.class)
public class ZipFileZip64IT extends AbstractIT {
private byte[] readBuffer = new byte[4096];
@Test
public void testZip64WithSingleLargeZipEntry() throws IOException {
long entrySize = InternalZipConstants.ZIP_64_SIZE_LIMIT + 1;
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
zipParameters.setEntrySize(entrySize);
createZip64FileWithEntries(1, entrySize, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, null, outputFolder, 1, false);
verifyZip64HeadersPresent();
}
@Test
public void testZip64WithCentralDirectoryOffsetGreaterThanZip64Limit() throws IOException {
long eachEntrySize = (InternalZipConstants.ZIP_64_SIZE_LIMIT / 2) + 100;
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEntrySize(eachEntrySize);
createZip64FileWithEntries(3, eachEntrySize, zipParameters);
ZipFileVerifier.verifyZipFileByExtractingAllFiles(generatedZipFile, null, outputFolder, 3, false);
verifyZip64HeadersPresent();
}
@Test
public void testZip64WithNumberOfEntriesGreaterThan70k() throws IOException {
long eachEntrySize = 100;
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEntrySize(eachEntrySize);
createZip64FileWithEntries(70000, eachEntrySize, zipParameters);
ZipFile zipFile = new ZipFile(generatedZipFile);
assertThat(zipFile.getFileHeaders()).hasSize(70000);
verifyZip64HeadersPresent();
}
private void verifyZip64HeadersPresent() throws IOException {
HeaderReader headerReader = new HeaderReader();
ZipModel zipModel = headerReader.readAllHeaders(new RandomAccessFile(generatedZipFile,
RandomAccessFileMode.READ.getValue()), InternalZipConstants.CHARSET_UTF_8);
assertThat(zipModel.getZip64EndOfCentralDirectoryLocator()).isNotNull();
assertThat(zipModel.getZip64EndOfCentralDirectoryRecord()).isNotNull();
assertThat(zipModel.isZip64Format()).isTrue();
}
private void createZip64FileWithEntries(int numberOfEntries, long eachEntrySize, ZipParameters zipParameters)
throws IOException {
int readLen;
try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(generatedZipFile))) {
for (int i = 0; i < numberOfEntries; i++) {
zipParameters.setFileNameInZip("FILE_" + i);
zipOutputStream.putNextEntry(zipParameters);
try(InputStream inputStream = new RandomInputStream(eachEntrySize)) {
while ((readLen = inputStream.read(readBuffer)) != -1) {
zipOutputStream.write(readBuffer, 0, readLen);
}
}
zipOutputStream.closeEntry();
}
}
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/crypto/ 0000775 0000000 0000000 00000000000 13576501616 0022041 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/crypto/PBKDF2/ 0000775 0000000 0000000 00000000000 13576501616 0022751 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/crypto/PBKDF2/BinToolsTest.java 0000664 0000000 0000000 00000002450 13576501616 0026206 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.crypto.PBKDF2;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
public class BinToolsTest {
@Rule
public final ExpectedException expectedException = ExpectedException.none();
@Test
public void bin2hexForValidInputReturnsValidHex() {
final byte[] b = {(byte) 112};
assertThat(BinTools.bin2hex(b)).isEqualTo("70");
}
@Test
public void bin2hexForEmptyInputReturnsEmptyString() {
assertThat(BinTools.bin2hex(new byte[]{})).isEqualTo("");
}
@Test
public void bin2hexForNullInputReturnsEmptyString() {
assertThat(BinTools.bin2hex(null)).isEqualTo("");
}
@Test
public void bin2hexForNullInputReturnsEmptyArray() {
assertThat(BinTools.hex2bin(null)).isEqualTo(new byte[]{});
}
@Test
public void hex2binForInvalidInputOutputIllegalArgumentException() {
expectedException.expect(IllegalArgumentException.class);
BinTools.hex2bin("foo");
}
@Test
public void hex2binCharacterInputOutputPositive() {
assertThat(BinTools.hex2bin('A')).isEqualTo(10);
}
@Test
public void hex2binInvalidInputOutputIllegalArgumentException() {
expectedException.expect(IllegalArgumentException.class);
BinTools.hex2bin('\u013c');
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/exception/ 0000775 0000000 0000000 00000000000 13576501616 0022517 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/exception/ZipExceptionTest.java 0000664 0000000 0000000 00000003704 13576501616 0026647 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.exception;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class ZipExceptionTest {
@Test
public void testZipExceptionForErrorMessage() {
String message = "SOME_MESSAGE";
ZipException zipException = new ZipException(message);
assertThat(zipException.getMessage()).isEqualTo(message);
assertThat(zipException.getType()).isEqualTo(ZipException.Type.UNKNOWN);
}
@Test
public void testZipExceptionWithRootException() {
String errorMessage = "SOME_MESSAGE";
Exception rootException = new RuntimeException(errorMessage);
ZipException zipException = new ZipException(rootException);
assertThat(zipException.getCause()).isEqualTo(rootException);
assertThat(zipException.getCause().getMessage()).isEqualTo(errorMessage);
assertThat(zipException.getType()).isEqualTo(ZipException.Type.UNKNOWN);
assertThat(zipException.getMessage()).contains(errorMessage);
}
@Test
public void testZipExceptionWithMessageAndRootException() {
String errorMessage = "SOME_MESSAGE";
String rootErrorMessage = "ROOT_ERROR_MESSAGE";
Exception rootException = new RuntimeException(rootErrorMessage);
ZipException zipException = new ZipException(errorMessage, rootException);
assertThat(zipException.getCause()).isEqualTo(rootException);
assertThat(zipException.getCause().getMessage()).isEqualTo(rootErrorMessage);
assertThat(zipException.getType()).isEqualTo(ZipException.Type.UNKNOWN);
assertThat(zipException.getMessage()).isEqualTo(errorMessage);
}
@Test
public void testZipExceptionWithMessageAndExceptionType() {
String errorMessage = "SOME_MESSAGE";
ZipException.Type exceptionType = ZipException.Type.WRONG_PASSWORD;
ZipException zipException = new ZipException(errorMessage, exceptionType);
assertThat(zipException.getType()).isEqualTo(exceptionType);
assertThat(zipException.getMessage()).isEqualTo(errorMessage);
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/headers/ 0000775 0000000 0000000 00000000000 13576501616 0022134 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/headers/FileHeaderFactoryTest.java 0000664 0000000 0000000 00000044655 13576501616 0027175 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.nio.charset.Charset;
import static net.lingala.zip4j.util.BitUtils.isBitSet;
import static net.lingala.zip4j.util.Zip4jUtil.javaToDosTime;
import static org.assertj.core.api.Assertions.assertThat;
public class FileHeaderFactoryTest {
private static final String FILE_NAME_IN_ZIP = "filename.txt";
private static final long ENTRY_CRC = 2323L;
private FileHeaderFactory fileHeaderFactory = new FileHeaderFactory();
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testGenerateFileHeaderWithoutFileNameThrowsException() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("fileNameInZip is null or empty");
fileHeaderFactory.generateFileHeader(new ZipParameters(), false, 0, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testGenerateFileHeaderDefaults() throws ZipException {
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(generateZipParameters(), false, 0, InternalZipConstants.CHARSET_UTF_8);
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.DEFLATE);
verifyCompressionLevelGridForDeflate(CompressionLevel.NORMAL,
fileHeader.getGeneralPurposeFlag()[0]);
assertThat(fileHeader.isEncrypted()).isFalse();
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.NONE);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
assertThat(fileHeader.getLastModifiedTime()).isNotZero();
assertThat(fileHeader.getCompressedSize()).isEqualTo(0);
assertThat(fileHeader.getUncompressedSize()).isEqualTo(0);
}
@Test
public void testGenerateFileHeaderForStoreWithoutEncryption() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, false);
}
@Test
public void testGenerateFileHeaderWhenEncryptingWithoutMethodThrowsException() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("Encryption method has to be set when encryptFiles flag is set in zip parameters");
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testGenerateFileHeaderWithStandardEncryption() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, false);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithNullKeyStrengthThrowsException() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid AES key strength");
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(null);
fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithoutKeyStrengthUsesDefault() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE, AesVersion.TWO);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithKeyStrength128() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_128);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_128,
CompressionMethod.DEFLATE, AesVersion.TWO);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithKeyStrength192() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_192);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_192,
CompressionMethod.DEFLATE, AesVersion.TWO);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithKeyStrength256() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE, AesVersion.TWO);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionVersionV1() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setAesVersion(AesVersion.ONE);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE, AesVersion.ONE);
}
@Test
public void testGenerateFileHeaderWithAesEncryptionWithNullVersionUsesV2() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
zipParameters.setAesVersion(null);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyFileHeader(fileHeader, zipParameters, false, 0, true);
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_256,
CompressionMethod.DEFLATE, AesVersion.TWO);
}
@Test
public void testGenerateFileHeaderWithLastModifiedFileTime() throws ZipException {
long lastModifiedFileTime = System.currentTimeMillis();
ZipParameters zipParameters = generateZipParameters();
zipParameters.setLastModifiedFileTime(lastModifiedFileTime);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
assertThat(fileHeader.getLastModifiedTime()).isEqualTo(javaToDosTime(zipParameters.getLastModifiedFileTime()));
}
@Test
public void testGenerateFileHeaderWithCompressionLevelMaximum() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setCompressionLevel(CompressionLevel.MAXIMUM);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyCompressionLevelGridForDeflate(CompressionLevel.MAXIMUM, fileHeader.getGeneralPurposeFlag()[0]);
}
@Test
public void testGenerateFileHeaderWithCompressionLevelFast() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setCompressionLevel(CompressionLevel.FAST);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyCompressionLevelGridForDeflate(CompressionLevel.FAST, fileHeader.getGeneralPurposeFlag()[0]);
}
@Test
public void testGenerateFileHeaderWithCompressionLevelFastest() throws ZipException {
ZipParameters zipParameters = generateZipParameters();
zipParameters.setCompressionLevel(CompressionLevel.FASTEST);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
verifyCompressionLevelGridForDeflate(CompressionLevel.FASTEST, fileHeader.getGeneralPurposeFlag()[0]);
}
@Test
public void testGenerateFileHeaderWithCorrectCharset() throws ZipException {
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(generateZipParameters(), false, 0, Charset.forName("Cp949"));
assertThat(isBitSet(fileHeader.getGeneralPurposeFlag()[1], 3)).isFalse();
}
@Test
public void testGenerateFileHeaderWithUTF8Charset() throws ZipException {
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(generateZipParameters(), false, 0, InternalZipConstants.CHARSET_UTF_8);
assertThat(isBitSet(fileHeader.getGeneralPurposeFlag()[1], 3)).isTrue();
}
@Test
public void testGenerateLocalFileHeader() {
long lastModifiedFileTime = javaToDosTime(System.currentTimeMillis());
FileHeader fileHeader = generateFileHeader(lastModifiedFileTime);
LocalFileHeader localFileHeader = fileHeaderFactory.generateLocalFileHeader(fileHeader);
verifyLocalFileHeader(localFileHeader, lastModifiedFileTime);
}
private ZipParameters generateZipParameters() {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setFileNameInZip(FILE_NAME_IN_ZIP);
zipParameters.setEntryCRC(ENTRY_CRC);
return zipParameters;
}
private FileHeader generateFileHeader(long lastModifiedFileTime) {
FileHeader fileHeader = new FileHeader();
fileHeader.setVersionNeededToExtract(20);
fileHeader.setCompressionMethod(CompressionMethod.STORE);
fileHeader.setLastModifiedTime(lastModifiedFileTime);
fileHeader.setUncompressedSize(1000L);
fileHeader.setFileName(FILE_NAME_IN_ZIP);
fileHeader.setFileNameLength(FILE_NAME_IN_ZIP.getBytes(InternalZipConstants.CHARSET_UTF_8).length);
fileHeader.setEncrypted(true);
fileHeader.setEncryptionMethod(EncryptionMethod.AES);
fileHeader.setCrc(1231231L);
fileHeader.setCompressedSize(23523L);
fileHeader.setGeneralPurposeFlag(new byte[] {2, 28});
fileHeader.setDataDescriptorExists(true);
return fileHeader;
}
private void verifyFileHeader(FileHeader fileHeader, ZipParameters zipParameters, boolean isSplitZip,
int diskNumberStart, boolean aesExtraDataRecordPresent) {
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getSignature()).isEqualTo(HeaderSignature.CENTRAL_DIRECTORY);
assertThat(fileHeader.getVersionMadeBy()).isEqualTo(20);
assertThat(fileHeader.getVersionNeededToExtract()).isEqualTo(20);
verifyCompressionMethod(fileHeader, zipParameters);
assertThat(fileHeader.isEncrypted()).isEqualTo(zipParameters.isEncryptFiles());
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(zipParameters.isEncryptFiles()
? zipParameters.getEncryptionMethod() : EncryptionMethod.NONE);
assertThat(fileHeader.getFileName()).isEqualTo(FILE_NAME_IN_ZIP);
assertThat(fileHeader.getFileNameLength()).isEqualTo(FILE_NAME_IN_ZIP.length());
verifyGeneralPurposeBytes(fileHeader.getGeneralPurposeFlag(), zipParameters);
assertThat(fileHeader.getDiskNumberStart()).isEqualTo(isSplitZip ? diskNumberStart : 0);
verifyLastModifiedFileTime(fileHeader, zipParameters);
assertThat(fileHeader.getExternalFileAttributes()).isEqualTo(new byte[4]);
assertThat(fileHeader.isDirectory()).isEqualTo(false);
if (zipParameters.isWriteExtendedLocalFileHeader()) {
assertThat(fileHeader.getUncompressedSize()).isEqualTo(0);
} else {
assertThat(fileHeader.getUncompressedSize()).isEqualTo(zipParameters.getEntrySize());
}
verifyCrc(fileHeader);
assertThat(fileHeader.isDataDescriptorExists()).isEqualTo(zipParameters.isWriteExtendedLocalFileHeader());
assertThat(fileHeader.getAesExtraDataRecord() != null).isEqualTo(aesExtraDataRecordPresent);
}
private void verifyLocalFileHeader(LocalFileHeader localFileHeader, long lastModifiedFileTime) {
assertThat(localFileHeader).isNotNull();
assertThat(localFileHeader.getSignature()).isEqualTo(HeaderSignature.LOCAL_FILE_HEADER);
assertThat(localFileHeader.getVersionNeededToExtract()).isEqualTo(20);
assertThat(localFileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.STORE);
assertThat(localFileHeader.getLastModifiedTime()).isEqualTo(lastModifiedFileTime);
assertThat(localFileHeader.getUncompressedSize()).isEqualTo(1000L);
assertThat(localFileHeader.getFileName()).isEqualTo(FILE_NAME_IN_ZIP);
assertThat(localFileHeader.getFileNameLength()).isEqualTo(FILE_NAME_IN_ZIP.length());
assertThat(localFileHeader.isEncrypted()).isEqualTo(true);
assertThat(localFileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.AES);
assertThat(localFileHeader.getCrc()).isEqualTo(1231231L);
assertThat(localFileHeader.getCompressedSize()).isEqualTo(23523L);
assertThat(localFileHeader.getGeneralPurposeFlag()).containsExactly(2, 28);
assertThat(localFileHeader.isDataDescriptorExists()).isTrue();
}
private void verifyCompressionMethod(FileHeader fileHeader, ZipParameters zipParameters) {
if (fileHeader.isEncrypted() && fileHeader.getEncryptionMethod().equals(EncryptionMethod.AES)) {
assertThat(fileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.AES_INTERNAL_ONLY);
} else {
assertThat(fileHeader.getCompressionMethod()).isEqualTo(zipParameters.getCompressionMethod());
}
}
private void verifyLastModifiedFileTime(FileHeader fileHeader, ZipParameters zipParameters) {
if (zipParameters.getLastModifiedFileTime() > 0) {
assertThat(fileHeader.getLastModifiedTime()).isEqualTo(javaToDosTime(
zipParameters.getLastModifiedFileTime()));
} else {
assertThat(fileHeader.getLastModifiedTime()).isGreaterThan(0);
}
}
private void verifyGeneralPurposeBytes(byte[] generalPurposeBytes, ZipParameters zipParameters) {
assertThat(generalPurposeBytes).isNotNull();
assertThat(generalPurposeBytes.length).isEqualTo(2);
assertThat(isBitSet(generalPurposeBytes[0], 0)).isEqualTo(zipParameters.isEncryptFiles());
if (zipParameters.getCompressionMethod() == CompressionMethod.DEFLATE) {
verifyCompressionLevelGridForDeflate(zipParameters.getCompressionLevel(),
generalPurposeBytes[0]);
} else {
assertThat(isBitSet(generalPurposeBytes[0], 1)).isFalse();
assertThat(isBitSet(generalPurposeBytes[0], 2)).isFalse();
}
assertThat(isBitSet(generalPurposeBytes[0], 3)).isEqualTo(zipParameters.isWriteExtendedLocalFileHeader());
assertThat(isBitSet(generalPurposeBytes[1], 3)).isTrue();
}
private void verifyCompressionLevelGridForDeflate(CompressionLevel compressionLevel,
byte firstByteOfGeneralPurposeBytes) {
if (compressionLevel == CompressionLevel.NORMAL) {
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 1)).isFalse();
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 2)).isFalse();
} else if (compressionLevel == CompressionLevel.MAXIMUM) {
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 1)).isTrue();
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 2)).isFalse();
} else if (compressionLevel == CompressionLevel.FAST) {
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 1)).isFalse();
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 2)).isTrue();
} else if (compressionLevel == CompressionLevel.FASTEST) {
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 1)).isTrue();
assertThat(isBitSet(firstByteOfGeneralPurposeBytes, 2)).isTrue();
}
}
private void verifyCrc(FileHeader fileHeader) {
if (fileHeader.isEncrypted() && fileHeader.getEncryptionMethod() == EncryptionMethod.ZIP_STANDARD) {
assertThat(fileHeader.getCrc()).isEqualTo(ENTRY_CRC);
} else {
assertThat(fileHeader.getCrc()).isEqualTo(0);
}
}
private void verifyAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord, AesKeyStrength aesKeyStrength,
CompressionMethod compressionMethod, AesVersion aesVersion) {
assertThat(aesExtraDataRecord).isNotNull();
assertThat(aesExtraDataRecord.getSignature()).isEqualTo(HeaderSignature.AES_EXTRA_DATA_RECORD);
assertThat(aesExtraDataRecord.getDataSize()).isEqualTo(7);
assertThat(aesExtraDataRecord.getVendorID()).isEqualTo("AE");
assertThat(aesExtraDataRecord.getCompressionMethod()).isEqualTo(compressionMethod);
assertThat(aesExtraDataRecord.getAesVersion()).isEqualTo(aesVersion);
assertThat(aesExtraDataRecord.getAesKeyStrength()).isEqualTo(aesKeyStrength);
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/headers/HeaderReaderIT.java 0000664 0000000 0000000 00000044476 13576501616 0025566 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.model.CentralDirectory;
import net.lingala.zip4j.model.EndOfCentralDirectoryRecord;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.util.BitUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class HeaderReaderIT extends AbstractIT {
private static final String FILE_NAME_PREFIX = "FILE_NAME_ÄÜß_";
private static final String END_OF_CENTRAL_DIR_COMMENT = "END_OF_CENTRAL_DIR_COMMENT_ÜÄÖÖÖÄ";
private FileHeaderFactory fileHeaderFactory = new FileHeaderFactory();
private HeaderReader headerReader = new HeaderReader();
private HeaderWriter headerWriter = new HeaderWriter();
@Test
public void testReadAllHeadersWith10Entries() throws IOException, ZipException {
int numberOfEntries = 10;
ZipModel actualZipModel = generateZipHeadersFile(numberOfEntries, EncryptionMethod.NONE);
try(RandomAccessFile randomAccessFile = initializeRandomAccessFile(actualZipModel.getZipFile())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10, false);
assertThat(readZipModel.getEndOfCentralDirectoryRecord().getComment()).isEmpty();
}
}
@Test
public void testReadAllHeadersWithEndOfCentralDirectoryComment() throws IOException, ZipException {
ZipModel actualZipModel = generateZipModel(1);
actualZipModel.getEndOfCentralDirectoryRecord().setComment(END_OF_CENTRAL_DIR_COMMENT);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = initializeRandomAccessFile(actualZipModel.getZipFile())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, InternalZipConstants.CHARSET_UTF_8);
verifyZipModel(readZipModel, 1, false);
EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = readZipModel.getEndOfCentralDirectoryRecord();
assertThat(endOfCentralDirectoryRecord.getComment()).isEqualTo(END_OF_CENTRAL_DIR_COMMENT);
}
}
@Test
public void testReadAllWithoutEndOfCentralDirectoryRecordThrowsException() throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(temporaryFolder.newFile(),
RandomAccessFileMode.WRITE.getValue())) {
//Create an empty file
randomAccessFile.seek(4000);
randomAccessFile.write(1);
headerReader.readAllHeaders(randomAccessFile, null);
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e.getMessage()).isEqualTo("Zip headers not found. Probably not a zip file");
}
}
@Test
public void testReadAllWithoutEnoughHeaderDataThrowsException() throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(temporaryFolder.newFile(),
RandomAccessFileMode.WRITE.getValue())) {
//Create an empty file
randomAccessFile.seek(1000);
randomAccessFile.write(1);
headerReader.readAllHeaders(randomAccessFile, null);
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e.getMessage()).isEqualTo("Zip headers not found. Probably not a zip file or a corrupted zip file");
assertThat(e.getCause() instanceof IOException);
}
}
@Test
public void testReadAllWithoutFileHeaderSignatureThrowsException() throws IOException, ZipException {
ZipModel actualZipModel = generateZipModel(2);
actualZipModel.getCentralDirectory().getFileHeaders().get(1).setSignature(HeaderSignature.DIGITAL_SIGNATURE);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
headerReader.readAllHeaders(randomAccessFile, null);
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e.getMessage()).isEqualTo("Expected central directory entry not found (#2)");
}
}
@Test
public void testReadAllWithFileNameContainsWindowsDriveExcludesIt() throws IOException, ZipException {
String fileName = "C:\\test.txt";
ZipModel actualZipModel = generateZipModel(1);
actualZipModel.getCentralDirectory().getFileHeaders().get(0).setFileName(fileName);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
FileHeader fileHeader = readZipModel.getCentralDirectory().getFileHeaders().get(0);
assertThat(fileHeader.getFileName()).isEqualTo("test.txt");
}
}
@Test
public void testReadAllWithoutFileNameWritesNull() throws IOException, ZipException {
ZipModel actualZipModel = generateZipModel(1);
actualZipModel.getCentralDirectory().getFileHeaders().get(0).setFileName(null);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
FileHeader fileHeader = readZipModel.getCentralDirectory().getFileHeaders().get(0);
assertThat(fileHeader.getFileName()).isNull();
}
}
@Test
public void testReadAllWithJapaneseCharacters() throws IOException, ZipException {
testWithoutUtf8FileName("公ゃ的年社", "育ざどろめ", true, false);
}
@Test
public void testReadAllWithoutUtf8FlagDecodesWithoutCharsetFlagForJapaneseCharactersDoesNotMatch()
throws IOException, ZipException {
testWithoutUtf8FileName("公ゃ的年社", "育ざどろめ", false, true);
}
@Test
public void testReadAllWithoutUtf8FlagDecodesWithoutCharsetFlagForEnglishCharactersMatches()
throws IOException, ZipException {
testWithoutUtf8FileName("SOME_TEXT", "SOME_COMMENT", true, true);
}
@Test
public void testReadAllWithAesEncryption() throws ZipException, IOException {
ZipModel actualZipModel = generateZipHeadersFile(3, EncryptionMethod.AES);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
for (FileHeader fileHeader : readZipModel.getCentralDirectory().getFileHeaders()) {
assertThat(fileHeader.getAesExtraDataRecord()).isNotNull();
assertThat(fileHeader.getAesExtraDataRecord().getAesKeyStrength()).isEqualTo(AesKeyStrength.KEY_STRENGTH_256);
}
}
}
@Test
public void testReadAllWithStandardZipEncryption() throws ZipException, IOException {
ZipModel actualZipModel = generateZipHeadersFile(3, EncryptionMethod.ZIP_STANDARD);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
for (FileHeader fileHeader : readZipModel.getCentralDirectory().getFileHeaders()) {
assertThat(fileHeader.isEncrypted()).isTrue();
assertThat(fileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.ZIP_STANDARD);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
@Test
public void testReadAllZip64Format() throws IOException, ZipException {
ZipModel actualZipModel = generateZipModel(1);
long entrySize = InternalZipConstants.ZIP_64_SIZE_LIMIT + 1;
actualZipModel.getCentralDirectory().getFileHeaders().get(0).setUncompressedSize(entrySize);
actualZipModel.getCentralDirectory().getFileHeaders().get(0).setCompressedSize(entrySize + 100);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
assertThat(readZipModel.isZip64Format()).isTrue();
assertThat(readZipModel.getZip64EndOfCentralDirectoryRecord()).isNotNull();
assertThat(readZipModel.getZip64EndOfCentralDirectoryLocator()).isNotNull();
FileHeader fileHeader = actualZipModel.getCentralDirectory().getFileHeaders().get(0);
assertThat(fileHeader.getUncompressedSize()).isEqualTo(entrySize);
assertThat(fileHeader.getCompressedSize()).isEqualTo(entrySize + 100);
}
}
@Test
public void testReadLocalFileHeader() throws ZipException, IOException {
long entrySize = InternalZipConstants.ZIP_64_SIZE_LIMIT + 1;
File headerFile = generateAndWriteLocalFileHeader(entrySize, EncryptionMethod.NONE);
try(InputStream inputStream = new FileInputStream(headerFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
assertThat(readLocalFileHeader).isNotNull();
assertThat(readLocalFileHeader.getCompressedSize()).isEqualTo(entrySize);
assertThat(readLocalFileHeader.getUncompressedSize()).isEqualTo(entrySize);
}
}
@Test
public void testReadLocalFileHeaderWithAesEncryption() throws ZipException, IOException {
long entrySize = InternalZipConstants.ZIP_64_SIZE_LIMIT - 1001 ;
File headerFile = generateAndWriteLocalFileHeader(entrySize, EncryptionMethod.AES);
try(InputStream inputStream = new FileInputStream(headerFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
assertThat(readLocalFileHeader).isNotNull();
assertThat(readLocalFileHeader.getCompressedSize()).isEqualTo(entrySize);
assertThat(readLocalFileHeader.getUncompressedSize()).isEqualTo(entrySize);
assertThat(readLocalFileHeader.getAesExtraDataRecord()).isNotNull();
assertThat(readLocalFileHeader.getAesExtraDataRecord().getAesKeyStrength())
.isEqualTo(AesKeyStrength.KEY_STRENGTH_256);
}
}
@Test
public void testReadDataDescriptorWithSignature() {
}
private void testWithoutUtf8FileName(String fileName, String entryComment, boolean shouldFileNamesMatch,
boolean unsetUtf8Flag) throws IOException, ZipException {
ZipModel actualZipModel = generateZipModel(3);
FileHeader secondFileHeader = actualZipModel.getCentralDirectory().getFileHeaders().get(1);
if (unsetUtf8Flag) {
// Unset utf8 flag
byte[] generalPurposeBytes = secondFileHeader.getGeneralPurposeFlag();
generalPurposeBytes[1] = BitUtils.unsetBit(generalPurposeBytes[1], 3);
secondFileHeader.setGeneralPurposeFlag(generalPurposeBytes);
}
secondFileHeader.setFileName(fileName);
secondFileHeader.setFileComment(entryComment);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
FileHeader fileHeader = readZipModel.getCentralDirectory().getFileHeaders().get(1);
if (shouldFileNamesMatch) {
assertThat(fileHeader.getFileName()).isEqualTo(fileName);
assertThat(fileHeader.getFileComment()).isEqualTo(entryComment);
} else {
assertThat(fileHeader.getFileName()).isNotEqualTo(fileName);
assertThat(fileHeader.getFileComment()).isNotEqualTo(entryComment);
}
assertThat(readZipModel.getCentralDirectory().getFileHeaders().get(0).getFileCommentLength()).isEqualTo(0);
assertThat(readZipModel.getCentralDirectory().getFileHeaders().get(0).getFileComment()).isNull();
assertThat(readZipModel.getCentralDirectory().getFileHeaders().get(2).getFileCommentLength()).isEqualTo(0);
assertThat(readZipModel.getCentralDirectory().getFileHeaders().get(2).getFileComment()).isNull();
}
}
private RandomAccessFile initializeRandomAccessFile(File headersFile) throws IOException {
return new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue());
}
private void verifyZipModel(ZipModel readZipModel, int numberOfExpectedEntries, boolean isZip64) {
assertThat(readZipModel).isNotNull();
verifyEndOfCentralDirectory(readZipModel.getEndOfCentralDirectoryRecord(), numberOfExpectedEntries, isZip64);
verifyCentralDirectory(readZipModel.getCentralDirectory(), numberOfExpectedEntries);
}
private void verifyEndOfCentralDirectory(EndOfCentralDirectoryRecord endOfCentralDirectoryRecord, int numberOfEntries,
boolean isZip64) {
assertThat(endOfCentralDirectoryRecord).isNotNull();
endOfCentralDirectoryRecord.setSignature(HeaderSignature.END_OF_CENTRAL_DIRECTORY);
assertThat(endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectory()).isEqualTo(numberOfEntries);
if (!isZip64) {
assertThat(endOfCentralDirectoryRecord.getNumberOfThisDisk()).isEqualTo(0);
assertThat(endOfCentralDirectoryRecord.getNumberOfThisDiskStartOfCentralDir()).isEqualTo(0);
assertThat(endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectoryOnThisDisk())
.isEqualTo(numberOfEntries);
assertThat(endOfCentralDirectoryRecord.getSizeOfCentralDirectory()).isNotZero();
}
}
private void verifyCentralDirectory(CentralDirectory centralDirectory, int numberOfExpectedEntries) {
assertThat(centralDirectory).isNotNull();
verifyFileHeaders(centralDirectory.getFileHeaders(), numberOfExpectedEntries);
}
private void verifyFileHeaders(List fileHeaders, int numberOfExpectedEntries) {
assertThat(fileHeaders).isNotEmpty();
assertThat(fileHeaders).hasSize(numberOfExpectedEntries);
for (int i = 0; i < numberOfExpectedEntries; i++) {
String expectedFileName = FILE_NAME_PREFIX + i;
FileHeader fileHeader = fileHeaders.get(i);
assertThat(fileHeader.getFileName()).isEqualTo(expectedFileName);
int expectedFileNameLength = expectedFileName.getBytes(InternalZipConstants.CHARSET_UTF_8).length;
assertThat(fileHeader.getFileNameLength()).isEqualTo(expectedFileNameLength);
}
}
private ZipModel generateZipHeadersFile(int numberOfEntries, EncryptionMethod encryptionMethod)
throws IOException, ZipException {
ZipModel zipModel = generateZipModel(numberOfEntries, encryptionMethod);
File headersFile = writeZipHeaders(zipModel);
zipModel.setZipFile(headersFile);
return zipModel;
}
private ZipModel generateZipModel(int numberOfEntries) throws ZipException {
return generateZipModel(numberOfEntries, EncryptionMethod.NONE);
}
private ZipModel generateZipModel(int numberOfEntries, EncryptionMethod encryptionMethod)
throws ZipException {
ZipParameters zipParameters = generateZipParameters(encryptionMethod);
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(generateFileHeaders(zipParameters, numberOfEntries));
return zipModel;
}
private ZipParameters generateZipParameters(EncryptionMethod encryptionMethod) {
ZipParameters zipParameters = new ZipParameters();
if (encryptionMethod != null && encryptionMethod != EncryptionMethod.NONE) {
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(encryptionMethod);
}
return zipParameters;
}
private List generateFileHeaders(ZipParameters zipParameters, int numberOfEntries)
throws ZipException {
List fileHeaders = new ArrayList<>();
for (int i = 0; i < numberOfEntries; i++) {
zipParameters.setFileNameInZip(FILE_NAME_PREFIX + i);
FileHeader fileHeader = fileHeaderFactory.generateFileHeader(zipParameters, false, 0, InternalZipConstants.CHARSET_UTF_8);
fileHeaders.add(fileHeader);
}
return fileHeaders;
}
private LocalFileHeader generateLocalFileHeader(long entrySize, EncryptionMethod encryptionMethod)
throws ZipException {
List fileHeaders = generateFileHeaders(generateZipParameters(encryptionMethod), 1);
LocalFileHeader localFileHeader = fileHeaderFactory.generateLocalFileHeader(fileHeaders.get(0));
localFileHeader.setCompressedSize(entrySize);
localFileHeader.setUncompressedSize(entrySize);
return localFileHeader;
}
private File generateAndWriteLocalFileHeader(long entrySize, EncryptionMethod encryptionMethod)
throws ZipException, IOException {
LocalFileHeader localFileHeader = generateLocalFileHeader(entrySize, encryptionMethod);
if (encryptionMethod != null && encryptionMethod != EncryptionMethod.NONE) {
localFileHeader.setEncrypted(true);
localFileHeader.setEncryptionMethod(encryptionMethod);
}
ZipModel zipModel = generateZipModel(1);
File headerFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headerFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeader, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
return headerFile;
}
private File writeZipHeaders(ZipModel zipModel) throws IOException, ZipException {
File headersFile = temporaryFolder.newFile();
try(SplitOutputStream splitOutputStream = new SplitOutputStream(headersFile)) {
headerWriter.finalizeZipFile(zipModel, splitOutputStream, InternalZipConstants.CHARSET_UTF_8);
return headersFile;
}
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/headers/HeaderUtilTest.java 0000664 0000000 0000000 00000025474 13576501616 0025701 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.CentralDirectory;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class HeaderUtilTest {
private static final String FILE_NAME = "test.txt";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testGetFileHeaderWithNullZipModelThrowsException() throws ZipException {
expectZipException("zip model is null, cannot determine file header with exact match for fileName: " + FILE_NAME);
HeaderUtil.getFileHeader(null, FILE_NAME);
}
@Test
public void testGetFileHeaderWithNullFileNameThrowsException() throws ZipException {
expectZipException("file name is null, cannot determine file header with exact match for fileName: null");
HeaderUtil.getFileHeader(new ZipModel(), null);
}
@Test
public void testGetFileHeaderWithEmptyFileNameThrowsException() throws ZipException {
expectZipException("file name is null, cannot determine file header with exact match for fileName: ");
HeaderUtil.getFileHeader(new ZipModel(), "");
}
@Test
public void testGetFileHeaderWithNullCentralDirectoryThrowsException() throws ZipException {
expectZipException("central directory is null, cannot determine file header with exact match for fileName: "
+ FILE_NAME);
ZipModel zipModel = new ZipModel();
zipModel.setCentralDirectory(null);
HeaderUtil.getFileHeader(zipModel, FILE_NAME);
}
@Test
public void testGetFileHeaderWithNullFileHeadersThrowsException() throws ZipException {
expectedException.expect(ZipException.class);
expectZipException("file Headers are null, cannot determine file header with exact match for fileName: "
+ FILE_NAME);
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(null);
zipModel.setCentralDirectory(centralDirectory);
HeaderUtil.getFileHeader(zipModel, FILE_NAME);
}
@Test
public void testGetFileHeaderWithEmptyFileHeadersReturnsNull() throws ZipException {
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(Collections.emptyList());
zipModel.setCentralDirectory(centralDirectory);
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, FILE_NAME);
assertThat(fileHeader).isNull();
}
@Test
public void testGetFileHeaderWithExactMatch() throws ZipException {
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(Arrays.asList(
generateFileHeader(null),
generateFileHeader(""),
generateFileHeader("SOME_OTHER_NAME"),
generateFileHeader(FILE_NAME)
));
zipModel.setCentralDirectory(centralDirectory);
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, FILE_NAME);
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getFileName()).isEqualTo(FILE_NAME);
}
@Test
public void testGetFileHeaderWithWindowsFileSeparator() throws ZipException {
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(Arrays.asList(
generateFileHeader(FILE_NAME),
generateFileHeader("SOME_OTHER_NAME\\")
));
zipModel.setCentralDirectory(centralDirectory);
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, "SOME_OTHER_NAME\\");
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getFileName()).isEqualTo("SOME_OTHER_NAME\\");
}
@Test
public void testGetFileHeaderWithUnixFileSeparator() throws ZipException {
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(Arrays.asList(
generateFileHeader(FILE_NAME),
generateFileHeader("SOME_OTHER_NAME/")
));
zipModel.setCentralDirectory(centralDirectory);
FileHeader fileHeader = HeaderUtil.getFileHeader(zipModel, "SOME_OTHER_NAME/");
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getFileName()).isEqualTo("SOME_OTHER_NAME/");
}
@Test
public void testGetFileHeaderWithoutAMatch() throws ZipException {
ZipModel zipModel = new ZipModel();
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(Arrays.asList(
generateFileHeader(FILE_NAME),
generateFileHeader("SOME_OTHER_NAME")
));
zipModel.setCentralDirectory(centralDirectory);
assertThat(HeaderUtil.getFileHeader(zipModel, "SHOULD_NOT_EXIST")).isNull();
}
@Test
public void testGetIndexOfFileHeaderWhenZipModelIsNullThrowsException() throws ZipException {
expectZipException("input parameters is null, cannot determine index of file header");
HeaderUtil.getIndexOfFileHeader(null, new FileHeader());
}
@Test
public void testGetIndexOfFileHeaderWhenFileHeaderlIsNullThrowsException() throws ZipException {
expectZipException("input parameters is null, cannot determine index of file header");
HeaderUtil.getIndexOfFileHeader(new ZipModel(), null);
}
@Test
public void testGetIndexOfFileHeaderWhenCentralDirectoryIsNullReturnsNegativeOne() throws ZipException {
ZipModel zipModel = new ZipModel();
zipModel.setCentralDirectory(null);
assertThat(HeaderUtil.getIndexOfFileHeader(zipModel, new FileHeader())).isEqualTo(-1);
}
@Test
public void testGetIndexOfFileHeaderWhenFileHeadersIsNullReturnsNegativeOne() throws ZipException {
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(null);
assertThat(HeaderUtil.getIndexOfFileHeader(zipModel, new FileHeader())).isEqualTo(-1);
}
@Test
public void testGetIndexOfFileHeaderWhenFileHeadersIsEmptyReturnsNegativeOne() throws ZipException {
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(Collections.emptyList());
assertThat(HeaderUtil.getIndexOfFileHeader(zipModel, new FileHeader())).isEqualTo(-1);
}
@Test
public void testGetIndexOfFileHeaderWithNullFileNameInFileHeaderThrowsException() throws ZipException {
expectZipException("file name in file header is empty or null, cannot determine index of file header");
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(Collections.singletonList(new FileHeader()));
HeaderUtil.getIndexOfFileHeader(zipModel, new FileHeader());
}
@Test
public void testGetIndexOfFileHeaderWithEmptyFileNameInFileHeaderThrowsException() throws ZipException {
expectZipException("file name in file header is empty or null, cannot determine index of file header");
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(Collections.singletonList(new FileHeader()));
FileHeader fileHeader = new FileHeader();
fileHeader.setFileName("");
HeaderUtil.getIndexOfFileHeader(zipModel, new FileHeader());
}
@Test
public void testGetIndexOfFileHeaderGetsIndexSuccessfully() throws ZipException {
String fileNamePrefix = "FILE_NAME_";
int numberOfEntriesToAdd = 10;
List fileHeadersInZipModel = generateFileHeaderWithFileNames(fileNamePrefix, numberOfEntriesToAdd);
ZipModel zipModel = new ZipModel();
zipModel.getCentralDirectory().setFileHeaders(fileHeadersInZipModel);
FileHeader fileHeaderToFind = new FileHeader();
for (int i = 0; i < numberOfEntriesToAdd; i++) {
fileHeaderToFind.setFileName(fileNamePrefix + i);
assertThat(HeaderUtil.getIndexOfFileHeader(zipModel, fileHeaderToFind)).isEqualTo(i);
}
fileHeaderToFind.setFileName(fileNamePrefix + numberOfEntriesToAdd);
assertThat(HeaderUtil.getIndexOfFileHeader(zipModel, fileHeaderToFind)).isEqualTo(-1);
}
@Test
public void testDecodeStringWithCharsetForUtf8() {
String utf8StringToEncode = "asdäüöö";
byte[] utf8EncodedBytes = utf8StringToEncode.getBytes(InternalZipConstants.CHARSET_UTF_8);
assertThat(HeaderUtil.decodeStringWithCharset(utf8EncodedBytes, true, null)).isEqualTo(utf8StringToEncode);
}
@Test
public void testDecodeStringWithCharsetWithoutUtf8ForUtf8String() {
String utf8StringToEncode = "asdäüöö";
byte[] utf8EncodedBytes = utf8StringToEncode.getBytes(InternalZipConstants.CHARSET_UTF_8);
assertThat(HeaderUtil.decodeStringWithCharset(utf8EncodedBytes, false, null)).isNotEqualTo(utf8StringToEncode);
}
@Test
public void testDecodeStringWithCharsetWithoutUtf8AndWithEnglishChars() {
String plainString = "asdasda234234";
byte[] plainEncodedBytes = plainString.getBytes();
assertThat(HeaderUtil.decodeStringWithCharset(plainEncodedBytes, false, null)).isEqualTo(plainString);
}
@Test
public void testDecodeStringWithCharsetWithISO8859AndFinnishChars() throws UnsupportedEncodingException {
String finnishString = "asdäüöö";
byte[] plainEncodedBytes = finnishString.getBytes("ISO-8859-1");
assertThat(HeaderUtil.decodeStringWithCharset(plainEncodedBytes, false, Charset.forName("ISO-8859-1"))).isEqualTo(finnishString);
}
@Test
public void testDecodeStringWithCharsetWithUTF8CharsetAndKoreanChars() {
String koreanString = "가나다";
byte[] plainEncodedBytes = koreanString.getBytes(InternalZipConstants.CHARSET_UTF_8);
assertThat(HeaderUtil.decodeStringWithCharset(plainEncodedBytes, true, null)).isEqualTo(koreanString);
}
@Test
public void testDecodeStringWithCharsetWithNullCharsetAndEnglishChars() {
String englishString = "asdasda234234";
byte[] plainEncodedBytes = englishString.getBytes();
assertThat(HeaderUtil.decodeStringWithCharset(plainEncodedBytes, false, null)).isEqualTo(englishString);
}
private List generateFileHeaderWithFileNames(String fileNamePrefix, int numberOfEntriesToAdd) {
List fileHeaders = new ArrayList<>();
for (int i = 0; i < numberOfEntriesToAdd; i++) {
fileHeaders.add(generateFileHeader(fileNamePrefix + i));
}
fileHeaders.add(generateFileHeader(""));
fileHeaders.add(generateFileHeader(null));
return fileHeaders;
}
private FileHeader generateFileHeader(String fileName) {
FileHeader fileHeader = new FileHeader();
fileHeader.setFileName(fileName);
return fileHeader;
}
private void expectZipException(String message) {
expectedException.expectMessage(message);
expectedException.expect(ZipException.class);
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/headers/HeaderWriterIT.java 0000664 0000000 0000000 00000076551 13576501616 0025637 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.headers;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.CountingOutputStream;
import net.lingala.zip4j.io.outputstream.SplitOutputStream;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.CentralDirectory;
import net.lingala.zip4j.model.DataDescriptor;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.Zip64ExtendedInfo;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.util.BitUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.RawIO;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static net.lingala.zip4j.util.Zip4jUtil.javaToDosTime;
import static org.assertj.core.api.Assertions.assertThat;
public class HeaderWriterIT extends AbstractIT {
private static final String FILE_NAME_PREFIX = "FILE_NAME_";
private static final long COMPRESSED_SIZE = 4234L;
private static final long UNCOMPRESSED_SIZE = 23423L;
private static final long COMPRESSED_SIZE_ZIP64 = InternalZipConstants.ZIP_64_SIZE_LIMIT + 1;
private static final long UNCOMPRESSED_SIZE_ZIP64 = InternalZipConstants.ZIP_64_SIZE_LIMIT + 1;
private static final int VERSION_MADE_BY = 20;
private static final int VERSION_NEEDED_TO_EXTRACT = 20;
private static final long LAST_MODIFIED_FILE_TIME = javaToDosTime(System.currentTimeMillis());
private static final byte[] EXTERNAL_FILE_ATTRIBUTES = new byte[] {23, 43, 0, 0};
private static final String FILE_COMMENT_PREFIX = "FILE_COMMENT_PREFIX_";
@Rule
public ExpectedException expectedException = ExpectedException.none();
private RawIO rawIO = new RawIO();
private HeaderWriter headerWriter = new HeaderWriter();
private HeaderReader headerReader = new HeaderReader();
@Test
public void testWriteLocalFileHeaderSimpleLocalFileHeaderSuccessScenario() throws IOException {
ZipModel zipModel = createZipModel(10);
LocalFileHeader localFileHeaderToWrite = createLocalFileHeader("LFH", COMPRESSED_SIZE, UNCOMPRESSED_SIZE, true);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeaderToWrite, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
verifyLocalFileHeader(readLocalFileHeader, FILE_NAME_PREFIX + "LFH", COMPRESSED_SIZE, UNCOMPRESSED_SIZE);
}
}
@Test
public void testWriteLocalFileHeaderForZip64Format() throws IOException {
ZipModel zipModel = createZipModel(10);
LocalFileHeader localFileHeaderToWrite = createLocalFileHeader("LFH", COMPRESSED_SIZE_ZIP64,
UNCOMPRESSED_SIZE_ZIP64, true);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeaderToWrite, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
verifyLocalFileHeader(readLocalFileHeader, FILE_NAME_PREFIX + "LFH", COMPRESSED_SIZE_ZIP64,
UNCOMPRESSED_SIZE_ZIP64);
verifyZip64ExtendedInfo(readLocalFileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64,
UNCOMPRESSED_SIZE_ZIP64, -1, -1);
}
verifyEntrySizesIsMaxValueInLFHWhenZip64Format(headersFile);
}
@Test
public void testWriteLocalFileHeaderJapaneseCharactersInFileNameAndWithUtf8FlagShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileName("公ゃ的年社", true, true);
}
@Test
public void testWriteLocalFileHeaderEnglishCharactersInFileNameWithoutUtf8ShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileName("SOME_TEXT", false, true);
}
@Test
public void testWriteLocalFileHeaderJapaneseCharactersInFileNameWithoutUtf8ShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileName("公ゃ的年社", false, true);
}
@Test
public void testWriteLocalFileHeaderJapaneseCharactersInFileNameWithCharsetMs932ShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileNameAndCharset("公ゃ的年社", false, true, CHARSET_MS_932);
}
@Test
public void testWriteLocalFileHeaderJapaneseCharactersInFileNameWithUTF8CharsetWithUtf8ShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileNameAndCharset("公ゃ的年社", true, true, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testWriteLocalFileHeaderJapaneseCharactersInFileNameWithUTF8CharsetWithoutUtf8ShouldMatch()
throws IOException {
testWriteLocalFileHeaderWithFileNameAndCharset("公ゃ的年社", false, true, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testWriteLocalFileHeaderWithAes256v1() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_256, AesVersion.ONE);
}
@Test
public void testWriteLocalFileHeaderWithAes192v1() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_192, AesVersion.ONE);
}
@Test
public void testWriteLocalFileHeaderWithAes128v1() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_128, AesVersion.ONE);
}
@Test
public void testWriteLocalFileHeaderWithAes256v2() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_256, AesVersion.TWO);
}
@Test
public void testWriteLocalFileHeaderWithAes192v2() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_192, AesVersion.TWO);
}
@Test
public void testWriteLocalFileHeaderWithAes128v2() throws IOException {
testWriteLocalFileHeaderWithAes(AesKeyStrength.KEY_STRENGTH_128, AesVersion.TWO);
}
@Test
public void testWriteExtendedLocalFileHeaderWhenLocalFileHeaderIsNullThrowsException() throws IOException {
expectedException.expectMessage("input parameters is null, cannot write extended local header");
expectedException.expect(ZipException.class);
headerWriter.writeExtendedLocalHeader(null, new FileOutputStream(temporaryFolder.newFile()));
}
@Test
public void testWriteExtendedLocalFileHeaderWhenOutputStreamIsNullThrowsException() throws IOException {
expectedException.expectMessage("input parameters is null, cannot write extended local header");
expectedException.expect(ZipException.class);
headerWriter.writeExtendedLocalHeader(new LocalFileHeader(), null);
}
@Test
public void testWriteExtendedLocalFileHeaderNonZip64FormatWritesSuccessfully() throws IOException {
testWriteExtendedLocalFileHeader(COMPRESSED_SIZE + 99, UNCOMPRESSED_SIZE + 423, 2342342L, false);
}
@Test
public void testWriteExtendedLocalFileHeaderZip64FormatWritesSuccessfully() throws IOException {
testWriteExtendedLocalFileHeader(COMPRESSED_SIZE_ZIP64 + 99, UNCOMPRESSED_SIZE_ZIP64 + 423, 32452342L, true);
}
@Test
public void testFinalizeZipFileWhenZipModelNullThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters is null, cannot finalize zip file");
headerWriter.finalizeZipFile(null, new FileOutputStream(temporaryFolder.newFile()), InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testFinalizeZipFileWhenOutputStreamIsNullThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters is null, cannot finalize zip file");
headerWriter.finalizeZipFile(new ZipModel(), null, InternalZipConstants.CHARSET_UTF_8);
}
@Test
public void testFinalizeZipFileForNonZip64Format() throws IOException {
ZipModel zipModel = createZipModel(10);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.finalizeZipFile(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10);
for (FileHeader fileHeader : readZipModel.getCentralDirectory().getFileHeaders()) {
assertThat(fileHeader.getZip64ExtendedInfo()).isNull();
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
assertThat(fileHeader.getExtraFieldLength()).isZero();
}
}
}
@Test
public void testFinalizeZipFileForZip64Format() throws IOException {
ZipModel zipModel = createZipModel(10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.finalizeZipFile(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, true);
List fileHeaders = readZipModel.getCentralDirectory().getFileHeaders();
for (FileHeader fileHeader : fileHeaders) {
verifyZip64ExtendedInfo(fileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, 0,
0);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
@Test
public void testFinalizeZipFileForAes() throws IOException {
ZipModel zipModel = createZipModel(10);
setFileHeadersAsAesEncrypted(zipModel.getCentralDirectory().getFileHeaders(), AesKeyStrength.KEY_STRENGTH_192);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.finalizeZipFile(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10);
for (FileHeader fileHeader : readZipModel.getCentralDirectory().getFileHeaders()) {
verifyAesExtraDataRecord(fileHeader.getAesExtraDataRecord(), AesKeyStrength.KEY_STRENGTH_192, AesVersion.TWO);
assertThat(fileHeader.getZip64ExtendedInfo()).isNull();
}
}
}
@Test
public void testFinalizeZipFileForZip64FormatForSplitFileWithSplitOutputStream() throws IOException {
ZipModel zipModel = createZipModel(10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64);
zipModel.setZip64EndOfCentralDirectoryRecord(null);
zipModel.setZip64EndOfCentralDirectoryLocator(null);
File headersFile = temporaryFolder.newFile();
try(SplitOutputStream outputStream = new SplitOutputStream(headersFile, 65536)) {
headerWriter.finalizeZipFile(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, true);
List fileHeaders = readZipModel.getCentralDirectory().getFileHeaders();
for (FileHeader fileHeader : fileHeaders) {
verifyZip64ExtendedInfo(fileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, 0,
0);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
@Test
public void testFinalizeZipFileForZip64FormatForSplitFileWithCountingOutputStream() throws IOException {
ZipModel zipModel = createZipModel(10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64);
File headersFile = temporaryFolder.newFile();
try(CountingOutputStream outputStream = new CountingOutputStream(new SplitOutputStream(headersFile, 65536))) {
headerWriter.finalizeZipFile(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, null);
verifyZipModel(readZipModel, 10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, true);
List fileHeaders = readZipModel.getCentralDirectory().getFileHeaders();
for (FileHeader fileHeader : fileHeaders) {
verifyZip64ExtendedInfo(fileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, 0,
0);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
@Test
public void testFinalizeZipFileWithoutValidationsWhenZipModelNullThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters is null, cannot finalize zip file");
headerWriter.finalizeZipFileWithoutValidations(null, new FileOutputStream(temporaryFolder.newFile()), null);
}
@Test
public void testFinalizeZipFileWithoutValidationsWhenOutputStreamIsNullThrowsException()
throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("input parameters is null, cannot finalize zip file");
headerWriter.finalizeZipFileWithoutValidations(new ZipModel(), null, null);
}
@Test
public void testFinalizeZipFileWithoutValidationsForNonZip64Format() throws IOException {
ZipModel zipModel = createZipModel(10);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.finalizeZipFileWithoutValidations(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, InternalZipConstants.CHARSET_UTF_8);
verifyZipModel(readZipModel, 10);
for (FileHeader fileHeader : readZipModel.getCentralDirectory().getFileHeaders()) {
assertThat(fileHeader.getZip64ExtendedInfo()).isNull();
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
assertThat(fileHeader.getExtraFieldLength()).isZero();
}
}
}
@Test
public void testFinalizeZipFileWithoutValidationsForZip64Format() throws IOException {
ZipModel zipModel = createZipModel(10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.finalizeZipFileWithoutValidations(zipModel, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, InternalZipConstants.CHARSET_UTF_8);
verifyZipModel(readZipModel, 10, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, true);
List fileHeaders = readZipModel.getCentralDirectory().getFileHeaders();
for (FileHeader fileHeader : fileHeaders) {
verifyZip64ExtendedInfo(fileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, 0,
0);
assertThat(fileHeader.getAesExtraDataRecord()).isNull();
}
}
}
@Test
public void testUpdateLocalFileHeaderWhenFileHeaderIsNullThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid input parameters, cannot update local file header");
headerWriter.updateLocalFileHeader(null, new ZipModel(), new SplitOutputStream(temporaryFolder.newFile()));
}
@Test
public void testUpdateLocalFileHeaderWhenZipModelIsNullThrowsException() throws IOException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("invalid input parameters, cannot update local file header");
headerWriter.updateLocalFileHeader(new FileHeader(), null, new SplitOutputStream(temporaryFolder.newFile()));
}
@Test
public void testUpdateLocalFileHeaderForNonZip64() throws IOException {
File headersFile = temporaryFolder.newFile();
createAndUpdateLocalFileHeader(headersFile, COMPRESSED_SIZE, UNCOMPRESSED_SIZE, 23423);
try (InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
assertThat(readLocalFileHeader.getCompressedSize()).isEqualTo(COMPRESSED_SIZE + 100);
assertThat(readLocalFileHeader.getUncompressedSize()).isEqualTo(UNCOMPRESSED_SIZE + 100);
assertThat(readLocalFileHeader.getCrc()).isEqualTo(23423);
assertThat(readLocalFileHeader.getZip64ExtendedInfo()).isNull();
}
}
@Test
public void testUpdateLocalFileHeaderForZip64() throws IOException {
File headersFile = temporaryFolder.newFile();
createAndUpdateLocalFileHeader(headersFile, COMPRESSED_SIZE_ZIP64, UNCOMPRESSED_SIZE_ZIP64, 546423);
try (InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
assertThat(readLocalFileHeader.getCompressedSize()).isEqualTo(COMPRESSED_SIZE_ZIP64 + 100);
assertThat(readLocalFileHeader.getUncompressedSize()).isEqualTo(UNCOMPRESSED_SIZE_ZIP64 + 100);
assertThat(readLocalFileHeader.getCrc()).isEqualTo(546423);
verifyZip64ExtendedInfo(readLocalFileHeader.getZip64ExtendedInfo(), COMPRESSED_SIZE_ZIP64 + 100,
UNCOMPRESSED_SIZE_ZIP64 + 100, -1, -1);
}
verifyEntrySizesIsMaxValueInLFHWhenZip64Format(headersFile);
}
public void createAndUpdateLocalFileHeader(File headersFile, long compressedSize, long uncompressedSize, long crc)
throws IOException {
ZipModel zipModel = createZipModel(3);
LocalFileHeader localFileHeaderToWrite = createLocalFileHeader("LFH", compressedSize, uncompressedSize, false);
localFileHeaderToWrite.setCompressedSize(compressedSize);
localFileHeaderToWrite.setUncompressedSize(uncompressedSize);
localFileHeaderToWrite.setCrc(10);
try (OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeaderToWrite, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try (SplitOutputStream splitOutputStream = new SplitOutputStream(headersFile)) {
FileHeader fileHeader = createFileHeaders(1, compressedSize + 100, uncompressedSize + 100).get(0);
fileHeader.setFileName(localFileHeaderToWrite.getFileName());
fileHeader.setFileNameLength(fileHeader.getFileName().getBytes(InternalZipConstants.CHARSET_UTF_8).length);
fileHeader.setCrc(crc);
headerWriter.updateLocalFileHeader(fileHeader, zipModel, splitOutputStream);
}
}
private void setFileHeadersAsAesEncrypted(List fileHeaders, AesKeyStrength aesKeyStrength) {
for (FileHeader fileHeader : fileHeaders) {
fileHeader.setEncrypted(true);
fileHeader.setEncryptionMethod(EncryptionMethod.AES);
fileHeader.setAesExtraDataRecord(createAesExtraDataRecord(aesKeyStrength, AesVersion.TWO));
}
}
private void verifyZipModel(ZipModel zipModel, int numberOFEntriesInCentralDirectory) {
verifyZipModel(zipModel, numberOFEntriesInCentralDirectory, COMPRESSED_SIZE, UNCOMPRESSED_SIZE, false);
}
private void verifyZipModel(ZipModel zipModel, int numberOFEntriesInCentralDirectory, long compressedSize,
long uncompressedSize, boolean isZip64) {
assertThat(zipModel).isNotNull();
assertThat(zipModel.getCentralDirectory()).isNotNull();
assertThat(zipModel.isZip64Format()).isEqualTo(isZip64);
assertThat(zipModel.getCentralDirectory().getFileHeaders()).hasSize(numberOFEntriesInCentralDirectory);
verifyFileHeaders(zipModel.getCentralDirectory().getFileHeaders(), compressedSize, uncompressedSize);
}
private void verifyFileHeaders(List fileHeaders, long compressedSize, long uncompressedSize) {
for (int i = 0; i < fileHeaders.size(); i++) {
FileHeader fileHeader = fileHeaders.get(i);
assertThat(fileHeader).isNotNull();
assertThat(fileHeader.getVersionMadeBy()).isEqualTo(VERSION_MADE_BY);
assertThat(fileHeader.getVersionNeededToExtract()).isEqualTo(VERSION_NEEDED_TO_EXTRACT);
assertThat(fileHeader.getFileName()).isEqualTo(FILE_NAME_PREFIX + i);
assertThat(fileHeader.getCompressedSize()).isEqualTo(compressedSize);
assertThat(fileHeader.getUncompressedSize()).isEqualTo(uncompressedSize);
assertThat(fileHeader.getFileComment()).isEqualTo(FILE_COMMENT_PREFIX + i);
}
}
private void testWriteExtendedLocalFileHeader(long compressedSize, long uncompressedSize, long crc,
boolean isZip64Format) throws IOException {
LocalFileHeader localFileHeader = createLocalFileHeader("SOME_NAME", compressedSize, uncompressedSize, true);
localFileHeader.setCrc(crc);
localFileHeader.setWriteCompressedSizeInZip64ExtraRecord(isZip64Format);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeExtendedLocalHeader(localFileHeader, outputStream);
}
try(InputStream inputStream = new FileInputStream(headersFile)) {
DataDescriptor dataDescriptor = headerReader.readDataDescriptor(inputStream, isZip64Format);
verifyDataDescriptor(dataDescriptor, compressedSize, uncompressedSize, crc);
}
}
private void verifyDataDescriptor(DataDescriptor dataDescriptor, long compressedSize, long uncompressedSize,
long crc) {
assertThat(dataDescriptor).isNotNull();
assertThat(dataDescriptor.getSignature()).isEqualTo(HeaderSignature.EXTRA_DATA_RECORD);
assertThat(dataDescriptor.getCompressedSize()).isEqualTo(compressedSize);
assertThat(dataDescriptor.getUncompressedSize()).isEqualTo(uncompressedSize);
assertThat(dataDescriptor.getCrc()).isEqualTo(crc);
}
private void testWriteLocalFileHeaderWithAes(AesKeyStrength aesKeyStrength, AesVersion aesVersion)
throws IOException {
ZipModel zipModel = createZipModel(10);
LocalFileHeader localFileHeaderToWrite = createLocalFileHeader("TEXT", COMPRESSED_SIZE, UNCOMPRESSED_SIZE, true);
localFileHeaderToWrite.setEncryptionMethod(EncryptionMethod.AES);
localFileHeaderToWrite.setAesExtraDataRecord(createAesExtraDataRecord(aesKeyStrength, aesVersion));
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeaderToWrite, outputStream, InternalZipConstants.CHARSET_UTF_8);
}
try(InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
assertThat(readLocalFileHeader.getEncryptionMethod()).isEqualTo(EncryptionMethod.AES);
verifyAesExtraDataRecord(readLocalFileHeader.getAesExtraDataRecord(), aesKeyStrength, aesVersion);
}
}
private AESExtraDataRecord createAesExtraDataRecord(AesKeyStrength aesKeyStrength, AesVersion aesVersion) {
AESExtraDataRecord aesDataRecord = new AESExtraDataRecord();
aesDataRecord.setSignature(HeaderSignature.AES_EXTRA_DATA_RECORD);
aesDataRecord.setDataSize(7);
aesDataRecord.setAesVersion(aesVersion);
aesDataRecord.setVendorID("AE");
aesDataRecord.setAesKeyStrength(aesKeyStrength);
aesDataRecord.setCompressionMethod(CompressionMethod.DEFLATE);
return aesDataRecord;
}
private void verifyAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord, AesKeyStrength aesKeyStrength,
AesVersion aesVersion) {
assertThat(aesExtraDataRecord).isNotNull();
assertThat(aesExtraDataRecord.getAesKeyStrength()).isEqualTo(aesKeyStrength);
assertThat(aesExtraDataRecord.getAesVersion()).isEqualTo(aesVersion);
assertThat(aesExtraDataRecord.getCompressionMethod()).isEqualTo(CompressionMethod.DEFLATE);
assertThat(aesExtraDataRecord.getVendorID()).isEqualTo("AE");
}
private void testWriteLocalFileHeaderWithFileName(String fileNameSuffix, boolean useUtf8,
boolean expectFileNamesToMatch) throws IOException {
testWriteLocalFileHeaderWithFileNameAndCharset(fileNameSuffix, useUtf8, expectFileNamesToMatch, InternalZipConstants.CHARSET_UTF_8);
}
private void testWriteLocalFileHeaderWithFileNameAndCharset(String fileNameSuffix, boolean useUtf8,
boolean expectFileNamesToMatch, Charset charset) throws IOException {
ZipModel zipModel = createZipModel(10);
LocalFileHeader localFileHeaderToWrite = createLocalFileHeader(fileNameSuffix, COMPRESSED_SIZE, UNCOMPRESSED_SIZE,
useUtf8);
File headersFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(headersFile)) {
headerWriter.writeLocalFileHeader(zipModel, localFileHeaderToWrite, outputStream, charset);
}
try(InputStream inputStream = new FileInputStream(headersFile)) {
LocalFileHeader readLocalFileHeader = headerReader.readLocalFileHeader(inputStream, charset);
if (expectFileNamesToMatch) {
assertThat(readLocalFileHeader.getFileName()).isEqualTo(FILE_NAME_PREFIX + fileNameSuffix);
} else {
assertThat(readLocalFileHeader.getFileName()).isNotEqualTo(FILE_NAME_PREFIX + fileNameSuffix);
}
}
}
private void verifyEntrySizesIsMaxValueInLFHWhenZip64Format(File headersFile) throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(headersFile, RandomAccessFileMode.READ.getValue())) {
randomAccessFile.seek(18);
long compressedSize = rawIO.readLongLittleEndian(randomAccessFile, 4);
assertThat(compressedSize).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT);
long uncompressedSize = rawIO.readLongLittleEndian(randomAccessFile, 4);
assertThat(uncompressedSize).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT);
}
}
private void verifyLocalFileHeader(LocalFileHeader localFileHeader, String expectedFileName, long compressedSize,
long uncompressedSize) {
assertThat(localFileHeader).isNotNull();
assertThat(localFileHeader.getVersionNeededToExtract()).isEqualTo(VERSION_NEEDED_TO_EXTRACT);
assertThat(localFileHeader.getFileName()).isEqualTo(expectedFileName);
assertThat(localFileHeader.getCompressedSize()).isEqualTo(compressedSize);
assertThat(localFileHeader.getUncompressedSize()).isEqualTo(uncompressedSize);
assertThat(localFileHeader.getCompressionMethod()).isEqualTo(CompressionMethod.DEFLATE);
assertThat(localFileHeader.getLastModifiedTime()).isEqualTo(LAST_MODIFIED_FILE_TIME);
}
private void verifyZip64ExtendedInfo(Zip64ExtendedInfo zip64ExtendedInfo, long compressedSize, long uncompressedSize,
int offsetStartOfLocalFileHeader, int diskNumberStart) {
assertThat(zip64ExtendedInfo).isNotNull();
assertThat(zip64ExtendedInfo.getCompressedSize()).isEqualTo(compressedSize);
assertThat(zip64ExtendedInfo.getUncompressedSize()).isEqualTo(uncompressedSize);
assertThat(zip64ExtendedInfo.getOffsetLocalHeader()).isEqualTo(offsetStartOfLocalFileHeader);
assertThat(zip64ExtendedInfo.getDiskNumberStart()).isEqualTo(diskNumberStart);
}
private LocalFileHeader createLocalFileHeader(String fileNameSuffix, long compressedSize, long uncompressedSize,
boolean useUtf8) {
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setVersionNeededToExtract(VERSION_NEEDED_TO_EXTRACT);
localFileHeader.setFileName(FILE_NAME_PREFIX + fileNameSuffix);
localFileHeader.setCompressedSize(compressedSize);
localFileHeader.setUncompressedSize(uncompressedSize);
localFileHeader.setGeneralPurposeFlag(generateGeneralPurposeBytes(useUtf8));
localFileHeader.setCompressionMethod(CompressionMethod.DEFLATE);
localFileHeader.setLastModifiedTime(LAST_MODIFIED_FILE_TIME);
return localFileHeader;
}
private ZipModel createZipModel(int numberOfEntriesInCentralDirectory) {
return createZipModel(numberOfEntriesInCentralDirectory, COMPRESSED_SIZE, UNCOMPRESSED_SIZE);
}
private ZipModel createZipModel(int numberOfEntriesInCentralDirectory, long compressedSize, long uncompressedSize) {
ZipModel zipModel = new ZipModel();
zipModel.setCentralDirectory(createCentralDirectory(numberOfEntriesInCentralDirectory, compressedSize,
uncompressedSize));
return zipModel;
}
private CentralDirectory createCentralDirectory(int numberOfEntriesInCentralDirectory, long compressedSize,
long uncompressedSize) {
CentralDirectory centralDirectory = new CentralDirectory();
centralDirectory.setFileHeaders(createFileHeaders(numberOfEntriesInCentralDirectory, compressedSize,
uncompressedSize));
return centralDirectory;
}
private byte[] generateGeneralPurposeBytes(boolean useUtf8) {
byte[] generalPurposeBytes = new byte[2];
if (useUtf8) {
generalPurposeBytes[1] = BitUtils.setBit(generalPurposeBytes[1], 3);
}
return generalPurposeBytes;
}
private List createFileHeaders(int numberOfEntriesInCentralDirectory, long compressedSize,
long uncompressedSize) {
List fileHeaders = new ArrayList<>();
for (int i = 0; i < numberOfEntriesInCentralDirectory; i++) {
FileHeader fileHeader = new FileHeader();
fileHeader.setVersionMadeBy(VERSION_MADE_BY);
fileHeader.setVersionNeededToExtract(VERSION_NEEDED_TO_EXTRACT);
fileHeader.setFileName(FILE_NAME_PREFIX + i);
fileHeader.setGeneralPurposeFlag(generateGeneralPurposeBytes(true));
fileHeader.setCompressedSize(compressedSize);
fileHeader.setUncompressedSize(uncompressedSize);
fileHeader.setCompressionMethod(CompressionMethod.DEFLATE);
fileHeader.setExternalFileAttributes(EXTERNAL_FILE_ATTRIBUTES);
fileHeader.setFileComment(FILE_COMMENT_PREFIX + i);
fileHeaders.add(fileHeader);
}
return fileHeaders;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/io/ 0000775 0000000 0000000 00000000000 13576501616 0021130 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/io/inputstream/ 0000775 0000000 0000000 00000000000 13576501616 0023503 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/io/inputstream/ZipInputStreamIT.java 0000664 0000000 0000000 00000027323 13576501616 0027550 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.inputstream;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import static net.lingala.zip4j.testutils.TestUtils.getTestFileFromResources;
import static net.lingala.zip4j.testutils.ZipFileVerifier.verifyFileContent;
import static org.assertj.core.api.Assertions.assertThat;
public class ZipInputStreamIT extends AbstractIT {
@Test
public void testExtractStoreWithoutEncryption() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.STORE);
extractZipFileWithInputStreams(createdZipFile, null);
}
@Test
public void testExtractStoreWithZipStandardEncryption() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.STORE, true, EncryptionMethod.ZIP_STANDARD, null, PASSWORD);
extractZipFileWithInputStreams(createdZipFile, PASSWORD);
}
@Test
public void testExtractStoreWithAesEncryption128() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128, PASSWORD);
extractZipFileWithInputStreams(createdZipFile, PASSWORD);
}
@Test
public void testExtractStoreWithAesEncryption256() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createdZipFile, PASSWORD);
}
@Test
public void testExtractDeflateWithoutEncryption() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.DEFLATE);
extractZipFileWithInputStreams(createdZipFile, null);
}
@Test
public void testExtractDeflateWithAesEncryption128() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128, PASSWORD);
extractZipFileWithInputStreams(createdZipFile, PASSWORD);
}
@Test
public void testExtractDeflateWithAesEncryption256() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createdZipFile, PASSWORD);
}
@Test
public void testExtractDeflateWithAesEncryption256AndV1() throws IOException {
File createdZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD, AesVersion.ONE);
extractZipFileWithInputStreams(createdZipFile, PASSWORD, InternalZipConstants.BUFF_SIZE, AesVersion.ONE);
}
@Test
public void testExtractWithReadLengthLessThan16WithAesAndStoreCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, 15, AesVersion.TWO);
}
@Test
public void testExtractWithReadLengthLessThan16WithAesAndDeflateCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, 15, AesVersion.TWO);
}
@Test
public void testExtractWithReadLengthLessThan16WithZipCryptoAndStoreCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, 12, null);
}
@Test
public void testExtractWithReadLengthLessThan16WithZipCryptoAndDeflateCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, 5, null);
}
@Test
public void testExtractWithReadLengthGreaterThanButNotMultipleOf16WithAesAndStoreCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, (16 * 4) + 1, AesVersion.TWO);
}
@Test
public void testExtractWithReadLengthGreaterThanButNotMultipleOf16WithAesAndDeflateCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, (16 * 8) - 10, AesVersion.TWO);
}
@Test
public void testExtractWithReadLengthGreaterThanButNotMultipleOf16WithZipCryptoAndStoreCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, (16 * 2) - 6, null);
}
@Test
public void testExtractWithReadLengthGreaterThanButNotMultipleOf16WithZipCryptoAndDeflateCompression() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, PASSWORD);
extractZipFileWithInputStreams(createZipFile, PASSWORD, (16 * 10) - 11, null);
}
@Test
public void testExtractWithRandomLengthWithAesAndDeflateCompression() throws IOException {
Random random = new Random();
File createZipFile = createZipFile(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, PASSWORD);
LocalFileHeader localFileHeader;
int readLen;
byte[] readBuffer = new byte[4096];
int numberOfEntriesExtracted = 0;
try (FileInputStream fileInputStream = new FileInputStream(createZipFile)) {
try (ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, PASSWORD)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
File extractedFile = temporaryFolder.newFile(localFileHeader.getFileName());
try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
while ((readLen = zipInputStream.read(readBuffer, 0, random.nextInt((25 - 1) + 1) + 1)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
verifyFileContent(getTestFileFromResources(localFileHeader.getFileName()), extractedFile);
numberOfEntriesExtracted++;
}
}
}
assertThat(numberOfEntriesExtracted).isEqualTo(FILES_TO_ADD.size());
}
@Test
public void testExtractFilesForZipFileWithInvalidExtraDataRecordIgnoresIt() throws IOException {
InputStream inputStream = new FileInputStream(getTestArchiveFromResources("invalid_extra_data_record.zip"));
ZipInputStream zipInputStream = new ZipInputStream(inputStream, "password".toCharArray());
byte[] b = new byte[4096];
while (zipInputStream.getNextEntry() != null) {
while (zipInputStream.read(b) != -1) {
}
}
zipInputStream.close();
}
@Test
public void testGetNextEntryReturnsNextEntryEvenIfEntryNotCompletelyRead() throws IOException {
File createZipFile = createZipFile(CompressionMethod.DEFLATE);
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(createZipFile));
int numberOfEntries = 0;
while (zipInputStream.getNextEntry() != null) {
numberOfEntries++;
}
assertThat(numberOfEntries).isEqualTo(FILES_TO_ADD.size());
}
@Test
public void testGetFileNamesWithChineseCharset() throws IOException {
InputStream inputStream = new FileInputStream(getTestArchiveFromResources("testfile_with_chinese_filename_by_7zip.zip"));
ZipInputStream zipInputStream = new ZipInputStream(inputStream, CHARSET_GBK);
LocalFileHeader localFileHeader;
String expactedFileName = "fff - 副本.txt";
Set filenameSet = new HashSet<>();
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
filenameSet.add(localFileHeader.getFileName());
}
assertThat(filenameSet.contains(expactedFileName)).isTrue();
}
private void extractZipFileWithInputStreams(File zipFile, char[] password) throws IOException {
extractZipFileWithInputStreams(zipFile, password, 4096, AesVersion.TWO);
}
private void extractZipFileWithInputStreams(File zipFile, char[] password, int bufferLength, AesVersion aesVersion)
throws IOException {
LocalFileHeader localFileHeader;
int readLen;
byte[] readBuffer = new byte[bufferLength];
int numberOfEntriesExtracted = 0;
try (FileInputStream fileInputStream = new FileInputStream(zipFile)) {
try (ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, password)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
File extractedFile = temporaryFolder.newFile(localFileHeader.getFileName());
try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
verifyLocalFileHeader(localFileHeader);
verifyFileContent(getTestFileFromResources(localFileHeader.getFileName()), extractedFile);
numberOfEntriesExtracted++;
}
}
}
assertThat(numberOfEntriesExtracted).isEqualTo(FILES_TO_ADD.size());
}
private void verifyLocalFileHeader(LocalFileHeader localFileHeader) {
assertThat(localFileHeader).isNotNull();
if (localFileHeader.isEncrypted()
&& localFileHeader.getEncryptionMethod().equals(EncryptionMethod.AES)
&& localFileHeader.getAesExtraDataRecord().getAesVersion().equals(AesVersion.TWO)) {
assertThat(localFileHeader.getCrc()).isZero();
}
}
private File createZipFile(CompressionMethod compressionMethod) throws IOException {
return createZipFile(compressionMethod, false, null, null, null);
}
private File createZipFile(CompressionMethod compressionMethod, boolean encryptFiles,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength, char[] password)
throws IOException {
return createZipFile(compressionMethod, encryptFiles, encryptionMethod, aesKeyStrength, password, AesVersion.TWO);
}
private File createZipFile(CompressionMethod compressionMethod, boolean encryptFiles,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength, char[] password,
AesVersion aesVersion)
throws IOException {
File outputFile = temporaryFolder.newFile("output.zip");
deleteFileIfExists(outputFile);
ZipFile zipFile = new ZipFile(outputFile, password);
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(compressionMethod);
zipParameters.setEncryptFiles(encryptFiles);
zipParameters.setEncryptionMethod(encryptionMethod);
zipParameters.setAesKeyStrength(aesKeyStrength);
zipParameters.setAesVersion(aesVersion);
zipFile.addFiles(AbstractIT.FILES_TO_ADD, zipParameters);
return outputFile;
}
private void deleteFileIfExists(File file) {
if (file.exists()) {
if (!file.delete()) {
throw new RuntimeException("Could not delete an existing zip file");
}
}
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/io/outputstream/ 0000775 0000000 0000000 00000000000 13576501616 0023704 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/io/outputstream/ZipOutputStreamIT.java 0000664 0000000 0000000 00000020671 13576501616 0030151 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.io.outputstream;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.AesVersion;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.BitUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static net.lingala.zip4j.testutils.TestUtils.getTestFileFromResources;
import static net.lingala.zip4j.testutils.ZipFileVerifier.verifyZipFileByExtractingAllFiles;
import static org.assertj.core.api.Assertions.assertThat;
public class ZipOutputStreamIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testZipOutputStreamStoreWithoutEncryption() throws IOException {
testZipOutputStream(CompressionMethod.STORE, false, null, null, null);
}
@Test
public void testZipOutputStreamStoreWithStandardEncryption() throws IOException {
testZipOutputStream(CompressionMethod.STORE, true, EncryptionMethod.ZIP_STANDARD, null, null);
}
@Test
public void testZipOutputStreamStoreWithAES256V1() throws IOException {
testZipOutputStream(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, AesVersion.ONE);
}
@Test
public void testZipOutputStreamStoreWithAES128V2() throws IOException {
testZipOutputStream(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128, AesVersion.TWO);
}
@Test
public void testZipOutputStreamStoreWithAES256V2() throws IOException {
testZipOutputStream(CompressionMethod.STORE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, AesVersion.TWO);
}
@Test
public void testZipOutputStreamDeflateWithoutEncryption() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, false, null, null, null);
}
@Test
public void testZipOutputStreamDeflateWithoutEncryptionAndKoreanFilename() throws IOException {
List filesToAdd = new ArrayList<>();
filesToAdd.add(getTestFileFromResources("가나다.abc"));
testZipOutputStream(CompressionMethod.DEFLATE, false, null, null, null, true,
filesToAdd, CHARSET_CP_949);
}
@Test
public void testZipOutputStreamDeflateWithStandardEncryption() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, null);
}
@Test
public void testZipOutputStreamDeflateWithStandardEncryptionWhenModifiedFileTimeNotSet()
throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.ZIP_STANDARD, null, null, false);
}
@Test
public void testZipOutputStreamDeflateWithAES128V1() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128, AesVersion.ONE);
}
@Test
public void testZipOutputStreamDeflateWithAES128() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_128, AesVersion.TWO);
}
@Test
public void testZipOutputStreamDeflateWithAES256() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, AesVersion.TWO);
}
@Test
public void testZipOutputStreamDeflateWithNullVersionUsesV2() throws IOException {
testZipOutputStream(CompressionMethod.DEFLATE, true, EncryptionMethod.AES, AesKeyStrength.KEY_STRENGTH_256, null);
}
@Test
public void testZipOutputStreamThrowsExceptionWhenEntrySizeNotSetForStoreCompression() throws IOException {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("uncompressed size should be set for zip entries of compression type store");
try(ZipOutputStream zos = initializeZipOutputStream(false, InternalZipConstants.CHARSET_UTF_8)) {
for (File fileToAdd : FILES_TO_ADD) {
zipParameters.setLastModifiedFileTime(fileToAdd.lastModified());
zipParameters.setFileNameInZip(fileToAdd.getName());
zos.putNextEntry(zipParameters);
}
}
}
private void testZipOutputStream(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength,
AesVersion aesVersion)
throws IOException {
testZipOutputStream(compressionMethod, encrypt, encryptionMethod, aesKeyStrength, aesVersion, true);
}
private void testZipOutputStream(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength,
AesVersion aesVersion, boolean setLastModifiedTime)
throws IOException {
testZipOutputStream(compressionMethod, encrypt, encryptionMethod, aesKeyStrength, aesVersion, true, FILES_TO_ADD, InternalZipConstants.CHARSET_UTF_8);
}
private void testZipOutputStream(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength,
AesVersion aesVersion, boolean setLastModifiedTime, List filesToAdd, Charset charset)
throws IOException {
ZipParameters zipParameters = buildZipParameters(compressionMethod, encrypt, encryptionMethod, aesKeyStrength);
zipParameters.setAesVersion(aesVersion);
byte[] buff = new byte[4096];
int readLen;
try(ZipOutputStream zos = initializeZipOutputStream(encrypt, charset)) {
for (File fileToAdd : filesToAdd) {
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
zipParameters.setEntrySize(fileToAdd.length());
}
if (setLastModifiedTime) {
zipParameters.setLastModifiedFileTime(fileToAdd.lastModified());
}
zipParameters.setFileNameInZip(fileToAdd.getName());
zos.putNextEntry(zipParameters);
try(InputStream inputStream = new FileInputStream(fileToAdd)) {
while ((readLen = inputStream.read(buff)) != -1) {
zos.write(buff, 0, readLen);
}
}
zos.closeEntry();
}
}
verifyZipFileByExtractingAllFiles(generatedZipFile, PASSWORD, outputFolder, filesToAdd.size(), true, charset);
verifyEntries();
}
private void verifyEntries() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile);
for (FileHeader fileHeader : zipFile.getFileHeaders()) {
byte[] generalPurposeBytes = fileHeader.getGeneralPurposeFlag();
assertThat(BitUtils.isBitSet(generalPurposeBytes[0], 3)).isTrue();
if (fileHeader.isEncrypted()
&& fileHeader.getEncryptionMethod().equals(EncryptionMethod.AES)) {
if (fileHeader.getAesExtraDataRecord().getAesVersion().equals(AesVersion.TWO)) {
assertThat(fileHeader.getCrc()).isZero();
} else if (fileHeader.getCompressedSize() > 0) {
assertThat(fileHeader.getCrc()).isNotZero();
}
}
}
}
private ZipOutputStream initializeZipOutputStream(boolean encrypt, Charset charset) throws IOException {
FileOutputStream fos = new FileOutputStream(generatedZipFile);
if (encrypt) {
return new ZipOutputStream(fos, PASSWORD, charset);
}
return new ZipOutputStream(fos, null, charset);
}
private ZipParameters buildZipParameters(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(compressionMethod);
zipParameters.setEncryptionMethod(encryptionMethod);
zipParameters.setAesKeyStrength(aesKeyStrength);
zipParameters.setEncryptFiles(encrypt);
return zipParameters;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/model/ 0000775 0000000 0000000 00000000000 13576501616 0021621 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/model/enums/ 0000775 0000000 0000000 00000000000 13576501616 0022750 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/model/enums/CompressionMethodTest.java 0000664 0000000 0000000 00000001441 13576501616 0030115 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.model.enums;
import net.lingala.zip4j.exception.ZipException;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class CompressionMethodTest {
@Test
public void testGetCompressionMethodFromCodeForUnknownTypeThrowsException() {
try {
CompressionMethod.getCompressionMethodFromCode(34);
fail("Should throw an exception");
} catch (ZipException e) {
assertThat(e.getType()).isEqualTo(ZipException.Type.UNKNOWN_COMPRESSION_METHOD);
}
}
@Test
public void testGetCompressionMethodFromCodeForDeflateReturnsDeflate() throws ZipException {
assertThat(CompressionMethod.getCompressionMethodFromCode(8)).isEqualTo(CompressionMethod.DEFLATE);
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/ 0000775 0000000 0000000 00000000000 13576501616 0022561 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/ControlledReadInputStream.java 0000664 0000000 0000000 00000001636 13576501616 0030527 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
import java.io.IOException;
import java.io.InputStream;
public class ControlledReadInputStream extends InputStream {
private InputStream inputStream;
private int readLimit;
private byte[] singleByteBuffer = new byte[1];
public ControlledReadInputStream(InputStream inputStream, int maximumNumberOfBytesToReadAtOnce) {
this.inputStream = inputStream;
this.readLimit = maximumNumberOfBytesToReadAtOnce;
}
@Override
public int read() throws IOException {
int readLen = read(singleByteBuffer);
if (readLen == -1) {
return -1;
}
return singleByteBuffer[0];
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int toRead = len > readLimit ? readLimit : len;
return inputStream.read(b, off, toRead);
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/HeaderVerifier.java 0000664 0000000 0000000 00000004020 13576501616 0026304 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.headers.HeaderReader;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.assertj.core.api.Assertions.assertThat;
public class HeaderVerifier {
HeaderReader headerReader = new HeaderReader();
public void verifyLocalFileHeaderUncompressedSize(File generatedZipFile, String fileNameInZipToVerify,
long expectedUncompressedSize) throws IOException {
LocalFileHeader localFileHeader = getLocalFileHeaderForEntry(generatedZipFile, fileNameInZipToVerify);
assertThat(localFileHeader.getUncompressedSize()).isEqualTo(expectedUncompressedSize);
}
private LocalFileHeader getLocalFileHeaderForEntry(File generatedZipFile, String fileNameInZipToVerify)
throws IOException {
InputStream inputStream = positionRandomAccessFileToLocalFileHeaderStart(generatedZipFile,
fileNameInZipToVerify);
return headerReader.readLocalFileHeader(inputStream, InternalZipConstants.CHARSET_UTF_8);
}
private InputStream positionRandomAccessFileToLocalFileHeaderStart(File generatedZipFile, String fileNameInZip)
throws IOException{
ZipFile zipFile = new ZipFile(generatedZipFile);
FileHeader fileHeader = zipFile.getFileHeader(fileNameInZip);
if (fileHeader == null) {
throw new RuntimeException("Cannot find an entry with name: " + fileNameInZip + " in zip file: "
+ generatedZipFile);
}
InputStream inputStream = new FileInputStream(generatedZipFile);
if (inputStream.skip(fileHeader.getOffsetLocalHeader()) != fileHeader.getOffsetLocalHeader()) {
throw new IOException("Cannot skip " + fileHeader.getOffsetLocalHeader() + " bytes for entry "
+ fileHeader.getFileName());
}
return inputStream;
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/RandomInputStream.java 0000664 0000000 0000000 00000002251 13576501616 0027040 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
public class RandomInputStream extends InputStream {
private static final Random RANDOM = new Random();
private long remaining;
private boolean streamClosed;
public RandomInputStream(long length) {
this.remaining = length;
this.streamClosed = false;
}
@Override
public int read() throws IOException {
if (remaining <= 0) {
return -1;
}
assertStreamNotClosed();
return RANDOM.nextInt(127);
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (remaining <= 0) {
return -1;
}
assertStreamNotClosed();
int toRead = len;
if (remaining <= len) {
toRead = (int) remaining;
}
RANDOM.nextBytes(b);
remaining -= toRead;
return toRead;
}
private void assertStreamNotClosed() throws IOException {
if (streamClosed) {
throw new IOException("Stream closed");
}
}
@Override
public void close() {
streamClosed = true;
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/SlowTests.java 0000664 0000000 0000000 00000000105 13576501616 0025367 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
public interface SlowTests {
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/TestUtils.java 0000664 0000000 0000000 00000002301 13576501616 0025360 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class TestUtils {
private static final String TEST_FILES_FOLDER_NAME = "test-files";
private static final String TEST_ARCHIVES_FOLDER_NAME = "test-archives";
public static File getTestFileFromResources(String fileName) {
return getFileFromResources(TEST_FILES_FOLDER_NAME, fileName);
}
public static File getTestArchiveFromResources(String fileName) {
return getFileFromResources(TEST_ARCHIVES_FOLDER_NAME, fileName);
}
public static Boolean isWindows() {
String os = System.getProperty("os.name").toLowerCase();
return (os.contains("win"));
}
private static File getFileFromResources(String parentFolder, String fileName) {
try {
String path = "/" + parentFolder + "/" + fileName;
String utfDecodedFilePath = URLDecoder.decode(TestUtils.class.getResource(path).getFile(),
InternalZipConstants.CHARSET_UTF_8.toString());
return new File(utfDecodedFilePath);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/testutils/ZipFileVerifier.java 0000664 0000000 0000000 00000006507 13576501616 0026472 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.testutils;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.util.CrcUtil;
import net.lingala.zip4j.util.FileUtils;
import net.lingala.zip4j.util.InternalZipConstants;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class ZipFileVerifier {
public static void verifyZipFileByExtractingAllFiles(File zipFileToExtract, File outputFolder,
int expectedNumberOfEntries) throws IOException {
verifyZipFileByExtractingAllFiles(zipFileToExtract, null, outputFolder, expectedNumberOfEntries);
}
public static void verifyZipFileByExtractingAllFiles(File zipFileToExtract, char[] password, File outputFolder,
int expectedNumberOfEntries) throws IOException {
verifyZipFileByExtractingAllFiles(zipFileToExtract, password, outputFolder, expectedNumberOfEntries, true);
}
public static void verifyZipFileByExtractingAllFiles(File zipFileToExtract, char[] password, File outputFolder,
int expectedNumberOfEntries, boolean verifyFileContents)
throws IOException {
verifyZipFileByExtractingAllFiles(zipFileToExtract, password, outputFolder, expectedNumberOfEntries, verifyFileContents, InternalZipConstants.CHARSET_UTF_8);
}
public static void verifyZipFileByExtractingAllFiles(File zipFileToExtract, char[] password, File outputFolder,
int expectedNumberOfEntries, boolean verifyFileContents, Charset charset)
throws IOException {
assertThat(zipFileToExtract).isNotNull();
assertThat(zipFileToExtract).exists();
ZipFile zipFile = new ZipFile(zipFileToExtract, password);
zipFile.setCharset(charset);
zipFile.extractAll(outputFolder.getPath());
assertThat(zipFile.getFileHeaders().size()).as("Number of file headers").isEqualTo(expectedNumberOfEntries);
List extractedFiles = FileUtils.getFilesInDirectoryRecursive(outputFolder, true, true);
assertThat(extractedFiles).hasSize(expectedNumberOfEntries);
if (verifyFileContents) {
verifyFolderContentsSameAsSourceFiles(outputFolder);
}
}
public static void verifyFileContent(File sourceFile, File extractedFile) throws IOException {
assertThat(extractedFile.length()).isEqualTo(sourceFile.length());
verifyFileCrc(sourceFile, extractedFile);
}
public static void verifyFolderContentsSameAsSourceFiles(File outputFolder) throws IOException {
File[] filesInOutputFolder = outputFolder.listFiles();
for (File file : filesInOutputFolder) {
if (file.isDirectory()) {
continue;
}
File sourceFile = TestUtils.getTestFileFromResources(file.getName());
verifyFileContent(sourceFile, file);
}
}
private static void verifyFileCrc(File sourceFile, File extractedFile) throws IOException {
ProgressMonitor progressMonitor = new ProgressMonitor();
long sourceFileCrc = CrcUtil.computeFileCrc(sourceFile, progressMonitor);
long extractedFileCrc = CrcUtil.computeFileCrc(extractedFile, progressMonitor);
assertThat(sourceFileCrc).isEqualTo(extractedFileCrc);
}
}
zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/ 0000775 0000000 0000000 00000000000 13576501616 0021476 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/BitUtilsTest.java 0000664 0000000 0000000 00000002663 13576501616 0024747 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class BitUtilsTest {
@Test
public void testIsBitSet() {
byte b = 0;
b = (byte) (b | 1);
b = (byte) (b | 1 << 3);
b = (byte) (b | 1 << 7);
assertThat(BitUtils.isBitSet(b, 0)).isTrue();
assertThat(BitUtils.isBitSet(b, 3)).isTrue();
assertThat(BitUtils.isBitSet(b, 7)).isTrue();
assertThat(BitUtils.isBitSet(b, 1)).isFalse();
assertThat(BitUtils.isBitSet(b, 2)).isFalse();
assertThat(BitUtils.isBitSet(b, 4)).isFalse();
assertThat(BitUtils.isBitSet(b, 5)).isFalse();
assertThat(BitUtils.isBitSet(b, 6)).isFalse();
}
@Test
public void testSetBit() {
byte b = 0;
b = BitUtils.setBit(b, 2);
b = BitUtils.setBit(b, 5);
b = BitUtils.setBit(b, 6);
assertThat((b & (1L << 2))).isNotZero();
assertThat((b & (1L << 5))).isNotZero();
assertThat((b & (1L << 6))).isNotZero();
assertThat((b & (1L))).isEqualTo(0);
assertThat((b & (1L << 1))).isEqualTo(0);
assertThat((b & (1L << 3))).isEqualTo(0);
assertThat((b & (1L << 4))).isEqualTo(0);
assertThat((b & (1L << 7))).isEqualTo(0);
}
@Test
public void unsetBit() {
byte b = 0;
b = (byte) (b | 1 << 3);
b = (byte) (b | 1 << 7);
b = BitUtils.unsetBit(b, 3);
assertThat(BitUtils.isBitSet(b, 3)).isFalse();
assertThat(BitUtils.isBitSet(b, 7)).isTrue();
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/CrcUtilIT.java 0000664 0000000 0000000 00000005610 13576501616 0024145 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.progress.ProgressMonitor;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
import static net.lingala.zip4j.testutils.TestUtils.getTestFileFromResources;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class CrcUtilIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private ProgressMonitor progressMonitor = new ProgressMonitor();
@Test
public void testComputeFileCrcThrowsExceptionWhenFileIsNull() throws IOException {
expectedException.expectMessage("input file is null or does not exist or cannot read. " +
"Cannot calculate CRC for the file");
expectedException.expect(ZipException.class);
CrcUtil.computeFileCrc(null, progressMonitor);
}
@Test
public void testComputeFileCrcThrowsExceptionWhenCannotReadFile() throws IOException {
expectedException.expectMessage("input file is null or does not exist or cannot read. " +
"Cannot calculate CRC for the file");
expectedException.expect(ZipException.class);
File unreadableFile = mock(File.class);
when(unreadableFile.exists()).thenReturn(true);
when(unreadableFile.canRead()).thenReturn(false);
CrcUtil.computeFileCrc(unreadableFile, progressMonitor);
}
@Test
public void testComputeFileCrcThrowsExceptionWhenFileDoesNotExist() throws IOException {
expectedException.expectMessage("input file is null or does not exist or cannot read. " +
"Cannot calculate CRC for the file");
expectedException.expect(ZipException.class);
CrcUtil.computeFileCrc(new File("DoesNotExist"), progressMonitor);
}
@Test
public void testComputeFileCrcGetsValueSuccessfully() throws IOException {
testComputeFileCrcForFile(getTestFileFromResources("sample.pdf"));
testComputeFileCrcForFile(getTestFileFromResources("sample_text1.txt"));
testComputeFileCrcForFile(getTestFileFromResources("sample_text_large.txt"));
}
private void testComputeFileCrcForFile(File file) throws IOException {
long actualFileCrc = calculateFileCrc(file);
assertThat(CrcUtil.computeFileCrc(file, progressMonitor)).isEqualTo(actualFileCrc);
}
private long calculateFileCrc(File file) throws IOException {
try(InputStream inputStream = new FileInputStream(file)) {
byte[] buffer = new byte[InternalZipConstants.BUFF_SIZE];
int readLen = -1;
CRC32 crc32 = new CRC32();
while((readLen = inputStream.read(buffer)) != -1) {
crc32.update(buffer, 0, readLen);
}
return crc32.getValue();
}
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/FileUtilsIT.java 0000664 0000000 0000000 00000006730 13576501616 0024504 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.testutils.TestUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import static org.assertj.core.api.Assertions.assertThat;
public class FileUtilsIT extends AbstractIT {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private ProgressMonitor progressMonitor = new ProgressMonitor();
@Test
public void testCopyFileThrowsExceptionWhenStartsIsLessThanZero() throws IOException, ZipException {
testInvalidOffsetsScenario(-1, 100);
}
@Test
public void testCopyFileThrowsExceptionWhenEndIsLessThanZero() throws IOException, ZipException {
testInvalidOffsetsScenario(0, -1);
}
@Test
public void testCopyFileThrowsExceptionWhenStartIsGreaterThanEnd() throws IOException, ZipException {
testInvalidOffsetsScenario(300, 100);
}
@Test
public void testCopyFilesWhenStartIsSameAsEndDoesNothing() throws IOException, ZipException {
File sourceFile = TestUtils.getTestFileFromResources("sample.pdf");
File outputFile = temporaryFolder.newFile();
try(RandomAccessFile randomAccessFile = new RandomAccessFile(sourceFile, RandomAccessFileMode.READ.getValue());
OutputStream outputStream = new FileOutputStream(outputFile)) {
FileUtils.copyFile(randomAccessFile, outputStream, 100, 100, progressMonitor);
}
assertThat(outputFile.exists()).isTrue();
assertThat(outputFile.length()).isZero();
}
@Test
public void testCopyFilesCopiesCompleteFile() throws IOException, ZipException {
File sourceFile = TestUtils.getTestFileFromResources("sample.pdf");
File outputFile = temporaryFolder.newFile();
try(RandomAccessFile randomAccessFile = new RandomAccessFile(sourceFile, RandomAccessFileMode.READ.getValue());
OutputStream outputStream = new FileOutputStream(outputFile)) {
FileUtils.copyFile(randomAccessFile, outputStream, 0, sourceFile.length(), progressMonitor);
}
assertThat(outputFile.length()).isEqualTo(sourceFile.length());
}
@Test
public void testCopyFilesCopiesPartOfFile() throws IOException, ZipException {
File sourceFile = TestUtils.getTestFileFromResources("sample.pdf");
File outputFile = temporaryFolder.newFile();
try(RandomAccessFile randomAccessFile = new RandomAccessFile(sourceFile, RandomAccessFileMode.READ.getValue());
OutputStream outputStream = new FileOutputStream(outputFile)) {
FileUtils.copyFile(randomAccessFile, outputStream, 500, 800, progressMonitor);
}
assertThat(outputFile.length()).isEqualTo(300);
}
private void testInvalidOffsetsScenario(int start, int offset) throws IOException, ZipException {
expectedException.expectMessage("invalid offsets");
expectedException.expect(ZipException.class);
File sourceFile = TestUtils.getTestFileFromResources("sample.pdf");
try(RandomAccessFile randomAccessFile = new RandomAccessFile(sourceFile, RandomAccessFileMode.READ.getValue());
OutputStream outputStream = new FileOutputStream(temporaryFolder.newFile())) {
FileUtils.copyFile(randomAccessFile, outputStream, start, offset, progressMonitor);
}
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/FileUtilsTest.java 0000664 0000000 0000000 00000031433 13576501616 0025105 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipModel;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.nio.file.spi.FileSystemProvider;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class FileUtilsTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testLastModifiedFileTimeWhenTimeIsLessThanZeroDoesNothing() {
FileUtils.setFileLastModifiedTime(mock(Path.class), -1);
}
@Test
public void testLastModifiedFileTimeWhenTimeIEqualToZeroDoesNothing() {
FileUtils.setFileLastModifiedTime(mock(Path.class), 0);
}
@Test
public void testLastModifiedFileTimeWhenFileDoesNotExistDoesNothing() throws IOException {
Path path = mock(Path.class);
FileSystemProvider fileSystemProvider = mockPath(path);
doThrow(new IOException("Some exception")).when(fileSystemProvider).checkAccess(path);
FileUtils.setFileLastModifiedTime(path, 1);
}
@Test
public void testLastModifiedFileTimeForValidTimeSetsTime() throws IOException {
Path path = mock(Path.class);
FileSystemProvider fileSystemProvider = mockPath(path);
BasicFileAttributeView basicFileAttributeView = mock(BasicFileAttributeView.class);
when(fileSystemProvider.getFileAttributeView(path, BasicFileAttributeView.class))
.thenReturn(basicFileAttributeView);
long currentTime = System.currentTimeMillis();
FileUtils.setFileLastModifiedTime(path, currentTime);
verify(basicFileAttributeView).setTimes(FileTime.fromMillis(Zip4jUtil.dosToJavaTme(currentTime)), null, null);
}
@Test
public void testLastModifiedFileTimeWhenIOExceptionDoesNothing() {
Path path = mock(Path.class);
FileSystemProvider fileSystemProvider = mockPath(path);
when(fileSystemProvider.getFileAttributeView(path, BasicFileAttributeView.class))
.thenThrow(new RuntimeException());
long currentTime = System.currentTimeMillis();
FileUtils.setFileLastModifiedTime(path, currentTime);
}
@Test
public void testLastModifiedFileTimeWithoutNIOSetsSuccessfully() {
File file = mock(File.class);
long currentTime = System.currentTimeMillis();
FileUtils.setFileLastModifiedTimeWithoutNio(file, currentTime);
verify(file).setLastModified(Zip4jUtil.dosToJavaTme(currentTime));
}
@Test
public void testGetFileAttributesReturnsEmptyBytesWhenNIONotSupported() {
File file = mock(File.class);
when(file.toPath()).thenThrow(new NoSuchMethodError("No method"));
byte[] fileAttributes = FileUtils.getFileAttributes(file);
assertThat(fileAttributes).hasSize(4);
assertThat(fileAttributes).contains(0, 0, 0, 0);
}
@Test
public void testGetFilesInDirectoryRecursiveThrowsExceptionWhenFileIsNull() throws ZipException {
expectedException.expectMessage("input path is null, cannot read files in the directory");
expectedException.expect(ZipException.class);
FileUtils.getFilesInDirectoryRecursive(null, true, true);
}
@Test
public void testGetFilesInDirectoryRecursiveReturnsEmptyWhenInputFileIsNotDirectory() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(false, true, filesInDirectory, 0, true, true);
}
@Test
public void testGetFilesInDirectoryRecursiveReturnsEmptyWhenCannotReadInputFile() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(true, false, filesInDirectory, 0, true, true);
}
@Test
public void testGetFilesInDirectoryRecursiveReturnsEmptyWhenFilesInDirIsNull() throws ZipException {
testGetFilesInDirectory(true, true, null, 0, true, true);
}
@Test
public void testGetFilesInDirectoryRecursiveWithHiddenModeOnListsHiddenFiles() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(true, true, filesInDirectory, 6, true, true);
}
@Test
public void testGetFilesInDirectoryRecursiveWithHiddenModeOffDoesNotListsHiddenFiles() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(true, true, filesInDirectory, 5, false, true);
}
@Test
public void testGetFilesInDirectoryRecursiveWithHiddenModeOffDoesNotListsHiddenFolders() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(true, true, filesInDirectory, 4, true, false);
}
@Test
public void testGetFilesInDirectoryRecursiveWithHiddenModeOffForFilesAndFolders() throws ZipException {
File[] filesInDirectory = generateFilesForDirectory();
testGetFilesInDirectory(true, true, filesInDirectory, 3, false, false);
}
@Test
public void testGetZipFileNameWithoutExtensionThrowsExceptionWhenNull() throws ZipException {
expectedException.expectMessage("zip file name is empty or null, cannot determine zip file name");
expectedException.expect(ZipException.class);
FileUtils.getZipFileNameWithoutExtension(null);
}
@Test
public void testGetZipFileNameWithoutExtensionThrowsExceptionWhenEmpty() throws ZipException {
expectedException.expectMessage("zip file name is empty or null, cannot determine zip file name");
expectedException.expect(ZipException.class);
FileUtils.getZipFileNameWithoutExtension("");
}
@Test
public void testGetZipFileNameWithoutExtensionForWindowsFileSeparator() throws ZipException {
final String ACTUAL_FILE_SEPARATOR = System.getProperty("file.separator");
System.setProperty("file.separator", "\\");
assertThat(FileUtils.getZipFileNameWithoutExtension("c:\\mydir\\somefile.zip")).isEqualTo("somefile");
System.setProperty("file.separator", ACTUAL_FILE_SEPARATOR);
}
@Test
public void testGetZipFileNameWithoutExtensionForUnixFileSeparator() throws ZipException {
final String ACTUAL_FILE_SEPARATOR = System.getProperty("file.separator");
System.setProperty("file.separator", "/");
assertThat(FileUtils.getZipFileNameWithoutExtension("/usr/srikanth/somezip.zip")).isEqualTo("somezip");
System.setProperty("file.separator", ACTUAL_FILE_SEPARATOR);
}
@Test
public void testGetSplitZipFilesThrowsExceptionWhenZipModelIsNull() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("cannot get split zip files: zipmodel is null");
FileUtils.getSplitZipFiles(null);
}
@Test
public void testGetSplitZipFilesReturnsNullWhenEndOfCentralDirectoryIsNull() throws ZipException {
ZipModel zipModel = new ZipModel();
zipModel.setEndOfCentralDirectoryRecord(null);
assertThat(FileUtils.getSplitZipFiles(zipModel)).isNull();
}
@Test
public void testGetSplitZipFilesThrowsExceptionWhenZipFileDoesNotExits() throws ZipException {
expectedException.expect(ZipException.class);
expectedException.expectMessage("zip file does not exist");
ZipModel zipModel = new ZipModel();
zipModel.setZipFile(new File("Does not exist"));
FileUtils.getSplitZipFiles(zipModel);
}
@Test
public void testGetSplitZipFilesForNonSplitArchiveReturnsSameFile() throws ZipException {
File zipFile = mockZipFileAsExists("somepath", "somefile");
ZipModel zipModel = new ZipModel();
zipModel.setSplitArchive(false);
zipModel.setZipFile(zipFile);
List splitFiles = FileUtils.getSplitZipFiles(zipModel);
assertThat(splitFiles).hasSize(1);
assertThat(splitFiles.get(0)).isSameAs(zipFile);
}
@Test
public void testGetSplitZipFilesWhenNumberOfDiskIsZeroReturnsSameFile() throws ZipException {
File zipFile = mockZipFileAsExists("somepath", "somefile");
ZipModel zipModel = new ZipModel();
zipModel.setSplitArchive(false);
zipModel.setZipFile(zipFile);
zipModel.getEndOfCentralDirectoryRecord().setNumberOfThisDisk(0);
List splitFiles = FileUtils.getSplitZipFiles(zipModel);
assertThat(splitFiles).hasSize(1);
assertThat(splitFiles.get(0)).isSameAs(zipFile);
}
@Test
public void testGetSplitZipFilesReturnsValidWhenSplitFile() throws ZipException {
final String FILE_SEPARATOR = System.getProperty("file.separator");
String path = FILE_SEPARATOR + "usr" + FILE_SEPARATOR + "parentdir" + FILE_SEPARATOR;
String zipFileName = "SomeName";
File zipFile = mockZipFileAsExists(path, zipFileName);
ZipModel zipModel = new ZipModel();
zipModel.setSplitArchive(true);
zipModel.setZipFile(zipFile);
zipModel.getEndOfCentralDirectoryRecord().setNumberOfThisDisk(4);
List splitFiles = FileUtils.getSplitZipFiles(zipModel);
assertThat(splitFiles).hasSize(5);
assertThat(splitFiles.get(0).getPath()).isEqualTo(path + zipFileName + ".z01");
assertThat(splitFiles.get(1).getPath()).isEqualTo(path + zipFileName + ".z02");
assertThat(splitFiles.get(2).getPath()).isEqualTo(path + zipFileName + ".z03");
assertThat(splitFiles.get(3).getPath()).isEqualTo(path + zipFileName + ".z04");
assertThat(splitFiles.get(4).getPath()).isEqualTo(path + zipFileName + ".zip");
}
@Test
public void testGetRelativeFileNameWhenRootFoldersAreNull() throws ZipException {
assertThat(FileUtils.getRelativeFileName("somefile.txt", null, null)).isEqualTo("somefile.txt");
}
@Test
public void testGetRelativeFileWithRootFolderNameInZip() throws ZipException {
String expectedRootFolder = "rootfolder" + InternalZipConstants.FILE_SEPARATOR + "somefile.txt";
assertThat(FileUtils.getRelativeFileName("somefile.txt", null, "rootfolder")).isEqualTo(expectedRootFolder);
}
@Test
public void testGetRelativeFileWithRootFolderNameInZipWithFileSeparator() throws ZipException {
String expectedRootFolder = "rootfolder" + InternalZipConstants.FILE_SEPARATOR + "somefile.txt";
assertThat(FileUtils.getRelativeFileName("somefile.txt", null, "rootfolder" + File.separator))
.isEqualTo(expectedRootFolder);
}
@Test
public void testGetRelativeFileWithRootFolderNameInZipWithSeparatorsInName() throws ZipException {
String expectedRootFolder = "rootfolder" + InternalZipConstants.FILE_SEPARATOR + "somefile.txt";
assertThat(FileUtils.getRelativeFileName("somefile.txt", null, "rootfolder\\")).isEqualTo(expectedRootFolder);
}
@Test
public void testIsZipEntryDirectoryWithWindowsFileSeparatorReturnsTrue() {
assertThat(FileUtils.isZipEntryDirectory("somename\\")).isTrue();
}
@Test
public void testIsZipEntryDirectoryWithUnixFileSeparatorReturnsTrue() {
assertThat(FileUtils.isZipEntryDirectory("somename/")).isTrue();
}
@Test
public void testIsZipEntryDirectoryWhichIsNotDirectoryReturnsFalse() {
assertThat(FileUtils.isZipEntryDirectory("somename")).isFalse();
}
private File mockZipFileAsExists(String path, String zipFileNameWithoutExtension) {
File file = mock(File.class);
when(file.exists()).thenReturn(true);
when(file.getName()).thenReturn(zipFileNameWithoutExtension + ".zip");
when(file.getPath()).thenReturn(path + zipFileNameWithoutExtension + ".zip");
return file;
}
private void testGetFilesInDirectory(boolean isDirectory, boolean canRead, File[] filesInDirectory,
int expectedReturnSize, boolean shouldReadHiddenFiles,
boolean shouldReadHiddenFolders) throws ZipException {
File file = mock(File.class);
when(file.isDirectory()).thenReturn(isDirectory);
when(file.canRead()).thenReturn(canRead);
when(file.listFiles()).thenReturn(filesInDirectory);
List returnedFiles = FileUtils.getFilesInDirectoryRecursive(file, shouldReadHiddenFiles,
shouldReadHiddenFolders);
assertThat(returnedFiles).hasSize(expectedReturnSize);
}
private File[] generateFilesForDirectory() {
return new File[]{
mockFile(false, false),
mockFile(false, false),
mockFile(true, false),
mockFile(true, true),
mockFile(false, true),
mockFile(true, true),
};
}
private File mockFile(boolean isHidden, boolean isDirectory) {
File file = mock(File.class);
when(file.isHidden()).thenReturn(isHidden);
when(file.isDirectory()).thenReturn(isDirectory);
return file;
}
private FileSystemProvider mockPath(Path path) {
FileSystemProvider fileSystemProvider = mock(FileSystemProvider.class);
FileSystem fileSystem = mock(FileSystem.class);
when(path.getFileSystem()).thenReturn(fileSystem);
when(path.getFileSystem().provider()).thenReturn(fileSystemProvider);
return fileSystemProvider;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/FileUtilsTestLinuxAndMac.java 0000664 0000000 0000000 00000013733 13576501616 0027174 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.spi.FileSystemProvider;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class FileUtilsTestLinuxAndMac {
private static final String ACTUAL_OS = System.getProperty("os.name");
@Before
public void setup() {
System.setProperty("os.name", "linux");
}
@After
public void cleanup() {
System.setProperty("os.name", ACTUAL_OS);
}
@Test
public void testSetFileAttributesWhenAttributesIsNullDoesNothing() {
FileUtils.setFileAttributes(mock(Path.class), null);
}
@Test
public void testSetFileAttributesWhenAttributesIsEmptyDoesNothing() {
FileUtils.setFileAttributes(mock(Path.class), new byte[0]);
}
@Test
public void testSetFileAttributesWhenNoAttributesSetDoesNothing() throws IOException {
Path path = mock(Path.class);
PosixFileAttributeView posixFileAttributeView = mockPosixFileAttributeView(path, false);
FileUtils.setFileAttributes(path, new byte[4]);
verifyZeroInteractions(posixFileAttributeView);
}
@Test
public void testSetFileAttributesWhenAttributesSet() throws IOException {
Path path = mock(Path.class);
PosixFileAttributeView posixFileAttributeView = mockPosixFileAttributeView(path, false);
byte fourthByte = 1; // Only first bit is set
byte thirdByte = -1; // All bits are set
FileUtils.setFileAttributes(path, new byte[]{0, 0, thirdByte, fourthByte});
ArgumentCaptor permissionsCaptor = ArgumentCaptor.forClass(Set.class);
verify(posixFileAttributeView).setPermissions(permissionsCaptor.capture());
verifyAllPermissionSet(permissionsCaptor.getValue());
}
@Test
public void testGetFileAttributesWhenFileIsNullReturnsEmptyBytes() {
byte[] attributes = FileUtils.getFileAttributes(null);
assertThat(attributes).contains(0, 0, 0, 0);
}
@Test
public void testGetFileAttributesAsDefinedForRegularFile() throws IOException {
testGetFileAttributesGetsAsDefined(false);
}
@Test
public void testGetFileAttributesAsDefinedForDirectory() throws IOException {
testGetFileAttributesGetsAsDefined(true);
}
private void testGetFileAttributesGetsAsDefined(boolean isDirectory) throws IOException {
File file = mock(File.class);
Path path = mock(Path.class);
when(file.toPath()).thenReturn(path);
when(file.exists()).thenReturn(true);
PosixFileAttributeView posixFileAttributeView = mockPosixFileAttributeView(path, isDirectory);
PosixFileAttributes posixFileAttributes = mock(PosixFileAttributes.class);
Set posixFilePermissions = getAllPermissions();
when(posixFileAttributes.permissions()).thenReturn(posixFilePermissions);
when(posixFileAttributeView.readAttributes()).thenReturn(posixFileAttributes);
byte[] fileAttributes = FileUtils.getFileAttributes(file);
assertThat(fileAttributes).hasSize(4);
assertThat(fileAttributes[0]).isEqualTo((byte) 0);
assertThat(fileAttributes[1]).isEqualTo((byte) 0);
assertThat(fileAttributes[2]).isEqualTo((byte) -1);
if (isDirectory) {
assertThat(fileAttributes[3]).isEqualTo((byte) 65);
} else {
assertThat(fileAttributes[3]).isEqualTo((byte) -127);
}
}
private Set getAllPermissions() {
return Stream.of(
PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE,
PosixFilePermission.OWNER_EXECUTE,
PosixFilePermission.GROUP_READ,
PosixFilePermission.GROUP_WRITE,
PosixFilePermission.GROUP_EXECUTE,
PosixFilePermission.OTHERS_READ,
PosixFilePermission.OTHERS_WRITE,
PosixFilePermission.OTHERS_EXECUTE
).collect(Collectors.toSet());
}
private void verifyAllPermissionSet(Set permissions) {
assertThat(permissions).contains(
PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE,
PosixFilePermission.OWNER_EXECUTE,
PosixFilePermission.GROUP_READ,
PosixFilePermission.GROUP_WRITE,
PosixFilePermission.GROUP_EXECUTE,
PosixFilePermission.OTHERS_READ,
PosixFilePermission.OTHERS_WRITE,
PosixFilePermission.OTHERS_EXECUTE
);
}
private PosixFileAttributeView mockPosixFileAttributeView(Path path, boolean isDirectory)
throws IOException {
FileSystemProvider fileSystemProvider = mock(FileSystemProvider.class);
FileSystem fileSystem = mock(FileSystem.class);
PosixFileAttributeView posixFileAttributeView = mock(PosixFileAttributeView.class);
when(path.getFileSystem()).thenReturn(fileSystem);
when(fileSystemProvider.getFileAttributeView(path, PosixFileAttributeView.class))
.thenReturn(posixFileAttributeView);
when(path.getFileSystem().provider()).thenReturn(fileSystemProvider);
mockRegularFileOrDirectory(fileSystemProvider, path, isDirectory);
return posixFileAttributeView;
}
private void mockRegularFileOrDirectory(FileSystemProvider fileSystemProvider, Path path, boolean isDirectory)
throws IOException {
BasicFileAttributes basicFileAttributes = mock(BasicFileAttributes.class);
when(basicFileAttributes.isRegularFile()).thenReturn(!isDirectory);
when(basicFileAttributes.isDirectory()).thenReturn(isDirectory);
when(fileSystemProvider.readAttributes(path, BasicFileAttributes.class)).thenReturn(basicFileAttributes);
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/FileUtilsTestWindows.java 0000664 0000000 0000000 00000010730 13576501616 0026455 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.DosFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import static net.lingala.zip4j.util.BitUtils.isBitSet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class FileUtilsTestWindows {
private static final String ACTUAL_OS = System.getProperty("os.name");
@Before
public void beforeClass() {
System.setProperty("os.name", "windows");
}
@After
public void cleanup() {
System.setProperty("os.name", ACTUAL_OS);
}
@Test
public void testSetFileAttributesWhenAttributesIsNullDoesNothing() {
FileUtils.setFileAttributes(mock(Path.class), null);
}
@Test
public void testSetFileAttributesWhenAttributesIsEmptyDoesNothing() {
FileUtils.setFileAttributes(mock(Path.class), new byte[0]);
}
@Test
public void testSetFileAttributesOnWindowsMachineWhenAttributesSet() throws IOException {
Path mockedPath = mock(Path.class);
DosFileAttributeView dosFileAttributeView = mockDosFileAttributeView(mockedPath, true);
byte attribute = 0;
attribute = BitUtils.setBit(attribute, 0);
attribute = BitUtils.setBit(attribute, 1);
attribute = BitUtils.setBit(attribute, 2);
attribute = BitUtils.setBit(attribute, 5);
FileUtils.setFileAttributes(mockedPath, new byte[]{attribute, 0, 0, 0});
verify(dosFileAttributeView).setReadOnly(true);
verify(dosFileAttributeView).setHidden(true);
verify(dosFileAttributeView).setSystem(true);
verify(dosFileAttributeView).setArchive(true);
}
@Test
public void testSetFileAttributesOnWindowsWhenNoAttributesSetDoesNothing() throws IOException {
Path mockedPath = mock(Path.class);
DosFileAttributeView dosFileAttributeView = mockDosFileAttributeView(mockedPath, true);
FileUtils.setFileAttributes(mockedPath, new byte[]{0, 0, 0, 0});
verifyZeroInteractions(dosFileAttributeView);
}
@Test
public void testGetFileAttributesWhenFileIsNullReturnsEmptyBytes() {
byte[] attributes = FileUtils.getFileAttributes(null);
assertThat(attributes).contains(0, 0, 0, 0);
}
@Test
public void testGetFileAttributesWhenFileDoesNotExistReturnsEmptyBytes() throws IOException {
File file = mock(File.class);
when(file.exists()).thenReturn(false);
byte[] attributes = FileUtils.getFileAttributes(file);
assertThat(attributes).contains(0, 0, 0, 0);
}
@Test
public void testGetFileAttributesReturnsAttributesAsDefined() throws IOException {
File file = mock(File.class);
Path path = mock(Path.class);
when(file.toPath()).thenReturn(path);
when(file.exists()).thenReturn(true);
DosFileAttributeView dosFileAttributeView = mockDosFileAttributeView(path, true);
DosFileAttributes dosFileAttributes = mock(DosFileAttributes.class);
when(dosFileAttributeView.readAttributes()).thenReturn(dosFileAttributes);
when(dosFileAttributes.isReadOnly()).thenReturn(true);
when(dosFileAttributes.isHidden()).thenReturn(true);
when(dosFileAttributes.isSystem()).thenReturn(true);
when(dosFileAttributes.isArchive()).thenReturn(true);
byte[] attributes = FileUtils.getFileAttributes(file);
assertThat(isBitSet(attributes[0], 0)).isTrue();
assertThat(isBitSet(attributes[0], 1)).isTrue();
assertThat(isBitSet(attributes[0], 2)).isTrue();
assertThat(isBitSet(attributes[0], 5)).isTrue();
}
private DosFileAttributeView mockDosFileAttributeView(Path path, boolean fileExists) throws IOException {
FileSystemProvider fileSystemProvider = mock(FileSystemProvider.class);
FileSystem fileSystem = mock(FileSystem.class);
DosFileAttributeView dosFileAttributeView = mock(DosFileAttributeView.class);
when(path.getFileSystem()).thenReturn(fileSystem);
when(fileSystemProvider.getFileAttributeView(path, DosFileAttributeView.class)).thenReturn(dosFileAttributeView);
when(path.getFileSystem().provider()).thenReturn(fileSystemProvider);
if (!fileExists) {
doThrow(new IOException()).when(fileSystemProvider).checkAccess(path);
}
return dosFileAttributeView;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/RawIOIT.java 0000664 0000000 0000000 00000017017 13576501616 0023565 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.model.enums.RandomAccessFileMode;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import static org.assertj.core.api.Assertions.assertThat;
public class RawIOIT extends AbstractIT {
private File fileToTest;
private RawIO rawIO = new RawIO();
@Before
public void before() throws IOException {
fileToTest = temporaryFolder.newFile();
writeDummyData(fileToTest);
}
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testReadLongLittleEndianWithRandomAccessFile() throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(fileToTest, RandomAccessFileMode.READ.getValue())) {
assertThat(rawIO.readLongLittleEndian(randomAccessFile)).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT + 1000);
assertThat(rawIO.readLongLittleEndian(randomAccessFile)).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT + 23423);
assertThat(rawIO.readLongLittleEndian(randomAccessFile, 4)).isEqualTo(32332);
}
}
@Test
public void testReadLongLittleEndianWithInputStream() throws IOException {
try(InputStream inputStream = new FileInputStream(fileToTest)) {
assertThat(rawIO.readLongLittleEndian(inputStream)).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT + 1000);
assertThat(rawIO.readLongLittleEndian(inputStream)).isEqualTo(InternalZipConstants.ZIP_64_SIZE_LIMIT + 23423);
assertThat(rawIO.readLongLittleEndian(inputStream, 4)).isEqualTo(32332);
}
}
@Test
public void testReadLongLittleEndianWithInputStreamNotEnoughDataThrowsException() throws IOException {
expectedException.expect(IOException.class);
expectedException.expectMessage("Could not fill buffer");
try(InputStream inputStream = new FileInputStream(fileToTest)) {
inputStream.skip(26);
rawIO.readLongLittleEndian(inputStream);
}
}
@Test
public void testReadLongLittleEndianWithByteArray() {
byte[] b = new byte[4];
rawIO.writeIntLittleEndian(b, 0, 234233);
assertThat(rawIO.readLongLittleEndian(b, 0)).isEqualTo(234233);
}
@Test
public void testReadIntLittleEndianWithRandomAccessFile() throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(fileToTest, RandomAccessFileMode.READ.getValue())) {
randomAccessFile.seek(16);
assertThat(rawIO.readIntLittleEndian(randomAccessFile)).isEqualTo(32332);
assertThat(rawIO.readIntLittleEndian(randomAccessFile)).isEqualTo(231);
}
}
@Test
public void testReadIntLittleEndianWithInputStream() throws IOException {
try(InputStream inputStream = new FileInputStream(fileToTest)) {
inputStream.skip(16);
assertThat(rawIO.readIntLittleEndian(inputStream)).isEqualTo(32332);
assertThat(rawIO.readIntLittleEndian(inputStream)).isEqualTo(231);
}
}
@Test
public void testReadIntLittleEndianWithByteArray() {
byte[] b = new byte[8];
rawIO.writeLongLittleEndian(b, 0, 23423L);
assertThat(rawIO.readIntLittleEndian(b)).isEqualTo(23423);
assertThat(rawIO.readIntLittleEndian(b, 1)).isEqualTo(91);
}
@Test
public void testReadShortLittleEndianWithRandomAccessFile() throws IOException {
try(RandomAccessFile randomAccessFile = new RandomAccessFile(fileToTest, RandomAccessFileMode.READ.getValue())) {
randomAccessFile.seek(24);
assertThat(rawIO.readShortLittleEndian(randomAccessFile)).isEqualTo(23);
assertThat(rawIO.readShortLittleEndian(randomAccessFile)).isEqualTo(77);
}
}
@Test
public void testReadShortLittleEndianWithInputStream() throws IOException {
try(InputStream inputStream = new FileInputStream(fileToTest)) {
inputStream.skip(24);
assertThat(rawIO.readShortLittleEndian(inputStream)).isEqualTo(23);
assertThat(rawIO.readShortLittleEndian(inputStream)).isEqualTo(77);
}
}
@Test
public void testReadShortLittleEndianWithByteArray() {
byte[] b = new byte[8];
rawIO.writeShortLittleEndian(b, 0, 88);
rawIO.writeShortLittleEndian(b, 2, 67);
assertThat(rawIO.readShortLittleEndian(b, 0)).isEqualTo(88);
assertThat(rawIO.readShortLittleEndian(b, 2)).isEqualTo(67);
}
@Test
public void testWriteShortLittleEndianWithOutputStream() throws IOException {
File shortFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(shortFile)) {
rawIO.writeShortLittleEndian(outputStream, 444);
}
try(InputStream inputStream = new FileInputStream(shortFile)) {
assertThat(rawIO.readShortLittleEndian(inputStream)).isEqualTo(444);
}
}
@Test
public void testWriteShortLittleEndianWithByteBuffer() {
byte[] b = new byte[10];
rawIO.writeShortLittleEndian(b, 0, 12);
rawIO.writeShortLittleEndian(b, 6, 67);
assertThat(rawIO.readShortLittleEndian(b, 0)).isEqualTo(12);
assertThat(rawIO.readShortLittleEndian(b, 6)).isEqualTo(67);
}
@Test
public void testWriteIntLittleEndianWithOutputStream() throws IOException {
File shortFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(shortFile)) {
rawIO.writeIntLittleEndian(outputStream, 4562);
}
try(InputStream inputStream = new FileInputStream(shortFile)) {
assertThat(rawIO.readIntLittleEndian(inputStream)).isEqualTo(4562);
}
}
@Test
public void testWriteIntLittleEndianWithByteBuffer() {
byte[] b = new byte[12];
rawIO.writeIntLittleEndian(b, 0, 23423);
rawIO.writeIntLittleEndian(b, 7, 6765);
assertThat(rawIO.readIntLittleEndian(b, 0)).isEqualTo(23423);
assertThat(rawIO.readIntLittleEndian(b, 7)).isEqualTo(6765);
}
@Test
public void testWriteLongLittleEndianWithOutputStream() throws IOException {
File shortFile = temporaryFolder.newFile();
try(OutputStream outputStream = new FileOutputStream(shortFile)) {
rawIO.writeLongLittleEndian(outputStream, 2342342L);
}
try(InputStream inputStream = new FileInputStream(shortFile)) {
assertThat(rawIO.readLongLittleEndian(inputStream)).isEqualTo(2342342L);
}
}
@Test
public void testWriteLongLittleEndianWithByteBuffer() {
byte[] b = new byte[50];
rawIO.writeLongLittleEndian(b, 0, 54545454233L);
rawIO.writeLongLittleEndian(b, 18, 9988898778L);
assertThat(rawIO.readLongLittleEndian(b, 0)).isEqualTo(54545454233L);
assertThat(rawIO.readLongLittleEndian(b, 18)).isEqualTo(9988898778L);
}
private void writeDummyData(File outputFile) throws IOException {
try (OutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] longByte = new byte[8];
byte[] intByte = new byte[4];
byte[] shortByte = new byte[2];
rawIO.writeLongLittleEndian(longByte, 0, InternalZipConstants.ZIP_64_SIZE_LIMIT + 1000);
outputStream.write(longByte);
rawIO.writeLongLittleEndian(longByte, 0, InternalZipConstants.ZIP_64_SIZE_LIMIT + 23423);
outputStream.write(longByte);
rawIO.writeIntLittleEndian(intByte, 0, 32332);
outputStream.write(intByte);
rawIO.writeIntLittleEndian(intByte, 0, 231);
outputStream.write(intByte);
rawIO.writeShortLittleEndian(shortByte, 0, 23);
outputStream.write(shortByte);
rawIO.writeShortLittleEndian(shortByte, 0, 77);
outputStream.write(shortByte);
}
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/UnzipUtilIT.java 0000664 0000000 0000000 00000007775 13576501616 0024561 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.AbstractIT;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.testutils.TestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
@RunWith(PowerMockRunner.class)
@PrepareForTest(FileUtils.class)
public class UnzipUtilIT extends AbstractIT {
@Test
public void testCreateZipInputStream() throws ZipException, IOException {
ZipFile zipFile = createZipFile();
ZipModel zipModel = createZipModel();
FileHeader fileHeader = zipFile.getFileHeaders().get(1);
File extractedFile = temporaryFolder.newFile();
try (InputStream inputStream = UnzipUtil.createZipInputStream(zipModel, fileHeader, "password".toCharArray());
OutputStream outputStream = new FileOutputStream(extractedFile)) {
byte[] b = new byte[InternalZipConstants.BUFF_SIZE];
int readLen = 0;
while ((readLen = inputStream.read(b)) != -1) {
outputStream.write(b, 0, readLen);
}
}
assertThat(extractedFile.length()).isEqualTo(TestUtils.getTestFileFromResources("sample_text_large.txt").length());
}
@Test
public void testApplyFileAttributes() {
byte[] externalFileAttributes = new byte[] {12, 34, 0, 0};
long currentTime = System.currentTimeMillis();
FileHeader fileHeader = new FileHeader();
fileHeader.setExternalFileAttributes(externalFileAttributes);
fileHeader.setLastModifiedTime(currentTime);
File file = mock(File.class);
Path path = mock(Path.class);
when(file.toPath()).thenReturn(path);
PowerMockito.mockStatic(FileUtils.class);
UnzipUtil.applyFileAttributes(fileHeader, file);
verifyStatic(FileUtils.class);
FileUtils.setFileLastModifiedTime(path, currentTime);
verifyStatic(FileUtils.class);
FileUtils.setFileAttributes(path, externalFileAttributes);
}
@Test
public void testApplyFileFileAttributesSetsLastModifiedTimeWithoutNio() {
byte[] externalFileAttributes = new byte[] {12, 34, 0, 0};
long currentTime = System.currentTimeMillis();
FileHeader fileHeader = new FileHeader();
fileHeader.setExternalFileAttributes(externalFileAttributes);
fileHeader.setLastModifiedTime(currentTime);
File file = mock(File.class);
Path path = mock(Path.class);
when(file.toPath()).thenThrow(new NoSuchMethodError("No method"));
PowerMockito.mockStatic(FileUtils.class);
UnzipUtil.applyFileAttributes(fileHeader, file);
verifyStatic(FileUtils.class, never());
FileUtils.setFileLastModifiedTime(path, currentTime);
verifyStatic(FileUtils.class, never());
FileUtils.setFileAttributes(path, externalFileAttributes);
verifyStatic(FileUtils.class);
FileUtils.setFileLastModifiedTimeWithoutNio(file, currentTime);
}
private ZipFile createZipFile() throws ZipException {
ZipFile zipFile = new ZipFile(generatedZipFile, "password".toCharArray());
zipFile.addFiles(Arrays.asList(
TestUtils.getTestFileFromResources("sample_text1.txt"),
TestUtils.getTestFileFromResources("sample_text_large.txt")
));
return zipFile;
}
private ZipModel createZipModel() {
ZipModel zipModel = new ZipModel();
zipModel.setZipFile(generatedZipFile);
zipModel.getEndOfCentralDirectoryRecord().setNumberOfThisDisk(0);
zipModel.setSplitArchive(false);
return zipModel;
}
} zip4j-2.2.8/src/test/java/net/lingala/zip4j/util/Zip4jUtilTest.java 0000664 0000000 0000000 00000025235 13576501616 0025046 0 ustar 00root root 0000000 0000000 package net.lingala.zip4j.util;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.testutils.ControlledReadInputStream;
import net.lingala.zip4j.testutils.RandomInputStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.IOException;
import java.util.TimeZone;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class Zip4jUtilTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testIsStringNotNullAndNotEmptyReturnsFalseWhenNull() {
assertThat(Zip4jUtil.isStringNotNullAndNotEmpty(null)).isFalse();
}
@Test
public void testIsStringNotNullAndNotEmptyReturnsFalseWhenEmpty() {
assertThat(Zip4jUtil.isStringNotNullAndNotEmpty("")).isFalse();
}
@Test
public void testIsStringNotNullAndNotEmptyReturnsFalseWithWhitespaces() {
assertThat(Zip4jUtil.isStringNotNullAndNotEmpty(" ")).isFalse();
}
@Test
public void testIsStringNotNullAndNotEmptyReturnsTrueForValidString() {
assertThat(Zip4jUtil.isStringNotNullAndNotEmpty(" Some string ")).isTrue();
}
@Test
public void testCreateDirectoryIfNotExistsThrowsExceptionWhenPathIsNull() throws ZipException {
expectedException.expectMessage("output path is null");
expectedException.expect(ZipException.class);
Zip4jUtil.createDirectoryIfNotExists(null);
}
@Test
public void testCreateDirectoryIfNotExistsThrowsExceptionWhenFileExistsButNotDirectory() throws ZipException {
File file = mock(File.class);
when(file.exists()).thenReturn(true);
when(file.isDirectory()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("output directory is not valid");
Zip4jUtil.createDirectoryIfNotExists(file);
}
@Test
public void testCreateDirectoryIfNotExistsReturnsTrueWhenFileExistsAndIsDirectory() throws ZipException {
File file = mock(File.class);
when(file.exists()).thenReturn(true);
when(file.isDirectory()).thenReturn(true);
assertThat(Zip4jUtil.createDirectoryIfNotExists(file)).isTrue();
}
@Test
public void testCreateDirectoryIfNotExistsThrowsExceptionWhenFileDoesNotExistAndCannotCreate() throws ZipException {
File file = mock(File.class);
when(file.exists()).thenReturn(false);
when(file.mkdirs()).thenReturn(false);
expectedException.expect(ZipException.class);
expectedException.expectMessage("Cannot create output directories");
Zip4jUtil.createDirectoryIfNotExists(file);
}
@Test
public void testCreateDirectoryIfNotExistsReturnsTrueWhenFileDoesNotExistAndCreated() throws ZipException {
File file = mock(File.class);
when(file.exists()).thenReturn(false);
when(file.mkdirs()).thenReturn(true);
assertThat(Zip4jUtil.createDirectoryIfNotExists(file)).isTrue();
}
@Test
public void testJavaToDosTime() {
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
assertThat(Zip4jUtil.javaToDosTime(1560526564503L)).isEqualTo(1322159234);
TimeZone.setDefault(defaultTimeZone);
}
@Test
public void testDosToJavaTime() {
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
assertThat(Zip4jUtil.dosToJavaTme(1322159234)).isEqualTo((1560526564503L / 1000) * 1000);
TimeZone.setDefault(defaultTimeZone);
}
@Test
public void testConvertCharArrayToByteArray() {
char[] charArray = "CharArray".toCharArray();
byte[] byteArray = Zip4jUtil.convertCharArrayToByteArray(charArray);
assertThat(byteArray.length).isEqualTo(charArray.length);
assertThat(byteArray[0]).isEqualTo((byte)'C');
assertThat(byteArray[1]).isEqualTo((byte)'h');
assertThat(byteArray[2]).isEqualTo((byte)'a');
assertThat(byteArray[3]).isEqualTo((byte)'r');
assertThat(byteArray[4]).isEqualTo((byte)'A');
assertThat(byteArray[5]).isEqualTo((byte)'r');
assertThat(byteArray[6]).isEqualTo((byte)'r');
assertThat(byteArray[7]).isEqualTo((byte)'a');
assertThat(byteArray[8]).isEqualTo((byte)'y');
}
@Test
public void testGetCompressionMethodForNonAesReturnsAsIs() {
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setCompressionMethod(CompressionMethod.DEFLATE);
assertThat(Zip4jUtil.getCompressionMethod(localFileHeader)).isEqualTo(CompressionMethod.DEFLATE);
}
@Test
public void testGetCompressionMethodForAesWhenAesExtraDataMissingThrowsException() {
expectedException.expectMessage("AesExtraDataRecord not present in local header for aes encrypted data");
expectedException.expect(RuntimeException.class);
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setCompressionMethod(CompressionMethod.AES_INTERNAL_ONLY);
Zip4jUtil.getCompressionMethod(localFileHeader);
}
@Test
public void testGetCompressionMethidForAesReturnsFromAesExtraDataRecord() {
AESExtraDataRecord aesExtraDataRecord = new AESExtraDataRecord();
aesExtraDataRecord.setCompressionMethod(CompressionMethod.STORE);
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setCompressionMethod(CompressionMethod.AES_INTERNAL_ONLY);
localFileHeader.setAesExtraDataRecord(aesExtraDataRecord);
assertThat(Zip4jUtil.getCompressionMethod(localFileHeader)).isEqualTo(CompressionMethod.STORE);
}
@Test
public void testReadFullyReadsCompleteBuffer() throws IOException {
byte[] b = new byte[3423];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(1000);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b)).isEqualTo(3423);
}
@Test
public void testReadFullyReadsCompleteBufferInOneShot() throws IOException {
byte[] b = new byte[4096];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(4097);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b)).isEqualTo(4096);
}
@Test
public void testReadFullyThrowsExceptionWhenCannotFillBuffer() throws IOException {
byte[] b = new byte[4097];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(500);
expectedException.expect(IOException.class);
expectedException.expectMessage("Cannot read fully into byte buffer");
Zip4jUtil.readFully(controlledReadInputStream, b);
}
@Test
public void testReadFullyOnEmptyStreamThrowsException() throws IOException {
byte[] b = new byte[4096];
RandomInputStream randomInputStream = new RandomInputStream(0);
ControlledReadInputStream controlledReadInputStream = new ControlledReadInputStream(randomInputStream, 100);
expectedException.expect(IOException.class);
expectedException.expectMessage("Cannot read fully into byte buffer");
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b)).isEqualTo(-1);
}
@Test
public void testReadFullyThrowsExceptionWhenRetryLimitExceeds() throws IOException {
byte[] b = new byte[151];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(10);
expectedException.expect(IOException.class);
expectedException.expectMessage("Cannot read fully into byte buffer");
Zip4jUtil.readFully(controlledReadInputStream, b);
}
@Test
public void testReadFullyWithLengthReadsCompleteLength() throws IOException {
byte[] b = new byte[1000];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(100);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b, 0, 900)).isEqualTo(900);
}
@Test
public void testReadFullyWithLengthReadsMaximumAvailable() throws IOException {
byte[] b = new byte[1000];
RandomInputStream randomInputStream = new RandomInputStream(150);
ControlledReadInputStream controlledReadInputStream = new ControlledReadInputStream(randomInputStream, 700);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b, 0, 900)).isEqualTo(150);
}
@Test
public void testReadFullyWithLengthReadsCompletelyIntoBuffer() throws IOException {
byte[] b = new byte[1000];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(10);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b, 0, 1000)).isEqualTo(1000);
}
@Test
public void testReadFullyWithNegativeLengthThrowsException() throws IOException {
byte[] b = new byte[1000];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(10);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Negative length");
Zip4jUtil.readFully(controlledReadInputStream, b, 0, -5);
}
@Test
public void testReadFullyWithNegativeOffsetThrowsException() throws IOException {
byte[] b = new byte[10];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(10);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Negative offset");
Zip4jUtil.readFully(controlledReadInputStream, b, -4, 10);
}
@Test
public void testReadFullyWithLengthZeroReturnsZero() throws IOException {
byte[] b = new byte[1000];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(100);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b, 0, 0)).isZero();
}
@Test
public void testReadFullyThrowsExceptionWhenOffsetPlusLengthGreaterThanBufferSize() throws IOException {
byte[] b = new byte[10];
ControlledReadInputStream controlledReadInputStream = initialiseControlledInputStream(10);
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Length greater than buffer size");
Zip4jUtil.readFully(controlledReadInputStream, b, 5, 10);
}
@Test
public void testReadFullyWithLengthOnAnEmptyStreamReturnsEOF() throws IOException {
byte[] b = new byte[1000];
RandomInputStream randomInputStream = new RandomInputStream(-1);
ControlledReadInputStream controlledReadInputStream = new ControlledReadInputStream(randomInputStream, 100);
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b, 0, 100)).isEqualTo(-1);
}
private ControlledReadInputStream initialiseControlledInputStream(int maxLengthToReadAtOnce) {
RandomInputStream randomInputStream = new RandomInputStream(4096);
return new ControlledReadInputStream(randomInputStream, maxLengthToReadAtOnce);
}
} zip4j-2.2.8/src/test/resources/ 0000775 0000000 0000000 00000000000 13576501616 0016355 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/resources/test-archives/ 0000775 0000000 0000000 00000000000 13576501616 0021136 5 ustar 00root root 0000000 0000000 zip4j-2.2.8/src/test/resources/test-archives/corrupt_extra_data_record_length.zip 0000664 0000000 0000000 00000537151 13576501616 0030467 0 ustar 00root root 0000000 0000000 PK 7,]8 AndroidManifest.xmlVKO[G>`^e
.jIQ HK\JBUAeU]tU]tџUUWYtU67}|yfΜ;g)FYzm 'S9'7
y'" e;&
xܩ!x EJ+ %X _ #* qDC%:}:-?Ke14܇e^D *óD{|jQ;sH_"{匈#G_buW=D<mmSsM/+7W-s}<,-)҇4ϡnm~9x:*xg+JFr,p%0#},{+i>[/ʰiQ(lV;YC<{}r9=v Ctn*jI@w4[GwV)|,&ei뽅hWPfb_d]s=z%5>8VXcJ[Lw\=\P#re>?g g/b)krU+̿Mp]"V'G+q3yO4^iήXOp?y}6vl6"\;6'_HunfJ[Q9Ʒj exp<
F,w$߲.2;3uWXm_ԩuS
;ggxu~Z986D4]+ϋ*+UU~fbKnZ@m{hϰCUKx"j`ZUuK08:˯$ 0Y)Jף}Y {5~(T3ͮ~6<hRs-~jSM(.f7[Kl-(;įCt):B#!fSKg9,mVں5>8/b#|=_$/j
5^6/f'|}_,_5 z|7RѳU91|"}ҤmqmQJ'hI_kQI1\EG9_vCbk6KluT/vOǨp$4w`Ltik5k \{/˱;f0? W7reisubp2mJb6 iִ샤ߌh| ^~
_Iŗ\{_@r?`YVASWW}5[kݛ}-dPKrb PK 7,]8 classes.dexy}{1cMd,eX%"c)*dd T$KH1He+d-K,Q)6[z|yxyss\k+ehTRTRm#:2f҅kDhz&|*M)5SX%KK7#I+&Π+)UݧTFJ}TjT[#;ajJV`ͰIB3*@=7L0rX_`/#\KPqVAxfǰ ȄQ
.e
B$(efHjPn' TJ[a7
_$\ԇQ`K`6ixC'?P@/.7Ѫ1 ^0 FtYl8sp"?j|{@* k`;iuc-10>p_7hš4x PBCZ@+h!xzCa$o$ ?a
`sP| a+gnZ
%_DI;2^U
[*TT-XgZ5:,oo(>i0(T[@2/4N0 FtX[%?ת*4N0ކ7-Ax(QSKJA lUZU"i
(]yC` ЪLҗS:۰[>]Oa|
G
Zaeb02,mS0A>CgL1 |9X'ZV`$| ;< ?C`b[73<AmZu3סL5pS02oi'c5];0ރmp*|KP v?P;Pp7tga&lP{C;ǰ9"d2NA䏴Ԅ{ ^6O;\bٴtt`5lp
JDs3 7>p?</G
x^y}`PԇvB !82AsNjAc`A;t0>]p
Jb샖+a6,uÜBS@
6y(tJB/ ]6p.AQn;x2]~8E1@C'` <aLu:CQ(eTju! -50@_H!<0>Oa-
`/oZFp'4Vp?t.0'!ExkvE;k 6pn1A0p `Lw`&̃e!OJA% w@)0 x
"XY=p
Ŝ! n <a [0>al sn 0x
ކ9! WIj@s9x
&4
N@)7a!cp
.C4 4:£Ra S`,/`l8 ąUYC7Oh{8 \ ́pT$h#t^
%Ȁ9l3rAkt`-l#yqAch=7g`LY06N3CE)d
s`%3p
\^P@kxzPcא
pE_U4#`a|+`/n9.P@s@{)0,++{+u
Ch]'< `8++j !XRX _
;wCXJG8 G/8נUy(Nha f'6
JB9H
:BW0&.̆O`9lQN%O%ASzBo,k;8W JT 5 02`.oϧJAUhwCxk0f§v!>U@hAO /dX_
GO
|,Ԅz@=X">UB5h aHq0>Ր
| g8AGTIH;OHJP0q0Vz?/']BT: H*&~?,\(B]h+%EX{ DET-x'!
3a,dN)|&t0f2
!XاA !C<#a2|
'
PjzA|a#|$cPn.:CoH0އvp op.S!P*@-hmt)a,LȆpt,Aq(
&4~
O*̀T1K(ա)<