diff --git a/src/backend/src/routers/down.js b/src/backend/src/routers/down.js index 77506911..78f13de3 100644 --- a/src/backend/src/routers/down.js +++ b/src/backend/src/routers/down.js @@ -25,14 +25,19 @@ const fs = require('../middleware/fs.js'); const { DB_WRITE } = require('../services/database/consts.js'); const { NodePathSelector } = require('../filesystem/node/selectors.js'); const { HLRead } = require('../filesystem/hl_operations/hl_read.js'); +const { UserActorType } = require('../services/auth/Actor.js'); // -----------------------------------------------------------------------// // GET /down // -----------------------------------------------------------------------// -router.post('/down', auth, fs, express.json(), async (req, res, next)=>{ +router.post('/down', auth, fs, express.json(), express.urlencoded({ extended: true }), async (req, res, next)=>{ // check subdomain - if(require('../helpers').subdomain(req) !== 'api') - next(); + const actor = req.actor; + + if ( ! actor || !(actor.type instanceof UserActorType) ) { + if(require('../helpers').subdomain(req) !== 'api') + next(); + } // check if user is verified if((config.strict_email_verification_required || req.user.requires_email_confirmation) && !req.user.email_confirmed) @@ -74,6 +79,12 @@ router.post('/down', auth, fs, express.json(), async (req, res, next)=>{ // stream data from S3 try{ + const esc_filename = (await fsnode.get('name')) + .replace(/[^a-zA-Z0-9-_\.]/g, '_'); + + res.setHeader('Content-Type', 'application/octet-stream'); + res.attachment(await fsnode.get('name')); + const hl_read = new HLRead(); const stream = await hl_read.run({ fsNode: fsnode, @@ -85,7 +96,6 @@ router.post('/down', auth, fs, express.json(), async (req, res, next)=>{ // }).createReadStream().on('error', error => { // console.log(error); // }); - res.attachment(await fsnode.get('name')); return stream.pipe(res); }catch(e){ console.log(e); diff --git a/src/gui/src/helpers.js b/src/gui/src/helpers.js index ab8500b8..3a5c404f 100644 --- a/src/gui/src/helpers.js +++ b/src/gui/src/helpers.js @@ -1225,6 +1225,36 @@ window.move_clipboard_items = function (el_target_container, target_path){ window.clipboard = []; } +function downloadFile(url, postData = {}) { + // Create a hidden iframe to trigger the download + const iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + document.body.appendChild(iframe); + + // Create a form in the iframe for the POST request + const form = document.createElement('form'); + form.action = url; + form.method = 'POST'; + iframe.contentDocument.body.appendChild(form); + + // Add POST data to the form + Object.entries(postData).forEach(([key, value]) => { + const input = document.createElement('input'); + input.type = 'hidden'; + input.name = key; + input.value = value; + form.appendChild(input); + }); + + // Submit the form to trigger the download + form.submit(); + + // Cleanup after a short delay (to ensure download starts) + setTimeout(() => { + document.body.removeChild(iframe); + }, 1000); +} + /** * Initiates a download for multiple files provided as an array of paths. * @@ -1250,7 +1280,7 @@ window.trigger_download = (paths)=>{ let urls = []; for (let index = 0; index < paths.length; index++) { urls.push({ - download: window.api_origin + "/down?path=" + paths[index], + download: window.origin + "/down?path=" + paths[index], filename: path.basename(paths[index]), }); } @@ -1267,6 +1297,10 @@ window.trigger_download = (paths)=>{ const { token } = await resp.json(); return token; })(); + + downloadFile(e.download, { anti_csrf }); + return; + fetch(e.download, { method: 'POST', headers: { @@ -1281,6 +1315,7 @@ window.trigger_download = (paths)=>{ .then(blob => { saveAs(blob, e.filename); }); + }); }