#!/bin/bash
#
# webbuild functions
# Copyright (c) 2012-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/autodist/config

SUDO_WRAPPER="sudo /usr/libexec/webbuild-sudo"
#STATEDIR=$WEBBUILD_STATEDIR
LOG=$WEBBUILD_STATEDIR/access_log
DEFAULT_ENVIRONMENT=0
[ "`uname -m`" = "x86_64" ] && HOST_IS_X86_64=1

function set_user_state_var() {
   local statevar=$1
   local statevalue=$2
   local stateuser=$3

   [ ! "$stateuser" ] && stateuser=$USER

   [ "$1" ] || return

   [ -e $WEBBUILD_STATEDIR/users/$stateuser.state ] || touch $WEBBUILD_STATEDIR/users/$stateuser.state
   sed -i "/^$statevar=/d" $WEBBUILD_STATEDIR/users/$stateuser.state
   [ "$statevalue" ] && echo "$statevar=$statevalue" >> $WEBBUILD_STATEDIR/users/$stateuser.state
}

function create_webbuild_db() {
   sqlite3 $WEBBUILD_STATEDIR/webbuild.db \
      "CREATE TABLE social_log(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, privacy BOOLEAN, user CHAR(40), type CHAR(40), target CHAR(40), email CHAR(80), text TEXT, time datetime default current_timestamp);"
}

function social_log() {
   local line=$1
   local SPRIVACY=0

   [ "$line" ] || return

   if [ ! "$STATE_FAKEUSER" ]; then

      [ -e $WEBBUILD_STATEDIR/webbuild.db ] || \
         creaqte_webbuild_db

      eval "$line"
      [ "$STATE_PRIVACYMODE" ] && $SPRIVACY=1
      sqlite3 $WEBBUILD_STATEDIR/webbuild.db \
         "INSERT into social_log (privacy, user, type, target, email, text) \
         values ($SPRIVACY,'$SUSER','$STYPE','$STARGET','$SEMAIL','$STEXT');"

      # Note: checking that URL does not point here again to avoid recursive requests
      if [ "$WEBBUILD_URL" -a "${WEBBUILD_URL/\/localhost\//}" = "$WEBBUILD_URL" ]; then
         eval $line
         USER_SECRET_FIXED=`echo $USER_SECRET | sed "s|\$|\\$|"`
         curl -s "$WEBBUILD_URL?REQUEST=message&USER=$USER&SECRET=`cgi_encodevar \"$USER_SECRET\"`&USER_EMAIL=$USER_EMAIL&\
TARGET=$STARGET&MESSAGE=`cgi_encodevar \"$STEXT\"`" >/dev/null
      fi
   fi
}

function cgi_encodevar() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo -n "${encoded}"    # You can either set a return variable (FASTER) 
#  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

function cgi_get_POST_upload()
# NOTE: only single file is supported
{
   local content_disposition content_filename content_type

   saveifs=$IFS
   IFS=$'\r'
   read -r
   read -r content_disposition
   eval content_filename=${content_disposition/*filename=}
   # security, remove any trailing path
   content_filename=${content_filename/*\/}

   read -r content_type
   read -r
   IFS=$saveifs
   head -n -1 | head -c -2 | cat > $WEBBUILD_STATEDIR/uploads/$content_filename   
}

#This code for getting code from post data is from http://oinkzwurgl.org/bash_cgi and
#was written by Phillippe Kehi <phkehi@gmx.net> and flipflip industries


# (internal) routine to store POST data
function cgi_get_POST_vars()
{
    # check content type
    # Handle uploads
    if [ "${CONTENT_TYPE:0:19}" = "multipart/form-data" ]; then
        cgi_get_POST_upload "${CONTENT_TYPE/*boundary=}"
        return
    fi
    #[ "${CONTENT_TYPE:0:33}" != "application/x-www-form-urlencoded" ] && \
    #   echo "Warning: you should probably use MIME type "\
    #        "application/x-www-form-urlencoded instead of ${CONTENT_TYPE}!" 1>&2
    # save POST variables (only first time this is called)
    [ -z "$QUERY_STRING_POST" \
      -a "$REQUEST_METHOD" = "POST" -a ! -z "$CONTENT_LENGTH" ] &&
        read -n $CONTENT_LENGTH QUERY_STRING_POST
    return
}

# (internal) routine to decode urlencoded strings
function cgi_decodevar()
{
    [ $# -ne 1 ] && return
    local v t h
    # replace all + with whitespace and append %%
    t="${1//+/ }%%"
    while [ ${#t} -gt 0 -a "${t}" != "%" ]; do
	v="${v}${t%%\%*}" # digest up to the first %
	t="${t#*%}"       # remove digested part
	# decode if there is anything to decode and if not at end of string
	if [ ${#t} -gt 0 -a "${t}" != "%" ]; then
	    h=${t:0:2} # save first two chars
	    t="${t:2}" # remove these
	    if [ "${h}" = "22" ]; then
	       v="${v}\\\""
	    elif [ "${h}" = "0A" ]; then
	       v="${v}\\\n"
	    elif [ "${h}" = "24" ]; then
	       v="${v}\\\$"
	    elif [ "${h}" = "60" ]; then
	       v="${v}\\\`"
	    else
	       v="${v}"`echo -e \\\\x${h}` # convert hex to special char
	    fi
	fi
    done
    # return decoded string
    echo "${v}"
    return
}

# routine to get variables from http requests
# usage: cgi_getvars method varname1 [.. varnameN]
# method is either GET or POST or BOTH
# the magic varible name ALL gets everything
function cgi_getvars()
{
    [ $# -lt 2 ] && return
    local q p k v s
    # get query
    case $1 in
	GET)
	    [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
	    ;;
	POST)
	    cgi_get_POST_vars
	    [ ! -z "${QUERY_STRING_POST}" ] && q="${QUERY_STRING_POST}&"
	    ;;
	BOTH)
	    [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
	    cgi_get_POST_vars
	    [ ! -z "${QUERY_STRING_POST}" ] && q="${q}${QUERY_STRING_POST}&"
	    ;;
    esac
    shift
    s=" $* "
    # parse the query data
    while [ ! -z "$q" ]; do
        p=`echo $q | sed "s|&.*||"`
        q=`echo $q | sed "s|[^&]*&||"`
	k="${p%%=*}"  # get the key (variable name) from it
	[ ! "$k" -o "$k" = "REMOTE_ADDR" -o "$k" = "REMOTE_HOST" -o "$k" = "REMOTE_PORT" -o "$k" = "REMOTE_USER" ] && continue
	v="${p#*=}"   # get the value from it
        # decode and evaluate var if requested
        if [ "$k" != "SPECTEXT" ]; then
           v=`cgi_decodevar "$v"`
        fi
        eval "$k=\"$v\""
    done
    return
}

function var2html()
{
   eval r=\$$1
   r="${r//\&/&amp;}"
   r="${r//\</&lt;}"
   r="${r//\\\n/<br>}"
   r="${r//\\/&#92;}"
   r="${r//\"/&quot;}"
   r="${r//\$/&#36;}"
   r="${r//\`/&#96;}"
   r="${r//\*/&#42;}"
   echo "${r}"
}

function kill_tree() {
   local killpid=$1

   [ $1 ] || return

   # tail here is used to avoid killing first pid, typically sh, which causes apache to stop since some time
   kill `pstree -pl $killpid | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tail -n+2 | tr "\n" " "`
   return $?
}

function parse_search_output() {
   local SEARCHARCH=$1
   echo -n "<style type=\"text/css\">\
.searchlink a:link { text-decoration:none; color:inherit; }\
.searchlink a:hover { text-decoration:underline; }\
.searchlink a:visited { text-decoration:underline; color:inherit; }\
</style><span class=searchlink>"
   while read line; do
      [ "$line" ] || continue
      set -- $line
      local REPOSITORY=${1/(*}
      local ARCH=`echo $1 | sed "s|.*(\(.*\)):|\1|"`
      local PKG=`echo $2 | sed "s|\(.*\)-[^-]*-[^-]*|\1|"`
      if [ "$ARCH" = "source" ]; then
         echo -n "<font color=lightgreen>"
      elif [ "$ARCH" = "$SEARCHARCH" ]; then
         echo -n "<font color=white>"
      else
         echo -n "<font color=gray>"
      fi
      echo -n "<a class=searchlink href=\"/distribution/distromatic.html?tag=$REPOSITORY\" target=_new>$REPOSITORY</a>($ARCH): "
      echo -n "<a class=searchlink href=\"/distribution/distromatic.html?tag=$REPOSITORY&pkg=$PKG.$ARCH\" target=_new>$2</a><br>"
      echo -n "</font>"
#      if [ "$ARCH" ]
#   $SUDO_WRAPPER 0 local "$USER" "" "autodist-repository search -i $REPSEARCHTEXT" | \
#      sed "s|\(.*(source).*\)|<font color=white><b>\1</b></font>|;
#           s|\(.*(${AUTOPORT_ARCH[$ENVIRONMENT]}).*\)|<font color=lightgreen>\1</font>|"
   done
   echo -n "</span>"
}

function parse_patch_output() {
   local PATCH_STARTED SAVE_IFS=$IFS

   IFS=''
   echo -n "<font color=gray>"
   sed "s|<|\&lt;|g;s|[[:cntrl:]]\[[0-9;]*m||g;
           s|^\(+++.*\)|<font color=white style=\"background-color:gray\"><b>\1</b></font>|;
           s|^\(---.*\)|<font color=white style=\"background-color:gray\"><b>\1</b></font>|;
           s|^\(-.*\)|<font color=red>\1</font>|;
           s|^\(+.*\)|<font color=lightgreen>\1</font>|;
           s|^ |\&nbsp;|;" |
   while read line; do
      [ "${line:0:3}" = "+++" ] && echo -n "</font>"
      echo "$line"
   done
   IFS=$SAVE_IFS
}

function parse_build_output() {
#s|\(.\{10000\}\).*|\1 [CUT - LONG LINE]|;
   sed "s|\r.*||;
        s/\x90\x8D.*//g;
        s|\\\|\\\\\\\|g;s|<|\&lt;|g;
        s|[[:cntrl:]]\[[0-9;]*m||g;
        s|&lt;font|<font|g;
        s|&lt;/font|</font|g;
        s|^\([\+#] .*\)|<font style=\"color:cyan\">\1</font>|;
        s|\(ftp[s]*://[[:alnum:]+\,:&?/_.=~%#-]*\)|<a href=\1 target=new>\1</a>|;
        s|\(http[s]*://[[:alnum:]+\,:&?/_.=~%#-]*\)|<a href=\1 target=new>\1</a>|;
        s|\(.*\)\(^.*error[^0-9A-Za-z]*:[[:space:]]*.*\)|<span class=\"outputboxerror\">\1<a %SRCURL%\2%SRCURLEND%>\2</a></span>|i;
        s|^\(== =.*\)|<span class=\"outputboxok\">\1</span>|;
        s|^[[:cntrl:]]*\([!%?=][!%!=>] .*\)|<font style=\"color:gold\">\1</font>|;
        s|[[:cntrl:]]||g;" | iconv -c | hint_search $1
}

function parse_generic_output() {
#        s|\(.\{10000\}\).*|\1 [CUT - LONG LINE]|;
   sed "s|\r.*||;
        s|<|\&lt;|g;
        s|[[:cntrl:]]\[[0-9;]*m||g;
        s|&lt;font|<font|g;
        s|&lt;/font|</font|g;
        s|^\([\+#] .*\)|<font style=\"color:cyan\">\1</font>|;
        s|\(ftp[s]*://[[:alnum:]+\,:&?/_.=~%#-]*\)|<a href=\1 target=new>\1</a>|;
        s|\(http[s]*://[[:alnum:]+\,:&?/_.=~%#-]*\)|<a href=\1 target=new>\1</a>|;" | hint_search $1
}

function hint_search() {
   while read line; do
      if [ "${line/\%SRCURL\%}" == "${line}" ]; then
         echo "$line"
      else
         local SEARCH_STRING=`echo "$line" | sed "s|.*%SRCURL%\(.*\)%SRCURLEND%.*|\1|;s|\&lt;|<|"`
         local SEARCH_STRING_ENCODED=`cgi_encodevar "I get this error while building $1: $SEARCH_STRING"`
         #echo "$line" | sed "s|%SRCURL%.*%SRCURLEND%|href=\"https://duckduckgo.gom/?q=$SEARCH_STRING_ENCODED\" target=_new title=\"Search this error on the Web\"|g"
         echo "$line" | sed "s|%SRCURL%.*%SRCURLEND%|href=\"https://chatgpt.com/?q=$SEARCH_STRING_ENCODED\" target=_new title=\"Query ChatGPT on this error\"|g"
      fi
   done
}

function print_environment_descr() {
   local i=$1

   if [ "${AUTOPORT_CHROOT[$i]}" ]; then
      echo -n "${AUTOPORT_CHROOT[$i]} - "
   elif [ "${AUTOPORT_CHROOT_USER[$i]}" ]; then
      echo -n "${AUTOPORT_CHROOT_USER[$i]} - "
   else
      echo -n "autodist - "
   fi
   if [ "${AUTOPORT_UPDATE[$i]}" ]; then
      echo -n "update"
   elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
      echo -n "chroot"
   elif [ "${AUTOPORT_NATIVE[$i]}" ]; then
      echo -n "native"
   elif [ "${AUTOPORT_CROSS[$i]}" ]; then
      echo -n "cross"
   else
      echo -n "unknown type"
   fi
   echo -n " for ${AUTOPORT_ARCH[$i]}"
   # (${AUTOPORT_BASE_REPOSITORY[$i]} based)"
}

function environment_rootdir() {
      local env=$1
      if [ "${AUTOPORT_CHROOT[$env]}" ]; then
         echo "/var/autoport/${AUTOPORT_CHROOT[$env]}"
      else
         echo ""
      fi
}

function environment_autoport_logdir() {
      local env=$1
      if [ "${AUTOPORT_CHROOT[$env]}" ]; then
         if [ "${AUTOPORT_CHROOT_USER[$env]}" != "autodist" ]; then
            echo "/var/autoport/${AUTOPORT_CHROOT[$env]}/home/${AUTOPORT_CHROOT_USER[$env]}/.autoport/"
         else
            echo "/var/autoport/${AUTOPORT_CHROOT[$env]}/var/autodist/.autoport/"
         fi
      elif [ "${AUTOPORT_NATIVE[$env]}" ]; then
         local envhome=`eval echo ~${AUTOPORT_CHROOT_USER[$env]}`
         echo "$envhome/.autoport"
      fi
}

function environment_logdir() {
      local env=$1
      local chroot=$2

      if [ "${AUTOPORT_CHROOT[$env]}" ]; then
         if [ "${AUTOPORT_CHROOT_USER[$env]}" != "autodist" ]; then
            if [ "$chroot" ]; then
               echo "/home/${AUTOPORT_CHROOT_USER[$env]}/.autodist/log/"
            else
               echo "/var/autoport/${AUTOPORT_CHROOT[$env]}/home/${AUTOPORT_CHROOT_USER[$env]}/.autodist/log/"
            fi
         else
            if [ "$chroot" ]; then
               echo "/var/autodist/log/"
            else
               echo "/var/autoport/${AUTOPORT_CHROOT[$env]}/var/autodist/log/"
            fi
         fi
      elif [ "${AUTOPORT_NATIVE[$env]}" ]; then
         local envhome=`eval echo ~${AUTOPORT_CHROOT_USER[$env]}`
         if [ "${AUTOPORT_CHROOT_USER[$env]}" = "autodist" ]; then
            echo "/var/autodist/log/"
         else
            echo "$envhome/.autodist/log/"
         fi
      else
         echo "/var/autodist/log/"
      fi
}
