From ee57cc221ff2edafd3c0f12a181214c602ed257e Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 22 Jul 2025 02:57:00 +0000 Subject: (대표님, 최겸) 이메일 템플릿, 벤더데이터 변경사항 대응, 기술영업 변경요구사항 구현 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/api/pdftron/createVendorDataReports.ts | 364 ++++++++++++++++++++++++--- 1 file changed, 330 insertions(+), 34 deletions(-) (limited to 'pages/api/pdftron/createVendorDataReports.ts') diff --git a/pages/api/pdftron/createVendorDataReports.ts b/pages/api/pdftron/createVendorDataReports.ts index f0c42926..e145b5d5 100644 --- a/pages/api/pdftron/createVendorDataReports.ts +++ b/pages/api/pdftron/createVendorDataReports.ts @@ -2,25 +2,238 @@ import type { NextApiRequest, NextApiResponse } from "next"; import type { File as FormidableFile } from "formidable"; import formidable from "formidable"; import fs from "fs/promises"; +import path from "path"; import { createReport } from "@/lib/pdftron/serverSDK/createReport"; export const config = { api: { - bodyParser: false, // ✅ 이게 false면 안 됨! + bodyParser: false, }, }; -// 서버 사이드용 DRM 복호화 함수 (API 라우트 내부에 정의) +// 보안 설정 +const SECURITY_CONFIG = { + ALLOWED_EXTENSIONS: new Set([ + 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', + 'txt', 'csv', 'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp' + ]), + FORBIDDEN_EXTENSIONS: new Set([ + 'exe', 'bat', 'cmd', 'scr', 'vbs', 'js', 'jar', 'com', 'pif', + 'msi', 'reg', 'ps1', 'sh', 'php', 'asp', 'jsp', 'py', 'pl', + 'html', 'htm', 'xhtml', 'xml', 'svg' + ]), + MAX_FILE_SIZE: 100 * 1024 * 1024, // 100MB + MAX_FILENAME_LENGTH: 255, +}; + +// 간단한 보안 검증 함수들 +function validateExtension(fileName: string): { valid: boolean; error?: string } { + const extension = path.extname(fileName).toLowerCase().substring(1); + + if (!extension) { + return { valid: false, error: "파일 확장자가 없습니다" }; + } + + if (SECURITY_CONFIG.FORBIDDEN_EXTENSIONS.has(extension)) { + return { valid: false, error: `금지된 파일 형식입니다: .${extension}` }; + } + + if (!SECURITY_CONFIG.ALLOWED_EXTENSIONS.has(extension)) { + return { valid: false, error: `허용되지 않은 파일 형식입니다: .${extension}` }; + } + + return { valid: true }; +} + +function validateFileName(fileName: string): { valid: boolean; error?: string } { + if (fileName.length > SECURITY_CONFIG.MAX_FILENAME_LENGTH) { + return { valid: false, error: "파일명이 너무 깁니다" }; + } + + // 위험한 문자 체크 + const dangerousPatterns = [ + /[<>:"'|?*]/, + /[\x00-\x1f]/, + /^\./, + /\.\./, + /\/|\\$/, + /javascript:/i, + /data:/i, + /vbscript:/i, + /on\w+=/i, + /