electron.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. const { app, BrowserWindow, Menu, protocol } = require('electron');
  2. const path = require('path');
  3. const fs = require('fs');
  4. const crypto = require('crypto');
  5. const algorithm = 'aes-256-ctr';
  6. const password = 'skyfffire-password';
  7. const key = crypto.createHash('sha256').update(password).digest();
  8. let memoryCache = {};
  9. // Function to decrypt a file and store its content in memory
  10. function decryptFile(filePath) {
  11. // console.log(`Decrypting: ${filePath}`);
  12. const fileContent = fs.readFileSync(filePath);
  13. const iv = fileContent.slice(0, 16); // Extract IV
  14. const encrypted = fileContent.slice(16); // Extract encrypted data
  15. const decipher = crypto.createDecipheriv(algorithm, key, iv);
  16. const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
  17. const relativePath = path.relative(process.resourcesPath, filePath).replace(/\\/g, '/');
  18. memoryCache[relativePath] = decrypted;
  19. // console.log(`Decrypted: ${filePath}, content: ${decrypted.slice(0, 100)}`);
  20. }
  21. // Recursively decrypt files in a directory and store their content in memory
  22. function decryptDirectory(directoryPath) {
  23. const files = fs.readdirSync(directoryPath);
  24. files.forEach(file => {
  25. const fullPath = path.join(directoryPath, file);
  26. // console.log(`Processing: ${fullPath}`);
  27. if (fs.lstatSync(fullPath).isDirectory()) {
  28. decryptDirectory(fullPath);
  29. } else {
  30. decryptFile(fullPath);
  31. }
  32. });
  33. }
  34. function createWindow() {
  35. const directoryToDecrypt = path.join(process.resourcesPath, 'app.asar', 'static');
  36. // console.log(`Decrypting directory: ${directoryToDecrypt}`);
  37. decryptDirectory(directoryToDecrypt);
  38. // Load index.html into memory
  39. const indexPath = path.join(process.resourcesPath, 'app.asar', 'index.html');
  40. const indexRelativePath = path.relative(process.resourcesPath, indexPath).replace(/\\/g, '/');
  41. memoryCache[indexRelativePath] = fs.readFileSync(indexPath);
  42. // console.log(`index: ${indexRelativePath}, content: ${memoryCache[indexRelativePath].slice(0, 100)}`);
  43. // Register a custom protocol to serve content from memory
  44. protocol.interceptBufferProtocol('file', (request, callback) => {
  45. const url = request.url.substr(7); // Remove 'file://' prefix
  46. const relativePath = path.relative(process.resourcesPath, url).replace(/\\/g, '/');
  47. console.log(`Intercepting request for: ${relativePath}`);
  48. if (memoryCache[relativePath]) {
  49. let mimeType = 'text/plain';
  50. if (relativePath.endsWith('.js')) {
  51. mimeType = 'application/javascript';
  52. } else if (relativePath.endsWith('.css')) {
  53. mimeType = 'text/css';
  54. } else if (relativePath.endsWith('.html')) {
  55. mimeType = 'text/html';
  56. }
  57. console.log(`Serving from memory: ${relativePath} as ${mimeType}`);
  58. callback({ mimeType: mimeType, data: memoryCache[relativePath] });
  59. } else {
  60. console.error(`File not found in memory: ${relativePath}`);
  61. callback({ error: -6 }); // FILE_NOT_FOUND
  62. }
  63. });
  64. const win = new BrowserWindow({
  65. width: 1600,
  66. height: 900,
  67. icon: path.join(__dirname, 'favicon.ico'), // 设置窗口图标
  68. webPreferences: {
  69. nodeIntegration: false,
  70. contextIsolation: true,
  71. },
  72. });
  73. // Load the index.html from memory using a data URL
  74. const indexHtmlContent = memoryCache[indexRelativePath].toString();
  75. win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(indexHtmlContent));
  76. // 打开调试工具
  77. win.webContents.openDevTools();
  78. // 创建菜单模板,只包含一个刷新按钮
  79. const menuTemplate = [
  80. {
  81. label: 'View',
  82. submenu: [
  83. {
  84. label: 'Reload',
  85. accelerator: 'CmdOrCtrl+R',
  86. click: () => {
  87. win.reload();
  88. },
  89. },
  90. ],
  91. },
  92. ];
  93. // 创建菜单
  94. const menu = Menu.buildFromTemplate(menuTemplate);
  95. // 设置应用程序的菜单
  96. Menu.setApplicationMenu(menu);
  97. }
  98. app.on('ready', createWindow);
  99. app.on('window-all-closed', () => {
  100. if (process.platform !== 'darwin') {
  101. app.quit();
  102. }
  103. });
  104. app.on('activate', () => {
  105. if (BrowserWindow.getAllWindows().length === 0) {
  106. createWindow();
  107. }
  108. });