diff --git a/app/ipc/export_handlers.ts b/app/ipc/export_handlers.ts index bfb6a03d..aec762f6 100644 --- a/app/ipc/export_handlers.ts +++ b/app/ipc/export_handlers.ts @@ -3,6 +3,8 @@ import { baseDir, downloadsDir } from "../utils/constants"; import fs from "fs"; import path from "path"; import { showFileDownloadedDialog } from "../utils/dialog"; +import { sanitizeFilename } from "../utils"; + export function setupExportHandlers() { ipcMain.handle("file-downloaded", async (_, filePath: string): Promise => { @@ -42,7 +44,8 @@ export function setupExportHandlers() { margins: { top: 0, right: 0, bottom: 0, left: 0 } }); browser.close(); - const destinationPath = path.join(downloadsDir, `${title}.pdf`); + const sanitizedTitle = sanitizeFilename(title); + const destinationPath = path.join(downloadsDir, `${sanitizedTitle}.pdf`); await fs.promises.writeFile(destinationPath, pdfBuffer); const success = await showFileDownloadedDialog(destinationPath); diff --git a/app/utils/constants.ts b/app/utils/constants.ts index 0ee28bbc..e1781244 100644 --- a/app/utils/constants.ts +++ b/app/utils/constants.ts @@ -1,7 +1,7 @@ import { app } from "electron" import path from "path" -export const localhost = "http://0.0.0.0" +export const localhost = "http://127.0.0.1" export const isDev = !app.isPackaged; diff --git a/app/utils/index.ts b/app/utils/index.ts index 568db0bd..eb9105c7 100644 --- a/app/utils/index.ts +++ b/app/utils/index.ts @@ -77,3 +77,7 @@ export async function findUnusedPorts(startPort: number = 40000, count: number = return ports; } + +export function sanitizeFilename(filename: string): string { + return filename.replace(/[\\/:*?"<>|]/g, '_'); +} \ No newline at end of file diff --git a/package.json b/package.json index 0613c7ab..a56d2358 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "scripts": { "dev": "rm -rf app_dist && tsc && electron .", - "setup:env": "npm install && cd servers/fastapi && poetry env remove --all && poetry install && pip remove hf_xet && cd ../../servers/nextjs && npm install", + "setup:env": "npm install && cd servers/fastapi && poetry env remove --all && poetry install && .venv/bin/pip uninstall -y hf_xet && cd ../../servers/nextjs && npm install", "install:pyinstaller": "cd servers/fastapi && .venv/bin/pip install pyinstaller", "build:ts": "rm -rf app_dist && tsc", "build:css": "tailwindcss -i ./resources/ui/assets/css/tailwind.import.css -o ./resources/ui/assets/css/tailwind.css --watch", diff --git a/servers/fastapi/api/routers/presentation/handlers/export_as_pptx.py b/servers/fastapi/api/routers/presentation/handlers/export_as_pptx.py index 78986ff2..fe9daa9b 100644 --- a/servers/fastapi/api/routers/presentation/handlers/export_as_pptx.py +++ b/servers/fastapi/api/routers/presentation/handlers/export_as_pptx.py @@ -11,7 +11,7 @@ from api.routers.presentation.models import ( from api.services.logging import LoggingService from api.services.instances import temp_file_service from api.sql_models import PresentationSqlModel -from api.utils import get_presentation_dir +from api.utils import get_presentation_dir, sanitize_filename from ppt_generator.pptx_presentation_creator import PptxPresentationCreator from api.services.database import get_sql_session @@ -44,7 +44,7 @@ class ExportAsPptxHandler(FetchPresentationAssetsMixin): ppt_path = os.path.join( self.presentation_dir, - f"""{presentation.title.replace('/', '_').replace(' ', '_').replace('"', "'")}.pptx""", + sanitize_filename(f"{presentation.title}.pptx") ) ppt_creator = PptxPresentationCreator(self.data.pptx_model, self.temp_dir) ppt_creator.create_ppt() diff --git a/servers/fastapi/api/utils.py b/servers/fastapi/api/utils.py index cd68ab62..5ec5f630 100644 --- a/servers/fastapi/api/utils.py +++ b/servers/fastapi/api/utils.py @@ -3,6 +3,7 @@ import json import os import sys import traceback +import re from typing import List, Optional import aiohttp @@ -139,3 +140,18 @@ async def handle_errors( extra=log_metadata.model_dump(), ) raise HTTPException(400, "Something went wrong while processing your request.") + + +def sanitize_filename(filename: str) -> str: + name, ext = os.path.splitext(filename) + sanitized = re.sub(r'[\\/:*?"<>|]', '_', name) + sanitized = re.sub(r'[\s_]+', '_', sanitized) + sanitized = sanitized.strip(' .') + + if not sanitized: + sanitized = 'untitled' + + if len(sanitized) > 200: + sanitized = sanitized[:200] + + return sanitized + ext diff --git a/servers/fastapi/server.py b/servers/fastapi/server.py index 40db9df9..3935ca6e 100644 --- a/servers/fastapi/server.py +++ b/servers/fastapi/server.py @@ -14,4 +14,4 @@ if __name__ == "__main__": ) args = parser.parse_args() - uvicorn.run("api.main:app", host="0.0.0.0", port=args.port, log_level="info") + uvicorn.run("api.main:app", host="127.0.0.1", port=args.port, log_level="info") diff --git a/servers/fastapi/server_autoreload.py b/servers/fastapi/server_autoreload.py index 4d5c00de..b0c4e49b 100644 --- a/servers/fastapi/server_autoreload.py +++ b/servers/fastapi/server_autoreload.py @@ -10,5 +10,5 @@ if __name__ == "__main__": args = parser.parse_args() uvicorn.run( - "api.main:app", host="0.0.0.0", port=args.port, log_level="info", reload=True + "api.main:app", host="127.0.0.1", port=args.port, log_level="info", reload=True ) diff --git a/servers/fastapi/server_test.py b/servers/fastapi/server_test.py index 4b547a5c..f2446056 100644 --- a/servers/fastapi/server_test.py +++ b/servers/fastapi/server_test.py @@ -5,5 +5,5 @@ load_dotenv() if __name__ == "__main__": uvicorn.run( - "api.main:app", host="0.0.0.0", port=8000, log_level="info", reload=True + "api.main:app", host="127.0.0.1", port=8000, log_level="info", reload=True )