Search in sources :

Example 6 with AbstractArchiveFile

use of com.mucommander.commons.file.archive.AbstractArchiveFile in project mucommander by mucommander.

the class UnpackJob method jobCompleted.

// //////////////////////
// Overridden methods //
// //////////////////////
@Override
protected void jobCompleted() {
    super.jobCompleted();
    // If the destination files are located inside an archive, optimize the archive file
    AbstractArchiveFile archiveFile = baseDestFolder.getParentArchive();
    if (archiveFile != null && archiveFile.isArchive() && archiveFile.isWritable())
        optimizeArchive((AbstractRWArchiveFile) archiveFile);
    // Unselect all files in the active table upon successful completion
    if (selectedEntries != null) {
        ActionManager.performAction(UnmarkAllAction.Descriptor.ACTION_ID, getMainFrame());
    }
}
Also used : AbstractArchiveFile(com.mucommander.commons.file.archive.AbstractArchiveFile) AbstractRWArchiveFile(com.mucommander.commons.file.archive.AbstractRWArchiveFile)

Example 7 with AbstractArchiveFile

use of com.mucommander.commons.file.archive.AbstractArchiveFile in project mucommander by mucommander.

the class UnpackJob method processFile.

/**
 * Unpacks the given archive file. If the file is a directory, its children will be processed recursively.
 * If the file is not an archive file nor a directory, it is not processed and <code>false</code> is returned.
 *
 * @param file          the file to unpack
 * @param recurseParams unused
 * @return <code>true</code> if the file has been processed successfully
 */
@Override
protected boolean processFile(AbstractFile file, Object recurseParams) {
    // Stop if interrupted
    if (getState() == FileJobState.INTERRUPTED)
        return false;
    // Destination folder
    AbstractFile destFolder = baseDestFolder;
    // If the file is a directory, process its children recursively
    if (file.isDirectory()) {
        do {
            // Loop for retries
            try {
                // List files inside archive file (can throw an IOException)
                AbstractFile[] archiveFiles = getCurrentFile().ls();
                // Recurse on zip's contents
                for (int j = 0; j < archiveFiles.length && getState() != FileJobState.INTERRUPTED; j++) {
                    // Notify job that we're starting to process this file (needed for recursive calls to processFile)
                    nextFile(archiveFiles[j]);
                    // Recurse
                    processFile(archiveFiles[j], destFolder);
                }
                // Return true when complete
                return true;
            } catch (IOException e) {
                // File could not be uncompressed properly
                DialogAction ret = showErrorDialog(errorDialogTitle, Translator.get("cannot_read_file", getCurrentFilename()));
                // Retry loops
                if (ret == FileJobAction.RETRY)
                    continue;
                // cancel, skip or close dialog will simply return false
                return false;
            }
        } while (true);
    }
    // Abort if the file is neither an archive file nor a directory
    if (!file.isArchive())
        return false;
    // 'Cast' the file as an archive file
    AbstractArchiveFile archiveFile = file.getAncestor(AbstractArchiveFile.class);
    String destSeparator = destFolder.getSeparator();
    // Unpack the archive, copying entries one by one, in the iterator's order
    try (ArchiveEntryIterator iterator = archiveFile.getEntryIterator()) {
        ArchiveEntry entry;
        while ((entry = iterator.nextEntry()) != null && getState() != FileJobState.INTERRUPTED) {
            String entryPath = entry.getPath();
            boolean processEntry = false;
            if (selectedEntries == null) {
                // Entries are processed
                processEntry = true;
            } else {
                // We need to determine if the entry should be processed or not
                // Process this entry if the selectedEntries set contains this entry, or a parent of this entry
                int nbSelectedEntries = selectedEntries.size();
                for (int i = 0; i < nbSelectedEntries; i++) {
                    ArchiveEntry selectedEntry = selectedEntries.get(i);
                    // selectedEntry is a parent of the current entry.
                    if (selectedEntry.isDirectory()) {
                        if (entryPath.startsWith(selectedEntry.getPath())) {
                            processEntry = true;
                            break;
                        // Note: we can't remove selectedEntryPath from the set, we still need it
                        }
                    } else if (entryPath.equals(selectedEntry.getPath())) {
                        // If the (regular file) entry is in the set, remove it as we no longer need it (will speed up
                        // subsequent searches)
                        processEntry = true;
                        selectedEntries.remove(i);
                        break;
                    }
                }
            }
            if (!processEntry)
                continue;
            DefaultMutableTreeNode entryNode = archiveFile.getArchiveEntryNode(entryPath);
            if (entryNode != null) {
                ArchiveEntry archiveEntry = (ArchiveEntry) entryNode.getUserObject();
                if (archiveEntry.isSymbolicLink()) {
                    Files.createSymbolicLink(FileSystems.getDefault().getPath(destFolder.getPath(), entry.getName()), FileSystems.getDefault().getPath(entry.getLinkTarget()));
                    continue;
                }
            }
            // Resolve the entry file
            AbstractFile entryFile = archiveFile.getArchiveEntryFile(entryPath);
            // Notify the job that we're starting to process this file
            nextFile(entryFile);
            // Figure out the destination file's path, relatively to the base destination folder
            String relDestPath = baseArchiveDepth == 0 ? entry.getPath() : PathUtils.removeLeadingFragments(entry.getPath(), "/", baseArchiveDepth);
            if (newName != null)
                relDestPath = newName + (PathUtils.getDepth(relDestPath, "/") <= 1 ? "" : "/" + PathUtils.removeLeadingFragments(relDestPath, "/", 1));
            if (!"/".equals(destSeparator))
                relDestPath = relDestPath.replace("/", destSeparator);
            // Create destination AbstractFile instance
            AbstractFile destFile = destFolder.getChild(relDestPath);
            // Check for ZipSlip (see https://snyk.io/research/zip-slip-vulnerability)
            do {
                if (destFolder.isParentOf(destFile))
                    break;
                DialogAction ret = showErrorDialog(errorDialogTitle, Translator.get("unpack.entry_out_of_target_dir", destFile.getName()));
                // Retry loops
                if (ret == FileJobAction.RETRY)
                    continue;
                // Cancel, skip or close dialog returns false
                return false;
            } while (true);
            // Check if the file does not already exist in the destination
            destFile = checkForCollision(entryFile, destFolder, destFile, false);
            if (destFile == null) {
                // A collision occurred and either the file was skipped, or the user cancelled the job
                continue;
            }
            // If the entry is a directory ...
            if (entryFile.isDirectory()) {
                // Create the directory in the destination, if it doesn't already exist
                if (!(destFile.exists() && destFile.isDirectory())) {
                    // Loop for retry
                    do {
                        try {
                            // Use mkdirs() instead of mkdir() to create any parent folder that doesn't exist yet
                            destFile.mkdirs();
                        } catch (IOException e) {
                            // Unable to create folder
                            DialogAction ret = showErrorDialog(errorDialogTitle, Translator.get("cannot_create_folder", entryFile.getName()));
                            // Retry loops
                            if (ret == FileJobAction.RETRY)
                                continue;
                            // Cancel or close dialog return false
                            return false;
                        // Skip continues
                        }
                        break;
                    } while (true);
                }
            } else // The entry is a regular file, copy it
            {
                // Create the file's parent directory(s) if it doesn't already exist
                AbstractFile destParentFile = destFile.getParent();
                if (!destParentFile.exists()) {
                    // Use mkdirs() instead of mkdir() to create any parent folder that doesn't exist yet
                    destParentFile.mkdirs();
                }
                // some archive file implementations (such as TAR) can speed things by an order of magnitude.
                if (!tryCopyFile(new ProxiedEntryFile(entryFile, entry, archiveFile, iterator), destFile, append, errorDialogTitle))
                    return false;
            }
        }
        return true;
    } catch (IOException e) {
        showErrorDialog(errorDialogTitle, Translator.get("cannot_read_file", archiveFile.getName()));
    }
    return false;
}
Also used : AbstractArchiveFile(com.mucommander.commons.file.archive.AbstractArchiveFile) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) DialogAction(com.mucommander.ui.dialog.DialogAction) ArchiveEntry(com.mucommander.commons.file.archive.ArchiveEntry) IOException(java.io.IOException) ArchiveEntryIterator(com.mucommander.commons.file.archive.ArchiveEntryIterator)

Example 8 with AbstractArchiveFile

use of com.mucommander.commons.file.archive.AbstractArchiveFile in project mucommander by mucommander.

the class CopyJob method jobCompleted.

// //////////////////////
// Overridden methods //
// //////////////////////
@Override
protected void jobCompleted() {
    super.jobCompleted();
    baseDestFolder.postCopyHook();
    // If the destination files are located inside an archive, optimize the archive file
    AbstractArchiveFile archiveFile = baseDestFolder.getParentArchive();
    if (archiveFile != null && archiveFile.isArchive() && archiveFile.isWritable())
        optimizeArchive((AbstractRWArchiveFile) archiveFile);
    // select the copied file in the active table after this job has finished (and hasn't been cancelled)
    if (files.size() == 1 && newName != null && baseDestFolder.equalsCanonical(files.elementAt(0).getParent())) {
        // Resolve new file instance now that it exists: some remote files do not immediately update file attributes
        // after creation, we need to get an instance that reflects the newly created file attributes
        selectFileWhenFinished(FileFactory.getFile(baseDestFolder.getAbsolutePath(true) + newName));
    }
}
Also used : AbstractArchiveFile(com.mucommander.commons.file.archive.AbstractArchiveFile) AbstractRWArchiveFile(com.mucommander.commons.file.archive.AbstractRWArchiveFile)

Example 9 with AbstractArchiveFile

use of com.mucommander.commons.file.archive.AbstractArchiveFile in project mucommander by mucommander.

the class DeleteJob method jobCompleted.

@Override
protected void jobCompleted() {
    super.jobCompleted();
    // If the source files are located inside an archive, optimize the archive file
    AbstractArchiveFile archiveFile = getBaseSourceFolder().getParentArchive();
    if (archiveFile != null && archiveFile.isArchive() && archiveFile.isWritable()) {
        while (true) {
            try {
                archiveToOptimize = ((AbstractRWArchiveFile) archiveFile);
                isOptimizingArchive = true;
                archiveToOptimize.optimizeArchive();
                break;
            } catch (IOException e) {
                if (showErrorDialog(errorDialogTitle, Translator.get("error_while_optimizing_archive", archiveFile.getName())) == FileJobAction.RETRY)
                    continue;
                break;
            }
        }
        isOptimizingArchive = true;
    }
}
Also used : AbstractArchiveFile(com.mucommander.commons.file.archive.AbstractArchiveFile) IOException(java.io.IOException) AbstractRWArchiveFile(com.mucommander.commons.file.archive.AbstractRWArchiveFile)

Aggregations

AbstractArchiveFile (com.mucommander.commons.file.archive.AbstractArchiveFile)9 AbstractRWArchiveFile (com.mucommander.commons.file.archive.AbstractRWArchiveFile)4 IOException (java.io.IOException)4 ArchiveEntry (com.mucommander.commons.file.archive.ArchiveEntry)3 AbstractFile (com.mucommander.commons.file.AbstractFile)2 AbstractArchiveEntryFile (com.mucommander.commons.file.archive.AbstractArchiveEntryFile)2 CopyJob (com.mucommander.job.impl.CopyJob)2 TransferFileJob (com.mucommander.job.impl.TransferFileJob)2 UnpackJob (com.mucommander.job.impl.UnpackJob)2 Vector (java.util.Vector)2 ArchiveEntryIterator (com.mucommander.commons.file.archive.ArchiveEntryIterator)1 FilePool (com.mucommander.commons.file.util.FilePool)1 PathTokenizer (com.mucommander.commons.file.util.PathTokenizer)1 DialogAction (com.mucommander.ui.dialog.DialogAction)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 URL (java.net.URL)1 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)1