From afe0aed976f5eeaff4cbd7e42947315c45314a80 Mon Sep 17 00:00:00 2001 From: TheDevRyan <175502913+The-Dev-Ryan@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:33:09 +0000 Subject: [PATCH] Improve plugin file handling and cleanup logic (#7434) * Improve plugin file handling and cleanup logic Adds checks and fallbacks for temporary directory write access when creating plugin zip files, and enhances error handling when creating write streams. Updates plugin removal to use fs.rmSync with force and recursive options, and adds error handling for directory removal. * Update pluginHandler.js --- pluginHandler.js | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/pluginHandler.js b/pluginHandler.js index 25171596..6276cb4e 100644 --- a/pluginHandler.js +++ b/pluginHandler.js @@ -384,10 +384,34 @@ module.exports.pluginHandler = function (parent) { parent.db.getPlugin(id, function (err, docs) { // the "id" would probably suffice, but is probably an sanitary issue, generate a random instead var randId = Math.random().toString(32).replace('0.', ''); - var fileName = obj.parent.path.join(require('os').tmpdir(), 'Plugin_' + randId + '.zip'); + var tmpDir = require('os').tmpdir(); + var fileName = obj.parent.path.join(tmpDir, 'Plugin_' + randId + '.zip'); + try { + obj.fs.accessSync(tmpDir, obj.fs.constants.W_OK); + } catch (e) { + var pluginTmpPath = obj.parent.path.join(obj.pluginPath, '_tmp'); + if (!obj.fs.existsSync(pluginTmpPath)) { + obj.fs.mkdirSync(pluginTmpPath, { recursive: true }); + } + fileName = obj.parent.path.join(pluginTmpPath, 'Plugin_' + randId + '.zip'); + } var plugin = docs[0]; if (plugin.repository.type == 'git') { - const file = obj.fs.createWriteStream(fileName); + var file; + try { + file = obj.fs.createWriteStream(fileName); + } catch (e) { + if (fileName.indexOf(tmpDir) >= 0) { + var pluginTmpPath = obj.parent.path.join(obj.pluginPath, '_tmp'); + if (!obj.fs.existsSync(pluginTmpPath)) { + obj.fs.mkdirSync(pluginTmpPath, { recursive: true }); + } + fileName = obj.parent.path.join(pluginTmpPath, 'Plugin_' + randId + '.zip'); + file = obj.fs.createWriteStream(fileName); + } else { + throw e; + } + } var dl_url = plugin.downloadUrl; if (version_only != null && version_only != false) dl_url = version_only.url; if (force_url != null) dl_url = force_url; @@ -411,7 +435,7 @@ module.exports.pluginHandler = function (parent) { var request = http.get(opts, function (response) { // handle redirections with grace if (response.headers.location) { - file.close(function () { obj.fs.unlink(file.path, function(err) { void err; }); }); + file.close(() => obj.fs.unlink(fileName, () => {})); return obj.installPlugin(id, version_only, response.headers.location, func); } response.pipe(file); @@ -544,7 +568,13 @@ module.exports.pluginHandler = function (parent) { parent.db.getPlugin(id, function (err, docs) { var plugin = docs[0]; let pluginPath = obj.parent.path.join(obj.pluginPath, plugin.shortName); - obj.fs.rmdirSync(pluginPath, { recursive: true }); + if (obj.fs.existsSync(pluginPath)) { + try { + obj.fs.rmSync(pluginPath, { recursive: true, force: true }); + } catch (e) { + console.log("Error removing plugin directory:", e); + } + } parent.db.deletePlugin(id, func); delete obj.plugins[plugin.shortName]; });