0

I created a simple code (and a test zip file with the password cat_666) to check if the entered password is correct (using zip4j library)

var filechooser = new FileChooser();
filechooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("zipfile", "*.zip"));
var archive = filechooser.showOpenDialog(null);
try {
    if (new ZipFile(archive).isEncrypted()) {
        System.out.println(correctPassword(archive, "cat.666"));
        System.out.println(correctPassword(archive, "cat_666"));
    } else {
        System.out.println("Without password");
    }
} catch (ZipException ex) {
}

public static String correctPassword(File archive, String password) {
    try {
        var fileHeaders = new ZipFile(archive).getFileHeaders();
        var smallest_size = fileHeaders.stream().map(f -> f.getComssedSize()).min(Long::compare).get();
        var smallest_file = fileHeaders.stream().filter(f -> f.getCompressedSize() == smallest_size).findFirst().get();
        new ZipFile(archive, password.toCharArray()).extractFile(smallest_file, "/tmp_directory");
        FileUtils.deleteDirectory(new File("C:/tmp_directory"));
    } catch (ZipException ex) {
        return password + " is not correct";
    } catch (IOException ex) {
        System.out.println("bad path");
    }
    return password + " is correct";
}

Although it works, there are three drawbacks.

  1. I call the method only when the file is encrypted. However, this validation alone requires a try catch, so it is there twice in the result.

  2. Password verification is probably not possible without extraction. Fortunately, it is possible to extract even one file and the size can be found even without a password, so I can extract the smallest file. However, its selection is unnecessarily complicated.

  3. By extracting the file, I want to delete it afterwards, for which it has to add another Commons-io library there.

Can it be simplified please?

Thank you

UPDATE:

I managed to partially solve the second problem to extract the smallest file to find the password. However, the code is unnecessarily complex.

Since extracting at least one file is obviously necessary, it's not worth solving the third problem (library size is negligible)

And the first problem is probably only an aesthetic detail, which I would ignore.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
Michal Rama
  • 173
  • 1
  • 1
  • 10
  • 2
    You could [list](https://github.com/srikanth-lingala/zip4j#list-all-files-in-a-zip) the files instead of extracting anything. – Federico klez Culloca Jul 19 '23 at 13:07
  • Are you sure that things don't fail as soon as you attempt to extract the large file? I tried a test and it appears that as soon as you try to extract something with a bad password, you get an exception. The size of the file did not come into account. – SedJ601 Jul 19 '23 at 16:13
  • 1
    I am not sure why you need a new library to delete files. Does `Files.delete` and `Files.deleteIfExists` not work? – SedJ601 Jul 19 '23 at 16:15
  • @SedJ601 Because I don't want to delete the file, but the entire newly created folder, which apparently java can't do. – Michal Rama Jul 19 '23 at 18:27
  • 1
    What error are you getting when you attempt to delete the folder? – SedJ601 Jul 19 '23 at 18:44
  • @FedericoklezCulloca Thank you, you are right. I can also get a list of files from the passworded archive, including their size. I just need to simplify the selection of the smallest file, please (I updated the code) – Michal Rama Jul 19 '23 at 20:35
  • @SedJ601 I don't know how big the file would cause the error (400MB wasn't a problem). And the correctness of the password is in the try catch. But as I said, the code already selects the smallest file, I just need to simplify it. P.S. As for the deletion, I need to delete the whole folder, which java supposedly can't do as stated [here](https://stackoverflow.com/questions/20281835/how-to-delete-a-folder-with-files-using-java/20281958#20281958), so I'm using an external library. – Michal Rama Jul 19 '23 at 20:46
  • 1
    The link you posted list many ways to delete all the files in a folder plus the folder. There is no need for a library. The library most likely uses one of these ways. `Files.walk(pathToBeDeleted) .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete);`. – SedJ601 Jul 19 '23 at 21:10
  • Given how good Apache's `FileUtils` appear to be, I would say keep using it. – SedJ601 Jul 19 '23 at 21:16
  • 1
    Another optimization you might want to use is [`Files.createTempDirectory`](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/nio/file/Files.html#createTempDirectory(java.nio.file.Path,java.lang.String,java.nio.file.attribute.FileAttribute...)) to create your temporary directory, rather than hardcoding `C:/tmp_directory`, which is not a portable solution. Also I removed the JavaFX tag as the question isn't JavaFX related. – jewelsea Jul 20 '23 at 00:21

0 Answers0