]> git.plutz.net Git - httpchat/commitdiff
framework
authorPaul Hänsch <paul@plutz.net>
Wed, 20 Nov 2019 19:55:07 +0000 (20:55 +0100)
committerPaul Hänsch <paul@plutz.net>
Wed, 20 Nov 2019 19:55:07 +0000 (20:55 +0100)
.gitignore [new file with mode: 0644]
index.cgi [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..22b5907
--- /dev/null
@@ -0,0 +1,3 @@
+&*
+@*
+serverkey
diff --git a/index.cgi b/index.cgi
new file mode 100755 (executable)
index 0000000..e84122c
--- /dev/null
+++ b/index.cgi
@@ -0,0 +1,236 @@
+#!/bin/sh
+
+_EXEC=.
+_DATA=.
+. "$_EXEC/cgilite/logging.sh"
+. "$_EXEC/cgilite/cgilite.sh"
+. "$_EXEC/cgilite/session.sh"
+. "$_EXEC/cgilite/storage.sh"
+
+
+LOCATION="$(PATH "$PATH_INFO")"
+LOCATION="${LOCATION#/}"
+LOCATION="${LOCATION%%/*}"
+
+yield_css(){
+  printf 'Content-Type: text/css; charset=utf-8\r\n\r\n'
+  cat <<ENDCSS
+* { box-sizing: border-box;}
+#chat {
+  position: fixed;
+  bottom: 2.5em;
+  left: 0; right: 0;
+  border: 1px solid #08b;
+  padding: 1ex;
+  margin: .5ex;
+  z-index: -1;
+}
+form#channel {
+  position: fixed;
+  bottom: 0;
+  left: 0; right: 0;
+}
+
+#check_settings { display: none; }
+#check_settings + label {
+  display: inline-block;
+}
+#check_settings + label:before {
+  content: '\2699';
+  padding: .5ex;
+  margin-left: .5ex;
+  margin-right: 2em;
+}
+#check_settings + label + #settings { display: none; }
+#check_settings:checked + label + #settings {
+  display: block;
+  position: fixed;
+  min-width: 20%; max-width: 90%;
+  width: 30em;
+  top: 3em;
+  left: 50%; transform: translate(-50%);
+  background-color: #FFF;
+  border: 1px solid;
+  border-radius: 1ex 1ex .5ex .5ex;
+}
+#settings h1 {
+  background-color: #08b;
+  margin: 0;
+  padding: 0 1ex;
+  font-size: 1em;
+  font-weight: bold;
+  border-bottom: 1px solid;
+  border-radius: 1ex 1ex 0 0;
+}
+#settings label[for=check_settings] {
+  position: absolute;
+  top: 0; right: 1px;
+  background-color: #F88;
+  border-left: 1px solid;
+  border-radius: 0 1ex 0 0;
+  width: 3ex;
+  overflow: hidden;
+}
+#settings label[for=check_settings]:before {
+  content: "x";
+  padding: 0 1ex;
+}
+#settings input[type=radio] { display: none; }
+#settings input[type=radio] + label + * { display: none; }
+#settings input[type=radio]:checked + label + * { display: block; }
+#settings input[type=radio] + label {
+  display: block;
+  font-weight: bold;
+  text-decoration: underline;
+  margin: -1px 1px; padding: 0 1ex;
+  border-top: 1px solid;
+  background-color: #EEE;
+}
+#settings input[type=radio] + label + * {
+  padding: 1ex 1ex .5ex 1ex;
+}
+
+form#channel input[name=message] {
+  display: inline-block;
+  position: absolute;
+  left: 4.5ex;
+  width: calc(100% - 5ex - 1px);
+}
+form#channel button[value=submit] { display: none; }
+#chat .message .date {
+  color: #888;
+  font-size: .75em;
+}
+#chat .message .nick {
+  font-weight: bold;
+}
+#chat .message .nick .indicator {
+  color: #888;
+}
+
+ENDCSS
+}
+
+yield_page(){
+  page="$1"
+  printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
+  { printf '[html
+    [head
+      [meta name="viewport" content="width=device-width"]
+      [link rel="stylesheet" type="text/css" href="/webchat.css"]
+      [title Webchat]
+    ] [body class="%s"
+  ' "$page"
+  cat
+  printf '] ]'
+  } |"$_EXEC/cgilite/html-sh.sed" -u
+}
+
+settings_menu(){
+  printf '
+    [input #check_settings type="checkbox"][label for=check_settings Settings]
+    [div #settings
+      [h1 Settings][label for=check_settings Close]
+      [input #set_nick type=radio name="setting" value="nick" selected][label for=set_nick Nickname]
+      [div [input name="nickname" value="%s"][submit "action" "nick" Set Cookie]]
+    ]
+  ' "$(HTML "${nickname#\?}")"
+}
+
+case ${LOCATION} in
+  \&?*) chatfile="$_DATA/${LOCATION}"
+       page=channel
+   ;;
+  @?*) if [ -d "$_DATA/${LOCATION}" ]; then
+        chatfile="$_DATA/${LOCATION}/?${SESSION_ID}"
+        page=channel
+      else
+        REDIRECT /
+      fi
+   ;;
+  ~?*) if [ -d "$_DATA/@${LOCATION#~}" ]; then
+        pubinfo="$_DATA/@${LOCATION#~}/pubinfo"
+        page=pubinfo
+      else 
+        REDIRECT /
+      fi
+   ;;
+  webchat.css) yield_css; exit 0;;
+  '') page=front;;
+  *) REDIRECT /;;
+esac
+
+if [ "$(COOKIE nick)" ]; then
+  nickname="?$(COOKIE nick)"
+else
+  nickname='?Guest'
+fi
+  
+if [ -f "$chatfile" ]; then
+  read -r channelkey x <"$chatfile"
+  channelkey="$( printf '%s-%s' "$channelkey" "$SESSION_ID" |sha256sum)"
+fi
+
+case "$page $(POST action)" in
+  channel\ create)
+    if [ ! -f "$chatfile" ]; then
+      { randomid; printf ' '; STRING "$nickname"; echo; } >"$chatfile"
+    fi
+    REDIRECT "$(URL "/$LOCATION")"
+    ;;
+  channel\ submit)
+    if [ -f "$chatfile" -a "$channelkey" = "$(POST channelkey)" ]; then
+      printf "%s %s: %s\n" "$(date +%F_%T)" "$(STRING "$nickname")" "$(POST message |STRING)" >>"$chatfile"
+    fi
+    REDIRECT "$(URL "/$LOCATION")"
+    ;;
+  channel\ nick)
+    SET_COOKIE +1209600 "nick=$(POST nickname |URL)"
+    REDIRECT "$(URL "/$LOCATION")"
+    ;;
+  channel\ *)
+    if [ ! -f "$chatfile" ]; then
+      yield_page create <<-EOF
+       [form #nonexist method=POST action="$(URL "/$LOCATION")"
+           There is no channel named $(HTML "$LOCATION")
+           [submit "action" "create" Create]
+        ]
+       EOF
+    else
+      { printf '
+        [form #channel method=POST action="%s"
+          [submit "action" "submit" style="display: none;"]
+          [input type=hidden name=channelkey value="%s"]
+          %s [input name="message" autofocus=true][submit "action" "submit" Send!]
+        ]
+      ' "$(URL "/$LOCATION")" "$channelkey" "$(settings_menu)"
+      SHESCAPE='s;[]&<>#."[];\\&;g;'
+
+      printf '[div #chat'
+      # tail -n30 -f "$chatfile" | {
+      #   read x
+      #   while read -r date nick message; do
+      #     printf '[p .message [span .date %s] [span .nick [span .indicator %s]%s:] [span .message %s]]\n' \
+      #            "${date#*_}" "${nick%${nick#?}}" "$(UNSTRING "${nick#?}" |HTML)" "$(UNSTRING "$message" |HTML)"
+      #     done
+      #   }
+      tail -n50 -f "$chatfile" \
+      | sed -nuE '
+        /^[^ ]+ [^ ]+ [^ ]+$/{
+        h; s;^([^ ]+) ([^ ]+) ([^ ]+)$;\1;; s;.*_;;;         s;.+;[p .message [span .date &];p;
+        g; s;^([^ ]+) ([^ ]+) ([^ ]+)$;a\2;; bESC; :A s;.;;; s;(.)(.+);[span .nick [span .indicator \1]\2];p;
+        g; s;^([^ ]+) ([^ ]+) ([^ ]+)$;b\3;; bESC; :B s;.;;; s;.+;[span .message &]];p;
+        }
+        b; :ESC
+        '"$UNSTRING"' '"$SHESCAPE"'
+        /^a/bA; /^b/bB;
+        '
+      } |yield_page channel
+    fi 
+    ;;
+  pubinfo\ *);;
+  front\ *) yield_page front <<-EOF
+       Front
+       EOF
+    ;;
+esac