From d8a86e90ea0142ba36a73760a411c51d8265575d Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 26 Jun 2026 14:11:36 +0800 Subject: [PATCH] =?UTF-8?q?refactor(calculate-version):=20=E5=B0=87?= =?UTF-8?q?=E9=A9=97=E8=AD=89=E5=B8=B8=E6=95=B8=E6=8A=BD=E9=9B=A2=E7=82=BA?= =?UTF-8?q?=E5=85=B7=E5=90=8D=E5=B8=B8=E6=95=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - config 將每段長度上限與允許字元抽為 MAX_REPO_NAME_LENGTH / REPO_SEGMENT_PATTERN(regex 提升至模組層級,避免每次重編譯) - releases 將片段截斷長度抽為 API_ERROR_SNIPPET_LENGTH Co-Authored-By: Claude Opus 4.8 (1M context) --- app/config.js | 10 +++++++--- app/releases.js | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/config.js b/app/config.js index 3aa85fb..4e37a2a 100644 --- a/app/config.js +++ b/app/config.js @@ -55,12 +55,16 @@ function assertHttpUrl(name, value) { } } -// 驗證 repository 為 owner/repo 格式(僅允許字母數字與 . _ -,且拒絕 . 與 .. 路徑穿越段) +// repository 每段名稱的最大長度與允許字元(字母數字與 . _ -) +const MAX_REPO_NAME_LENGTH = 100; +const REPO_SEGMENT_PATTERN = /^[A-Za-z0-9._-]+$/; + +// 驗證 repository 為 owner/repo 格式(拒絕 . 與 .. 路徑穿越段、空段、過長或含非法字元的段) function assertRepository(name, value) { const parts = value.split('/'); const isRepoFormatValid = parts.length === 2 - && parts.every((part) => part.length > 0 && part.length <= 100 - && /^[A-Za-z0-9._-]+$/.test(part) + && parts.every((part) => part.length > 0 && part.length <= MAX_REPO_NAME_LENGTH + && REPO_SEGMENT_PATTERN.test(part) && part !== '.' && part !== '..'); if (!isRepoFormatValid) { throw new Error(`${name} 格式錯誤,必須為 owner/repo`); diff --git a/app/releases.js b/app/releases.js index 3799e93..51982d3 100644 --- a/app/releases.js +++ b/app/releases.js @@ -3,6 +3,9 @@ // 每頁取得的 release 筆數 const RELEASES_PER_PAGE = 10; +// JSON 解析失敗時,附在錯誤訊息中的回應內容片段最大字元數 +const API_ERROR_SNIPPET_LENGTH = 200; + /** * 以分頁方式取得指定 Gitea repo 的所有 release,並回傳合併後的陣列。 * @@ -64,7 +67,7 @@ async function fetchReleases(baseUrl, options = {}) { pageJson = JSON.parse(text); } catch { // 以字元(而非 UTF-16 碼元)截斷回傳內容片段,避免拆分多位元組字元造成亂碼 - const contentSnippet = Array.from(text).slice(0, 200).join(''); + const contentSnippet = Array.from(text).slice(0, API_ERROR_SNIPPET_LENGTH).join(''); throw new Error(`release API 回傳資料無法解析 (page=${page}),回應內容片段:「${contentSnippet}」`); }