diff options
Diffstat (limited to 'src/main/ipcMain.ts')
-rw-r--r-- | src/main/ipcMain.ts | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/main/ipcMain.ts b/src/main/ipcMain.ts index d62888c..1dcb17c 100644 --- a/src/main/ipcMain.ts +++ b/src/main/ipcMain.ts @@ -24,19 +24,50 @@ import { IpcEvents } from "@utils/IpcEvents"; import { Queue } from "@utils/Queue"; import { BrowserWindow, ipcMain, shell } from "electron"; import { mkdirSync, readFileSync, watch } from "fs"; -import { open, readFile, writeFile } from "fs/promises"; -import { join } from "path"; +import { open, readdir, readFile, writeFile } from "fs/promises"; +import { join, normalize } from "path"; import monacoHtml from "~fileContent/../components/monacoWin.html;base64"; -import { ALLOWED_PROTOCOLS, QUICKCSS_PATH, SETTINGS_DIR, SETTINGS_FILE } from "./utils/constants"; +import { getThemeInfo, stripBOM, UserThemeHeader } from "./themes"; +import { ALLOWED_PROTOCOLS, QUICKCSS_PATH, SETTINGS_DIR, SETTINGS_FILE, THEMES_DIR } from "./utils/constants"; mkdirSync(SETTINGS_DIR, { recursive: true }); +mkdirSync(THEMES_DIR, { recursive: true }); + +export function ensureSafePath(basePath: string, path: string) { + const normalizedBasePath = normalize(basePath); + const newPath = join(basePath, path); + const normalizedPath = normalize(newPath); + return normalizedPath.startsWith(normalizedBasePath) ? normalizedPath : null; +} function readCss() { return readFile(QUICKCSS_PATH, "utf-8").catch(() => ""); } +async function listThemes(): Promise<UserThemeHeader[]> { + const files = await readdir(THEMES_DIR).catch(() => []); + + const themeInfo: UserThemeHeader[] = []; + + for (const fileName of files) { + const data = await getThemeData(fileName).then(stripBOM).catch(() => null); + if (!data) continue; + const parsed = getThemeInfo(data, fileName); + themeInfo.push(parsed); + } + + return themeInfo; +} + +function getThemeData(fileName: string) { + fileName = fileName.replace(/\?v=\d+$/, ""); + const safePath = ensureSafePath(THEMES_DIR, fileName); + if (!safePath) return Promise.reject(`Unsafe path ${fileName}`); + return readFile(safePath, "utf-8"); +} + export function readSettings() { try { return readFileSync(SETTINGS_FILE, "utf-8"); @@ -75,6 +106,10 @@ ipcMain.handle(IpcEvents.SET_QUICK_CSS, (_, css) => cssWriteQueue.push(() => writeFile(QUICKCSS_PATH, css)) ); +ipcMain.handle(IpcEvents.GET_THEMES_DIR, () => THEMES_DIR); +ipcMain.handle(IpcEvents.GET_THEMES_LIST, () => listThemes()); +ipcMain.handle(IpcEvents.GET_THEME_DATA, (_, fileName) => getThemeData(fileName)); + ipcMain.handle(IpcEvents.GET_SETTINGS_DIR, () => SETTINGS_DIR); ipcMain.on(IpcEvents.GET_SETTINGS, e => e.returnValue = readSettings()); @@ -90,6 +125,10 @@ export function initIpc(mainWindow: BrowserWindow) { mainWindow.webContents.postMessage(IpcEvents.QUICK_CSS_UPDATE, await readCss()); }, 50)); }); + + watch(THEMES_DIR, { persistent: false }, debounce(() => { + mainWindow.webContents.postMessage(IpcEvents.THEME_UPDATE, void 0); + })); } ipcMain.handle(IpcEvents.OPEN_MONACO_EDITOR, async () => { |