]> git.plutz.net Git - cgilite/blobdiff - users.sh
Fix broken range requests when running in dash
[cgilite] / users.sh
index 87143d8718aa1083e1b1d9d5bb3ec93b2cca8372..f616ca02baca5d07c7199640ab436e064f4d405a 100755 (executable)
--- a/users.sh
+++ b/users.sh
@@ -1,5 +1,19 @@
 #!/bin/sh
 
+# Copyright 2021 - 2023 Paul Hänsch
+# 
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+# 
+# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 [ -n "$include_users" ] && return 0
 include_users="$0"
 
@@ -12,10 +26,15 @@ USER_REGISTRATION="${USER_REGISTRATION-true}"
 USER_REQUIREEMAIL="${USER_REQUIREEMAIL-true}"
 USER_ACCOUNTPAGE="${USER_ACCOUNTPAGE}"
 
+USER_ACCOUNTEXPIRE="${USER_ACCOUNTEXPIRE:-$((86400 * 730))}"
+USER_CONFIRMEXPIRE="${USER_CONFIRMEXPIRE:-86400}"
+
 MAILFROM="${MAILDOMAIN-noreply@${HTTP_HOST%:*}}"
 
 HTTP_HOST="$(HEADER Host)"
 
+[ "$HTTPS" ] && SCHEMA=https || SCHEMA=http
+
 # == FILE FORMAT ==
 # UID  UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
 #              (pending|active|deleted)
@@ -31,6 +50,10 @@ LOCAL_USER='local \
   USER_EXPIRE USER_DEVICES USER_FUTUREUSE
 '
 
+# == TRANSLATIONS ==
+# override all functions marked with "TRANSLATION"
+# sed -n '/TRANSLATION$/,/^}/p;' <cgilite/users.sh
+
 unset USER_IDMAP
 eval "$UNSET_USER"
 
@@ -66,7 +89,7 @@ read_user() {
 update_user() {
   # internal function for user update
   local uid="$1" uname status email pwsalt pwhash expire devices futureuse
-  local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+  local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
   local arg
 
   for arg in "$@"; do case $arg in
@@ -79,15 +102,15 @@ update_user() {
   esac; done
 
   if LOCK "$user_db"; then
-    while read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES \
+    while read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES \
                   FUTUREUSE; do
-    if [ "$UID" = "$uid" ]; then
+    if [ "$UID_" = "$uid" ]; then
       printf '%s       %s      %s      %s      %s      %s      %i      %s      %s\n' \
              "$uid" "$(STRING "${uname-$(UNSTRING "$UNAME")}")" \
              "${status:-${status-${STATUS}}${status+\\}}" \
              "${email:-${email-${EMAIL}}${email+\\}}" \
              "${pwsalt:-${PWSALT}}" "${pwhash:-${PWHASH}}" \
-             "${expire:-$((_DATE + 86400 * 730))}" \
+             "${expire:-$((_DATE + USER_ACCOUNTEXPIRE))}" \
              "$(STRING "${devices-$(UNSTRING "$DEVICES")}")" \
              "${FUTUREUSE:-\\}"
     elif [ "$STATUS" = pending -a ! "$EXPIRE" -ge "$_DATE" ]; then
@@ -95,7 +118,7 @@ update_user() {
       :
     else
       printf '%s       %s      %s      %s      %s      %s      %i      %s      %s\n' \
-             "$UID" "$UNAME" "$STATUS" "$EMAIL" "$PWSALT" "$PWHASH" \
+             "$UID_" "$UNAME" "$STATUS" "$EMAIL" "$PWSALT" "$PWHASH" \
              "$EXPIRE" "$DEVICES" "$FUTUREUSE"
     fi
     done <"$user_db" >"${user_db}.$$"
@@ -116,7 +139,7 @@ new_user(){
       return 1
     fi
     printf '%s \\      %s      \\      \\      \\      %i      \\      \\\n' \
-           "$user" "pending" "$(( $_DATE + 86400 ))" >>"$user_db"
+           "$user" "pending" "$(( _DATE + USER_CONFIRMEXPIRE ))" >>"$user_db"
   else
     return 1
   fi
@@ -189,9 +212,9 @@ user_checkemail(){
 
 user_nameexist(){
   local uname="$(STRING "$1")"
-  local UID    UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
+  local UID_   UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
   [ -f "$user_db" -a -r "$user_db" ] \
-  && while read -r UID UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
+  && while read -r UID_        UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
     [ "$EXPIRE" -gt "$_DATE" -a "$UNAME" = "$uname" ] && return 0
   done <"$user_db"
   return 1
@@ -199,9 +222,9 @@ user_nameexist(){
 
 user_emailexist(){
   local email="$(STRING "$1")"
-  local UID    UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
+  local UID_   UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
   [ -f "$user_db" -a -r "$user_db" ] \
-  && while read -r UID UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
+  && while read -r UID_        UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
     [ "$EXPIRE" -gt "$_DATE" -a "$EMAIL" = "$email" ] && return 0
   done <"$user_db"
   return 1
@@ -213,6 +236,30 @@ user_pwhash(){
   printf '%s\n' "${hash%% *}"
 }
 
+user_register_email() {  # TRANSLATION
+  "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
+       From: ${MAILFROM}
+       To: ${email}
+       Subject: Your account registration at ${HTTP_HOST%:*}
+
+       Someone tried to sign up for a user account using this email address.
+
+       You can activate your account using this link:
+
+           ${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
+
+       This registration link will expire after $((USER_CONFIRMEXPIRE / 3600)) hours.
+
+       If you did not request an account at ${HTTP_HOST%:*}, then someone else
+       probably entered your email address by accident. In this case you shoud
+       simply ignore this message and we will remove your email address from
+       our database within the next day.
+
+       This is an automatic email. Any direct reply will not be received.
+       Your Account Registration Robot.
+       EOF
+}
+
 user_register(){
   # reserve account, send registration mail
   # preliminary uid, expiration, signature
@@ -231,30 +278,10 @@ user_register(){
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
     elif user_emailexist "$email"; then
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
-    elif new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))"; then
+    elif new_user "$uid" status=pending email="$email" expire="$((_DATE + USER_CONFIRMEXPIRE))"; then
       debug "Sending Activation Link:" \
-            "https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
-      "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
-       From: ${MAILFROM}
-       To: ${email}
-       Subject: Your account registration at ${HTTP_HOST%:*}
-
-       Someone tried to sign up for a user account using this email address.
-
-       You can activate your account using this link:
-
-           https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
-
-       This registration link will expire after 24 hours.
-
-       If you did not request an account at ${HTTP_HOST%:*}, then someone else
-       probably entered your email address by accident. In this case you shoud
-       simply ignore this message and we will remove your email address from
-       our database within the next day.
-
-       This is an automatic email. Any direct reply will not be received.
-       Your Account Registration Robot.
-       EOF
+            "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+      user_register_email
       REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
     else
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
@@ -269,7 +296,7 @@ user_register(){
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_EMPTYTOOSHORT"
     elif [ "$pw" != "$pwconfirm" ]; then
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_MISMATCH"
-    elif new_user "$uid" uname="$uname" status=active email="$email" password="$pw" expire="$((_DATE + 86400 * 730))"; then
+    elif new_user "$uid" uname="$uname" status=active email="$email" password="$pw" expire="$((_DATE + USER_ACCOUNTEXPIRE))"; then
       SESSION_COOKIE new
       SESSION_BIND user_id "$uid"
 
@@ -284,19 +311,8 @@ user_register(){
   fi
 }
 
-user_invite(){
-  local uid="$(timeid)"
-  local email="$(POST email |user_checkemail)"
-  local message="$(POST message)"
-
-  if [ ! "email" ]; then
-    REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
-  elif user_emailexist "$email"; then
-    REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
-  elif new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))"; then
-    debug "Sending Invitation Link:" \
-          "https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
-    "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
+user_invite_email(){  # TRANSLATION
+  "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
        From: ${MAILFROM}
        To: ${email}
        Subject: You have been invited to ${HTTP_HOST%:*}
@@ -307,9 +323,9 @@ user_invite(){
 
        You can create your account using this link:
 
-           https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
+           ${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
 
-       This registration link will expire after 24 hours.
+       This registration link will expire after $((USER_CONFIRMEXPIRE / 3600)) hours.
 
        If you do not know what this is about, then someone else probably
        entered your email address by accident. In this case you shoud
@@ -319,6 +335,21 @@ user_invite(){
        This is an automatic email. Any direct reply will not be received.
        Your Account Registration Robot.
        EOF
+}
+
+user_invite(){
+  local uid="$(timeid)"
+  local email="$(POST email |user_checkemail)"
+  local message="$(POST message)"
+
+  if [ ! "email" ]; then
+    REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
+  elif user_emailexist "$email"; then
+    REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
+  elif new_user "$uid" status=pending email="$email" expire="$((_DATE + USER_CONFIRMEXPIRE))"; then
+    debug "Sending Invitation Link:" \
+          "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+    user_invite_email
     REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
   else
     REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
@@ -365,15 +396,15 @@ user_login(){
   # set cookie
   # keep logged in - device cookie?
   # initialize new session!
-  local UID    UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
+  local UID_   UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
   local uname="$(POST uname |STRING)" pw="$(POST pw)"
 
   [ -f "$user_db" -a -r "$user_db" ] \
-  && while read -r UID UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
+  && while read -r UID_        UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE; do
     if [ "$UNAME" = "$uname" -o "$EMAIL" = "$uname" ]; then
       if [ "$STATUS" = active -a "$EXPIRE" -gt "$_DATE" -a "$PWHASH" = "$(user_pwhash "$PWSALT" "$pw")" ]; then
         SESSION_COOKIE new
-        SESSION_BIND user_id "$UID"
+        SESSION_BIND user_id "$UID_"
         REDIRECT "${_BASE}${PATH_INFO}#USER_LOGGED_IN"
       fi
     fi
@@ -392,7 +423,7 @@ user_logout(){
 
 user_update(){
   # todo: username update, email update / email confirm
-  local UID    UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
+  local UID_   UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
   # local uname="$(POST uname |STRING)"
   local uid oldpw pw pwconfirm
 
@@ -402,18 +433,18 @@ user_update(){
   pwconfirm="$(POST pwconfirm)"
 
 
-  read -r UID  UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE <<-EOF
+  read -r UID_ UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE <<-EOF
        $(grep "^${uid} " "$user_db")
        EOF
 
-  if [ "$UID" = "$USER_ID" -a "$PWHASH" = "$(user_pwhash "$PWSALT" "$oldpw")" ]; then
+  if [ "$UID_" = "$USER_ID" -a "$PWHASH" = "$(user_pwhash "$PWSALT" "$oldpw")" ]; then
     if [ "$pw" -a "$pw" = "$pwconfirm" ]; then
       update_user "${uid}" password="$pw"
       REDIRECT "${_BASE}${PATH_INFO}#UPDATE_SUCCESS"
     else
       REDIRECT "${_BASE}${PATH_INFO}#ERROR_PWMISMATCH"
     fi
-  elif [ "$UID" = "$USER_ID" ]; then
+  elif [ "$UID_" = "$USER_ID" ]; then
     REDIRECT "${_BASE}${PATH_INFO}#ERROR_INVALID_AUTH_PASSWORD"
   else
     REDIRECT "${_BASE}${PATH_INFO}#ERROR_NOTLOGGEDIN"
@@ -444,6 +475,10 @@ read_user "$(SESSION_VAR user_id)"
     :;;
 esac
 
+export USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+       USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+
+
 w_user_update(){
   if [ ! "$USER_ID" ]; then
     cat <<-EOF
@@ -465,17 +500,15 @@ w_user_update(){
   fi
 }
 
-w_user_register(){
-  if [ "$(GET user_confirm)" ]; then
-    w_user_confirm
-  elif [ "$USER_REGISTRATION" != true -a -s "$user_db" ]; then
-    cat <<-EOF
+w_user_register_disabled(){  # TRANSLATION
+  cat <<-EOF
        [div #user_register .disabled
        User Registration is disabled.
        ]
        EOF
-  elif [ "$USER_REQUIREEMAIL" = true ]; then
-    cat <<-EOF
+}
+w_user_register_sendmail(){  # TRANSLATION
+  cat <<-EOF
        [form #user_register .registeremail method=POST
          [p We will send an activation mail to your email address.
            You can continue the signup process when you click on the
@@ -484,8 +517,9 @@ w_user_register(){
          [submit "action" "user_register" Sign Up]
        ]
        EOF
-  elif [ "$USER_REQUIREEMAIL" != true ]; then
-    cat <<-EOF
+}
+w_user_register_direct(){  # TRANSLATION
+  cat <<-EOF
        [form #user_register .registername method=POST
           [input name=uname placeholder="Choose Username" tooltip="Your username may contain any character but the @ sign. It must be at least 3 characters long, and it must start with a letter." pattern="^\[\\\\p{L}\]\[\\\\p{L}0-9 -~\]{2,127}$" autocomplete=off]
          [input type=password name=pw placeholder="Choose Passphrase" pattern=".{6,}"]
@@ -493,20 +527,22 @@ w_user_register(){
          [submit "action" "user_register" Sign Up]
        ]
        EOF
-  fi
 }
 
-w_user_confirm(){
-  local UID    UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
-  local user_confirm="$(GET user_confirm)"
-  local uid="${user_confirm% *}" signature="${user_confirm#* }"
+w_user_register(){
+  if [ "$(GET user_confirm)" ]; then
+    w_user_confirm
+  elif [ "$USER_REGISTRATION" != true -a -s "$user_db" ]; then
+    w_user_register_disabled
+  elif [ "$USER_REQUIREEMAIL" = true ]; then
+    w_user_register_sendmail
+  elif [ "$USER_REQUIREEMAIL" != true ]; then
+    w_user_register_direct
+  fi
+}
 
-  if [ "$signature" = "$(session_mac "$uid")" ]; then
-    read -r UID        UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE <<-EOF
-       $(grep "^${uid} " "$user_db")
-       EOF
-    if [ "$STATUS" = pending -a "$EXPIRE" -gt "$_DATE" ]; then
-      cat <<-EOF
+w_user_confirm_proceed(){  # TRANSLATION
+  cat <<-EOF
        [form #user_confirm method=POST
          [input type=hidden name=uid value="${uid}"]
          [input type=hidden name=signature value="${signature}"]
@@ -519,66 +555,108 @@ w_user_confirm(){
          [submit "action" "user_confirm" Finish Registration]
        ]
        EOF
-    else
-      cat <<-EOF
+}
+w_user_confirm_expired(){  # TRANSLATION
+  cat <<-EOF
        [div #user_confirm .expired
          [p This activation link is not valid anymore.]
        ]
        EOF
-    fi
-  else
-    cat <<-EOF
+}
+w_user_confirm_invalid(){  # TRANSLATION
+  cat <<-EOF
        [div #user_confirm .invalid
          [p This activation link is invalid. Make sure you copied the whole activation link from your email and be careful not to include any line breaks.]
        ]
        EOF
+}
+
+w_user_confirm(){
+  local UID_   UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE
+  local user_confirm="$(GET user_confirm)"
+  local uid="${user_confirm% *}" signature="${user_confirm#* }"
+
+  if [ "$signature" = "$(session_mac "$uid")" ]; then
+    read -r UID_       UNAME   STATUS  EMAIL   PWSALT  PWHASH  EXPIRE  DEVICES FUTUREUSE <<-EOF
+       $(grep "^${uid} " "$user_db")
+       EOF
+    if [ "$STATUS" = pending -a "$EXPIRE" -gt "$_DATE" ]; then
+      w_user_confirm_proceed
+    else
+      w_user_confirm_expired
+    fi
+  else
+    w_user_confirm_invalid
   fi
 }
 
-w_user_invite(){
-  if [ "$(GET user_confirm)" ]; then
-    w_user_confirm
-  elif [ "$USER_ID" -a "$SENDMAIL" ]; then
-    cat <<-EOF
+w_user_invite_email(){  # TRANSLATION
+  cat <<-EOF
        [form #user_invite method=POST
          [input placeholder="Email Recipient" name=email autocomplete=off]
          [textarea name="message" placeholder="Message to recipient" . ]
          [submit "action" "user_invite" Send Invitation]
        ]
        EOF
-  elif [ "$USER_ID" ]; then
-    uid="$(timeid)"
-    new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))"
-    cat <<-EOF
-        [p An anonymous user account has been set up. Send the following link to the intended user, so they may claim their account. The link will remain valid for 24 hours.]
-        [p . $(HTML "https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")" |debug)]
+}
+w_user_invite_link(){  # TRANSLATION
+  cat <<-EOF
+       [div #user_invite .link
+          [p An anonymous user account has been set up. Send the following link to the intended user, so they may claim their account. The link will remain valid for $((USER_CONFIRMEXPIRE / 3600)) hours.]
+          [a href="$(HTML "$invlink")" . $(HTML "$invlink")]
 
-        [p [a href="#" . Set up another account]]
+          [p [a href="#" . Set up another account]]
+       ]
        EOF
-  else
-    cat <<-EOF
+}
+w_user_invite_deny(){  # TRANSLATION
+  cat <<-EOF
        [div #user_invite .notallowed
          Only registered users may send an invitation to another user.
        ]
        EOF
+}
+
+w_user_invite(){
+  local uid invlink
+
+  if [ "$(GET user_confirm)" ]; then
+    w_user_confirm
+  elif [ "$USER_ID" -a "$SENDMAIL" ]; then
+    w_user_invite_email
+  elif [ "$USER_ID" ]; then
+    uid="$(timeid)"
+    new_user "$uid" status=pending expire="$((_DATE + USER_CONFIRMEXPIRE))"
+    invlink="${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+    debug "New Invitation Link: $invlink"
+    w_user_invite_link
+  else
+    w_user_invite_deny
   fi
 }
 
-w_user_login(){
-  if [ ! "$USER_ID" ]; then
-    cat <<-EOF
+w_user_login_logon(){  # TRANSLATION
+  cat <<-EOF
        [form #user_login .login method=POST
-         [input name=uname placeholder="Username or Email" autocomplete=off]
+         [input name=uname placeholder="Username or Email"]
          [input type=password name=pw placeholder="Passphrase"]
          [submit "action" "user_login" Login]
        ]
        EOF
-  elif [ "$USER_ID" ]; then
-    cat <<-EOF
+}
+w_user_login_logoff(){  # TRANSLATION
+  cat <<-EOF
        [form #user_login .logout method=POST
          [p Logged in as [span . $(HTML ${USER_NAME})]]
          [submit "action" "user_logout" Logout]
        ]
        EOF
+}
+
+w_user_login(){
+  if [ ! "$USER_ID" ]; then
+    w_user_login_logon
+  elif [ "$USER_ID" ]; then
+    w_user_login_logoff
   fi
 }