Skip to content

Commit

Permalink
#106 Do not use CD when extract all entries
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-cherednik committed Dec 22, 2024
1 parent f8f6b6c commit 96d39b0
Show file tree
Hide file tree
Showing 141 changed files with 1,560 additions and 973 deletions.
48 changes: 21 additions & 27 deletions src/main/java/ru/olegcherednik/zip4jvm/UnzipIt.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package ru.olegcherednik.zip4jvm;

import ru.olegcherednik.zip4jvm.engine.UnzipEngine;
import ru.olegcherednik.zip4jvm.exception.IncorrectPasswordException;
import ru.olegcherednik.zip4jvm.model.settings.UnzipSettings;
import ru.olegcherednik.zip4jvm.model.src.SrcZip;
Expand All @@ -30,7 +29,6 @@
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

import static ru.olegcherednik.zip4jvm.utils.ValidationUtils.requireDirectory;
Expand All @@ -53,7 +51,7 @@ public final class UnzipIt {
/**
* Destination directory for extracted files; by default its directory where {@link #zip} archive is located
*/
private Path destDir;
private Path dstDir;
/** setting for unzip files */
private UnzipSettings settings = UnzipSettings.DEFAULT;

Expand All @@ -65,22 +63,22 @@ public final class UnzipIt {
*/
public static UnzipIt zip(Path zip) {
requireNotNull(zip, "UnzipIt.zip");
return new UnzipIt(SrcZip.of(zip)).destDir(zip.getParent());
return new UnzipIt(SrcZip.of(zip)).dstDir(zip.getParent());
}

/**
* Set destination directory for extracted files. By default, all files are extracted into {@link #zip} archive
* located directory.<br>
* If given directory is not exists, then it will be created.
*
* @param destDir not {@literal null} destination directory
* @param dstDir not {@literal null} destination directory
* @return not {@literal null} {@link UnzipIt} instance
*/
public UnzipIt destDir(Path destDir) {
requireNotNull(destDir, "UnzipIt.destDir");
requireDirectory(destDir, "UnzipIt.destDir");
public UnzipIt dstDir(Path dstDir) {
requireNotNull(dstDir, "UnzipIt.dstDir");
requireDirectory(dstDir, "UnzipIt.dstDir");

this.destDir = destDir;
this.dstDir = dstDir;
return this;
}

Expand Down Expand Up @@ -108,20 +106,20 @@ public UnzipIt password(char[] password) {
}

/**
* Extract all existed in {@link #zip} archive entries into {@link #destDir} using {@link #settings}.
* Extract all existed in {@link #zip} archive entries into {@link #dstDir} using {@link #settings}.
*
* @throws IOException in case of any problem with file access
* @throws IncorrectPasswordException in case of password incorrect
*/
public void extract() throws IOException, IncorrectPasswordException {
new UnzipEngine(srcZip, settings).extract(destDir);
open().extract(dstDir);
}

/**
* Extract entry with {@code fileName} into {@link #destDir} using {@link #settings}.<br>
* Extract entry with {@code fileName} into {@link #dstDir} using {@link #settings}.<br>
* If {@code fileName} is a regular file entry, then only single regular file will be extracted into the root of
* {@link #destDir}.<br>
* If {@code fileName} is a directory, then entire directory will be extracted into the root of {@link #destDir}
* {@link #dstDir}.<br>
* If {@code fileName} is a directory, then entire directory will be extracted into the root of {@link #dstDir}
* keeping the initial structure.
*
* @param fileName not blank file name
Expand All @@ -130,16 +128,15 @@ public void extract() throws IOException, IncorrectPasswordException {
*/
public void extract(String fileName) throws IOException, IncorrectPasswordException {
requireNotBlank(fileName, "UnzipIt.fileName");

extract(Collections.singleton(fileName));
open().extract(dstDir, fileName);
}

/**
* Extract entries with {@code fileNames} into {@link #destDir} using {@link #settings}. Each entry is extracted
* Extract entries with {@code fileNames} into {@link #dstDir} using {@link #settings}. Each entry is extracted
* separately.<br>
* If {@code fileName} is a regular file entry, then only single regular file will be extracted into the root of
* {@link #destDir}.<br>
* If {@code fileName} is a directory, then entire directory will be extracted into the root of {@link #destDir}
* {@link #dstDir}.<br>
* If {@code fileName} is a directory, then entire directory will be extracted into the root of {@link #dstDir}
* keeping the initial structure.
*
* @param fileNames not {@literal null} file names
Expand All @@ -148,23 +145,19 @@ public void extract(String fileName) throws IOException, IncorrectPasswordExcept
*/
public void extract(Collection<String> fileNames) throws IOException {
requireNotNull(fileNames, "UnzipIt.fileNames");

ZipFile.Reader zipFile = open();

for (String fileName : fileNames)
zipFile.extract(destDir, fileName);
open().extract(dstDir, fileNames);
}

/**
* Retrieve entry with given {@code fileName} as {@link InputStream}. If given {@code fileName} is directory entry,
* then empty {@link InputStream}
* will be retrieved.
* then empty {@link InputStream} will be retrieved.
*
* @param fileName not blank file name
* @return not {@literal null} {@link InputStream} instance; for directory entry retrieve empty {@link InputStream}
* @throws IOException in case of any problem with file access
* @throws IncorrectPasswordException in case of password incorrect
*/
public InputStream stream(String fileName) {
public InputStream stream(String fileName) throws IOException {
requireNotBlank(fileName, "UnzipIt.fileName");
return ZipFile.reader(srcZip, settings).extract(fileName).getInputStream();
}
Expand All @@ -176,6 +169,7 @@ public InputStream stream(String fileName) {
* @return not {@literal null} instance of {@link ZipFile.Reader}
* @throws IOException in case of any problem with file access
*/
// @NotNull
public ZipFile.Reader open() throws IOException {
return ZipFile.reader(srcZip, settings);
}
Expand Down
19 changes: 11 additions & 8 deletions src/main/java/ru/olegcherednik/zip4jvm/ZipFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
*/
package ru.olegcherednik.zip4jvm;

import ru.olegcherednik.zip4jvm.engine.InfoEngine;
import ru.olegcherednik.zip4jvm.engine.UnzipEngine;
import ru.olegcherednik.zip4jvm.engine.ZipEngine;
import ru.olegcherednik.zip4jvm.engine.info.InfoEngine;
import ru.olegcherednik.zip4jvm.engine.unzip.UnzipEngine;
import ru.olegcherednik.zip4jvm.engine.zip.ZipEngine;
import ru.olegcherednik.zip4jvm.exception.EntryNotFoundException;
import ru.olegcherednik.zip4jvm.model.CentralDirectory;
import ru.olegcherednik.zip4jvm.model.ExternalFileAttributes;
Expand All @@ -42,6 +42,7 @@
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.Collection;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

Expand All @@ -65,7 +66,7 @@ static Info info(SrcZip srcZip, ZipInfoSettings settings) throws IOException {
}

/**
* This is an abstraction of the single zip file entry not related to the specific zip file setting. It does not
* This is an abstraction of the single zip file entry not related to the specific zip file settings. It does not
* matter what it is (a regular file, directory, symlink, etc.). This class is used to make client define an entry
* that will be converted to the internal concrete entry type while zipping and unzipping.
*/
Expand Down Expand Up @@ -118,7 +119,7 @@ public static Entry regularFile(InputStreamSupplier inputStreamSupplier,
}

public InputStream getInputStream() {
return Quietly.doQuietly(inputStreamSupplier);
return Quietly.doRuntime(inputStreamSupplier);
}
}

Expand All @@ -143,11 +144,13 @@ public interface Writer extends Closeable {

public interface Reader extends Iterable<ZipFile.Entry> {

void extract(Path destDir) throws IOException;
void extract(Path dstDir) throws IOException;

void extract(Path destDir, String fileName) throws IOException;
void extract(Path dstDir, String fileName) throws IOException;

ZipFile.Entry extract(String fileName);
void extract(Path dstDir, Collection<String> fileNames) throws IOException;

ZipFile.Entry extract(String fileName) throws IOException;

default Stream<Entry> stream() {
return StreamSupport.stream(spliterator(), false);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ru/olegcherednik/zip4jvm/ZipInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public void printShortInfo(PrintStream out) throws IOException {
ZipFile.info(srcZip, settings).printTextInfo(out);
}

public void decompose(Path destDir) throws IOException {
ZipFile.info(srcZip, settings).decompose(destDir);
public void decompose(Path dstDir) throws IOException {
ZipFile.info(srcZip, settings).decompose(dstDir);
}

public CentralDirectory.FileHeader getFileHeader(String entryName) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final class AesEncoder implements Encoder {
private final AesEngine engine;

public static AesEncoder create(ZipEntry zipEntry) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
AesStrength strength = AesEngine.getStrength(zipEntry.getEncryptionMethod());
byte[] salt = strength.generateSalt();
byte[] key = AesEngine.createKey(zipEntry.getPassword(), salt, strength);
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/ru/olegcherednik/zip4jvm/crypto/aes/AesEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public final class AesEngine implements Engine {

@Override
public byte encrypt(byte b) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
byte bb = cipherUpdate(b);
mac.update(bb);
return bb;
Expand All @@ -71,7 +71,7 @@ public byte encrypt(byte b) {
public int decrypt(byte[] buf, int offs, int len) {
assert len > 0;

Quietly.doQuietly(() -> {
Quietly.doRuntime(() -> {
mac.update(buf, offs, len);
cipherUpdate(buf, offs, len);
});
Expand Down Expand Up @@ -118,15 +118,15 @@ public byte[] getMac() {
}

public static byte[] createKey(char[] password, byte[] salt, AesStrength strength) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
int keyLength = strength.getSize() * 2 + 16;
KeySpec keySpec = new PBEKeySpec(password, salt, ITERATION_COUNT, keyLength);
return SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(keySpec).getEncoded();
});
}

public static Cipher createCipher(SecretKeySpec secretKeySpec) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
// use custom AES implementation, so no worry for DECRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
Expand All @@ -135,7 +135,7 @@ public static Cipher createCipher(SecretKeySpec secretKeySpec) {
}

public static Mac createMac(SecretKeySpec secretKeySpec) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKeySpec);
return mac;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public int getBlockSize() {
public int decrypt(byte[] buf, int offs, int len) {
assert len > 0;

return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
if (decryptedBytes >= compressedSize)
return 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public int getBlockSize() {

@Override
public int decrypt(byte[] buf, int offs, int len) {
return Quietly.doQuietly(() -> cipher.update(buf, offs, len, buf, offs));
return Quietly.doRuntime(() -> cipher.update(buf, offs, len, buf, offs));
}

// ---------- Encrypt ----------
Expand Down Expand Up @@ -88,7 +88,7 @@ public static Cipher createCipher(DecryptionHeader decryptionHeader,
char[] password,
AesStrength strength,
ByteOrder byteOrder) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
IvParameterSpec iv = new IvParameterSpec(decryptionHeader.getIv());
byte[] randomData = decryptRandomData(decryptionHeader, password, strength, iv);
byte[] fileKey = getFileKey(decryptionHeader, randomData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final class PkwareDecoder implements Decoder {
private final long compressedSize;

public static PkwareDecoder create(ZipEntry zipEntry, DataInput in) {
return Quietly.doQuietly(() -> {
return Quietly.doRuntime(() -> {
requireNotEmpty(zipEntry.getPassword(), zipEntry.getFileName() + ".password");

PkwareEngine engine = new PkwareEngine(zipEntry.getPassword());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ private void copyPayload(Path dir, ZipEntry zipEntry, ZipEntryBlock.LocalFileHea

Block content = diagLocalFileHeader.getContent();
long size = zipEntry.getCompressedSize();
long offs = content.getRelativeOffs() + content.getSize();
long offs = content.getDiskOffs() + content.getSize();

EncryptionMethod encryptionMethod = zipEntry.getEncryptionMethod();

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/ru/olegcherednik/zip4jvm/decompose/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static void print(Path file, Consumer<PrintStream> consumer) throws FileN
}

public static void copyLarge(ZipModel zipModel, Path out, Block block) throws IOException {
copyLarge(zipModel, out, block.getRelativeOffs(), block.getSize());
copyLarge(zipModel, out, block.getDiskOffs(), block.getSize());
}

public static void copyLarge(ZipModel zipModel, Path out, long offs, long size) throws IOException {
Expand All @@ -66,11 +66,11 @@ public static void copyLarge(ZipModel zipModel, Path out, long offs, long size)
}

public static void copyByteArray(Path out, byte[] buf, Block block) throws IOException {
ValidationUtils.requireLessOrEqual(block.getAbsoluteOffs(), Integer.MAX_VALUE, "block.absoluteOffs");
ValidationUtils.requireLessOrEqual(block.getAbsOffs(), Integer.MAX_VALUE, "block.absoluteOffs");
ValidationUtils.requireLessOrEqual(block.getSize(), Integer.MAX_VALUE, "block.size");

try (OutputStream fos = Files.newOutputStream(out)) {
fos.write(buf, (int) block.getAbsoluteOffs(), (int) block.getSize());
fos.write(buf, (int) block.getAbsOffs(), (int) block.getSize());
}
}

Expand Down
Loading

0 comments on commit 96d39b0

Please sign in to comment.