const { app, BrowserWindow, Menu, protocol } = require('electron'); const path = require('path'); const fs = require('fs'); const crypto = require('crypto'); const algorithm = 'aes-256-ctr'; const password = 'skyfffire-password'; const key = crypto.createHash('sha256').update(password).digest(); let memoryCache = {}; // Function to decrypt a file and store its content in memory function decryptFile(filePath) { const fileContent = fs.readFileSync(filePath); const iv = fileContent.slice(0, 16); // Extract IV const encrypted = fileContent.slice(16); // Extract encrypted data const decipher = crypto.createDecipheriv(algorithm, key, iv); const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]); const relativePath = path.relative(process.resourcesPath, filePath).replace(/\\/g, '/'); memoryCache[relativePath] = decrypted; } // Recursively decrypt files in a directory and store their content in memory function decryptDirectory(directoryPath) { const files = fs.readdirSync(directoryPath); files.forEach(file => { const fullPath = path.join(directoryPath, file); if (fs.lstatSync(fullPath).isDirectory()) { decryptDirectory(fullPath); } else { decryptFile(fullPath); } }); } function createWindow() { const directoryToDecrypt = path.join(process.resourcesPath, 'app.asar', 'static'); decryptDirectory(directoryToDecrypt); // Load index.html into memory const indexPath = path.join(process.resourcesPath, 'app.asar', 'index.html'); const indexRelativePath = path.relative(process.resourcesPath, indexPath).replace(/\\/g, '/'); memoryCache[indexRelativePath] = fs.readFileSync(indexPath); // Register a custom protocol to serve content from memory protocol.registerBufferProtocol('file', (request, callback) => { const url = request.url.substr(7); // Remove 'file://' prefix const relativePath = path.relative(process.resourcesPath, url).replace(/\\/g, '/'); console.log(`Intercepting request for: ${relativePath}`); if (memoryCache[relativePath]) { let mimeType = 'text/plain'; if (relativePath.endsWith('.js')) { mimeType = 'application/javascript'; } else if (relativePath.endsWith('.css')) { mimeType = 'text/css'; } else if (relativePath.endsWith('.html')) { mimeType = 'text/html'; } console.log(`Serving from memory: ${relativePath} as ${mimeType}`); callback({ mimeType: mimeType, data: memoryCache[relativePath] }); } else { console.error(`File not found in memory: ${relativePath}`); callback({ error: -6 }); // FILE_NOT_FOUND } }); const win = new BrowserWindow({ width: 1600, height: 900, icon: path.join(__dirname, 'favicon.ico'), // 设置窗口图标 webPreferences: { nodeIntegration: false, contextIsolation: true, }, }); // Load the index.html from memory using a data URL const indexHtmlContent = memoryCache[indexRelativePath].toString(); win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(indexHtmlContent)); // 打开调试工具 win.webContents.openDevTools(); // 创建菜单模板,只包含一个刷新按钮 const menuTemplate = [ { label: 'View', submenu: [ { label: 'Reload', accelerator: 'CmdOrCtrl+R', click: () => { win.reload(); }, }, ], }, ]; // 创建菜单 const menu = Menu.buildFromTemplate(menuTemplate); // 设置应用程序的菜单 Menu.setApplicationMenu(menu); } app.on('ready', createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });