#!/bin/bash
# -*- ENCODING: UTF-8 -*-

# picasum
#
# Checksums tool.
#
# Copyright (c) 2013-2026: Alexis Puente Montiel   < pica (a) picalibre.org >
#
# Licensed according to GNU AGPL version 3.0.
#
# It is libre/free software; you can use, redistribute and/or modify it according to the terms of GNU AGPL as published by GNU, version 3.0, 19 November 2007.
#
# It is distributed in the hope that it will be useful, but without any warranty. Read GNU AGPL version 3.0 for additional details.
#
# A copy of GNU AGPL version 3.0 is available at /usr/share/doc/<software-package-name>/agpl-3.0.txt (additionally on Internet as text at https://www.gnu.org/licenses/agpl-3.0.txt and as HTML at https://www.gnu.org/licenses/agpl-3.0-standalone.html ).
#
# Note: Additionally to the official e-mails, picalibre.org is strictly the only official site for this software project, please consider using it to download, report bugs and contribute.
#
# Depends: bash, coreutils, dialog | yad | yad-pica | zenity, findutils, gawk | mawk | original-awk, grep, sed
# Recommends: libdigest-sha3-perl, libdigest-whirlpool-perl, lxterminal | sakura | xfce4-terminal, rhash, x11-xkb-utils


### SCRIPT VARIABLES ########################################

CNAME="picasum"
VERSION="1.3.1"
TITLE="PicaSum"
ICON="/usr/share/icons/picasum.png"

# Translations
if [ "$LANG" = "" ] ; then export $(cat /etc/default/locale | grep -a 'LANG=') ; fi
TEXTDOMAIN=picasum
TEXTDOMAINDIR=/usr/share/locale/

# Write errors to log
ERRORLOG="$HOME/.${CNAME}.log"
if [ -e "$ERRORLOG" ] ; then
	mv -f $ERRORLOG ${ERRORLOG}.ant
fi
if [ -e "$ERRORLOG" ] ; then rm -rf "$ERRORLOG" ; fi

for i in /etc/pica-global.dist /etc/pica-global.orig /etc/pica-global /etc/pica-global.local ~/.pica-global ~/pica-global ; do
	if [ -f "$i" ] ; then
	cat "$i"
	source "$i"
	source <(cat $i | sed -e "s/=\(YES\|Yes\|yes\|y\|SÍ\|SI\|Sí\|Si\|sí\|si\|S\|s\)/=Y/g" -e "s/=\(No\|no\|n\)/=N/g" -e "s/=\"\(YES\|Yes\|yes\|y\|SÍ\|SI\|Sí\|Si\|sí\|si\|S\|s\)\"/=Y/g" -e "s/=\"\(No\|no\|n\)\"/=N/g")
	fi
done
if [ "$DEBUG" = "Y" ] ; then
	set -xv
	DEBUG="Y"
else
	ERRORLOG="/tmp/.${CNAME}_$(id -nu).log"
	if [ -e "$ERRORLOG" ] ; then mv -f $ERRORLOG ${ERRORLOG}.ant ; fi
	if [ -e "$ERRORLOG" ] ; then rm -rf "$ERRORLOG" ; fi
fi
if [ "$DEBUG" = "" ] ; then DEBUG="N" ; fi
if [ "$DEBUG" != "N" ] ; then
exec > >(tee -a "$ERRORLOG") 2>&1
echo "$0" "$*" >> "$ERRORLOG"
echo "$CNAME" "$VERSION" >> "$ERRORLOG"
echo $(date +%Y-%m-%d_%H:%M:%S) $"Start" >> "$ERRORLOG"
echo "env:" >> "$ERRORLOG"
env >> "$ERRORLOG"
echo "set:" >> "$ERRORLOG"
set >> "$ERRORLOG"
#else
#exec 2>>"$ERRORLOG"
fi

# Description:
BDESCRIP=$"Checksums tool."
LDESCRIP=$"$TITLE is a tool to calculate or check 'checksums' (check codes using hash functions)."

# Documentation:
docu_info () {
echo "$CNAME ($VERSION) - $BDESCRIP"
echo 
echo $"Usage:" $CNAME [$"OPTIONS"]
echo 
echo $"Options:"
echo -e "$ODESCRIP"
echo 
echo $"'man $CNAME' for more information."
echo 
}
ODESCRIP=" -r""\t"$"Use 'rhash' instead of 'GNU coreutils'.""\n"" -t""\t"$"Use terminal interface.""\n"" -k""\t"$"Use 'kdialog' if possible.""\n"" -y""\t"$"Use 'yad' if possible (by default in graphical sessions).""\n"" -z""\t"$"Use 'zenity' if possible.""\n"" -x""\t"$"Show help documentation."

while getopts rtkyzx OPTION ; do
	case $OPTION in
		r )   RHASH="Y"          ;;
		t )   T="Y" ; G="N"      ;;
		k )   SDIALOG="kdialog"  ;;
		y )   SDIALOG="yad"      ;;
		z )   SDIALOG="zenity"   ;;
		x )   docu_info ; exit 0 ;;
	esac
done

if [ "$RHASH" = "Y" ] ; then
	if [ "$(command -v rhash)" = "" ] ; then
		RHASH="N"
	fi
fi


### DIALOG ########################################

#DEFAULTDIALOGLIST="yad zenity kdialog"
DEFAULTDIALOGLIST="yad zenity"

#if [ -t 0 ] ; then
if [ "$(setxkbmap 1>/dev/null 2>&1 ; echo $? )" -ne 0 ] ; then
	G="N" ; T="Y"
fi

if [ "$G" != "N" ] ; then
	
	if   [ "$SDIALOG" = "kdialog" ] ; then
		DIALOGLIST="kdialog yad zenity"
	elif [ "$SDIALOG" = "yad" ] ; then
		DIALOGLIST="yad zenity kdialog"
	elif [ "$SDIALOG" = "zenity" ] ; then
		DIALOGLIST="zenity yad kdialog"
	else
		DIALOGLIST="$DEFAULTDIALOGLIST"
	fi
	
	if [ "$DIALOGLIST" = "" ] ; then
		if [ "$DEFAULTDIALOGLIST" != "" ] ; then
			DIALOGLIST="$DEFAULTDIALOGLIST"
		else
			DIALOGLIST="yad zenity kdialog"
		fi
	fi
	
	if [ "$(command -v $DIALOGLIST)" = "" ] ; then
		G="N" ; T="Y"
	fi

fi


if [ "$G" = "N" ] ; then

	if [ "$(command -v dialog)" = "" ] ; then
		echo $"ERROR: No supported dialog is installed. $TITLE cannot continue."
		exit 1
	else
		
		DIALOG="dialog --cr-wrap --keep-window --output-fd 1"
		#DIALOG="dialog --cr-wrap --keep-window --output-fd 1 --no-lines --no-shadow"
		if [ "$TITLE" != "" ] ; then
			WICON="--backtitle $(echo $TITLE | sed 's| |-|g')"
		fi
		WTITLE="--title"
		WTEXT=""
		H="0"
		W="0"
		LH="0"
		CALENDAR="--calendar"
		DATEFORMAT="--date-format %Y-%m-%d"
		WTIME="--timebox"
		TIMEFORMAT="--time-format %H:%M:%S"
		DSEL="--dselect"
		FSEL="--fselect"
		WRITE="--inputbox"
		PREWRITE=""
		COLUMN=""
		PRINTCOLUMN1=""
		PRINTCOLUMN2=""
		HIDECOLUMN1=""
		HIDECOLUMN2=""
		#INPUTSEPARATOR="--column-separator"
		#OUTPUTSEPARATOR="--separate-output"
		MONOLIST="--menu"
		#MONOLIST="--radiolist"
		MULTIPLELIST="--separate-output --checklist"
		PRE=""
		POST="off"
		PRES=""
		POSTS="on"

		INFO="--msgbox"
		WAIT="--infobox"

		QYN="--yesno"
		QYNC="--yesno"
		WYN="--yesno"
		WCC="--yesno"
		WYNC="--yesno"
		WM="--msgbox"
		ERROR="--msgbox"

		FORM="--form"
		FORMT=""
		FORMSELPRE=""
		FORMSELPOST=""
		#FORMCALPRE=""
		#FORMCALPOST=""
		#FORMCLPRE=""
		#FORMCLPOST=""
		PRELAB1="1 1"
		POSTLAB1="1 10 999 0"
		PRELAB2="2 1"
		POSTLAB2="2 10 999 0"
		PRELAB3="3 1"
		POSTLAB3="3 10 999 0"

		YES="--yes-label"
		NO="--no-label"
		OK="--ok-label"
		CONTINUE="--ok-label"
		CANCEL="--cancel-label"
		EXTRABUTTON="--extra-button --extra-label"
	
	fi

else

	for i in $DIALOGLIST ; do

		if [ "$(command -v $i)" != "" ] ; then
	
			if [ "$i" = "yad" ] ; then
		
				if [ "$(yad --version | tail -n 1 | cut -d ' ' -f 1 | cut -d '.' -f 1)" -lt 2 ] ; then
					DIALOG="yad --center"  # --selectable-labels (bug in Yad < 2.0) https://github.com/v1cont/yad/blob/master/NEWS
				else
					DIALOG="yad --center --selectable-labels"  # --on-top
				fi
				if [ "$ICON" != "" ] ; then
					WICON="--window-icon $ICON"
				fi
				WTITLE="--title"
				WTEXT="--text"
				H=""
				if [ "$(yad --version | tail -n 1 | grep -aE ^'7.2')" != "" ] ; then
					W="--width=640"
				else
					W="--width=640 --text-width=640 --fixed"  # https://github.com/v1cont/yad/issues/107  https://github.com/v1cont/yad/issues/140
				fi
				LH=""
				CALENDAR="--calendar"
				DATEFORMAT="--date-format %Y-%m-%d"
				WTIME="--separator=\n --columns 3 --form"
				#TIMEFORMAT="--time-format %H:%M:%S"
				DSEL="--file --directory --filename"  # Deleted *-selection alias for --file in Yad 4.0
				FSEL="--file --filename"              # Deleted *-selection alias for --file in Yad 4.0
				WRITE="--entry"
				PREWRITE="--entry-text"
				COLUMN="--column="
				PRINTCOLUMN1="--print-column=01"
				PRINTCOLUMN2="--print-column=02"
				HIDECOLUMN1="--hide-column=01"
				HIDECOLUMN2="--hide-column=02"
				#INPUTSEPARATOR="--item-separator"
				#OUTPUTSEPARATOR="--separator="
				#MONOLIST="--entry"
				MONOLIST="--separator=\n --list --search-column=1 --no-headers"
				MONOLISTH="--separator=\n --list --search-column=1"
				MULTIPLELIST="--separator= --list --checklist --search-column=2 --no-headers"
				MULTIPLELISTH="--separator= --list --checklist --search-column=2"
				PRE="FALSE"
				POST=""
				PRES="TRUE"
				POSTS=""
				# standard gtk keybindings for next and previous search are ctrl+g and ctrl+shift+g while you can redefine them in gtk-keys.css for your theme  # https://github.com/v1cont/yad/issues/127
			
				INFO="--image=/usr/share/icons/picalibre/rm/play.png --button="$"OK"
				WAIT="--image=/usr/share/icons/picalibre/rm/play.png --no-buttons"
			
				QYN="--image=/usr/share/icons/picalibre/rm/question.png --button="$"Yes"":0 --button="$"No"":1"
				QYNC="--image=/usr/share/icons/picalibre/rm/question.png --button="$"Yes"":0 --button="$"No"":1 --button="$"Cancel"":1"
				WYN="--image=/usr/share/icons/picalibre/rm/warning.png --button="$"Yes"":0 --button="$"No"":1"
				WCC="--image=/usr/share/icons/picalibre/rm/warning.png --button="$"Continue"":0 --button="$"Cancel"":1"
				WYNC="--image=/usr/share/icons/picalibre/rm/warning.png --button="$"Yes"":0 --button="$"No"":1 --button="$"Cancel"":1"
				WM="--image=/usr/share/icons/picalibre/rm/warning.png --button="$"OK"
				ERROR="--image=/usr/share/icons/picalibre/rm/error.png --button="$"OK"
			
				FORM="--separator=\n --form"
				FORMT="--field"
				FORMSELPRE="--field"
				FORMSELPOST=":FL"
				FORMCALPRE="--field"
				FORMCALPOST=":DT"
				FORMCLPRE="--field"
				FORMCLPOST=":CB"
				PRELAB1=""
				POSTLAB1=""
				PRELAB2=""
				POSTLAB2=""
				PRELAB3=""
				POSTLAB3=""
			
				YES="--button"
				NO="--button"
				OK="--button"
				CONTINUE="--button"
				CANCEL="--button"
				EXTRABUTTON="--button"
		
			elif [ "$i" = "zenity" ] ; then
		
				DIALOG="zenity"
				if [ "$ICON" != "" ] ; then
					WICON="--window-icon $ICON"
				fi
				WTITLE="--title"
				WTEXT="--text"
				H=""
				W="--width=640"
				LH=""
				CALENDAR="--calendar"
				DATEFORMAT="--date-format %Y-%m-%d"
				WTIME="--separator : --forms"
				#TIMEFORMAT="--time-format %H:%M:%S"
				DSEL="--file-selection --directory --filename"
				FSEL="--file-selection --filename"
				WRITE="--entry"
				PREWRITE="--entry-text"
				COLUMN="--column="
				PRINTCOLUMN1="--print-column=01"
				PRINTCOLUMN2="--print-column=02"
				HIDECOLUMN1="--hide-column=01"
				HIDECOLUMN2="--hide-column=02"
				#INPUTSEPARATOR=""
				#OUTPUTSEPARATOR="--separator=\n"
				MONOLIST="--separator=\n --list --hide-header"
				MONOLISTH="--separator=\n --list"
				MULTIPLELIST="--separator=\n --list --checklist --hide-header"
				MULTIPLELISTH="--separator=\n --list --checklist"
				PRE="FALSE"
				POST=""
				PRES="TRUE"
				POSTS=""
			
				INFO="--info"
				WAIT="--info"
			
				QYN="--question"
				QYNC="--question"
				WYN="--question"
				WCC="--question"
				WYNC="--question"
				WM="--warning"
				ERROR="--error"
			
				FORM="--forms"
				FORMT="--add-entry"
				FORMSELPRE="--add-entry"
				FORMSELPOST=""
				FORMCALPRE="--add-calendar"
				FORMCALPOST=""
				if [ "$(zenity --version | cut -d '.' -f 1 )" -ge 3 ] || [ "$(zenity --version | sed 's|\.||g')" -ge 3102 ] ; then
					FORMCLPOST="--combo-values"
					FORMCLPRE="--add-combo"
				fi
				PRELAB1=""
				POSTLAB1=""
				PRELAB2=""
				POSTLAB2=""
				PRELAB3=""
				POSTLAB3=""
			
				# Zenity <3 does not support custom buttons.
				if [ "$(zenity --version | cut -d '.' -f 1 )" -ge 3 ] ; then
					YES="--ok-label"
					NO="--cancel-label"
					OK="--ok-label"
					CONTINUE="--ok-label"
					CANCEL="--cancel-label"
					#EXTRABUTTON=""
				fi
		
#			elif [ "$i" = "kdialog" ] ; then
#		
#				# CAUTION: All 'kdialog' (TDE, KDE Plasma 4, KDE Plasma 5, KDE Plasma 6,...) are included here!
#			
#				DIALOG="kdialog"
#				if [ "$ICON" != "" ] ; then
#					WICON="--icon $ICON"
#				fi
#				WTITLE="--title"
#				WTEXT=""
#				H=""
#				W=""
#				LH=""
#				# No "--calendar" in TDE-kdialog + No "--date-format" both TDE and Plasma = There is no usable version of kdialog for calendars
#				#CALENDAR="--calendar"
#				#DATEFORMAT="--date-format %Y-%m-%d"
#				#WTIME="--timebox"
#				#TIMEFORMAT="--time-format %H:%M:%S"
#				DSEL="--getexistingdirectory"
#				FSEL="--getsavefilename"
#				#FSEL="--getopenfilename"
#				WRITE="--inputbox"
#				PREWRITE=""
#				COLUMN=""
#				PRINTCOLUMN1=""
#				PRINTCOLUMN2=""
#				HIDECOLUMN1=""
#				HIDECOLUMN2=""
#				#INPUTSEPARATOR=""
#				#OUTPUTSEPARATOR="--separate-output"
#				MONOLIST="--menu"
#				#MONOLIST="--combobox"
#				#MONOLIST="--radiolist"
#				MULTIPLELIST="--separate-output --checklist"
#				PRE=""
#				POST="off"
#				PRES=""
#				POSTS="on"
#			
#				INFO="--msgbox"
#				WAIT="--msgbox"
#			
#				QYN="--yesno"
#				QYNC="--yesnocancel"
#				WYN="--warningyesno"
#				WCC="--warningcontinuecancel"
#				WYNC="--warningyesnocancel"
#				WM="--sorry"
#				ERROR="--error"
#			
#				# No "--form" in any kdialog version
#				#FORM="--form"
#				#FORMT=""
#				#FORMSELPRE=""
#				#FORMSELPOST=""
#				#FORMCALPRE=""
#				#FORMCALPOST=""
#				#FORMCLPRE=""
#				#FORMCLPOST=""
#				#PRELAB1=""
#				#POSTLAB1=""
#				#PRELAB2=""
#				#POSTLAB2=""
#				#PRELAB3=""
#				#POSTLAB3=""
#			
#				# TDE-kdialog does not support custom buttons.
#				if [ "$(kdialog --version | grep -a Qt | grep -aEo "[0-9]" | head -n 1)" -ge 4 ] || [ "$(kdialog --version | grep -aEi kdialog | grep -aEo "[0-9]" | head -n 1)" -gt 1 ] ; then
#					YES="--yes-label"
#					NO="--no-label"
#					OK="--continue-label"
#					CONTINUE="--continue-label"
#					CANCEL="--cancel-label"
#					EXTRABUTTON="--cancel-label"
#				fi
		
			else
		
				true
		
			fi
		
		if [ "$DIALOG" != "" ] ; then break ; fi
		
		fi

	done

fi

if [ "$DIALOG" = "" ] ; then
	echo $"ERROR: No supported dialog is installed. $TITLE cannot continue."
	exit 1
fi


### TERMINAL SELECTION ########################################

if [ "$G" != "N" ] && [ "$(command -v lxterminal sakura xfce4-terminal)" = "" ] ; then $DIALOG $WICON $WTITLE "$TITLE" $WM    $WTEXT $"WARNING: Neither 'lxterminal', nor 'sakura' nor 'xfce4-terminal' are installed, $TITLE might fail." $H $W ; fi

TERMINAL () {
if [ "$G" = "N" ] ; then
	if [ "$TT" != "$TITLE" ] ; then echo "$TT" ; sleep 1 ; fi
	$COM
else
	if [ "$(command -v sakura)" != "" ] ; then
#		sakura -t "$TT" -e "$COM"  # https://bugs.debian.org/782396
		sakura -t "$TT" -x "$COM"  # sakura '-e' bug en Debian 13 "Trixie": Segment violation
	elif [ "$(command -v lxterminal)" != "" ] ; then
		lxterminal -t "$TT" -e "$COM"
	elif [ "$(command -v xfce4-terminal)" != "" ] ; then
		xfce4-terminal -T "$TT" -e "$COM"
	else
		x-terminal-emulator -t "$TT" -e "$COM"
	fi
fi
}


### BASICFUN ########################################

check_exit () {

TAILERRORLOG=$(cat "$ERRORLOG" | grep -aE "[a-zA-Z0-9\=\[]" | tail -n 10 )

echo $(date +%Y-%m-%d_%H:%M:%S)

exit 1

}

# "try again or exit" dialog window
input_error () {

echo $(date +%Y-%m-%d_%H:%M:%S)

$DIALOG $WICON $WTITLE "$TITLE" $WYN   $WTEXT $"Something went wrong.\n\nDo you want to try again?" $H $W

if [ "$?" -ne 0 ] ; then
	exit 1
else
	SEL=""
	$REFUN
fi

}


### DIRECT SHORTCUT ########################################

PREPATH=$(echo "$*" | tr " " "\n" | grep -aEi "^/")
if [ "$PREPATH" != "" ] && [ "$(echo "$PREPATH" | grep -a -c ^)" -eq 1 ] ; then
CALC=$"Calculate"
CHECK=$"Check"
TDIR=$"Select the folder/directory containing the files"
TFILE=$"Select the file"
	if [ -d "$PREPATH" ] ; then
		GENOPT="$CALC"
		SEL="$PREPATH"
		TYPEOPT="$TDIR"
	elif [ -f "$PREPATH" ] ; then
		TESTSUM=$(echo "$PREPATH" | grep -aEio 'md5|b2|sha1|sha256|sha512|sha3|whirlpool' )
		if [ "$TESTSUM" = "" ] ; then
			GENOPT="$CALC"
			SEL="$PREPATH"
			TYPEOPT="$TFILE"
		else
			GENOPT="$CHECK"
			SEL="$PREPATH"
			CONFIRM="N"
		fi
	else
		true
	fi
fi


### WELCOME ########################################

	if [ "$SEL" = "" ] ; then

if [ "$WELCOME" != "N" ] ; then

$DIALOG $WICON $WTITLE "$TITLE" $INFO  $WTEXT $"Welcome to $TITLE.\n\n$TITLE is a tool to calculate or check 'checksums' (check codes using hash functions).\n\n$TITLE is libre/free software, licensed according to 'GNU AGPL version 3.0'.\n\nIt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.\n\nMore information at www.picalibre.org\n" $H $W

if [ "$?" -ne 0 ] ; then
	exit 0
fi

fi

	fi


### SEL ########################################

selsumcalc () {

unset SUMLIST

if [ "$RHASH" = "Y" ] ; then
	if [ "$(rhash --version 2>&1 | sed 's|[a-zA-Z -]||g' | cut -d '.' -f 1)" -gt 1 ] || [ "$(rhash --version 2>&1 | sed 's|[a-zA-Z -]||g' | awk -F '.' '{print $1$2}')" -ge 13 ] ; then
		SUMLIST=$(printf "$PRE md5\t(MD5) $POST  $PRE sha1\t(SHA1) $POST  $PRE sha256\t(SHA256) $POST  $PRE sha512\t(SHA512) $POST  $PRE sha3-224\t(SHA3-224) $POST  $PRE sha3-256\t(SHA3-256) $POST  $PRE sha3-512\t(SHA3-512) $POST  $PRE whirlpool\t(Whirlpool) $POST")  # BLAKE 2 since 1.4.1 (2021-01-07) but NOT for ARM   # BLAKE 3 since 1.4.6 (2025-05-14)    https://rhash.sourceforge.net/changelog.php  https://github.com/rhash/RHash/releases/
	else
		SUMLIST=$(printf "$PRE md5\t(MD5) $POST  $PRE sha1\t(SHA1) $POST  $PRE sha256\t(SHA256) $POST  $PRE sha512\t(SHA512) $POST  $PRE whirlpool\t(WHIRLPOOL) $POST")
	fi
else
	for i in md5sum b2sum sha1sum sha256sum sha512sum sha3sum whirlpoolsum ; do  # b2sum (GNU coreutils) since Debian 9 "Stretch" with 8.26 (2016-11-30).  # b3sum (the Rust version, not the C version, not GNU coreutils) since Debian 12 "Bookworm".
		if [ "$(command -v $i)" != "" ] ; then SUMLIST=$(printf "$SUMLIST $PRE $i\t("$(echo $i | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g')") $POST ") ; fi
	done
fi

SUMSEL=$($DIALOG $WICON $WTITLE "$TITLE" $MULTIPLELIST $WTEXT $"Please select.\n\n* MD5 is the fastest but it is weak (it can be used to check copies of personal files but must NOT be used to verify files that may have been fraudulently manipulated).\n\n* SHA1 is fast (50% slower than MD5) but it is also weak.\n\n* Among those considered strong, the fastest on 32-bit processors is SHA256 (3 times slower than MD5) while on 64-bit processors it is BLAKE2b (speed close to MD5 on 64-bit processors, but x4 times slower on 32-bit processors) followed by SHA512 (twice as slow as MD5 on 64-bit processors).\n\n* SHA3 is considered strong but is slower than those previously mentioned, with increasing slowness with increasing number: SHA3-224 (3 times slower than MD5 on 64-bit processors and x8 or more on 32-bit processors), SHA3-256 (6% slower than SHA3-224), SHA3-512 (twice as slow as SHA3-224).\n\n* Whirlpool is considered strong but is slow (speed close to SHA3-512).\n\n" $H $W $LH $COLUMN $COLUMN $COLUMN $SUMLIST | sed 's|(.*)||g' | sed 's|^TRUE||g' )

if [ "$?" -ne 0 ] || [ "$SUMSEL" = "" ] ; then
	exit 0
fi

}


selsumcheck () {

unset SUMLIST

for i in md5sum b2sum sha1sum sha256sum sha512sum sha3sum whirlpoolsum ; do  # b2sum (GNU coreutils) since Debian 9 "Stretch" with 8.26 (2016-11-30).  # b3sum (the Rust version, not the C version, not GNU coreutils) since Debian 12 "Bookworm".
	if [ "$(command -v $i)" != "" ] ; then SUMLIST=$(printf "$SUMLIST $i ("$(echo $i | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g')") ") ; fi
done

CHECKSUM=$($DIALOG $WICON $WTITLE "$TITLE" $MONOLIST $WTEXT $"Please select the checksum to use:" $H $W $LH $COLUMN $COLUMN $SUMLIST | head -n 1 )

if [ "$?" -ne 0 ] || [ "$CHECKSUM" = "" ] ; then
	exit 0
fi

}


### SCRIPT ########################################

CALC=$"Calculate"
CHECK=$"Check"

	if [ "$SEL" = "" ] ; then

GENOPT=$($DIALOG $WICON $WTITLE "$TITLE" $MONOLIST $WTEXT $"Please select an option:" $H $W $LH $COLUMN $COLUMN "$CALC" " " "$CHECK" " " | head -n 1 )

if [ "$?" -ne 0 ] || [ "$GENOPT" = "" ] ; then
	exit 0
fi

	fi

if [ "$GENOPT" != "$CALC" ] && [ "$GENOPT" != "$CHECK" ] ; then
	check_exit
fi


if [ "$GENOPT" = "$CALC" ] ; then

		if [ "$SEL" = "" ] ; then
	
	TDIR=$"Select the folder/directory containing the files"
	TFILE=$"Select the file"

	TYPEOPT=$($DIALOG $WICON $WTITLE "$TITLE" $MONOLIST $WTEXT $"Please select an option:" $H $W $LH $COLUMN $COLUMN "$TDIR" " " "$TFILE" " " | head -n 1 )

	if [ "$?" -ne 0 ] || [ "$TYPEOPT" = "" ] ; then
		exit 0
	fi
	
		fi

	if [ "$TYPEOPT" != "$TDIR" ] && [ "$TYPEOPT" != "$TFILE" ] ; then
		check_exit
	fi

	if [ "$TYPEOPT" = "$TDIR" ] ; then
	
		seldir () {
	
			if [ "$SEL" = "" ] ; then
		
		SEL=$($DIALOG $WICON $WTITLE $"Select the folder/directory containing the files" $DSEL /home/ $H $W)
	
		if [ "$?" -ne 0 ] ; then
			exit 0
		fi
	
		if [ "$SEL" = "" ] ; then
			REFUN=seldir
			input_error ; return
		fi
	
		if [ ! -d "$SEL" ] ; then
			REFUN=seldir
			input_error ; return
		fi
		
			fi
	
		}
	
		seldir
	
	
		selsumcalc
	
	
		for CHECKSUM in $SUMSEL ; do
cat > /tmp/${CNAME}_${CHECKSUM} <<EOF
#!/bin/bash

CNAME=$CNAME
VERSION=$VERSION
TITLE=$TITLE

# Translations
if [ "\$LANG" = "" ] ; then export $(cat /etc/default/locale | grep -a 'LANG=') ; fi
TEXTDOMAIN=$TEXTDOMAIN
TEXTDOMAINDIR=$TEXTDOMAINDIR

ERRORLOG="$ERRORLOG"
if [ "$DEBUG" = "Y" ] ; then
	set -xv
fi
if [ "$DEBUG" != "N" ] ; then
exec > >(tee -a "\$ERRORLOG") 2>&1
echo "\$0" "\$*" >> "\$ERRORLOG"
fi

################################

echo $"Please wait..."

cd "$SEL"

if [ -e "$CHECKSUM.txt" ] ; then rm -fv "$CHECKSUM.txt" ; fi

if [ "$RHASH" = "Y" ] ; then
	rhash --percents --$CHECKSUM -r . | tee -a "$CHECKSUM.txt"
else
	find {,.[!.],..?}* -type f ! -name $CHECKSUM.txt -print0 2>>"$ERRORLOG" | sort -z | xargs -r0 $(echo $CHECKSUM | sed 's|--| --percents --|g' | sed 's|deep|deep -l -e |g') | tee -a "$CHECKSUM.txt"
fi

#if [ "\$(cat /etc/passwd | grep -aE ^\$(whoami): | cut -d ':' -f 3 )" -eq 0 ] ; then
if [ "\$(id -u)" -eq 0 ] ; then
	for i in \$(cat /etc/passwd | awk -F ':' '{print \$3,\$1}' | sort -n | grep -aEi "00[0-9] " | awk '{print \$2}') ; do AUSER=\$(users | sed 's| |\n|g' | grep -aE "^\$i\$" | head -n 1) ; if [ "\$AUSER" != "" ] ; then
		chown \$(id -nu \$i):\$(id -ng \$i) "$CHECKSUM.txt"
		break
	fi ; done
fi

EOF
		chmod +x /tmp/${CNAME}_${CHECKSUM}
		TT="$(echo $CHECKSUM | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g' | sed 's|RHASH--||g' | sed 's|DEEP||g')" ; COM="bash /tmp/${CNAME}_${CHECKSUM}" ; TERMINAL ; rm -f /tmp/${CNAME}_${CHECKSUM}
		done
	
		for CHECKSUM in $SUMSEL ; do
			sed -i "s|.* $CHECKSUM.txt$||g" $(echo "$(for CHECKSUM in $SUMSEL ; do echo "$SEL/$CHECKSUM.txt" ; done)")
		done
		sed -i "/^$/d" $(echo "$(for CHECKSUM in $SUMSEL ; do echo "$SEL/$CHECKSUM.txt" ; done)")
	
	
		unset RESULT
		for CHECKSUM in $SUMSEL ; do
			RESULT=$(cat "$SEL/$CHECKSUM.txt" | sed 's| |_|3g')
			$DIALOG $WICON $WTITLE "$(echo $CHECKSUM | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g' | sed 's|RHASH--||g' | sed 's|DEEP||g')" $MONOLIST $WTEXT "$SEL/$CHECKSUM.txt" $H $W $LH $COLUMN $COLUMN $RESULT | head -n 1
		done
	
		exit 0
	
	fi


	if [ "$TYPEOPT" = "$TFILE" ] ; then
	
		selfile () {
	
			if [ "$SEL" = "" ] ; then
		
		SEL=$($DIALOG $WICON $WTITLE $"Select the file" $FSEL /home/ $H $W)
	
		if [ "$?" -ne 0 ] ; then
			exit 0
		fi
	
		if [ "$SEL" = "" ] ; then
			REFUN=selfile
			input_error ; return
		fi
	
		if [ ! -f "$SEL" ] ; then
			REFUN=selfile
			input_error ; return
		fi
		
			fi
	
		SELFILE=$(echo "$SEL" | awk -F '/' '{print $NF}')
		SELDIR=$(echo "$SEL" | sed "s|/$SELFILE$||g")
	
		}
	
		selfile
	
	
		selsumcalc
	
	
cat > /tmp/${CNAME}_$(echo $SUMSEL | sed 's| |_|g') <<EOF
#!/bin/bash

CNAME=$CNAME
VERSION=$VERSION
TITLE=$TITLE

# Translations
if [ "\$LANG" = "" ] ; then export $(cat /etc/default/locale | grep -a 'LANG=') ; fi
TEXTDOMAIN=$TEXTDOMAIN
TEXTDOMAINDIR=$TEXTDOMAINDIR

ERRORLOG="$ERRORLOG"
if [ "$DEBUG" = "Y" ] ; then
	set -xv
fi
if [ "$DEBUG" != "N" ] ; then
exec > >(tee -a "\$ERRORLOG") 2>&1
echo "\$0" "\$*" >> "\$ERRORLOG"
fi

################################

echo $"Please wait..."

cd "$SELDIR"

for CHECKSUM in $(echo $SUMSEL) ; do

echo \$CHECKSUM : | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g' | sed 's|RHASH--||g' | sed 's|DEEP||g'

if [ -e "$SELFILE.\$CHECKSUM.txt" ] ; then rm -fv "$SELFILE.\$CHECKSUM.txt" ; fi

if [ "$RHASH" = "Y" ] ; then
	rhash --percents --\$CHECKSUM "$SELFILE" | tee -a "$SELFILE.\$CHECKSUM.txt"
else
	\$(echo \$CHECKSUM | sed 's|--| --percents --|g' | sed 's|deep|deep -l -e |g') "$SELFILE" | tee -a "$SELFILE.\$CHECKSUM.txt"
fi

#if [ "\$(cat /etc/passwd | grep -aE ^\$(whoami): | cut -d ':' -f 3 )" -eq 0 ] ; then
if [ "\$(id -u)" -eq 0 ] ; then
	for i in \$(cat /etc/passwd | awk -F ':' '{print \$3,\$1}' | sort -n | grep -aEi "00[0-9] " | awk '{print \$2}') ; do AUSER=\$(users | sed 's| |\n|g' | grep -aE "^\$i\$" | head -n 1) ; if [ "\$AUSER" != "" ] ; then
		chown \$(id -nu \$i):\$(id -ng \$i) "$SELFILE.\$CHECKSUM.txt"
		break
	fi ; done
fi

done

EOF
		chmod +x /tmp/${CNAME}_$(echo $SUMSEL | sed 's| |_|g')
		TT="$SELFILE" ; COM="bash /tmp/${CNAME}_$(echo $SUMSEL | sed 's| |_|g')" ; TERMINAL ; rm -f /tmp/${CNAME}_$(echo $SUMSEL | sed 's| |_|g')
	
	
		unset RESULT
		for CHECKSUM in $SUMSEL ; do
			RESULT=$(printf "$RESULT $(echo $CHECKSUM | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g' | sed 's|RHASH--||g' | sed 's|DEEP||g') $(cat "$SELDIR/$SELFILE.$CHECKSUM.txt" | awk '{print $1}') ")
		done
		$DIALOG $WICON $WTITLE "$TITLE" $MONOLIST $WTEXT "$SELFILE" $H $W $LH $COLUMN $COLUMN $RESULT | head -n 1
	
		exit 0
	
	fi

fi


if [ "$GENOPT" = "$CHECK" ] ; then

	selfile () {

		if [ "$SEL" = "" ] ; then
	
	SEL=$($DIALOG $WICON $WTITLE $"Select the checksum file" $FSEL /home/ $H $W)

	if [ "$?" -ne 0 ] ; then
		exit 0
	fi

	if [ "$SEL" = "" ] ; then
		REFUN=selfile
		input_error ; return
	fi

	if [ ! -f "$SEL" ] ; then
		REFUN=selfile
		input_error ; return
	fi
	
		fi

	SELFILE=$(echo "$SEL" | awk -F '/' '{print $NF}')
	SELDIR=$(echo "$SEL" | sed "s|/$SELFILE$||g")

	}

	selfile


	if [ "$RHASH" = "Y" ] ; then
		CHECKSUM=rhash   # BLAKE 2 since 1.4.1 (2021-01-07) but NOT for ARM   # BLAKE 3 since 1.4.6 (2025-05-14)    https://rhash.sourceforge.net/changelog.php  https://github.com/rhash/RHash/releases/
	else
		TESTSUM=$(echo "$SELFILE" | grep -aEio 'md5|b2|sha1|sha256|sha512|sha3|whirlpool' )
		if [ "$TESTSUM" != "" ] && [ "$(echo $TESTSUM | grep -a -c ^ )" -eq 1 ] ; then
			if [ "$CONFIRM" = "N" ] ; then
				CHECKSUM=$(echo ${TESTSUM}sum | tr "[A-Z]" "[a-z]" )
			else
				TESTSUMN=$(echo $TESTSUM | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g')
				if [ "$TESTSUMN" != "" ] && [ "$(echo $TESTSUMN | grep -a -c ^ )" -eq 1 ] ; then
					$DIALOG $WICON $WTITLE "$TEST" $QYN   $WTEXT $"Is $TESTSUMN the checksum to use?\n\n(If in doubt, select 'Yes/OK'.)" $H $W
					if [ "$?" -eq 0 ] ; then
						CHECKSUM=$(echo ${TESTSUM}sum | tr "[A-Z]" "[a-z]" )
					else
						selsumcheck
					fi
				else
					selsumcheck
				fi
			fi
		else
			selsumcheck
		fi
	fi


cat > /tmp/${CNAME}_${CHECKSUM} <<EOF
#!/bin/bash

CNAME=$CNAME
VERSION=$VERSION
TITLE=$TITLE

# Translations
if [ "\$LANG" = "" ] ; then export $(cat /etc/default/locale | grep -a 'LANG=') ; fi
TEXTDOMAIN=$TEXTDOMAIN
TEXTDOMAINDIR=$TEXTDOMAINDIR

ERRORLOG="$ERRORLOG"
if [ "$DEBUG" = "Y" ] ; then
	set -xv
fi
if [ "$DEBUG" != "N" ] ; then
exec > >(tee -a "\$ERRORLOG") 2>&1
echo "\$0" "\$*" >> "\$ERRORLOG"
fi

################################

echo $"Please wait..."

rm -rf /tmp/picasum_0 /tmp/picasum_1

cd "$SELDIR"

$(echo $CHECKSUM | sed 's|rhash|rhash --percents|g') -c "$SELFILE"

if [ "\$?" -eq 0 ] ; then
	touch /tmp/picasum_0
else
	touch /tmp/picasum_1
	set +xv
	printf "\\n\\n\\n"
	echo $"Verification failed (non-localized file or non-matching sum)."
	echo " "
	echo $"Close this window or press the 'Enter/Return' key (usually the largest key on the keyboard after the 'space' key) to close."
	echo " "
	read KEY
	exit 1
fi

EOF

	chmod +x /tmp/${CNAME}_${CHECKSUM}
	TT="$(echo $CHECKSUM | sed 's|sum||g' | sed 's|b2|BLAKE2|g' | tr "[a-z]" "[A-Z]" | sed 's|WHIRLPOOL|Whirlpool|g' | sed 's|RHASH--||g' | sed 's|DEEP||g')" ; COM="bash /tmp/${CNAME}_${CHECKSUM}" ; TERMINAL ; rm -f /tmp/${CNAME}_${CHECKSUM}

	if   [ -e "/tmp/picasum_0" ] ; then
		$DIALOG $WICON $WTITLE "$TITLE" $INFO  $WTEXT $"All right (all checksums have been successfully verified)." $H $W
		rm -rf /tmp/picasum_*
		exit 0
	elif [ -e "/tmp/picasum_1" ] ; then
		$DIALOG $WICON $WTITLE "$TITLE" $ERROR $WTEXT $"Verification failed (non-localized file or non-matching sum)." $H $W
		rm -rf /tmp/picasum_*
		exit 1
	else
		echo $"No /tmp/picasum_0, no /tmp/picasum_1."
	fi

fi


exit 0
