From 22675b4895c3824ff863f711045c9e12de5b3ddd Mon Sep 17 00:00:00 2001 From: HowToMeetLadies Date: Sat, 26 Apr 2025 19:40:48 +0200 Subject: [PATCH 1/2] fix: prevent file descriptor leaks by replacing direct fs.readFileSync usage Moved file reading logic to a new FileHelper (app/back-end/helpers/file.js) using openSync, readSync, and closeSync to ensure file descriptors are properly managed. Replaced all occurrences of fs.readFileSync with the new helper. Branch: fix-readFileSync-fd-leak --- app/back-end/app.js | 17 ++++++------ app/back-end/author.js | 3 ++- app/back-end/events/app.js | 7 ++--- app/back-end/events/credits.js | 3 ++- app/back-end/events/page.js | 5 ++-- app/back-end/events/plugins-api.js | 7 ++--- app/back-end/events/site.js | 7 ++--- app/back-end/events/sync.js | 3 ++- app/back-end/helpers/file.js | 26 +++++++++++++++++++ app/back-end/helpers/updates.helper.js | 3 ++- app/back-end/helpers/utils.js | 3 ++- .../helpers/validators/language-config.js | 4 +-- .../helpers/validators/plugin-config.js | 4 +-- app/back-end/image.js | 5 ++-- app/back-end/languages.js | 7 ++--- app/back-end/modules/backup/backup.js | 3 ++- .../modules/backup/create-from-backup.js | 3 ++- app/back-end/modules/deploy/deployment.js | 13 +++++----- app/back-end/modules/deploy/ftp-alt.js | 3 ++- app/back-end/modules/deploy/github-pages.js | 5 ++-- app/back-end/modules/deploy/gitlab-pages.js | 6 ++--- app/back-end/modules/deploy/google-cloud.js | 3 ++- app/back-end/modules/deploy/sftp.js | 5 ++-- app/back-end/modules/import/wxr-parser.js | 3 ++- .../modules/plugins/plugins-helpers.js | 6 ++--- .../render-html/handlebars/helpers/css.js | 5 ++-- .../render-html/handlebars/helpers/js.js | 5 ++-- .../modules/render-html/helpers/gdpr.js | 8 +++--- .../modules/render-html/helpers/sitemap.js | 5 ++-- .../modules/render-html/helpers/template.js | 7 ++--- .../modules/render-html/renderer-cache.js | 3 ++- .../modules/render-html/renderer-context.js | 4 +-- .../modules/render-html/renderer-plugins.js | 3 ++- app/back-end/modules/render-html/renderer.js | 21 ++++++++------- .../render-html/validators/theme-config.js | 4 +-- app/back-end/plugins.js | 13 +++++----- app/back-end/site.js | 9 ++++--- app/back-end/themes.js | 23 ++++++++-------- 38 files changed, 160 insertions(+), 104 deletions(-) create mode 100644 app/back-end/helpers/file.js diff --git a/app/back-end/app.js b/app/back-end/app.js index 07618343d..1c472fd3a 100644 --- a/app/back-end/app.js +++ b/app/back-end/app.js @@ -24,6 +24,7 @@ const Plugins = require('./plugins.js'); const DBUtils = require('./helpers/db.utils.js'); const Site = require('./site.js'); const Utils = require('./helpers/utils.js'); +const FileHelper = require('./helpers/file.js'); // List of the Event classes const EventClasses = require('./events/_modules.js'); // Migration classes @@ -52,7 +53,7 @@ class App { this.initPath = path.join(this.appDir, 'config', 'window-config.json'); this.appConfigPath = path.join(this.appDir, 'config', 'app-config.json'); this.tinymceOverridedConfigPath = path.join(this.appDir, 'config', 'tinymce.override.json'); - this.versionData = JSON.parse(fs.readFileSync(__dirname + '/builddata.json', 'utf8')); + this.versionData = JSON.parse(FileHelper.readFileSync(__dirname + '/builddata.json', 'utf8')); this.windowBounds = null; this.appConfig = null; this.tinymceOverridedConfig = {}; @@ -165,8 +166,8 @@ class App { // Check if both config.json files exists if (fs.existsSync(appThemeConfig) && fs.existsSync(userThemeConfig)) { - let appThemeData = JSON.parse(fs.readFileSync(appThemeConfig, 'utf8')); - let userThemeData = JSON.parse(fs.readFileSync(userThemeConfig, 'utf8')); + let appThemeData = JSON.parse(FileHelper.readFileSync(appThemeConfig, 'utf8')); + let userThemeData = JSON.parse(FileHelper.readFileSync(userThemeConfig, 'utf8')); // If app theme is newer version than the existing one if(compare(appThemeData.version, userThemeData.version) === 1) { @@ -231,7 +232,7 @@ class App { let themeDir = path.join(siteDir, 'input', 'themes', themes.currentTheme(true)); let themeOverridesDir = path.join(siteDir, 'input', 'themes', themes.currentTheme(true) + '-override'); let themeConfig = Themes.loadThemeConfig(themeConfigPath, themeDir); - let menuStructure = fs.readFileSync(menuConfigPath, 'utf8'); + let menuStructure = FileHelper.readFileSync(menuConfigPath, 'utf8'); let parsedMenuStructure = {}; try { @@ -283,7 +284,7 @@ class App { // Load the config let defaultSiteConfig = JSON.parse(JSON.stringify(defaultAstCurrentSiteConfig)); - let siteConfig = fs.readFileSync(configFilePath); + let siteConfig = FileHelper.readFileSync(configFilePath); siteConfig = JSON.parse(siteConfig); if (siteConfig.name !== siteName) { @@ -437,7 +438,7 @@ class App { loadConfig () { // Try to get window bounds try { - this.windowBounds = JSON.parse(fs.readFileSync(this.initPath, 'utf8')); + this.windowBounds = JSON.parse(FileHelper.readFileSync(this.initPath, 'utf8')); } catch (e) { console.log('The window-config.json file will be created'); } @@ -490,7 +491,7 @@ class App { // Try to get application config try { - this.appConfig = JSON.parse(fs.readFileSync(this.appConfigPath, 'utf8')); + this.appConfig = JSON.parse(FileHelper.readFileSync(this.appConfigPath, 'utf8')); this.appConfig = Utils.mergeObjects(JSON.parse(JSON.stringify(defaultAstAppConfig)), this.appConfig); } catch (e) { if (this.hasPermissionsErrors(e)) { @@ -518,7 +519,7 @@ class App { loadAdditionalConfig () { // Try to get TinyMCE overrided config try { - this.tinymceOverridedConfig = JSON.parse(fs.readFileSync(this.tinymceOverridedConfigPath, 'utf8')); + this.tinymceOverridedConfig = JSON.parse(FileHelper.readFileSync(this.tinymceOverridedConfigPath, 'utf8')); } catch (e) {} if (this.appConfig.sitesLocation) { diff --git a/app/back-end/author.js b/app/back-end/author.js index 8549d0866..5ff97579f 100644 --- a/app/back-end/author.js +++ b/app/back-end/author.js @@ -8,6 +8,7 @@ const slug = require('./helpers/slug'); const ImageHelper = require('./helpers/image.helper.js'); const Themes = require('./themes.js'); const Utils = require('./helpers/utils.js'); +const FileHelper = require('./helpers/file.js'); /** * Author Model - used for operations connected with author management @@ -366,7 +367,7 @@ class Author extends Model { let themeConfigPath = path.join(this.application.sitesDir, this.site, 'input', 'config', 'theme.config.json'); if (fs.existsSync(themeConfigPath)) { - let themeConfigString = fs.readFileSync(themeConfigPath, 'utf8'); + let themeConfigString = FileHelper.readFileSync(themeConfigPath, 'utf8'); themesHelper.checkAndCleanImages(themeConfigString); } } diff --git a/app/back-end/events/app.js b/app/back-end/events/app.js index 926f32e06..0ef9f8ea6 100644 --- a/app/back-end/events/app.js +++ b/app/back-end/events/app.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('../helpers/file.js'); const ipcMain = require('electron').ipcMain; const Themes = require('../themes.js'); const Languages = require('../languages.js'); @@ -97,7 +98,7 @@ class AppEvents { * Save app color theme config */ ipcMain.on('app-save-color-theme', function (event, theme) { - let appConfig = fs.readFileSync(appInstance.appConfigPath, 'utf8'); + let appConfig = FileHelper.readFileSync(appInstance.appConfigPath, 'utf8'); try { appConfig = JSON.parse(appConfig); @@ -440,7 +441,7 @@ class AppEvents { } let filePath = path.join(appInstance.app.getPath('logs'), filename); - let fileContent = fs.readFileSync(filePath, 'utf8'); + let fileContent = FileHelper.readFileSync(filePath, 'utf8'); event.sender.send('app-log-file-loaded', { fileContent: fileContent @@ -458,7 +459,7 @@ class AppEvents { return; } - let appConfig = fs.readFileSync(appInstance.appConfigPath, 'utf8'); + let appConfig = FileHelper.readFileSync(appInstance.appConfigPath, 'utf8'); try { appConfig = JSON.parse(appConfig); diff --git a/app/back-end/events/credits.js b/app/back-end/events/credits.js index ae7ab5f61..e728e4a73 100644 --- a/app/back-end/events/credits.js +++ b/app/back-end/events/credits.js @@ -1,6 +1,7 @@ const fs = require('fs-extra'); const path = require('path'); const ipcMain = require('electron').ipcMain; +const FileHelper = require('../helpers/file.js'); /* * Events for the IPC communication regarding credits @@ -18,7 +19,7 @@ class CreditsEvents { } if(fs.existsSync(filePath)) { - licenseText = fs.readFileSync(filePath, 'utf-8'); + licenseText = FileHelper.readFileSync(filePath, 'utf-8'); } event.sender.send('app-license-loaded', licenseText); diff --git a/app/back-end/events/page.js b/app/back-end/events/page.js index d6d1748c2..01d5968ee 100644 --- a/app/back-end/events/page.js +++ b/app/back-end/events/page.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const FileHelper = require('../helpers/file.js'); const ipcMain = require('electron').ipcMain; const Page = require('../page.js'); @@ -85,7 +86,7 @@ class PageEvents { let pagesFile = path.join(this.app.sitesDir, siteName, 'input', 'config', 'pages.config.json'); if (fs.existsSync(pagesFile)) { - let pagesHierarchy = JSON.parse(fs.readFileSync(pagesFile, { encoding: 'utf8' })); + let pagesHierarchy = JSON.parse(FileHelper.readFileSync(pagesFile, { encoding: 'utf8' })); pagesHierarchy = this.removeDuplicatedDataFromHierarchy(pagesHierarchy); event.sender.send('app-pages-hierarchy-loaded', pagesHierarchy); } else { @@ -104,7 +105,7 @@ class PageEvents { // Update pages hierarchy during post conversion ipcMain.on('app-pages-hierarchy-update', (event, postIDs) => { let pagesFile = path.join(this.app.sitesDir, pagesData.siteName, 'input', 'config', 'pages.config.json'); - let pagesHierarchy = JSON.parse(fs.readFileSync(pagesFile, { encoding: 'utf8' })); + let pagesHierarchy = JSON.parse(FileHelper.readFileSync(pagesFile, { encoding: 'utf8' })); for (let i = 0; i < postIDs.length; i++) { pagesHierarchy.push({ diff --git a/app/back-end/events/plugins-api.js b/app/back-end/events/plugins-api.js index 1cafe3158..93722783d 100644 --- a/app/back-end/events/plugins-api.js +++ b/app/back-end/events/plugins-api.js @@ -1,6 +1,7 @@ const ipcMain = require('electron').ipcMain; const fs = require('fs'); const path = require('path'); +const FileHelper = require('../helpers/file.js'); /* * Events for the IPC communication regarding plugins @@ -19,7 +20,7 @@ class PluginsApiEvents { return false; } - let fileContent = fs.readFileSync(filePath); + let fileContent = FileHelper.readFileSync(filePath); fileContent = fileContent.toString(); return fileContent; }); @@ -34,7 +35,7 @@ class PluginsApiEvents { return false; } - let fileContent = fs.readFileSync(filePath); + let fileContent = FileHelper.readFileSync(filePath); fileContent = fileContent.toString(); return fileContent; }); @@ -50,7 +51,7 @@ class PluginsApiEvents { return false; } - let fileContent = fs.readFileSync(filePath); + let fileContent = FileHelper.readFileSync(filePath); fileContent = fileContent.toString(); return fileContent; }); diff --git a/app/back-end/events/site.js b/app/back-end/events/site.js index 514e727ce..aad6e0e8b 100644 --- a/app/back-end/events/site.js +++ b/app/back-end/events/site.js @@ -1,6 +1,7 @@ const fs = require('fs-extra'); const os = require('os'); const path = require('path'); +const FileHelper = require('../helpers/file.js'); const slug = require('./../helpers/slug'); const passwordSafeStorage = require('keytar'); const ipcMain = require('electron').ipcMain; @@ -130,7 +131,7 @@ class SiteEvents { } let configFile = path.join(appInstance.sitesDir, siteName, 'input', 'config', 'site.config.json'); - let oldConfig = fs.readFileSync(configFile, 'utf8'); + let oldConfig = FileHelper.readFileSync(configFile, 'utf8'); let themesPath = path.join(appInstance.sitesDir, siteName, 'input', 'themes'); let newThemeConfig = {}; oldConfig = JSON.parse(oldConfig); @@ -340,7 +341,7 @@ class SiteEvents { let themeConfigPath = path.join(appInstance.sitesDir, siteName, 'input', 'config', 'theme.config.json'); if (fs.existsSync(themeConfigPath)) { - let themeConfigString = fs.readFileSync(themeConfigPath, 'utf8'); + let themeConfigString = FileHelper.readFileSync(themeConfigPath, 'utf8'); themesHelper.checkAndCleanImages(themeConfigString); } @@ -604,7 +605,7 @@ class SiteEvents { } let configPath = path.join(appInstance.sitesDir, siteName, 'input', 'config', 'site.config.json'); - let config = fs.readFileSync(configPath, 'utf8'); + let config = FileHelper.readFileSync(configPath, 'utf8'); try { config = JSON.parse(config); diff --git a/app/back-end/events/sync.js b/app/back-end/events/sync.js index 5b09ce1f2..8c9dfff19 100644 --- a/app/back-end/events/sync.js +++ b/app/back-end/events/sync.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('../helpers/file.js'); const ipcMain = require('electron').ipcMain; /* @@ -23,7 +24,7 @@ class SyncEvents { saveSyncStatus(status, siteName) { let configFile = path.join(this.app.sitesDir, siteName, 'input', 'config', 'site.config.json'); - let configContent = fs.readFileSync(configFile, 'utf8'); + let configContent = FileHelper.readFileSync(configFile, 'utf8'); configContent = JSON.parse(configContent); configContent.synced = status; diff --git a/app/back-end/helpers/file.js b/app/back-end/helpers/file.js new file mode 100644 index 000000000..0ae9a87c9 --- /dev/null +++ b/app/back-end/helpers/file.js @@ -0,0 +1,26 @@ +const fs = require('fs'); + +/** + * FileHelper wraps fs.readFileSync to avoid leaking file descriptors. + */ +class FileHelper { + /** + * Reads a file synchronously, ensuring the file descriptor is closed. + * @param {string|Buffer|URL|integer} path - filename or file descriptor + * @param {Object|string} [options] - options or encoding + * @returns {string|Buffer} + */ + static readFileSync(path, options) { + let fd; + try { + fd = fs.openSync(path, 'r'); + return fs.readFileSync(fd, options); + } finally { + if (fd !== undefined) { + try { fs.closeSync(fd); } catch (e) { /* ignore */ } + } + } + } +} + +module.exports = FileHelper; diff --git a/app/back-end/helpers/updates.helper.js b/app/back-end/helpers/updates.helper.js index 4e27dbd3e..987c55daa 100644 --- a/app/back-end/helpers/updates.helper.js +++ b/app/back-end/helpers/updates.helper.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const FileHelper = require('./file.js'); const https = require('https'); class UpdatesHelper { @@ -44,7 +45,7 @@ class UpdatesHelper { readExistingData () { if (fs.existsSync(this.filePath)) { - let body = fs.readFileSync(this.filePath, 'utf8'); + let body = FileHelper.readFileSync(this.filePath, 'utf8'); this.handleResponse(body); } else { this.sendError(); diff --git a/app/back-end/helpers/utils.js b/app/back-end/helpers/utils.js index e94b32ac8..31c7292df 100644 --- a/app/back-end/helpers/utils.js +++ b/app/back-end/helpers/utils.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./file.js'); const normalizePath = require('normalize-path'); /* @@ -299,7 +300,7 @@ class UtilsHelper { } try { - themeConfig = JSON.parse(fs.readFileSync(themeConfigPath)); + themeConfig = JSON.parse(FileHelper.readFileSync(themeConfigPath)); } catch(e) { console.log('The theme config.json file is corrupted'); return {}; diff --git a/app/back-end/helpers/validators/language-config.js b/app/back-end/helpers/validators/language-config.js index d3805e547..3a22756c5 100644 --- a/app/back-end/helpers/validators/language-config.js +++ b/app/back-end/helpers/validators/language-config.js @@ -1,4 +1,4 @@ -const fs = require('fs-extra'); +const FileHelper = require('../file.js'); /** * Checks if language config file meets the requirements @@ -7,7 +7,7 @@ const fs = require('fs-extra'); * @returns {boolean|string} */ function languageConfigValidator(configPath) { - let configContent = fs.readFileSync(configPath); + let configContent = FileHelper.readFileSync(configPath); let configParsed = false; try { diff --git a/app/back-end/helpers/validators/plugin-config.js b/app/back-end/helpers/validators/plugin-config.js index 94043548e..8fed22df9 100644 --- a/app/back-end/helpers/validators/plugin-config.js +++ b/app/back-end/helpers/validators/plugin-config.js @@ -1,4 +1,4 @@ -const fs = require('fs-extra'); +const FileHelper = require('../file.js'); /** * Checks if plugin config file meets the requirements @@ -7,7 +7,7 @@ const fs = require('fs-extra'); * @returns {boolean|string} */ function pluginConfigValidator(configPath) { - let configContent = fs.readFileSync(configPath); + let configContent = FileHelper.readFileSync(configPath); let configParsed = false; try { diff --git a/app/back-end/image.js b/app/back-end/image.js index 63217061c..1677528de 100644 --- a/app/back-end/image.js +++ b/app/back-end/image.js @@ -2,6 +2,7 @@ * Image instance */ +const FileHelper = require('./helpers/file.js'); const fs = require('fs-extra'); const path = require('path'); const Model = require('./model.js'); @@ -207,7 +208,7 @@ class Image extends Model { let themesHelper = new Themes(this.application, { site: this.site }); let currentTheme = themesHelper.currentTheme(); let siteConfigPath = path.join(this.siteDir, 'input', 'config', 'site.config.json'); - let siteConfig = JSON.parse(fs.readFileSync(siteConfigPath)); + let siteConfig = JSON.parse(FileHelper.readFileSync(siteConfigPath)); siteConfig = Utils.mergeObjects(defaultSiteConfig, siteConfig); let imagesQuality = 60; let alphaQuality = 100; @@ -547,7 +548,7 @@ class Image extends Model { }; // Get content of the SVG image - let svgFileContent = fs.readFileSync(imagePath, 'utf8'); + let svgFileContent = FileHelper.readFileSync(imagePath, 'utf8'); // Look for the non-percentage values in the tag let svgWidth = svgFileContent.match(/\/mi); let svgHeight = svgFileContent.match(/\/mi); diff --git a/app/back-end/languages.js b/app/back-end/languages.js index 5876d10be..ef56efe01 100644 --- a/app/back-end/languages.js +++ b/app/back-end/languages.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./helpers/file.js'); const UtilsHelper = require('./helpers/utils.js'); const languageConfigValidator = require('./helpers/validators/language-config.js'); const normalizePath = require('normalize-path'); @@ -43,7 +44,7 @@ class Languages { continue; } - let languageData = fs.readFileSync(configPath, 'utf8'); + let languageData = FileHelper.readFileSync(configPath, 'utf8'); languageData = JSON.parse(languageData); output.push({ @@ -78,7 +79,7 @@ class Languages { continue; } - let languageData = fs.readFileSync(configPath, 'utf8'); + let languageData = FileHelper.readFileSync(configPath, 'utf8'); languageData = JSON.parse(languageData); output.push({ @@ -168,7 +169,7 @@ class Languages { return false; } - let languageConfig = fs.readFileSync(configPath, 'utf8'); + let languageConfig = FileHelper.readFileSync(configPath, 'utf8'); try { languageConfig = JSON.parse(languageConfig); diff --git a/app/back-end/modules/backup/backup.js b/app/back-end/modules/backup/backup.js index cccac60a7..e0203d743 100644 --- a/app/back-end/modules/backup/backup.js +++ b/app/back-end/modules/backup/backup.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const Utils = require('./../../helpers/utils.js'); const moment = require('moment'); const archiver = require('archiver'); @@ -368,7 +369,7 @@ class Backup { * */ static checkSiteName(siteName, configFilePath) { - let configContent = fs.readFileSync(configFilePath); + let configContent = FileHelper.readFileSync(configFilePath); try { configContent = JSON.parse(configContent); diff --git a/app/back-end/modules/backup/create-from-backup.js b/app/back-end/modules/backup/create-from-backup.js index 1fe3edfc1..86a085110 100644 --- a/app/back-end/modules/backup/create-from-backup.js +++ b/app/back-end/modules/backup/create-from-backup.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const tar = require('tar-fs'); const Utils = require('./../../helpers/utils.js'); @@ -119,7 +120,7 @@ class CreateFromBackup { getSiteName () { let configFilePath = path.join(this.tempDir, 'input', 'config', 'site.config.json'); - let configContent = fs.readFileSync(configFilePath, 'utf8'); + let configContent = FileHelper.readFileSync(configFilePath, 'utf8'); let siteNameData = false; try { diff --git a/app/back-end/modules/deploy/deployment.js b/app/back-end/modules/deploy/deployment.js index e1359d806..f0a7b7a0a 100644 --- a/app/back-end/modules/deploy/deployment.js +++ b/app/back-end/modules/deploy/deployment.js @@ -1,6 +1,7 @@ // Necessary packages const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const crypto = require('crypto'); const normalizePath = require('normalize-path'); const isBinaryFileSync = require('isbinaryfile').isBinaryFileSync; @@ -152,7 +153,7 @@ class Deployment { fileList.push({ path: filePath, type: 'file', - md5: crypto.createHash('md5').update(fs.readFileSync(path.join(this.inputDir, filePath))).digest('hex') + md5: crypto.createHash('md5').update(FileHelper.readFileSync(path.join(this.inputDir, filePath))).digest('hex') }); } @@ -189,7 +190,7 @@ class Deployment { let fileSizePrepared = Buffer.from((stats.size).toString().split('')); fileMD5 = crypto.createHash('md5').update(fileSizePrepared).digest('hex'); } else { - fileMD5 = crypto.createHash('md5').update(fs.readFileSync(path.join(this.inputDir, filePath))).digest('hex'); + fileMD5 = crypto.createHash('md5').update(FileHelper.readFileSync(path.join(this.inputDir, filePath))).digest('hex'); } fileList.push({ @@ -225,7 +226,7 @@ class Deployment { let revisionID = false; if (fs.existsSync(syncRevisionPath)) { - let syncRevisionContent = fs.readFileSync(syncRevisionPath); + let syncRevisionContent = FileHelper.readFileSync(syncRevisionPath); syncRevisionContent = JSON.parse(syncRevisionContent); revisionID = syncRevisionContent.revision; } @@ -234,7 +235,7 @@ class Deployment { let isExpectedCopy = revisionID === content.revision; this.compareFilesList(isExpectedCopy); } else { - let filesToCheck = fs.readFileSync(path.join(this.configDir, 'files-remote.json')); + let filesToCheck = FileHelper.readFileSync(path.join(this.configDir, 'files-remote.json')); let checkSum = crypto.createHash('md5').update(filesToCheck).digest('hex'); let isExpectedCopy = checkSum === content.revision; this.compareFilesList(isExpectedCopy); @@ -257,7 +258,7 @@ class Deployment { let remoteFiles = false; if (remoteFileListExists) { - remoteFiles = fs.readFileSync(path.join(this.configDir, 'files-remote.json'), 'utf8'); + remoteFiles = FileHelper.readFileSync(path.join(this.configDir, 'files-remote.json'), 'utf8'); if (remoteFiles) { try { @@ -292,7 +293,7 @@ class Deployment { * Wait for user answer or just continue sync if remote files list exists */ continueSync (remoteFiles) { - let localFiles = fs.readFileSync(path.join(this.inputDir, 'files.publii.json'), 'utf8'); + let localFiles = FileHelper.readFileSync(path.join(this.inputDir, 'files.publii.json'), 'utf8'); if (localFiles) { localFiles = JSON.parse(localFiles); diff --git a/app/back-end/modules/deploy/ftp-alt.js b/app/back-end/modules/deploy/ftp-alt.js index 7c72df9fb..26d140f4a 100644 --- a/app/back-end/modules/deploy/ftp-alt.js +++ b/app/back-end/modules/deploy/ftp-alt.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const ftp = require('basic-ftp'); const passwordSafeStorage = require('keytar'); const slug = require('./../../helpers/slug'); @@ -115,7 +116,7 @@ class FTPAlt { normalizePath(path.join(this.deployment.configDir, 'remote-files.json')), normalizePath(path.join(this.deployment.outputDir, 'files.publii.json')) ); - let fileToCompare = fs.readFileSync(normalizePath(path.join(this.deployment.configDir, 'remote-files.json'))); + let fileToCompare = FileHelper.readFileSync(normalizePath(path.join(this.deployment.configDir, 'remote-files.json'))); this.deployment.checkLocalListWithRemoteList(fileToCompare); console.log(`[${ new Date().toUTCString() }] <- files.publii.json`); process.send({ diff --git a/app/back-end/modules/deploy/github-pages.js b/app/back-end/modules/deploy/github-pages.js index cc9a82002..f29ea0e3a 100644 --- a/app/back-end/modules/deploy/github-pages.js +++ b/app/back-end/modules/deploy/github-pages.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const passwordSafeStorage = require('keytar'); const slug = require('./../../helpers/slug'); const githubApi = require("github"); @@ -491,7 +492,7 @@ class GithubPages { let fileSize = fs.statSync(file.path).size; if(!this.isBinaryFile(file.path)) { - let fileContent = fs.readFileSync(file.path); + let fileContent = FileHelper.readFileSync(file.path); fileSize = fileContent.length; calculatedHash = crypto.createHash('sha1') .update("blob " + fileSize + "\0" + fileContent) @@ -518,7 +519,7 @@ class GithubPages { } createBlob(filePath) { - let fileContent = fs.readFileSync(filePath, { encoding: 'base64' }); + let fileContent = FileHelper.readFileSync(filePath, { encoding: 'base64' }); console.log(`[${ new Date().toUTCString() }] CREATE BLOB: ${filePath}`); return this.apiRequest( diff --git a/app/back-end/modules/deploy/gitlab-pages.js b/app/back-end/modules/deploy/gitlab-pages.js index 8cfdebf22..23f0618a7 100644 --- a/app/back-end/modules/deploy/gitlab-pages.js +++ b/app/back-end/modules/deploy/gitlab-pages.js @@ -2,8 +2,8 @@ * Class used to upload files to the Github Pages */ -const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const passwordSafeStorage = require('keytar'); const slug = require('./../../helpers/slug'); const { Gitlab } = require('@gitbeaker/node'); @@ -436,7 +436,7 @@ class GitlabPages { updateFilesListFile () { this.setUploadProgress(98); let localFilesListPath = path.join(this.deployment.inputDir, 'files.publii.json'); - let localFilesContent = fs.readFileSync(localFilesListPath); + let localFilesContent = FileHelper.readFileSync(localFilesListPath); let actionType = 'create'; let commit = []; @@ -497,7 +497,7 @@ class GitlabPages { } readFile (filePath) { - return Buffer.from(fs.readFileSync(filePath)).toString('base64'); + return Buffer.from(FileHelper.readFileSync(filePath)).toString('base64'); } isBinaryFile (fullPath) { diff --git a/app/back-end/modules/deploy/google-cloud.js b/app/back-end/modules/deploy/google-cloud.js index fe7a79dc7..0d7e5fc04 100644 --- a/app/back-end/modules/deploy/google-cloud.js +++ b/app/back-end/modules/deploy/google-cloud.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const { Storage } = require('@google-cloud/storage'); const normalizePath = require('normalize-path'); const stripTags = require('striptags'); @@ -99,7 +100,7 @@ class GoogleCloud { }, function(err) { if (!err) { let downloadedFilePath = path.join(self.deployment.configDir, 'temp-files-remote.json'); - let downloadedFile = fs.readFileSync(downloadedFilePath); + let downloadedFile = FileHelper.readFileSync(downloadedFilePath); self.deployment.checkLocalListWithRemoteList(downloadedFile); } else { self.deployment.compareFilesList(false); diff --git a/app/back-end/modules/deploy/sftp.js b/app/back-end/modules/deploy/sftp.js index a5906ab4c..ec7b6875f 100644 --- a/app/back-end/modules/deploy/sftp.js +++ b/app/back-end/modules/deploy/sftp.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const sftpClient = require('ssh2-sftp-client'); const passwordSafeStorage = require('keytar'); const slug = require('./../../helpers/slug'); @@ -49,7 +50,7 @@ class SFTP { connectionSettings.passphrase = passphrase; } - connectionSettings.privateKey = fs.readFileSync(keyPath); + connectionSettings.privateKey = FileHelper.readFileSync(keyPath); } this.connection.connect(connectionSettings).then(() => { @@ -378,7 +379,7 @@ class SFTP { connectionSettings.passphrase = passphrase; } - connectionSettings.privateKey = fs.readFileSync(keyPath); + connectionSettings.privateKey = FileHelper.readFileSync(keyPath); } let testFilePath = normalizePath(path.join(app.sitesDir, siteName, 'input', 'publii.test')); diff --git a/app/back-end/modules/import/wxr-parser.js b/app/back-end/modules/import/wxr-parser.js index f26c3e857..9c1c0c5de 100644 --- a/app/back-end/modules/import/wxr-parser.js +++ b/app/back-end/modules/import/wxr-parser.js @@ -1,6 +1,7 @@ const fs = require('fs'); const url = require('url'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const moment = require('moment'); const { XMLParser } = require('fast-xml-parser'); const download = require('image-downloader'); @@ -53,7 +54,7 @@ class WxrParser { */ loadFile(filePath) { this.filePath = filePath; - this.fileContent = fs.readFileSync(this.filePath, 'utf8'); + this.fileContent = FileHelper.readFileSync(this.filePath, 'utf8'); this.fileContent = this.fileContent.trim(); this.parseFile(); } diff --git a/app/back-end/modules/plugins/plugins-helpers.js b/app/back-end/modules/plugins/plugins-helpers.js index dd9efda74..5e9bd2df7 100644 --- a/app/back-end/modules/plugins/plugins-helpers.js +++ b/app/back-end/modules/plugins/plugins-helpers.js @@ -1,5 +1,5 @@ -const fs = require('fs'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); class PluginsHelpers { // Returns a list of active plugins for given site plugins config file; @@ -9,7 +9,7 @@ class PluginsHelpers { let activePlugins = []; try { - fileContent = fs.readFileSync(sitePluginsConfigPath); + fileContent = FileHelper.readFileSync(sitePluginsConfigPath); fileContent = fileContent.toString(); fileContent = JSON.parse(fileContent); } catch (e) { @@ -36,7 +36,7 @@ class PluginsHelpers { let pluginConfig; try { - pluginConfig = fs.readFileSync(pluginConfigPath); + pluginConfig = FileHelper.readFileSync(pluginConfigPath); pluginConfig = pluginConfig.toString(); pluginConfig = JSON.parse(pluginConfig); } catch (e) { diff --git a/app/back-end/modules/render-html/handlebars/helpers/css.js b/app/back-end/modules/render-html/handlebars/helpers/css.js index 47d2426e7..e9bf37e55 100644 --- a/app/back-end/modules/render-html/handlebars/helpers/css.js +++ b/app/back-end/modules/render-html/handlebars/helpers/css.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const FileHelper = require('./../../../../helpers/file.js'); const crypto = require('crypto'); const path = require('path'); const memoize = require('fast-memoize'); @@ -16,9 +17,9 @@ function getMD5(localPath, overridedLocalPath) { let fileContent = ''; if (fs.existsSync(overridedLocalPath)) { - fileContent = fs.readFileSync(overridedLocalPath); + fileContent = FileHelper.readFileSync(overridedLocalPath); } else { - fileContent = fs.readFileSync(localPath); + fileContent = FileHelper.readFileSync(localPath); } return crypto.createHash('md5').update(fileContent).digest('hex'); diff --git a/app/back-end/modules/render-html/handlebars/helpers/js.js b/app/back-end/modules/render-html/handlebars/helpers/js.js index a592d0a4f..6b94a3478 100644 --- a/app/back-end/modules/render-html/handlebars/helpers/js.js +++ b/app/back-end/modules/render-html/handlebars/helpers/js.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const FileHelper = require('./../../../../helpers/file.js'); const crypto = require('crypto'); const path = require('path'); const memoize = require('fast-memoize'); @@ -16,9 +17,9 @@ function getMD5(localPath, overridedLocalPath) { let fileContent = ''; if (fs.existsSync(overridedLocalPath)) { - fileContent = fs.readFileSync(overridedLocalPath); + fileContent = FileHelper.readFileSync(overridedLocalPath); } else { - fileContent = fs.readFileSync(localPath); + fileContent = FileHelper.readFileSync(localPath); } return crypto.createHash('md5').update(fileContent).digest('hex'); diff --git a/app/back-end/modules/render-html/helpers/gdpr.js b/app/back-end/modules/render-html/helpers/gdpr.js index e2efa88b9..59cb8b555 100644 --- a/app/back-end/modules/render-html/helpers/gdpr.js +++ b/app/back-end/modules/render-html/helpers/gdpr.js @@ -1,7 +1,7 @@ -const fs = require('fs-extra'); +const FileHelper = require('./../../../helpers/file.js'); class Gdpr { static popupHtmlOutput (configuration, renderer) { - let template = fs.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/template.html', 'utf8'); + let template = FileHelper.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/template.html', 'utf8'); let output = Gdpr.parseTemplate(configuration, template, renderer); return output; } @@ -128,12 +128,12 @@ class Gdpr { } static popupCssOutput () { - let output = fs.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/gdpr.css', 'utf8'); + let output = FileHelper.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/gdpr.css', 'utf8'); return output; } static popupJsOutput (configuration) { - let scriptCode = fs.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/gdpr.js', 'utf8'); + let scriptCode = FileHelper.readFileSync(__dirname + '/../../../../default-files/gdpr-assets/gdpr.js', 'utf8'); let consentModeScripts = ''; if (configuration.gConsentModeEnabled) { diff --git a/app/back-end/modules/render-html/helpers/sitemap.js b/app/back-end/modules/render-html/helpers/sitemap.js index 5779ccd49..58b358083 100644 --- a/app/back-end/modules/render-html/helpers/sitemap.js +++ b/app/back-end/modules/render-html/helpers/sitemap.js @@ -6,6 +6,7 @@ const fs = require('fs'); const path = require('path'); +const FileHelper = require('./../../../helpers/file.js'); const util = require('util'); const moment = require('moment'); const normalizePath = require('normalize-path'); @@ -696,7 +697,7 @@ class Sitemap { let filePath = path.join(this.baseDirectory, currentPath, subpage, 'index.html'); if (fs.existsSync(filePath)) { - let postFileContent = fs.readFileSync(filePath, 'utf8'); + let postFileContent = FileHelper.readFileSync(filePath, 'utf8'); if (postFileContent.indexOf('name="robots" content="noindex') === -1) { this.fileList.push(currentPath + '/' + subpage + '/'); @@ -776,7 +777,7 @@ class Sitemap { * Save sitemap.xml and sitemap.xsl files */ saveXML () { - let xslContent = fs.readFileSync(__dirname + '/../../../../default-files/theme-files/sitemap.xsl'); + let xslContent = FileHelper.readFileSync(__dirname + '/../../../../default-files/theme-files/sitemap.xsl'); let xslFilePath = path.join(this.baseDirectory, 'sitemap.xsl'); let sitemapFilePath = path.join(this.baseDirectory, 'sitemap.xml'); diff --git a/app/back-end/modules/render-html/helpers/template.js b/app/back-end/modules/render-html/helpers/template.js index ae582040f..5f8cf28f2 100644 --- a/app/back-end/modules/render-html/helpers/template.js +++ b/app/back-end/modules/render-html/helpers/template.js @@ -1,6 +1,7 @@ // Necessary packages const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./../../../helpers/file.js'); const minifyHTML = require('html-minifier').minify; const Utils = require('./../../../helpers/utils.js'); @@ -29,7 +30,7 @@ class TemplateHelper { // Load default config file let defaultConfigPath = path.join(__dirname, '..', '..', '..', '..', 'default-files', 'theme-files', 'config.json'); - let defaultConfig = JSON.parse(fs.readFileSync(defaultConfigPath, 'utf8')); + let defaultConfig = JSON.parse(FileHelper.readFileSync(defaultConfigPath, 'utf8')); // Return merged config return Utils.mergeObjects(defaultConfig, themeConfig); @@ -51,7 +52,7 @@ class TemplateHelper { return this.loadedTemplates[filePath]; } - this.loadedTemplates[filePath] = fs.readFileSync(filePath, 'utf8'); + this.loadedTemplates[filePath] = FileHelper.readFileSync(filePath, 'utf8'); return this.loadedTemplates[filePath]; } @@ -74,7 +75,7 @@ class TemplateHelper { return this.loadedPartialTemplates[filePath]; } - this.loadedPartialTemplates[filePath] = fs.readFileSync(filePath, 'utf8'); + this.loadedPartialTemplates[filePath] = FileHelper.readFileSync(filePath, 'utf8'); return this.loadedPartialTemplates[filePath]; } diff --git a/app/back-end/modules/render-html/renderer-cache.js b/app/back-end/modules/render-html/renderer-cache.js index f3167f8be..118753be1 100644 --- a/app/back-end/modules/render-html/renderer-cache.js +++ b/app/back-end/modules/render-html/renderer-cache.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const Page = require('./items/page'); const Post = require('./items/post'); const Author = require('./items/author'); @@ -394,7 +395,7 @@ class RendererCache { let pagesConfigPath = path.join(this.renderer.inputDir, 'config', 'pages.config.json'); if (fs.existsSync(pagesConfigPath)) { - let pagesStructure = JSON.parse(fs.readFileSync(pagesConfigPath)); + let pagesStructure = JSON.parse(FileHelper.readFileSync(pagesConfigPath)); let pagesStructureForHierarchy = JSON.parse(JSON.stringify(pagesStructure)); let flatPagesStructure = {}; let pagesStack = [...pagesStructure]; diff --git a/app/back-end/modules/render-html/renderer-context.js b/app/back-end/modules/render-html/renderer-context.js index 63dc1a0a8..2b4e0119f 100644 --- a/app/back-end/modules/render-html/renderer-context.js +++ b/app/back-end/modules/render-html/renderer-context.js @@ -1,6 +1,6 @@ // Necessary packages -const fs = require('fs'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); const slug = require('./../../helpers/slug'); const ContentHelper = require('./helpers/content'); const URLHelper = require('./helpers/url'); @@ -60,7 +60,7 @@ class RendererContext { // Menu config let menuConfigPath = path.join(this.inputDir, 'config', 'menu.config.json'); - let menuConfigContent = fs.readFileSync(menuConfigPath); + let menuConfigContent = FileHelper.readFileSync(menuConfigPath); let menuData = JSON.parse(menuConfigContent); let menus = { assigned: {}, diff --git a/app/back-end/modules/render-html/renderer-plugins.js b/app/back-end/modules/render-html/renderer-plugins.js index c53b26318..883b1de4f 100644 --- a/app/back-end/modules/render-html/renderer-plugins.js +++ b/app/back-end/modules/render-html/renderer-plugins.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const FileHelper = require('./../../helpers/file.js'); class RendererPlugins { constructor (sitePath) { @@ -201,7 +202,7 @@ class RendererPlugins { try { if (filePath) { - fileContent = fs.readFileSync(filePath).toString(); + fileContent = FileHelper.readFileSync(filePath).toString(); } else { return; } diff --git a/app/back-end/modules/render-html/renderer.js b/app/back-end/modules/render-html/renderer.js index a6a34b631..64b562656 100644 --- a/app/back-end/modules/render-html/renderer.js +++ b/app/back-end/modules/render-html/renderer.js @@ -1,5 +1,6 @@ // Necessary packages const fs = require('fs-extra'); +const FileHelper = require('./../../helpers/file.js'); const listAll = require('ls-all'); const path = require('path'); const Handlebars = require('handlebars'); @@ -545,7 +546,7 @@ class Renderer { let defaultSiteConfig = JSON.parse(JSON.stringify(defaultAstCurrentSiteConfig)); // Site config let configPath = path.join(this.inputDir, 'config', 'site.config.json'); - this.siteConfig = JSON.parse(fs.readFileSync(configPath)); + this.siteConfig = JSON.parse(FileHelper.readFileSync(configPath)); this.siteConfig = UtilsHelper.mergeObjects(defaultSiteConfig, this.siteConfig); if(this.previewMode) { @@ -613,7 +614,7 @@ class Renderer { let translations = false; try { - translations = JSON.parse(fs.readFileSync(path)); + translations = JSON.parse(FileHelper.readFileSync(path)); } catch(e) { return false; } @@ -683,7 +684,7 @@ class Renderer { if (!template && optionalPartials.indexOf(allPartials[i]) > -1) { let optionalPartialPath = path.join(__dirname, '..', '..', '..', 'default-files', 'theme-files', allPartials[i] + '.hbs'); - template = fs.readFileSync(optionalPartialPath, 'utf8'); + template = FileHelper.readFileSync(optionalPartialPath, 'utf8'); } if(!template) { @@ -1945,7 +1946,7 @@ class Renderer { cssPath = overridedCssPath; } - return fs.readFileSync(cssPath, 'utf8'); + return FileHelper.readFileSync(cssPath, 'utf8'); } /** @@ -1997,7 +1998,7 @@ class Renderer { let customCSSPath = path.join(this.sitesDir, this.siteName, 'input', 'config', 'custom-css.css'); if (UtilsHelper.fileExists(customCSSPath)) { - return fs.readFileSync(customCSSPath, 'utf8'); + return FileHelper.readFileSync(customCSSPath, 'utf8'); } return ''; @@ -2146,7 +2147,7 @@ class Renderer { if((inputFile === 'feed-xml.hbs' || inputFile === 'feed-json.hbs') && !template) { // Load default feed.hbs file if it not exists inside the theme directory let feedPath = path.join(__dirname, '..', '..', '..', 'default-files', 'theme-files', inputFile); - template = fs.readFileSync(feedPath, 'utf8'); + template = FileHelper.readFileSync(feedPath, 'utf8'); } if(!template) { @@ -2251,7 +2252,7 @@ class Renderer { */ relativizeUrlsInFile (file, outputDir) { let filePath = path.join(outputDir, file); - let content = fs.readFileSync(filePath, 'utf8'); + let content = FileHelper.readFileSync(filePath, 'utf8'); let depth = file.replace(/\\/gmi, '/').split('/').length - 2; let relativeDomain = './' + '../'.repeat(depth); @@ -2274,7 +2275,7 @@ class Renderer { return; } - let pluginsConfig = fs.readFileSync(sitePluginsConfigPath); + let pluginsConfig = FileHelper.readFileSync(sitePluginsConfigPath); try { pluginsConfig = JSON.parse(pluginsConfig); @@ -2320,7 +2321,7 @@ class Renderer { if (fs.existsSync(pluginPath)) { try { - pluginData = fs.readFileSync(pluginPath, 'utf8'); + pluginData = FileHelper.readFileSync(pluginPath, 'utf8'); pluginData = JSON.parse(pluginData); } catch (e) { pluginData = {}; @@ -2331,7 +2332,7 @@ class Renderer { if (fs.existsSync(pluginConfigPath)) { try { - pluginSavedConfig = fs.readFileSync(pluginConfigPath, 'utf8'); + pluginSavedConfig = FileHelper.readFileSync(pluginConfigPath, 'utf8'); pluginSavedConfig = JSON.parse(pluginSavedConfig); } catch (e) { pluginSavedConfig = {}; diff --git a/app/back-end/modules/render-html/validators/theme-config.js b/app/back-end/modules/render-html/validators/theme-config.js index e6db78b88..f2be4ebed 100644 --- a/app/back-end/modules/render-html/validators/theme-config.js +++ b/app/back-end/modules/render-html/validators/theme-config.js @@ -1,4 +1,4 @@ -const fs = require('fs-extra'); +const FileHelper = require('./../../../helpers/file.js'); /** * Checks if theme config file meets the requirements @@ -7,7 +7,7 @@ const fs = require('fs-extra'); * @returns {boolean|string} */ function themeConfigValidator(configPath) { - let configContent = fs.readFileSync(configPath); + let configContent = FileHelper.readFileSync(configPath); let configParsed = false; try { diff --git a/app/back-end/plugins.js b/app/back-end/plugins.js index 65a5ed684..7afd5f4f7 100644 --- a/app/back-end/plugins.js +++ b/app/back-end/plugins.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./helpers/file.js'); const UtilsHelper = require('./helpers/utils.js'); const pluginConfigValidator = require('./helpers/validators/plugin-config.js'); @@ -39,7 +40,7 @@ class Plugins { continue; } - let pluginData = fs.readFileSync(configPath, 'utf8'); + let pluginData = FileHelper.readFileSync(configPath, 'utf8'); pluginData = JSON.parse(pluginData); output.push({ @@ -103,7 +104,7 @@ class Plugins { return {}; } - let pluginsConfig = fs.readFileSync(sitePluginsConfigPath); + let pluginsConfig = FileHelper.readFileSync(sitePluginsConfigPath); try { pluginsConfig = JSON.parse(pluginsConfig); @@ -201,7 +202,7 @@ class Plugins { if (fs.existsSync(pluginPath)) { try { - let pluginData = fs.readFileSync(pluginPath, 'utf8'); + let pluginData = FileHelper.readFileSync(pluginPath, 'utf8'); output.pluginData = JSON.parse(pluginData); output.pluginData.path = path.join(this.appDir, 'plugins', pluginName); } catch (e) { @@ -213,7 +214,7 @@ class Plugins { if (fs.existsSync(pluginConfigPath)) { try { - let pluginConfig = fs.readFileSync(pluginConfigPath, 'utf8'); + let pluginConfig = FileHelper.readFileSync(pluginConfigPath, 'utf8'); output.pluginConfig = pluginConfig; } catch (e) { output.pluginConfig = {}; @@ -246,7 +247,7 @@ class Plugins { if (fs.existsSync(pluginPath)) { try { - pluginData = fs.readFileSync(pluginPath, 'utf8'); + pluginData = FileHelper.readFileSync(pluginPath, 'utf8'); pluginData = JSON.parse(pluginData); } catch (e) { pluginData = {}; @@ -257,7 +258,7 @@ class Plugins { if (fs.existsSync(pluginConfigPath)) { try { - pluginSavedConfig = fs.readFileSync(pluginConfigPath, 'utf8'); + pluginSavedConfig = FileHelper.readFileSync(pluginConfigPath, 'utf8'); pluginSavedConfig = JSON.parse(pluginConfig); } catch (e) { pluginSavedConfig = {}; diff --git a/app/back-end/site.js b/app/back-end/site.js index ea5fdc872..b2de19605 100644 --- a/app/back-end/site.js +++ b/app/back-end/site.js @@ -5,6 +5,7 @@ const fs = require('fs-extra'); const os = require('os'); const path = require('path'); +const FileHelper = require('./helpers/file.js'); const Database = os.platform() === 'linux' ? require('node-sqlite3-wasm').Database : require('better-sqlite3'); const DBUtils = require('./helpers/db.utils.js'); const Themes = require('./themes.js'); @@ -126,7 +127,7 @@ class Site { try { let db = new DBUtils(new Database(dbPath)); - db.exec(fs.readFileSync(this.application.basedir + '/back-end/sql/1.0.0.sql', 'utf8')); + db.exec(FileHelper.readFileSync(this.application.basedir + '/back-end/sql/1.0.0.sql', 'utf8')); db.close(); } catch (error) { console.log('DB error', error); @@ -460,7 +461,7 @@ class Site { fs.copySync(sitePath, newSitePath); Site.updateNameAndUUIDInSiteConfig(newSitePath, newCatalogFreeName, siteName); let configFilePath = path.join(newSitePath, 'input', 'config', 'site.config.json'); - let siteConfig = fs.readFileSync(configFilePath); + let siteConfig = FileHelper.readFileSync(configFilePath); siteConfig = JSON.parse(siteConfig); appInstance.addSite(newCatalogFreeName, siteConfig); @@ -501,7 +502,7 @@ class Site { */ static updateNameAndUUIDInSiteConfig (sitePath, newSiteSlug, newSiteName) { let configFilePath = path.join(sitePath, 'input', 'config', 'site.config.json'); - let siteConfig = fs.readFileSync(configFilePath); + let siteConfig = FileHelper.readFileSync(configFilePath); siteConfig = JSON.parse(siteConfig); siteConfig.name = newSiteSlug; siteConfig.uuid = 'uuid-' + (new Date().getTime()) + '-' + (Math.floor(Math.random() * (999999999 - 100000000 + 1)) + 100000000); @@ -519,7 +520,7 @@ class Site { let cssNormal = false; if (UtilsHelper.fileExists(cssPathNormal)) { - cssNormal = fs.readFileSync(cssPathNormal, 'utf8'); + cssNormal = FileHelper.readFileSync(cssPathNormal, 'utf8'); } return { diff --git a/app/back-end/themes.js b/app/back-end/themes.js index eed6a9e25..25c9d7977 100644 --- a/app/back-end/themes.js +++ b/app/back-end/themes.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const path = require('path'); +const FileHelper = require('./helpers/file.js'); const slug = require('./helpers/slug'); const UtilsHelper = require('./helpers/utils.js'); const themeConfigValidator = require('./modules/render-html/validators/theme-config.js'); @@ -66,7 +67,7 @@ class Themes { continue; } - let themeData = fs.readFileSync(configPath, 'utf8'); + let themeData = FileHelper.readFileSync(configPath, 'utf8'); themeData = JSON.parse(themeData); output.push({ @@ -84,11 +85,11 @@ class Themes { * Load informations about the current theme */ currentTheme(returnDir = false) { - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); if(!returnDir && siteData.theme) { - let themeData = fs.readFileSync(path.join(this.sitePath, siteData.theme, 'config.json')); + let themeData = FileHelper.readFileSync(path.join(this.sitePath, siteData.theme, 'config.json')); themeData = JSON.parse(themeData); if(themeData.name) { @@ -144,7 +145,7 @@ class Themes { if (UtilsHelper.fileExists(oldConfigPath)) { try { - let oldConfig = fs.readFileSync(oldConfigPath); + let oldConfig = FileHelper.readFileSync(oldConfigPath); oldConfig = JSON.parse(oldConfig); basicConfig = { config: { @@ -238,7 +239,7 @@ class Themes { */ loadPostTemplates() { let postTemplates = []; - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); if(siteData.theme) { @@ -266,7 +267,7 @@ class Themes { */ loadPageTemplates() { let pageTemplates = []; - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); if(siteData.theme) { @@ -294,7 +295,7 @@ class Themes { */ loadTagTemplates() { let tagTemplates = []; - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); if(siteData.theme) { @@ -322,7 +323,7 @@ class Themes { */ loadAuthorTemplates() { let authorTemplates = []; - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); if(siteData.theme) { @@ -425,7 +426,7 @@ class Themes { // Load default config let defaultConfigPath = path.join(__dirname, '..', 'default-files', 'theme-files', 'config.json'); - let defaultThemeConfig = JSON.parse(fs.readFileSync(defaultConfigPath)); + let defaultThemeConfig = JSON.parse(FileHelper.readFileSync(defaultConfigPath)); // Load basic theme config let themeLocalConfig = UtilsHelper.loadThemeConfig(themeDir); @@ -441,7 +442,7 @@ class Themes { let themeSavedConfig; try { - themeSavedConfig = JSON.parse(fs.readFileSync(themeConfigPath)); + themeSavedConfig = JSON.parse(FileHelper.readFileSync(themeConfigPath)); } catch (err) { console.log('(!) The saved theme config is malformed. Loading default theme config instead.'); return; @@ -482,7 +483,7 @@ class Themes { * Remove unused images */ checkAndCleanImages(configString) { - let siteData = fs.readFileSync(this.siteConfigPath, 'utf8'); + let siteData = FileHelper.readFileSync(this.siteConfigPath, 'utf8'); siteData = JSON.parse(siteData); let authors = new Authors(this.appInstance, {site: siteData.name}); let authorsData = authors.load(); From 0611169c5180a582f3bc81819402f07b904d9982 Mon Sep 17 00:00:00 2001 From: HowToMeetLadies Date: Sat, 26 Apr 2025 20:18:18 +0200 Subject: [PATCH 2/2] fix: correct typo by replacing updatedHierarchy with pagesHierarchy branch: fix-typo-updatedHierarchy-after-fix-readFileSync-fd-leak --- app/back-end/events/page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/back-end/events/page.js b/app/back-end/events/page.js index 01d5968ee..6108d5e27 100644 --- a/app/back-end/events/page.js +++ b/app/back-end/events/page.js @@ -116,7 +116,7 @@ class PageEvents { pagesHierarchy = this.removeNullDataFromHierarchy(pagesHierarchy); pagesHierarchy = this.removeDuplicatedDataFromHierarchy(pagesHierarchy); - fs.writeFileSync(pagesFile, JSON.stringify(updatedHierarchy, null, 4), { encoding: 'utf8' }); + fs.writeFileSync(pagesFile, JSON.stringify(pagesHierarchy, null, 4), { encoding: 'utf8' }); }); }