#!/bin/bash
#
# Tool for generating various logs and sending them to the internet.
#
# NOTE: Even though much effort for removing personal information
#       has been made, logs may still contain some personal information.
#       Thus the user may create an additional filter for removing
#       personal data from the logs.
#       See the end of function "RemovePersonalData"
#       and file "$DIR_OF_CONFIG/eos-log-tool-filter.bash" below.
#

Breakpoint() {
    :;
}

source /usr/share/endeavouros/scripts/eos-script-lib-yad || exit 1

export -f eos_yad
AssignIconVariables_in_eos_bash_shared

DIE() {
    echo "$progname: error: $1" >&2
    exit 1
}

TT() { echo "<tt>$1</tt>" ; }

MsgOld() {
    local -r msg="$1"
    local -r title="$2"
    shift 2
    local width=$((${#msg} * 10))
    local -r highlimit=650
    local -r lowlimit=200

    test $width -gt $highlimit && width=$highlimit
    test $width -lt $lowlimit  && width=$lowlimit

    echo "$msg" | eos_yad --text-info --title="$title" --formatted --wrap \
                          --width=$width --height=100 --button=yad-quit "$@"
}
Msg() {
    local -r msg="$1"
    local -r title="$2"
    local icon="$3"

    if [ -n "$icon" ] ; then
        shift 3
    else
        icon="$ICO_TIPS"
        shift 2
    fi
    local -r cmd=(
        eos_yad --form --title="$title" --text="$msg"
        --image=$icon --button=yad-quit "$@"
    )
    "${cmd[@]}"
}
ErrorMsg() {
    local -r msg="$1"
    Msg "$msg" "Error" $ICO_ERROR
}
WarningMsg() {
    local -r msg="$1"
    Msg "$msg" "Warning"
}

Header() { printf "%s\n\n" "#################### $* ########################" ; }
Footer() { printf "\n\n" ; }

Cmd() {
    local -r cmd="$1"

    echo "==> Handling '$*'" >&2

    if [ "$cmd" = "cat" ] ; then
        if [ "${2::1}" = "." ] ; then
            cd                  # $HOME stuff: go to $HOME to hide unnecessary info
        fi
    fi

    case "$cmd" in
        pkexec)
            shift
            SUDO_CMDS+=" ; echo '$(Header "$@")' >> $FILE_OF_LOGS"
            SUDO_CMDS+=" ; $* >> $FILE_OF_LOGS"
            SUDO_CMDS+=" ; echo '$(Footer)' >> $FILE_OF_LOGS"
            return
            ;;
        FuncCall)
            # params: FuncCall "func"
            Header "$2" >> $FILE_OF_LOGS
            "$2"        >> $FILE_OF_LOGS
            Footer      >> $FILE_OF_LOGS
            return
            ;;
        "")
            echo "==> $FUNCNAME: empty command!" >&2
            return
            ;;
        *)
            Header "$@" >> "$FILE_OF_LOGS"
            if [ -x /usr/bin/"$cmd" ] ; then
                "$@" 2>/dev/null >> "$FILE_OF_LOGS"
            else
                WarningMsg "Command '$cmd' not found."
                echo "Sorry, command '$cmd' not found." >> "$FILE_OF_LOGS"
            fi
            Footer >> "$FILE_OF_LOGS"
            ;;
    esac
}

SendToInternet() {
    echo "==> Sending $FILE_OF_LOGS2 to a pastebin service." >&2

    local -r logdata="$(cat "$FILE_OF_LOGS")"

    if [ -z "$logdata" ] ; then
        ErrorMsg "No logs found!"
        return 1
    fi

    local exitcode=0
    local url
    url="$(echo "$logdata" | eos-sendlog)"
    exitcode=$?
    if [ $exitcode -ne 0 ] ; then
        ErrorMsg "Sending log data failed!"
        exit 1
    fi

    # Ad hoc tests for the URL.

    if [ ${#url} -gt 100 ] ; then
        # Reject too long URL.
        ErrorMsg "Sending log data failed (returned invalid URL)!"
        exit 1
    fi
    case "$url" in
        [hH][tT][tT][pP]://* | [hH][tT][tT][pP][sS]://*)       # OK, accept URL that start with http:// or https://.
            ;;
        "")                                                    # Reject empty URL.
            local -r logfilesize=$(stat -c %s "$FILE_OF_LOGS")
            if [ $logfilesize -gt $EOS_LOG_TOOL_MAX_LOG_SIZE ] ; then
                ErrorMsg "Sending log data failed (returned empty URL)!\nLog size $logfilesize bytes too large?"
            else
                ErrorMsg "Sending log data failed (returned empty URL)!"
            fi
            exit 1
            ;;
        *)                                                     # Reject any other URL string.
            ErrorMsg "Sending log data failed (returned invalid URL)!"
            exit 1
            ;;
    esac
    echo "$(date '+%Y-%m-%d %H:%M:%s'): $url" >> "$DIR_OF_CONFIG"/url-list.txt
    if [[ -x /usr/bin/xclip ]]; then
        eos_yad --text="$url" --button="cancel":1 --button="copy":0 --title="Result URL" --width=300
        test $? -eq 0 && echo "$url" | xclip -i -selection clipboard
    else
        echo "$url" | eos_yad --text-info --width=300 --title="Result URL" &
    fi
    rm -f "$FILE_OF_LOGS" "$FILE_OF_LOGS.bak"
    sendToInternet=yes
}

UserNames() {
    local -r low="$1"     # lowest  user id number
    local -r high="$2"    # highest user id number
    local nr
    local user users=""

    for nr in $(cat /etc/passwd | cut -d ':' -f 3) ; do
        if [ $nr -ge $low ] && [ $nr -le $high ] ; then
            user=$(grep ":$nr:" /etc/passwd | cut -d ':' -f 1)
            if [ -z "$users" ] ; then
                users="$user"
            else
                users+=" $user"
            fi
        fi
    done
    echo "$users"
}

RemovePersonalData() {
    if [ ! -r "$FILE_OF_LOGS" ] ; then
        ErrorMsg "Logs not found at $FILE_OF_LOGS2!"
        exit 1
    fi
    cp -a "$FILE_OF_LOGS" "$FILE_OF_LOGS.bak"
    local user
    local uid=$(id -u)
    local ssid="foobarfoobarfoobar"
    local mac="foobarfoobarfoobar"
    local interface="$(ifconfig | grep "^[a-z]" | sed 's|: .*||' | grep -v "^lo$" | head -n1)"

    if [ -x /usr/bin/iwgetid ] ; then
        ssid=$(iwgetid -r)
        mac=$(iwgetid -ra)
    fi

    local -r user2="_user_"
    local -r mac2="_mac_address_"
    local -r ip2="_ip_address_"
    local -r ssid2="_ssid_"
    local -r uid2="_uid_"
    local -r interface2="_interface_"

    # hide real user names (that are found in /etc/passwd) from logs
    for user in $(UserNames 1000 50000) ; do
        sed -i "$FILE_OF_LOGS" \
            -e "s| IN=$interface | IN=$interface2 |g" \
            -e "s| $interface:| $interface2:|g" \
            -e "s| $interface NIC| $interface2 NIC|g" \
            -e "s|($interface)|($interface2)|g" \
            -e "s| \([iI]nterface\) $interface\.| \1 $interface2\.|g" \
            -e "s| on $interface\.| on $interface2\.|g" \
            -e "s|uid=$uid |uid=$uid2 |g" \
            -e "s|uid=$uid)|uid=$uid2)|g" \
            -e "s|UID $uid|UID $uid2|g" \
            -e "s|/run/user/$uid|/run/user/$uid2|g" \
            -e "s|@$uid |@$uid2 |g" \
            -e "s|/$uid]|/$uid2]|g" \
            -e "s|owned by '$uid' |owned by '$uid2' |g" \
            -e "s| $user | $user2 |g" \
            -e "s|/$user/|/$user2/|g" \
            -e "s|\"$user\"|\"$user2\"|g" \
            -e "s|$user:$user|$user2:$user2|g" \
            -e "s|/$user|/$user2|g" \
            -e "s| $user$| $user2|g" \
            -e "s| $user:| $user2:|g" \
            -e "s|'$user'|'$user2'|g" \
            -e "s| $user\.| $user2.|g" \
            -e "s|:$user |:$user2 |g" \
            -e "s|:$user)|:$user2)|g" \
            -e "s| $user)| $user2)|g" \
            -e "s| $user(| $user2(|g" \
            -e "s|‘$user:|‘_user_:|g" \
            -e "s|\[$user\]|[_user_]|g" \
            -e "s|$user\"|$user2\"|g" \
            -e "s|LOGNAME=$user|LOGNAME=$user2|" \
            -e "s|USERNAME=$user|USERNAME=$user2|" \
            -e "s|USER=$user|USER=$user2|" \
            -e "s| with address .*\.$| with address $ip2.|" \
            -e "s| new address record for .* on \(.*\)$| new address record for $ip2 on \1|" \
            -e "s| policy: set '.*' (\(.*\)) as default for | policy: set '$ssid2' (\1) as default for |" \
            -e "s| connection '.*' | connection '$ssid2' |" \
            -e "s|set MAC address to .* (|set MAC address to $mac2 (|" \
            -e "s| associate with .* (| associate with $mac2 (|" \
            -e "s| access point '.*' | access point '$ssid2' |" \
            -e "s|'ssid' value '.*'$|'ssid' value '$ssid2'|" \
            -e "s|(SSID='.*' |(SSID='$ssid2' |" \
            -e "s| wireless network \".*\"$| wireless network \"$ssid2\"|" \
            -e "s|192\.168\.[0-9]*\.[0-9]*|$ip2|" \
            -e "s| fe80::[0-9a-f:]*\([ \.]\)|$ip2\1|" \
            -e "s|'$ssid'|'$ssid2'|" \
            -e "s|$mac|$mac2|"
            
    done

    # hide hostname from logs
    sed -i "$FILE_OF_LOGS" \
        -e 's| '$HOSTNAME' | _hostname_ |g' \
        -e 's|"'$HOSTNAME'"|"_hostname_"|g' \
        -e 's|<'$HOSTNAME'>|<_hostname_>|g' \
        -e 's|='$HOSTNAME' |=_hostname_ |g' \
        -e 's| '$HOSTNAME'\.| _hostname_.|g' \
        -e 's| '$HOSTNAME'"| _hostname_"|g' \
        -e 's|-'$HOSTNAME':|-_hostname_:|g' \
        -e "s|'"$HOSTNAME"'|'_hostname_'|g"

    # User may create an additional filter for removing
    # any remaining personal data from the logs.
    local -r filter="$DIR_OF_CONFIG"/${progname}-filter.bash
    if [ -r "$filter" ] ; then
        # $filter refers to user's own bash script
        # $FILE_OF_LOGS is the file containing all gathered logs
        bash "$filter" "$FILE_OF_LOGS"
    fi
    removePersonalInfo=yes

    echo "==> Personal data removed from file $FILE_OF_LOGS2." >&2
}

IsInstalled() { expac -Q %n "$1" &> /dev/null ; }

PrintPkgData() {
    local pkg ver desc
    local ix
    for ((ix=0; ix<${#data[@]}; ix=ix+3 )) ; do
        pkg="$( echo "${data[ix]}"   | sed 's|[^:]*: ||')"
        ver="$( echo "${data[ix+1]}" | sed 's|[^:]*: ||')"
        desc="$(echo "${data[ix+2]}" | sed 's|[^:]*: ||')"
        
        printf "%s$separator%s$separator%s\n" "$pkg" "$ver" "$desc"
    done | Columnize
}
Columnize() { column -t -s "$separator" ; }

ForeignPkgInfo() {
    local data
    readarray -t data < <(LANG=C pacman -Qmi | grep -P '^Name|^Version|^Description')
    PrintPkgData
}
NativePkgInfo() {
    if [ -x /usr/bin/expac ] ; then
        # expac is much faster
        expac -Q "%n$separator%v" | Columnize
    else
        local data
        readarray -t data < <(LANG=C pacman -Qni | grep -P '^Name|^Version|^Description')
        PrintPkgData
    fi
}

Local_ShowForeignPackages() {
    Cmd FuncCall ForeignPkgInfo            # "$xx" "$line"    # does special handling
}
Local_ShowNativePackages() {
    Cmd FuncCall NativePkgInfo             # "$xx" "$line"    # does special handling
}

Local_ShowEosInstallLog() {
    case "$instlog" in
        /home/*)    Cmd cat "$instlog"
                    ;;
        /var/log/*) Cmd pkexec cat "$instlog"
                    ;;
        *)          WarningMsg "no EndeavourOS install log found!"
                    echo "Sorry, EndeavourOS install log was not found." >> "$FILE_OF_LOGS"
                    ;;
    esac
}

FindInstallLog() {
    # find where the install log exists
    local -r instlogs=(
        /home/liveuser/endeavour-install.log       # in the installer
        /var/log/endeavour-install.log             # in the installed system
        /var/log/Calamares.log                     # in the installed system (also older installs)
    )
    local log
    for log in "${instlogs[@]}" ; do
        if [ -f $log ] ; then                       #  note: some files in /var/log may be readable only by root, thus option -f
            instlog="$log"
            break
        fi
    done
}

GetNameAndVersion() { expac -Q '%n %v' "$1" ; }

Options() {
    local opts
    local lopts="help,enable-inxi,enable-journal,changelog"
    local sopts="hij"

    opts="$(/usr/bin/getopt -o=$sopts --longoptions $lopts --name "$progname" -- "$@")" || {
        Options -h
        return 1
    }

    eval set -- "$opts"

    while true ; do
        case "$1" in
            -i | --enable-inxi)
                enable_inxi=yes
                ;;
            -j | --enable-journal)
                enable_journal=yes
                ;;
            --changelog)
                $(eos_select_browser) $(eos-github2gitlab https://github.com/endeavouros-team/PKGBUILDS/commits/master/$progname)
                exit 0
                ;;

#            --option-with-value)   echo "$1: $2"; shift  ;;

            -h | --help)
                cat <<EOF >&2
Usage: $progname [options]
Options:
  -i, --enable-inxi       Enable the inxi tool. It is versatile but might be quite slow with some operations.
  -j, --enable-journal    Enable showing journal logs.
                          Note that some journal logs *may* still contain data you'd want to hide.
  -h, --help              This help.
EOF
#            --changelog        Show changelog (=git commits) of this app.
                exit 0
                ;;
            
            --) shift ; break ;;
        esac
        shift
    done
}

Main()
{
    local -r progname=eos-log-tool
    eos_assert_deps $progname yad || return 1
    local enable_journal=no
    local enable_inxi=no
    local lspci_y=no              # is automatically selected (=yes) when inxi is not available
    local -r separator=$'\x0c'    # column separator character for usage with the 'column' app (Form Feed)

    local installer_mode=no
    if [ "$LOGNAME" = "liveuser" ] && [ -d /etc/calamares ] && [ -x /usr/bin/calamares ] ; then
        installer_mode=yes
    fi

    Options "$@"

    [ "$enable_inxi" = "no" ] && lspci_y=yes

    local -r FILE_OF_LOGS=$HOME/$progname.logs
    local -r FILE_OF_LOGS2="\$HOME/$progname.logs"
    local -r DIR_OF_CONFIG="$HOME/.config/$progname"
    local -r DIR_OF_CONFIG2="\$HOME/.config/$progname"

    local SUDO_CMDS=":"                                           # collects commands that need elevated privileges

    # option values, can be changed in the config file
    local EOS_LOG_TOOL_JOURNAL_OPTS="--since '20 minutes ago'"
    local EOS_LOG_TOOL_MAX_LOG_SIZE=500000                        # bytes

    local -r conffile="/etc/$progname.conf"
    local -r conffile_tt="<tt>$conffile</tt>"

    if [ -r $conffile ] ; then
        source $conffile                                # may change option values
    fi

    local instlog=""

    FindInstallLog

    # commands to be logged
    local -r cmd_inxi="inxi -Fxxc0 --za"
    local -r cmd_journal0="journalctl -b -0"
    local -r cmd_journal1="journalctl -b -1"
    local -r cmd_journal2="journalctl -b -2"
    local    cmd_journalX="journalctl $EOS_LOG_TOOL_JOURNAL_OPTS"
    local -r cmd_blame="systemd-analyze blame"
    local -r cmd_lspci="lspci -vnn"
    local -r cmd_lsusb="lsusb"
    local -r cmd_hwinfo="hwinfo --short"
    local -r cmd_X_sess_err="cat ~/.xsession-errors"
    local -r cmd_dm="cat /var/log/lightdm/lightdm.log"
    local -r cmd_dm_X="cat /var/log/lightdm/x-0.log"
    local -r cmd_grub="cat /boot/grub/grub.cfg"
    local -r cmd_fstab="cat /etc/fstab"
    local -r cmd_lsblk="lsblk -f -o+SIZE"
    local -r cmd_fdisk="fdisk -l"
    local -r cmd_pacman_conf="cat /etc/pacman.conf"
    local -r cmd_instlog="cat $instlog"
    local -r cmd_native="pacman -Qn"
    local -r cmd_foreign="pacman -Qm"
    local    cmd_X_events="cat /var/log/Xorg.0.log"

    if [ $installer_mode = yes ] ; then
        local -r xlogfile="$HOME/.local/share/xorg/Xorg.0.log"
        if [ -e "$xlogfile" ] ; then
            cmd_X_events="cat $xlogfile"
        else
            WarningMsg "file ${xlogfile} does not exist"
        fi
    fi

    local FieldInfo=()                                            # information for the logging commands

    # offsets of array index for "fields" in FieldInfo and FieldInfo1
    local -r offset_name=0
    local -r offset_selected=1
    local -r offset_installed=2
    local -r offset_tip=3
    local -r offset_command=4

    local FieldInfo1=(
        # Name                                                                Selected    Installed  Tip                                                                                          Command
        # ----                                                                --------    ---------  ---                                                                                          -------
    )
    if  [ "$enable_journal" = "yes" ] ; then
        FieldInfo1+=(
        "System journal, most recent"                                         "true"     ""         "Journal from the most recent boot: $(TT "$cmd_journal0")"                                    "pkexec $cmd_journal0"
        "System journal, 2nd most recent"                                     ""         ""         "Journal from the second most recent boot: $(TT "$cmd_journal1")"                             "pkexec $cmd_journal1"
        "System journal, 3rd most recent"                                     ""         ""         "Journal from the third most recent boot: $(TT "$cmd_journal2")"                              "pkexec $cmd_journal2"
        "System journal, user defined options in file\n$conffile"             ""         ""         "Journal by user: $(TT "$cmd_journalX")"                                                      "pkexec $cmd_journalX"
        )
    fi
    FieldInfo1+=(
        "System boot-up performance statistics"                               ""         ""         "Time that running units took to initialize: $(TT "$cmd_blame")"                              "$cmd_blame"
        "Information about the PCI devices"                                   "$lspci_y" ""         "Information related to PCI devices: $(TT "$cmd_lspci")"                                      "$cmd_lspci"
        "Information about the USB devices"                                   ""         ""         "Information related to USB devices: $(TT "$cmd_lsusb")"                                      "$cmd_lsusb"
    )
    if  [ "$enable_inxi" = "yes" ] ; then
        FieldInfo1+=(
            "Information about hardware (inxi)"                               "true"     "inxi"     "Information about hardware and software using $(TT "$cmd_inxi")"                             "$cmd_inxi"
        )
    fi
    FieldInfo1+=(
        "Information about hardware (hwinfo)"                                 ""         ""         "Summary of hardware: $(TT "$cmd_hwinfo")"                                                    "$cmd_hwinfo"
        "EndeavourOS install log"                                             ""         ""         "The log about the install of EndeavourOS: $(TT "$cmd_instlog")"                              "Local_ShowEosInstallLog"
        "X session errors"                                                    ""         ""         "Lists X session errors: $(TT "$cmd_X_sess_err")"                                             "$cmd_X_sess_err"
        "Xorg log"                                                            ""         ""         "Log about Xorg events: $(TT "$cmd_X_events")"                                                "$cmd_X_events"
        "Display manager log"                                                 ""         "lightdm"  "Display manager (lightdm) log: $(TT "$cmd_dm")"                                              "pkexec $cmd_dm"
        "Display manager log, X related"                                      ""         "lightdm"  "Display manager log, X server related: $(TT "$cmd_dm_X")"                                    "pkexec $cmd_dm_X"
        "Grub configuration file"                                             ""         "grub"     "Grub (bootloader) configuration file: $(TT "$cmd_grub")"                                     "pkexec $cmd_grub"
        "Filesystem mountpoints (fstab)"                                      ""         ""         "Static information about the filesystem and mointpoints: $(TT "$cmd_fstab")"                 "$cmd_fstab"
        "Disks and partitions (lsblk)"                                        ""         ""         "List information about disks, partitions, labels, uuids: $(TT "$cmd_lsblk")"                 "$cmd_lsblk"
        "Disks and partitions (fdisk)"                                        ""         ""         "Another list of disk and partition information: $(TT "$cmd_fdisk")"                          "pkexec $cmd_fdisk"
        "Pacman configuration file"                                           "true"     ""         "Pacman (package manager) configuration file: $(TT "$cmd_pacman_conf")"                       "$cmd_pacman_conf"
        "Native packages"                                                     ""         ""         "List native packages (=from pacman repositories): $(TT "$cmd_native") (slow without expac)"  "Local_ShowNativePackages"
        "Foreign packages"                                                    "true"     ""         "List foreign packages (=not from pacman repositories): $(TT "$cmd_foreign")"                 "Local_ShowForeignPackages"
    )

    # information for the yad buttons
    local -r ButtonInfo=(
        # Name                       Tip                                   Command
        # ----                       ---                                   -------

        "Save logs locally"          "Save logs to a local file"           ""                # 4
        "Send logs to the internet"  "Send selected logs to the internet"  "SendToInternet"  # 6
    )

    # exit codes for the yad buttons
    local -r code_cancel=1
    local -r code_localsave=4
    local -r code_send_to_internet=6
    local -r code_close_window=252

    local cmds=()
    local sendToInternet=no
    local removePersonalInfo=no
    local helptext=""
    local name selected installed tip command
    local ix jx xx count=0
    local -r tool_image=/usr/share/icons/Qogir/scalable/apps/logviewer.svg   # $ICO_QUESTION

    mkdir -p "$DIR_OF_CONFIG"
    rm -f "$FILE_OF_LOGS"

    helptext+="<i><b>$(GetNameAndVersion $progname)</b></i>\n\n"
    helptext+="Select the logs you want to save locally, and optionally share to the internet. \n"
    helptext+="Logs will will be saved to file <b>$FILE_OF_LOGS2</b>.\n"
    helptext+="If you share to the internet, you'll receive a URL which refers to the shared page.\n"
    helptext+="A list of received URLs is stored in folder <b>$DIR_OF_CONFIG2</b>.\n\n"
    helptext+="Note: <tt>$progname</tt> tries to remove personal data from the logs, but the removal is not perfect always. \n"
    helptext+="Tip: Use option <tt>--enable-journal</tt> to see <i>journalctl</i> choices.\n"
    helptext+="Tip: Use option <tt>--enable-inxi</tt> to see the <i>inxi</i> alternative.\n"

    local log_tool_cmd=(                 # the yad command
        eos_yad
        --scroll
        --columns=2
        --form
        --title="EndeavourOS log tools"
        --text="$helptext"
        # --width=600        # not needed?
        --image=$tool_image
        --button="yad-cancel!!Cancel this operation":$code_cancel
        --button="yad-save!!Save the logs to file $FILE_OF_LOGS2":$code_localsave
        --button="Share logs to the internet!$ICO_SHARE!Send the logs using <tt>eos-sendlog</tt>":$code_send_to_internet
    )

    # Skip entries that don't have the app installed

    for ((ix=0; ix < ${#FieldInfo1[@]}; ix+=5)) ; do
        installed="${FieldInfo1[$((ix+2))]}"
        if [ -n "$installed" ] ; then
            IsInstalled "$installed" || continue
        fi
        FieldInfo+=("${FieldInfo1[$((ix + offset_name))]}")
        FieldInfo+=("${FieldInfo1[$((ix + offset_selected))]}")
        FieldInfo+=("${FieldInfo1[$((ix + offset_installed))]}")
        FieldInfo+=("${FieldInfo1[$((ix + offset_tip))]}")
        FieldInfo+=("${FieldInfo1[$((ix + offset_command))]}")
    done

    # Add entries to the yad command

    for ((ix=0; ix < ${#FieldInfo[@]}; ix+=5)) ; do
        name="${FieldInfo[$((      ix + offset_name ))]}"
        selected="${FieldInfo[$((  ix + offset_selected ))]}"
        installed="${FieldInfo[$(( ix + offset_installed ))]}"
        tip="${FieldInfo[$((       ix + offset_tip ))]}"
        command="${FieldInfo[$((   ix + offset_command ))]}"
        
        [ -z "$selected" ] && selected=false

        if [ -n "$installed" ] ; then
            IsInstalled "$installed" || continue
        fi
        ((count++))
        log_tool_cmd+=(--field="$name!$tip":chk $selected)            # adds a log command entry to the yad command
    done
    log_tool_cmd+=( --height=$((35 * count)) )            # was: 550

    # Run the yad command

    local result retval

    result=$("${log_tool_cmd[@]}")                                    # execute the yad command
    retval=$?

    case "$retval" in
        $code_localsave | $code_send_to_internet) [ -n "$result" ] || DIE "No result from yad!" ;;
        $code_cancel | $code_close_window)        return ;;
        *)                                        DIE "Invalid exit code $retval from yad!" ;;
    esac

    # Now $retval is either $code_localsave or $code_send_to_internet

    # From the command result, analyze which subcommands should be executed
    local true_indexes=()
    jx=1
    for ((ix=0; ix < ${#FieldInfo[@]}; ix+=5)) ; do
        xx="$(echo "$result" | cut -d'|' -f $jx)"
        case "$xx" in
            true | TRUE) true_indexes+=($ix) ;;
        esac
        ((jx++))
    done

    for ((ix=0; ix < ${#true_indexes[@]}; ix++)) ; do
        jx=${true_indexes[$ix]}
        command="${FieldInfo[$((jx + offset_command))]}"
        case "$command" in
            Local_*)    ;;
            "pkexec "*) command="$(echo "$command" | sed 's|^pkexec |Cmd pkexec |')" ;;
            *)          command="$(echo "$command" | sed 's|^|Cmd |')" ;;
        esac
        $command
        cmds+=("$command")
    done

    if [ "$SUDO_CMDS" != ":" ] ; then
        pkexec bash -c "$SUDO_CMDS"
    fi

    # All logs are now saved into a file.

    RemovePersonalData    # always remove personal data!

    case "$retval" in
        $code_localsave)         Msg "Log file $(TT "$FILE_OF_LOGS2") created." "Info" ;;
        $code_send_to_internet)  SendToInternet ;;
    esac
}

Main "$@"
