From 1915ebd8eeacf71975e39f7280110bd00992aa20 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 15 Mar 2022 15:52:00 +0100 Subject: [PATCH] basic locking and editing --- index.cgi | 5 ++-- page_edit.sh | 55 ++++++++++++++++++++++++++++++++++++++ session_lock.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++++ themes/default.sh | 9 ++++--- 4 files changed, 130 insertions(+), 7 deletions(-) create mode 100755 page_edit.sh create mode 100755 session_lock.sh diff --git a/index.cgi b/index.cgi index 76f1bef..2d4954f 100755 --- a/index.cgi +++ b/index.cgi @@ -79,6 +79,8 @@ attachment() { fi } +. "$_EXEC/page_edit.sh" + case "${PATH_INFO}" in /"[.]"/*) FILE "${_EXEC}/${PATH_INFO#/\[.\]}" @@ -91,9 +93,6 @@ case "${PATH_INFO}" in theme_404 fi ;; - */"[edit]") - theme_editor "${PATH_INFO%\[edit\]}" - ;; */"[login]") [ "$USER_NAME" ] \ && REDIRECT "./" \ diff --git a/page_edit.sh b/page_edit.sh new file mode 100755 index 0000000..9bb9f5f --- /dev/null +++ b/page_edit.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +. "${_EXEC}/themes/default.sh" +. "${_EXEC}/session_lock.sh" + +wiki_text() { + # Print source text of a wiki page + # Get page from data or underlay dir + local page="$(PATH "$1")" + + if [ -f "$_DATA/pages/$page/#page.md" ]; then + cat -- "$_DATA/pages/$page/#page.md" + elif [ -f "$_EXEC/pages/$page/#page.md" ]; then + cat -- "$_EXEC/pages/$page/#page.md" + else + return 1 + fi +} + +edit_page="${PATH_INFO%\[edit\]}" +edit_file="$_DATA/pages/$edit_page/#page.md" +[ "$REQUEST_METHOD" = POST ] && edit_action="$(POST action)" + +debug "RM: $REQUEST_METHOD ea: $edit_action" + +if [ "$edit_page" = "$PATH_INFO" ]; then + unset edit_page edit_action edit_file + # END EDIT SCRIPT, continue in index.cgi + +elif [ "$edit_action" = update ]; then + mkdir -p -- "${edit_file%/#page.md}" + + if S_LOCK "$edit_file"; then + POST pagetext >"$edit_file" + S_RELEASE "$edit_file" + REDIRECT "${_BASE}${PATH_INFO%\[edit\]}" |debug + else + export ERRMSG="ERR_NOLOCK" + REDIRECT "${_BASE}${PATH_INFO%\[edit\]}/[edit]" |debug + fi + +elif [ "$edit_action" = cancel ]; then + S_RELEASE "$edit_file" + REDIRECT "${_BASE}${PATH_INFO%\[edit\]}" |debug + +elif mkdir -p -- "${edit_file%/#page.md}" && S_LOCK "$edit_file"; then + # Display editor page + SESSION_COOKIE + theme_editor "$edit_page" + +else + export ERRMSG="ERR_NOLOCK" + theme_page "$edit_page" + +fi diff --git a/session_lock.sh b/session_lock.sh new file mode 100755 index 0000000..f55c9cd --- /dev/null +++ b/session_lock.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +. "$_EXEC/cgilite/storage.sh" +. "$_EXEC/cgilite/session.sh" + +LOCK_TIMEOUT="${LOCK_TIMEOUT:-1200}" + +S_LOCK(){ + local file="$1" timeout="${2:-$LOCK_TIMEOUT}" + local date sid + + printf "%i %s\n" "$_DATE" "$SESSION_ID" >>"${file}.lock" + + if ! read date sid <"${file}.lock"; then + debug "Unable to access lock: ${file}.lock" + + elif [ $((date + timeout)) -lt $_DATE ]; then + # Override stale lock + if LOCK "${file}.lock" 1; then + debug "Overriding stale lock: ${file}.lock" + printf "%i %s\n" "$_DATE" "$SESSION_ID" >"${file}.lock" + RELEASE "${file}.lock" + return 0 + else + return 1 + fi + + elif [ "$sid" = "$SESSION_ID" -a "$date" -ne "$_DATE" ]; then + # Refresh aged lock + printf "%i %s\n" "$_DATE" "$SESSION_ID" >"${file}.lock" + return 0 + + elif [ "$sid" = "$SESSION_ID" ]; then + # Simple success + return 0 + + else + return 1 + fi +} + +S_RELEASE(){ + local file="$1" timeout="${2:-$LOCK_TIMEOUT}" + local date sid + + if ! read date sid <"${file}.lock"; then + # File was not locked + return 0 + + elif [ "$sid" = "$SESSION_ID" -a $((date + timeout)) -lt $_DATE ]; then + # if lock is stale, protect against stale override before release + if LOCK "${file}.lock" 1; then + rm -- "${file}.lock" + RELEASE "${file}.lock" + return 0 + else + return 1 + fi + + elif [ "$sid" = "$SESSION_ID" ]; then + # Simple success + rm -- "${file}.lock" + return 0 + + else + return 1 + fi +} diff --git a/themes/default.sh b/themes/default.sh index 56b57ae..c096f82 100755 --- a/themes/default.sh +++ b/themes/default.sh @@ -39,7 +39,7 @@ theme_editor(){ local page="$1" title title="${page%/}"; title="${title##*/}" - # Important! Web Server response including newline newline + # Important! Web Server response including newline printf "%s\r\n" "Content-Type: text/html; charset=utf-8" "" cat <<-EOF @@ -50,9 +50,10 @@ theme_editor(){ $(theme_header)
- - - + + + +
$(theme_footer) -- 2.39.2