docs: public static void extractZip(
          final Enumeration<? extends ZipEntry> enumeration,
          final GetStream streamSource,
          final File dest,
          final FilenameFilter filter,
          final renamer rename,
          final streamCopier copier
      ) throws IOException {
  
          while (enumeration.hasMoreElements()) {
              final ZipEntry entry = enumeration.nextElement();
              if (null != filter && !filter.accept(dest, entry.getName())) {
                  continue;
              }
              String name = entry.getName();
              if (null != rename) {
                  name = rename.rename(name);
              }
              final File destFile = new File(dest, name);
  
              if (!destFile.toPath().normalize().startsWith(dest.toPath().normalize())) {
                  throw new IOException(String.format("Path is outside of destination directory: %s", destFile));
              }
              if (entry.isDirectory() && !destFile.isDirectory()) {
                  if (!destFile.mkdirs()) {
                      throw new IOException("Unable to make directory: " + destFile);
                  }
              } else if (!entry.isDirectory()) {
                  if (!destFile.exists()) {
                      //create parent dirs if necessary
                      File parent = destFile.getParentFile();
                      if (!parent.exists() && !parent.mkdirs()) {
                          throw new IOException("Unable to create parent dir for file: " + destFile.getAbsolutePath());
                      }
                      if (!destFile.createNewFile()) {
                          throw new IOException("Unable to create file: " + destFile.getAbsolutePath());
                      }
                  }
                  try (InputStream entryStream = streamSource.getInputStream(entry)) {
                      try (FileOutputStream fileOut = new FileOutputStream(destFile)) {
                          if (null != copier) {
                              copier.copyStream(entryStream, fileOut);
                          } else {
                              copyStream(entryStream, fileOut);
                          }
                      }
                  }
              }
          }
      }