From 4ae67e117aa5269b53a8233f6fffad8f1c5b011a Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Wed, 26 Nov 2025 04:08:02 +0000 Subject: [PATCH] Add SendFile --- backend/modules/RoutingManager.js | 2 +- backend/server.js | 38 ++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/backend/modules/RoutingManager.js b/backend/modules/RoutingManager.js index b1c930a..4f8cb9b 100644 --- a/backend/modules/RoutingManager.js +++ b/backend/modules/RoutingManager.js @@ -38,7 +38,7 @@ function loadChapters(db, bookName) { chapterNumber: row.chapter_number, filename: row.filename, displayName: row.display_name, - url: `/books/${row.folder_name}/${encodeURIComponent(row.filename)}` + url: `/pdf/${row.folder_name}/${encodeURIComponent(row.filename)}` })); resolve(chapters); } diff --git a/backend/server.js b/backend/server.js index 2b29b9e..fe48d0d 100644 --- a/backend/server.js +++ b/backend/server.js @@ -37,13 +37,49 @@ const db = new sqlite3.Database(dbPath, (err) => { const RoutingManager = require('./modules/RoutingManager'); // Middleware -app.use(express.static('../frontend/public')); +// Serve only specific static assets, not the entire public directory +app.use('/styles', express.static('../frontend/public/styles')); app.use(express.json()); app.use(cookieParser()); // Setup routes using RoutingManager RoutingManager.setupRoutes(app, db); +// PDF serving route using sendFile +app.get('/pdf/:bookName/:chapterFile', (req, res) => { + const { bookName, chapterFile } = req.params; + + // Construct the absolute path to the PDF file + const pdfPath = path.resolve(__dirname, '../frontend/public/books', bookName, chapterFile); + + // Security check: ensure the path is within the allowed directory + const allowedDirectory = path.resolve(__dirname, '../frontend/public/books'); + if (!pdfPath.startsWith(allowedDirectory)) { + console.warn(`Security violation: Attempted access to ${pdfPath}`); + return res.status(403).json({ error: 'Access denied' }); + } + + // Check if file exists before serving + fs.access(pdfPath, fs.constants.F_OK, (err) => { + if (err) { + console.error(`PDF file not found: ${pdfPath}`); + return res.status(404).json({ error: 'PDF file not found' }); + } + + // Serve the PDF file using sendFile + res.sendFile(pdfPath, (sendErr) => { + if (sendErr) { + console.error(`Error serving PDF file: ${sendErr.message}`); + if (!res.headersSent) { + res.status(500).json({ error: 'Error serving PDF file' }); + } + } else { + console.log(`Successfully served PDF: ${bookName}/${chapterFile}`); + } + }); + }); +}); + // Start server app.listen(PORT, '0.0.0.0', () => {