Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiple download and browse while downloading #1242

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 91 additions & 5 deletions tinyfilemanager.php
Original file line number Diff line number Diff line change
Expand Up @@ -891,23 +891,38 @@ function get_file_path () {

// Download
if (isset($_GET['dl'], $_POST['token'])) {
if(!verifyToken($_POST['token'])) {
// Verify the token to ensure it's valid
if (!verifyToken($_POST['token'])) {
fm_set_msg("Invalid Token.", 'error');
exit;
}

// Clean the download file path
$dl = urldecode($_GET['dl']);
$dl = fm_clean_path($dl);
$dl = str_replace('/', '', $dl);
$dl = fm_clean_path($dl);
$dl = str_replace('/', '', $dl); // Prevent directory traversal attacks

// Define the file path
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}

// Check if the file exists and is valid
if ($dl != '' && is_file($path . '/' . $dl)) {
fm_download_file($path . '/' . $dl, $dl, 1024);
// Close the session to prevent session locking
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}

// Call the download function
fm_download_file($path . '/' . $dl, $dl, 1024); // Download with a buffer size of 1024 bytes
exit;
} else {
// Handle the case where the file is not found
fm_set_msg(lng('File not found'), 'error');
$FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
}

Expand Down Expand Up @@ -1053,6 +1068,75 @@ function get_file_path () {
exit();
}

// Mass downloading
if (isset($_POST['group'], $_POST['download'], $_POST['token']) && !FM_READONLY) {

// Verify token to ensure it's valid
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng("Invalid Token."), 'error');
exit;
}

$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}

$errors = 0;
$files = $_POST['file']; // List of selected files
if (is_array($files) && count($files)) {

// Create a new ZIP archive
$zip = new ZipArchive();
$zip_filename = 'download_' . date('Y-m-d_H-i-s') . '.zip';
$zip_filepath = sys_get_temp_dir() . '/' . $zip_filename;

if ($zip->open($zip_filepath, ZipArchive::CREATE) !== TRUE) {
fm_set_msg(lng('Cannot create ZIP file'), 'error');
$FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}

foreach ($files as $f) {
if ($f != '') {
$new_path = $path . '/' . fm_clean_path($f); // Sanitize the file path

if (is_file($new_path)) {
// Add the file to the ZIP archive
$zip->addFile($new_path, basename($new_path));
} else {
$errors++;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It clearly does not work with folders, so prompting Download selected files and folders? is misleading.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vadasziattila can you add folder as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here is a good opportunity to make good use of the included FM_Zipper class.
Just a suggestion, but this would work okay:

// Mass downloading
if (isset($_POST['group'], $_POST['download'], $_POST['token']) && !FM_READONLY) {

    // Verify token to ensure it's valid
    if(!verifyToken($_POST['token'])) {
        fm_set_msg(lng("Invalid Token."), 'error');
        exit;
    }

    $path = FM_ROOT_PATH;
    if (FM_PATH != '') {
        $path .= '/' . FM_PATH;
    }

    $files = $_POST['file']; // List of selected files
    if (is_array($files) && count($files)) {
        // Create a new ZIP archive
        $zip = new FM_Zipper();
        $zip_filename = 'download_' . date('Y-m-d_H-i-s') . '.zip';
        $zip_filepath = sys_get_temp_dir() . '/' . $zip_filename;

        chdir($path);
        $sanitized_filepaths = array();
        foreach($files as $f){
            if ($f != '') {
                array_push($sanitized_filepaths, fm_clean_path($f)); // Sanitize the file path
            }
        }
        $res = $zip->create($zip_filepath, $sanitized_filepaths);

        if ($res && file_exists($zip_filepath)) {
            // Serve the ZIP file for download
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . $zip_filename . '"');
            header('Content-Length: ' . filesize($zip_filepath));
            readfile($zip_filepath);
            // Remove the ZIP file from the temporary directory after download
            unlink($zip_filepath);
            exit;
        } else {
            fm_set_msg(lng('Error creating ZIP file'), 'error');
        }
    } else {
        fm_set_msg(lng('Nothing selected'), 'alert');
    }

    $FM_PATH = FM_PATH;
    fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}

}
}
}

// Close the ZIP archive
$zip->close();

// Check for errors
if ($errors == 0) {
// Serve the ZIP file for download
if (file_exists($zip_filepath)) {
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zip_filename . '"');
header('Content-Length: ' . filesize($zip_filepath));
readfile($zip_filepath);
// Remove the ZIP file from the temporary directory after download
unlink($zip_filepath);
exit;
} else {
fm_set_msg(lng('Error creating ZIP file'), 'error');
}
} else {
fm_set_msg(lng('Error while adding items to ZIP'), 'error');
}
} else {
fm_set_msg(lng('Nothing selected'), 'alert');
}

$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}

// Mass deleting
if (isset($_POST['group'], $_POST['delete'], $_POST['token']) && !FM_READONLY) {

Expand Down Expand Up @@ -2225,6 +2309,8 @@ class="edit-file"><i class="fa fa-pencil-square-o"></i> <?php echo lng('Advanced
<li class="list-inline-item"> <a href="#/select-all" class="btn btn-small btn-outline-primary btn-2" onclick="select_all();return false;"><i class="fa fa-check-square"></i> <?php echo lng('SelectAll') ?> </a></li>
<li class="list-inline-item"><a href="#/unselect-all" class="btn btn-small btn-outline-primary btn-2" onclick="unselect_all();return false;"><i class="fa fa-window-close"></i> <?php echo lng('UnSelectAll') ?> </a></li>
<li class="list-inline-item"><a href="#/invert-all" class="btn btn-small btn-outline-primary btn-2" onclick="invert_all();return false;"><i class="fa fa-th-list"></i> <?php echo lng('InvertSelection') ?> </a></li>
<li class="list-inline-item"><input type="submit" class="hidden" name="download" id="a-download" value="Download" onclick="return confirm('<?php echo lng('Download selected files and folders?'); ?>')">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Download selected files and folders?
Does it work for folders though?

<a href="javascript:document.getElementById('a-download').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-download"></i> <?php echo lng('Download') ?> </a></li>
<li class="list-inline-item"><input type="submit" class="hidden" name="delete" id="a-delete" value="Delete" onclick="return confirm('<?php echo lng('Delete selected files and folders?'); ?>')">
<a href="javascript:document.getElementById('a-delete').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-trash"></i> <?php echo lng('Delete') ?> </a></li>
<li class="list-inline-item"><input type="submit" class="hidden" name="zip" id="a-zip" value="zip" onclick="return confirm('<?php echo lng('Create archive?'); ?>')">
Expand Down