mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
Fix: Centralize default download path and enhance path validation logic
This commit is contained in:
@@ -16,11 +16,14 @@ async function downloadController(req, res) {
|
||||
};
|
||||
|
||||
if (!options.url || !isValidUrl(options.url)) return res.status(400).send("❌ Invalid URL !");
|
||||
if (options.outputFolder && !isSafePath(options.outputFolder)) return res.status(400).send("❌ Save Path Not Allowed.");
|
||||
if (options.outputFolder && !isSafePath(options.outputFolder)) {
|
||||
logger.warn(`Unsafe download path rejected: ${options.outputFolder}`);
|
||||
return res.status(400).send("❌ Save Path Not Allowed.");
|
||||
}
|
||||
|
||||
// Get output folder when the download is finished,
|
||||
const filePath = await fetchDownload(options, listeners, speedListeners);
|
||||
notifyDownloadFinished(filePath);
|
||||
// Get output folder when the download is finished
|
||||
const outputFolder = await fetchDownload(options, listeners, speedListeners);
|
||||
notifyDownloadFinished(outputFolder);
|
||||
res.send("✅ Download Done !");
|
||||
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const { app } = require("electron");
|
||||
const config = require("../../config");
|
||||
|
||||
const { logger } = require("../logger.js");
|
||||
|
||||
// Centralisation de tous les chemins de ressources
|
||||
// Centralized resource paths
|
||||
const resourcesPath = config.localMode
|
||||
? path.join(__dirname, "../../ressources")
|
||||
: process.resourcesPath;
|
||||
|
||||
// Chemins des binaires
|
||||
// Default download folder (centralized)
|
||||
const defaultDownloadFolder = path.join(os.homedir(), "Downloads", "Freedom Loader");
|
||||
|
||||
// Binary paths
|
||||
let userYtDlp;
|
||||
let ffmpegPath;
|
||||
let denoPath;
|
||||
@@ -32,14 +36,14 @@ if (config.localMode) {
|
||||
|
||||
}
|
||||
|
||||
// Chemins des icônes de notification
|
||||
// Notification icon paths
|
||||
const iconPaths = {
|
||||
confirm: path.join(resourcesPath, "confirm-icon.png"),
|
||||
error: path.join(resourcesPath, "error.png"),
|
||||
app: path.join(resourcesPath, "app-icon.ico")
|
||||
};
|
||||
|
||||
// Chemins des binaires pour vérification
|
||||
// Binary paths for verification
|
||||
const binaryPaths = {
|
||||
ytDlp: path.join(resourcesPath, "binaries", "yt-dlp.exe"),
|
||||
ffmpeg: path.join(resourcesPath, "binaries", "ffmpeg.exe"),
|
||||
@@ -51,4 +55,4 @@ if (!userYtDlp){ logger.error("Missing YT-DLP")}
|
||||
if (!ffmpegPath){ logger.error("Missing FFMPEG")}
|
||||
if (!denoPath){ logger.error("Missing DENO")}
|
||||
|
||||
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath };
|
||||
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder };
|
||||
|
||||
@@ -12,10 +12,35 @@ function isValidUrl(url) {
|
||||
}
|
||||
|
||||
function isSafePath(folder) {
|
||||
if (!folder || folder.length < 3) return false;
|
||||
const unsafe = ["System32", "/etc", "\\Windows"];
|
||||
const resolved = path.resolve(folder);
|
||||
return !unsafe.some(u => resolved.includes(u));
|
||||
if (!folder || typeof folder !== "string") return false;
|
||||
|
||||
try {
|
||||
// Normalize path and resolve symlinks
|
||||
const resolved = path.resolve(folder).toLowerCase().replace(/\//g, "\\");
|
||||
|
||||
// Block Windows system directories (on any drive)
|
||||
const unsafePaths = [
|
||||
"\\windows\\",
|
||||
"\\system32\\",
|
||||
"\\program files\\",
|
||||
"\\program files (x86)\\",
|
||||
"\\programdata\\",
|
||||
"\\$recycle.bin\\",
|
||||
"\\system volume information\\"
|
||||
];
|
||||
|
||||
// Check if path contains any unsafe directory
|
||||
if (unsafePaths.some(unsafe => resolved.includes(unsafe))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow all drives (C:, D:, E:, etc.) but block system folders
|
||||
return true;
|
||||
|
||||
} catch (err) {
|
||||
// In case of path resolution error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { isValidUrl, isSafePath };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { execFile } = require("child_process");
|
||||
const { userYtDlp } = require("../helpers/path");
|
||||
const path = require("path");
|
||||
const { userYtDlp, defaultDownloadFolder } = require("../helpers/path");
|
||||
const fs = require("fs");
|
||||
const { logger } = require("../logger");
|
||||
const { buildYtDlpArgs } = require("../helpers/buildArgs");
|
||||
@@ -9,8 +8,16 @@ const notify = require("../helpers/notify")
|
||||
function fetchDownload(options, listeners, speedListeners) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const outputFolder = options.outputFolder || path.join(process.env.USERPROFILE, "Downloads", "Freedom Loader");
|
||||
fs.mkdirSync(outputFolder, { recursive: true });
|
||||
const outputFolder = options.outputFolder || defaultDownloadFolder;
|
||||
|
||||
// Create download folder if it doesn't exist
|
||||
try {
|
||||
fs.mkdirSync(outputFolder, { recursive: true });
|
||||
logger.info(`Output folder ready: ${outputFolder}`);
|
||||
} catch (err) {
|
||||
logger.error(`Failed to create output folder: ${err.message}`);
|
||||
return reject(new Error(`Unable to create download folder: ${err.message}`));
|
||||
}
|
||||
|
||||
const args = buildYtDlpArgs({ ...options, outputFolder });
|
||||
logger.info(`[yt-dlp args] ${args.join(" ")}`);
|
||||
@@ -31,7 +38,7 @@ function fetchDownload(options, listeners, speedListeners) {
|
||||
if (!line.trim()) return;
|
||||
logger.info(`[yt-dlp] ${line}`);
|
||||
|
||||
/* Barre de Chargement*/
|
||||
/* Progress Bar */
|
||||
if (line.startsWith("[download] Destination:")) listeners.forEach(fn => fn("reset"));
|
||||
const match = line.match(/\[download\]\s+(\d+\.\d+)%/);
|
||||
if (match) listeners.forEach(fn => fn(parseFloat(match[1])));
|
||||
|
||||
Reference in New Issue
Block a user