feat(wiki): 三個目錄頁改走專用存取庫,比對鍵改用裸 HASH
What:LOG_CONTENTS、LEARN_CONTENTS、REPORT_CONTENTS 改由 wiki-repo CONTENTS 解析並透過 wiki-contents.sh upsert 寫入,內容頁仍各走自己的型別。LOG 與 REPORT 的目錄頁新增一欄裸 HASH 當比對鍵。 Why:比對鍵原本是含網址的儲存格,換主機、換存取庫或 URL 編碼有差就比對不到, upsert 會走附加分支,同一頁多出第二列而舊列永遠不再更新。REPORT 更脆:存取庫一換, 雜湊與網址同時變,四個期間的列會一次全部重複。 How:worklog-pending.sh 的 valid_hash 放寬成 40 碼、8 碼與 H 加 7 碼三種形狀。 放寬的是長度不是字元集——先剝字元再比長度的順序保留,路徑穿越與換行注入照樣擋下。 年報不得沿用日誌存取庫那條規則收斂到內容頁,目錄頁同住一庫是另一回事。 Who:jsc-log
This commit is contained in:
@@ -21,7 +21,10 @@
|
||||
# worklog-pending.sh commit <hash> <claim> 寫入成功後清掉併入清單上的暫存檔
|
||||
# worklog-pending.sh abort <hash> <claim> 寫入失敗後保留暫存,只丟掉合併檔與併入清單
|
||||
#
|
||||
# <hash> 為 jsc-gitea/tools/hash-id 算出的 8 碼工作日誌 hash,也就是 LOG_{HASH} 的 HASH。
|
||||
# <hash> 為 jsc-gitea/tools/hash-id 算出的工作日誌 hash,也就是 LOG_{HASH} 的 HASH。
|
||||
# 現行是完整 40 碼大寫十六進位;8 碼那種是舊規則留下的暫存檔,還沒遷移完之前一併收。
|
||||
# 舊規則的首碼落在 0-9ABC 就改寫成 H 加原前 7 碼,十六個首碼有十三個會命中,所以既有的
|
||||
# 8 碼暫存大多長成 H1A2B3C4。不收這種,遷移期間存進去的內容就再也取不回來。
|
||||
# 存放位置: $JSC_HOME/worklog-pending/{hash}/{UTC 時間}-{pid}.md(JSC_HOME 預設 ~/.jsc)
|
||||
# 合併檔: $JSC_HOME/worklog-pending/.merge/{hash}-{UTC 時間}-{pid}.md
|
||||
# 併入清單: 同名換副檔名 .claim,一行一個被併走的暫存檔路徑
|
||||
@@ -55,11 +58,45 @@ EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
valid_hash() { # 只收 8 碼大寫英數,擋掉路徑穿越
|
||||
case "$1" in
|
||||
[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]) return 0 ;;
|
||||
*) echo "[jsc][工作日誌暫存][ERR]:hash 須為 8 碼大寫英數,收到「${1:-空值}」。" >&2; exit 2 ;;
|
||||
# hash 會直接拼進暫存目錄路徑,這裡是整支腳本唯一的格式驗證,擋的是路徑穿越。
|
||||
# 放寬長度不等於放寬字元集:先確認每一個字都是十六進位,再比對長度。字元集這一關先過,
|
||||
# 「.」與「/」才進不了路徑;只看長度就會讓 ../ 那類值溜進來。
|
||||
# 字元檢查逐字剝,不呼叫 grep 之類逐行比對的工具:值裡夾一個換行,逐行比對會拿第一行
|
||||
# 當整個值判過,那正是路徑穿越要的缺口。
|
||||
#
|
||||
# 這份樣式與 jsc-gitea/tools/page-name.sh、jsc-hooks/hooks/comment-scope.sh 是三份各自
|
||||
# 獨立的定義,故意不共用:hook 與這個暫存區都必須自足,執行期不能相依別的 plugin 的安裝
|
||||
# 路徑——那個路徑每個 CLI 不一樣,也可能根本沒裝,抓不到就等於整道護欄失效。三份的一致性
|
||||
# 改在稽核時比對。
|
||||
valid_hash() {
|
||||
raw="${1:-}"
|
||||
# H 開頭先剝掉再驗其餘:舊規則把首碼落在 0-9ABC 的 hash 改寫成 H 加原前 7 碼,
|
||||
# H 本身不是十六進位字元,不先剝就會被逐字剝那一關擋掉。剝的是固定字面 H,
|
||||
# 不是一個字元集,所以放進來的字仍然只有 H 與十六進位這兩種。
|
||||
case "$raw" in
|
||||
H*) rest="${raw#H}"; hprefixed=1 ;;
|
||||
*) rest="$raw"; hprefixed=0 ;;
|
||||
esac
|
||||
while :; do
|
||||
case "$rest" in
|
||||
[0-9A-F]*) rest="${rest#?}" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$rest" ]; then
|
||||
if [ "$hprefixed" -eq 1 ]; then
|
||||
case "$raw" in
|
||||
????????) return 0 ;;
|
||||
esac
|
||||
else
|
||||
case "$raw" in
|
||||
????????????????????????????????????????) return 0 ;;
|
||||
????????) return 0 ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
echo "[jsc][工作日誌暫存][ERR]:hash 須為 40 碼大寫十六進位(現行),或 8 碼大寫十六進位、H 加 7 碼大寫十六進位(尚未遷移的舊暫存),收到「${1:-空值}」。" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
valid_claim() { # 併入清單只認 merge 產出的那一份,擋掉拿別處的清單來刪檔
|
||||
|
||||
Reference in New Issue
Block a user