]> git.plutz.net Git - webtxt/commitdiff
working framework
authorPaul Hänsch <paul@plutz.net>
Fri, 19 Mar 2021 12:36:49 +0000 (13:36 +0100)
committerPaul Hänsch <paul@plutz.net>
Fri, 19 Mar 2021 12:36:49 +0000 (13:36 +0100)
index.cgi [new file with mode: 0755]
session_lock.sh [new file with mode: 0644]

diff --git a/index.cgi b/index.cgi
new file mode 100755 (executable)
index 0000000..04128e4
--- /dev/null
+++ b/index.cgi
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+_EXEC="${_EXEC:-.}"
+_DATA="${_DATA:-.}"
+
+. "$_EXEC"/cgilite/cgilite.sh
+. "$_EXEC"/cgilite/session.sh
+. "$_EXEC"/cgilite/file.sh
+. "$_EXEC"/session_lock.sh
+
+yield_page(){
+  page="$1"
+  printf '%s\r\n' 'Content-Type: text/html; charset=utf-8' \
+                  "Content-Security-Policy: script-src 'none'" \
+                  ''
+  { printf '[html
+    [head
+      [meta name="viewport" content="width=device-width"]
+      [link rel="stylesheet" type="text/css" href="common.css"]
+      [link rel="stylesheet" type="text/css" href="webnote.css"]
+      [title Webnote]
+    ] [body class="%s"
+  ' "$page"
+  cat
+  printf '] ]'
+  } |"$_EXEC/cgilite/html-sh.sed" -u
+}
+
+case ${PATH_INFO##*/} in
+  favicon.ico) printf '%s\r\n' 'Content-Length: 0' '';;
+  common.css) FILE "$_EXEC/cgilite/common.css";;
+  webnote.css) FILE "$_EXEC/webnote.css";;
+  '') yield_page <<-EOF
+       [form .new action=new [button type=submit New Note]
+         [ul .recent
+         $({ COOKIE pages; echo; } |tr \  \\n |while read page; do
+           [ "$(printf %s "$page" |checkid)" ] && printf '[li [a href="./%s" . %s]]' "$page" "$page"
+         done)]
+       ]
+       EOF
+    return 0
+    ;;
+  new)
+    newid="$(timeid)"
+    touch "$_DATA/$newid"
+    REDIRECT "./$newid"
+    ;;
+esac
+
+doc="$_DATA/$(printf %s ${PATH_INFO##*/} |checkid)"
+
+if [ ! -f "$doc" ]; then
+  REDIRECT "${PATH_INFO%%/*}/"
+  return 0
+fi
+
+[ $REQUEST_METHOD = POST ] && case $(POST action) in
+  edit)
+    if temp=$(SLOCK "$doc"); then
+      yield_page <<-EOF
+       [form method=POST
+          [input type=hidden name=session_key value="$SESSION_KEY"]
+         [button type=submit name=action value=cancel Cancel]
+         [button type=submit name=action value=update Update]
+         [textarea name=document . $(HTML <"$doc")]
+       ]
+       EOF
+    else
+      yield_page <<-EOF
+       [p .error .locked Someone else is already editing this Dokument. Wait a few minutes and try again. [a href="$PATH_INFO" Nothing else I can do.]]
+       EOF
+    fi
+    return 0
+    ;;
+  cancel)
+    RELEASE_SLOCK "$doc"
+    REDIRECT "$PATH_INFO"
+    ;;
+  update)
+    if temp=$(CHECK_SLOCK "$doc"); then
+      RELEASE_SLOCK "$doc"
+      POST document >"${doc}"
+      REDIRECT "$PATH_INFO"
+    else
+      yield_page <<-EOF
+       [p .error .stolen Your edit took too long and someone else is now editing this file. [a href="$PATH_INFO" Dang, I must be quicker next time!]]
+       [p Copy your Content for reference:]
+       [div .text . $(POST document |HTML)]
+       EOF
+    fi
+    return 0
+    ;;
+esac
+
+COOKIE pages |tr \  \\n |grep -qF "${doc##*/}" \
+|| SET_COOKIE +$((90 * 86400)) pages="$(COOKIE pages && printf ' %s' "${doc##*/}" || printf '%s' "${doc##*/}")"
+
+yield_page <<-EOF
+       [form method=POST
+          [input type=hidden name=session_key value="$SESSION_KEY"]
+         [button type=submit name=action value=edit Edit]
+       ]
+       [div .text
+       $(HTML <"$doc")
+       ]
+       EOF
diff --git a/session_lock.sh b/session_lock.sh
new file mode 100644 (file)
index 0000000..de1641a
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+[ "$include_session_lock" ] && return 0
+include_session_lock="$0"
+
+SLOCK(){
+  local file="$1";
+  local timeout="${2-900}"
+  local lockdir="$_DATA/lock/${file#$_DATA}"; lockdir="${lockdir%/}"
+  local ovlock="${lockdir%/*}/delete.${lockdir##*/}"
+  local tempfile="$lockdir/${SESSION_ID}"
+  local lockexpire=$(( $(date +%s) - timeout ))
+
+  mkdir -p "${lockdir%/*}"
+
+  if [ -e "$lockdir" ] \
+     && [ "$(stat -c %Y "$lockdir")" -lt "$lockexpire" ] \
+     && mkdir "$ovlock"; then
+    [ "$(stat -c %Y "$lockdir")" -lt "$lockexpire" ] \
+    && rm -r "$lockdir"
+    rmdir "$ovlock"
+  fi
+
+  printf '%s\n' "$tempfile"
+  if mkdir "$lockdir" 2>&-; then
+    cp "$file" "$tempfile"
+    return 0
+  else
+    return 1
+  fi
+}
+
+CHECK_SLOCK(){
+  local file="$1";
+  local lockdir="$_DATA/lock/${file#$_DATA}"; lockdir="${lockdir%/}"
+  local tempfile="$lockdir/${SESSION_ID}"
+
+  printf '%s\n' "$tempfile"
+  if [ -f "$tempfile" ]; then
+    touch "$lockdir"
+    return 0
+  else
+    return 1
+  fi
+}
+
+RELEASE_SLOCK(){
+  local file="$1";
+  local lockdir="$_DATA/lock/${file#$_DATA}"; lockdir="${lockdir%/}"
+  local ovlock="${lockdir%/*}/delete.${lockdir##*/}"
+  local tempfile="$lockdir/${SESSION_ID}"
+
+  if [ -f "$tempfile" ] && mkdir "$ovlock"; then
+    [ -f "$tempfile" ] && rm -r "$lockdir"
+    rmdir "$ovlock"
+    return 0
+  else
+    return 1
+  fi
+}