]> git.plutz.net Git - webtxt/commitdiff
Merge commit '280b6cc5ddcedd4f744806f965e0165fb0a8f0b2'
authorPaul Hänsch <paul@plutz.net>
Sun, 25 Jul 2021 02:46:25 +0000 (04:46 +0200)
committerPaul Hänsch <paul@plutz.net>
Sun, 25 Jul 2021 02:46:25 +0000 (04:46 +0200)
12 files changed:
Makefile [new file with mode: 0644]
cgilite/cgilite.sh [moved from cgilite.sh with 100% similarity]
cgilite/common.css [moved from common.css with 100% similarity]
cgilite/file.sh [moved from file.sh with 100% similarity]
cgilite/html-sh.sed [moved from html-sh.sed with 100% similarity]
cgilite/logging.sh [moved from logging.sh with 100% similarity]
cgilite/markdown.awk [moved from markdown.awk with 100% similarity]
cgilite/session.sh [moved from session.sh with 100% similarity]
cgilite/storage.sh [moved from storage.sh with 100% similarity]
index.cgi [new file with mode: 0755]
session_lock.sh [new file with mode: 0644]
webnote.css [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..24781a9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+.PHONY: _subtrees
+
+_subtrees: _cgilite
+
+cgilite:
+       git subtree add --squash -P $@ https://git.plutz.net/git/$@ master
+
+_cgilite: cgilite
+       git subtree pull --squash -P $< https://git.plutz.net/git/$< master
similarity index 100%
rename from cgilite.sh
rename to cgilite/cgilite.sh
similarity index 100%
rename from common.css
rename to cgilite/common.css
similarity index 100%
rename from file.sh
rename to cgilite/file.sh
similarity index 100%
rename from html-sh.sed
rename to cgilite/html-sh.sed
similarity index 100%
rename from logging.sh
rename to cgilite/logging.sh
similarity index 100%
rename from markdown.awk
rename to cgilite/markdown.awk
similarity index 100%
rename from session.sh
rename to cgilite/session.sh
similarity index 100%
rename from storage.sh
rename to cgilite/storage.sh
diff --git a/index.cgi b/index.cgi
new file mode 100755 (executable)
index 0000000..f2e065e
--- /dev/null
+++ b/index.cgi
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+_EXEC="${_EXEC:-${0%/*}/}"
+_DATA="${_DATA:-.}"
+
+. "$_EXEC"/cgilite/cgilite.sh
+. "$_EXEC"/cgilite/session.sh
+. "$_EXEC"/cgilite/file.sh
+. "$_EXEC"/session_lock.sh
+
+git init "$_DATA" >/dev/null &
+
+export MD_HTML="false"
+markdown() {
+  local awkbin=`which awk`
+  if [ "$awkbin" ]; then
+    "$awkbin" -f "$_EXEC"/cgilite/markdown.awk
+  else
+    busybox awk -f "$_EXEC"/cgilite/markdown.awk
+  fi
+}
+
+yield_page(){
+  title="${1:-WebTXT}" page="$2"
+  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 %s]
+    ] [body class="%s"
+  ' "$title" "$page"
+  cat
+  printf '] ]'
+  } |"$_EXEC/cgilite/html-sh.sed" -u
+}
+
+pagename() {
+  local name page="${1##*/}"
+  name="$(sed -nE "/[a-zA-Z0-9].[^\r   ]/{s;\r$;;; p; q;};" "$_DATA/$page")"
+  [ "$name" ] && printf %s "$name" \
+              || printf %s "$page"
+}
+
+recent="$(COOKIE pages)"
+
+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]
+          $(if [ "$recent" ]; then
+           printf '[h2 Recent Pages][ul .recent'
+           for page in $recent; do
+             [ -f "$_DATA/$(printf %s "$page" |checkid)" ] \
+              && printf '[li [a href="./%s" . %s]]' "$page" "$(pagename "$page" |HTML)"
+           done
+            printf ']'
+         fi)
+       ]
+       EOF
+    return 0
+    ;;
+  new)
+    newid="$(timeid)"
+    touch "$_DATA/$newid"
+    git -C "$_DATA" add "$newid" >/dev/null
+    git -C "$_DATA" commit -m "new note \"${newid}\"" "$newid" >/dev/null
+    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 "$(pagename "$doc" |HTML)" <<-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 "$(pagename "$doc" |HTML) - Error" <<-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}"
+      git -C "$_DATA" commit -m "update note ${doc##*/} \"$(pagename "$doc")\"" "${doc##*/}" >/dev/null
+      REDIRECT "$PATH_INFO"
+    else
+      yield_page "$(pagename "$doc" |HTML) - Error" <<-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
+
+printf %s "$recent" |grep -qwF "${doc##*/}" \
+|| SET_COOKIE +$((90 * 86400)) pages="${recent}${recent+ }${doc##*/}" Path="${PATH_INFO%/*}/"
+
+yield_page "$(pagename "$doc" |HTML)" <<-EOF
+       [form method=POST
+          [input type=hidden name=session_key value="$SESSION_KEY"]
+         [button type=submit name=action value=edit Edit]
+       ]
+       [div .text . $(markdown <"$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
+}
diff --git a/webnote.css b/webnote.css
new file mode 100644 (file)
index 0000000..484cbc7
--- /dev/null
@@ -0,0 +1,35 @@
+body {
+  margin: .5em 1em;
+}
+button {
+  margin-bottom: 1em;
+}
+@media print { button { display: none; }}
+textarea {
+  display: block;
+  font-family: monospace;
+  width: 100%;
+  height: 90vh;
+  height: calc(100vh - 4.5em);
+}
+
+div.text {
+  max-width: 100%;
+  overflow: auto;
+}
+
+form.new {
+  text-align: center;
+  margin-top: 1em;
+}
+
+.new button {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+ul.recent {
+  display: inline-block;
+  text-align: left;
+}