const express = require('express'); const router = express.Router(); const fs = require('fs').promises; const path = require('path'); // 获取XNCore环境变量 const xnCorePath = process.env.XNCore || ''; // 默认IDL文件保存目录,使用XNCore环境变量下的IDL子文件夹 const IDL_BASE_DIR = xnCorePath ? path.join(xnCorePath, 'IDL') : path.join(process.cwd(), 'idl_files'); // 确保IDL文件目录存在 async function ensureIdlDirExists() { try { await fs.mkdir(IDL_BASE_DIR, { recursive: true }); } catch (error) { console.error('创建IDL目录失败:', error); } } // 初始化确保目录存在 ensureIdlDirExists(); // 安全地获取文件路径,避免路径遍历攻击 function getSafePath(filePath) { // 确保文件路径以.idl结尾 if (!filePath.toLowerCase().endsWith('.idl')) { filePath += '.idl'; } // 使用path.join确保路径在IDL_BASE_DIR下 const safePath = path.join(IDL_BASE_DIR, path.basename(filePath)); return safePath; } // 列出所有IDL文件 router.get('/list', async (req, res) => { try { // 确保目录存在 await ensureIdlDirExists(); // 读取目录 const files = await fs.readdir(IDL_BASE_DIR); // 过滤出.idl文件 const idlFiles = files.filter(file => file.toLowerCase().endsWith('.idl')); // 获取文件信息 const fileInfos = await Promise.all(idlFiles.map(async (file) => { const filePath = path.join(IDL_BASE_DIR, file); const stats = await fs.stat(filePath); return { name: file, size: stats.size, modified: stats.mtime }; })); res.json({ files: fileInfos }); } catch (error) { console.error('列出IDL文件失败:', error); res.status(500).json({ error: '列出IDL文件失败', message: error.message }); } }); // 读取IDL文件内容 router.get('/read', async (req, res) => { try { const filename = req.query.filename; if (!filename) { return res.status(400).json({ error: '缺少文件名参数' }); } const filePath = getSafePath(filename); // 读取文件内容 const content = await fs.readFile(filePath, 'utf-8'); res.json({ content, filename: path.basename(filePath) }); } catch (error) { console.error('读取IDL文件失败:', error); if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } res.status(500).json({ error: '读取IDL文件失败', message: error.message }); } }); // 保存IDL文件内容 router.post('/save', async (req, res) => { try { const { filename, content } = req.body; if (!filename || content === undefined) { return res.status(400).json({ error: '缺少必要参数' }); } // 确保目录存在 await ensureIdlDirExists(); const filePath = getSafePath(filename); // 写入文件内容 await fs.writeFile(filePath, content, 'utf-8'); res.json({ success: true, filename: path.basename(filePath) }); } catch (error) { console.error('保存IDL文件失败:', error); res.status(500).json({ error: '保存IDL文件失败', message: error.message }); } }); // 新建IDL文件 router.post('/create', async (req, res) => { try { const { filename } = req.body; if (!filename) { return res.status(400).json({ error: '缺少文件名参数' }); } // 确保目录存在 await ensureIdlDirExists(); const filePath = getSafePath(filename); // 检查文件是否已存在 try { await fs.access(filePath); return res.status(409).json({ error: '文件已存在' }); } catch (accessError) { // 文件不存在,可以创建 } // 创建具有默认内容的IDL文件 const defaultContent = `module XNSim { struct YourStruct { // 在此添加字段 }; };`; // 写入文件内容 await fs.writeFile(filePath, defaultContent, 'utf-8'); res.json({ success: true, filename: path.basename(filePath), content: defaultContent }); } catch (error) { console.error('创建IDL文件失败:', error); res.status(500).json({ error: '创建IDL文件失败', message: error.message }); } }); // 删除IDL文件 router.delete('/delete', async (req, res) => { try { const filename = req.query.filename; if (!filename) { return res.status(400).json({ error: '缺少文件名参数' }); } const filePath = getSafePath(filename); // 删除文件 await fs.unlink(filePath); res.json({ success: true, filename: path.basename(filePath) }); } catch (error) { console.error('删除IDL文件失败:', error); if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } res.status(500).json({ error: '删除IDL文件失败', message: error.message }); } }); module.exports = router;