#! /bin/bash
#
#
##-L	This documentation and this script are GPL licensed. Enjoy.
##-L
##-L	#######################################
##-L	# This program is Free Software; you can redistribute it and/or
##-L	# modify it under the terms of the GNU General Public License
##-L	# as published by the Free Software Foundation; either version 2
##-L	# of the License, or (at your option) any later version.
##-L	#
##-L	# This program is distributed in the hope that it will be useful,
##-L	# but WITHOUT ANY WARRANTY; without even the implied warranty of
##-L	# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##-L	# GNU General Public License for more details.
##-L	#
##-L	# You should have received a copy of the GNU General Public License
##-L	# along with this program; if not, write to the Free Software
##-L	# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
##-L	#
##-L	#######################################
##-L	#Copyright: this script is an original work from SISalp www.sisalp.fr 2025
##-L	#par dominique.chabord@sisalp.org SISalp.org
##-L
##-L
##-L

#-------------------------------------------------------------------------
#echo "`date +\"%A_%x-%H:%M:%S\"` user : `/usr/bin/whoami` ; parameters : $0 $*"
MYVERSION="4-nov-2025-1"
REVISION="12-mar-2026-1 Last Update : `stat -c %z $0 | cut -d"." -f1`"
PW_DIR="$HOME/pw"
PASSWORD_FILE="$PW_DIR/pw.passwords"
LOG_FILE="$PW_DIR/pw.log"

#
#============================CHANGE LOG=================================--)
##v	Change-log for xoe
##v
##v	Version 4-nov-2025
##v	==================
##v	Creation initiale du script


#-------------------------------------------------------------------------
ECHO ()
#-------------------------------------------------------------------------
{
case "$pw_log" in
verbose)
	echo "$*"
	;;
log)
	echo "$*" >> $LOG_FILE
	;;
silent)
	;;
esac
}
#-------------------------------------------------------------------------
CHECK_OPTIONS ()
#-------------------------------------------------------------------------
{
co_option="-"
co_param="9 3 3"
pw_log="silent"
				for param in $* ; do
					case "$param" in
					--get|--forget|--prefix|--remove)
						#echo "$LINENO option $param"
						;;
					--save)
						if [ ! -d  $PW_DIR ] ; then
							mkdir -p $PW_DIR
						fi
						;;
					--verbose)
						pw_log="verbose"
						;;
					--log)
						if [ ! -d  $PW_DIR ] ; then
							mkdir -p $PW_DIR
						fi
						pw_log="log"
						;;

					-*l*|-*L*|-*n*|-*s*|-*a*|-)
						#echo "$LINENO option $param"
						co_option=""
						;;
					[1-9][0-9][0-9]|[1-9][0-9]|[1-9])
						#echo "$LINENO param $param"
						co_param=""
						;;
					esac
				done
				PARAMETERS="$co_option $* $co_param"
}
#-------------------------------------------------------------------------
NEW_PASSWORD ()
#-------------------------------------------------------------------------
{
				pw_letters=( a b c d e f g h i j k m n o p q r s t u v w x y z A B C D E F G H I J K L M N P Q R S T U V W X Y Z 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 )
				#pw_letters=(a b c d e f g h i j k m n o p q r s t u v w x y z A B C D E F G H I J K L M N P Q R S T U V W X Y Z 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 "," ";" ":" "!" "?" "%" "&" "=" "+" )
				pw_range="${#pw_letters[*]}"
				NEW_PWD=""
				ECHO "$LINENO parameters $*"
				for nb_digit in $* ; do
					#echo "$LINENO parameter $nb_digit"
					case "$add_prefix:$save_password:$get_password:$forget_password" in
					*yes*)
						case "$add_prefix" in
						*yes*)
							pw_prefix="$nb_digit"
							add_prefix="done"
							ECHO "$LINENO define a prefix $pw_prefix"
							;;
						esac
						case "$save_password" in
						*yes*)
							pw_add_reference="$nb_digit"
							save_password="done"
							ECHO "$LINENO order to register for $pw_add_reference"
							;;
						esac
						case "$get_password" in
						*yes*)
							pw_get_reference="$nb_digit"
							get_password="done"
							ECHO "$LINENO order to find registered $pw_get_reference if any"
							;;
						esac
						case "$forget_password" in
						*yes*)
							pw_forget_reference="$nb_digit"
							forget_password="done"
							ECHO "$LINENO order to forget registered $pw_get_reference if any"
							;;
						esac
						;;
					esac
					case "$nb_digit" in
					--prefix)
						add_prefix="yes"
						#echo "$LINENO add_prefix $add_prefix"
						;;
					--save)
						save_password="yes"
						;;
					--get)
						get_password="yes"
						;;
					--forget)
						forget_password="yes"
						;;
					--remove)
						remove_password="done"
						ECHO "$LINENO order to remove all registered passwords if any"
						;;
					--log)
						;;
					--verbose)
						;;
					-*)
						letters=""
						LETTERS=""
						numbers=""
						specials=""
						case "$nb_digit" in
						-*l*|-*a*|-)
							letters="a b c d e f g h i j k m n o p q r s t u v w x y z"
							;;
						esac
						case "$nb_digit" in	
						-*L*|-*a*|-)
							LETTERS="A B C D E F G H I J K L M N P Q R S T U V W X Y Z"
							;;
						esac
						case "$nb_digit" in	
						-*n*|-*a*|-)
							numbers="1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0"
							;;
						esac
						case "$nb_digit" in	
						-*s*|-*a*)
							#specials="\",\" \";\" \":\" \"!\" \"?\" \"%\" \"&\" \"=\" \"+\""
							specials=", ; : ! ? % & = +"
							;;
						esac	
						pw_letters=( $letters $LETTERS $numbers $specials )
						ECHO "$LINENO pw_letters ${pw_letters[*]}"
						;;
					[1-9][0-9][0-9]|[1-9][0-9]|[1-9])
						pw_range="${#pw_letters[*]}"
						if [ ! -z "$NEW_PWD" ] ; then NEW_PWD="${NEW_PWD}_" ; fi
						ECHO "$LINENO pick $nb_digit characters in pw_letters"
						for ((  pw_digit = 1 ;  pw_digit <= $nb_digit ;  pw_digit++  )) ; do
							pw_index="$(($RANDOM%$pw_range))"
							NEW_PWD="${NEW_PWD}""${pw_letters[$pw_index]}"
						done
						;;
					esac
				done
				case "$add_prefix" in
				done)
					NEW_PWD="$pw_prefix.$NEW_PWD"
					ECHO "$LINENO add prefix $pw_prefix"
					;;
				esac
				case "$forget_password" in
				done)
					if [ -f  $PASSWORD_FILE ] ; then
						mv $PASSWORD_FILE $PASSWORD_FILE.old
						cat $PASSWORD_FILE.old | sed s/^$pw_forget_reference/#$pw_forget_reference/ > $PASSWORD_FILE
						ECHO "$LINENO forget registered $pw_get_reference if any"
					fi
					;;
				esac
				case "$remove_password" in
				done)
					if [ -f  $PASSWORD_FILE ] ; then
						mv -b $PASSWORD_FILE $PASSWORD_FILE.removed
					fi
					ECHO "$LINENO remove all registered passwords if any"
					;;
				esac
				case "$save_password" in
				done)
					REGISTERED="$pw_add_reference:	$NEW_PWD	`date`"
					echo "$REGISTERED" >> $PASSWORD_FILE
					ECHO "$LINENO register new password for $pw_add_reference"
					;;
				esac
				case "$get_password" in
				done)
					REGISTERED="No registered password for $pw_get_reference"
					ECHO "$LINENO find registered $pw_get_reference if any"
					if [ -f  $PASSWORD_FILE ] ; then
						if cat $PASSWORD_FILE | grep "^$pw_get_reference:" > /dev/null 2>&1 ; then
							REGISTERED=`cat $PASSWORD_FILE | grep "^$pw_get_reference:"`
							NEW_PWD=`cat $PASSWORD_FILE | grep "^$pw_get_reference:" | tail -n 1 | cut -f2`
							ECHO "$LINENO found registered $pw_get_reference password $NEW_PWD"
						fi
					fi
					;;
				esac
}
#-------------------------------------------------------------------------
case "$1" in
#-------------------------------------------------------------------------
--history)
	if [ -f  $PASSWORD_FILE ] ; then
		if [ -z "$2" ] ; then
			cat $PASSWORD_FILE
		else
			if ! cat $PASSWORD_FILE | grep "^$2\|^#$2" ; then
				echo "no history for $2"
			fi
		fi
	else
		echo "no history"
	fi
	exit 0
	;;
#-------------------------------------------------------------------------
--update)
	echo "$LINENO:PW script --update"
	cd /usr/local/bin
	mv $0 $0.old-version
	if wget -q http://download.sisalp.net/scripts/PW -O PW ; then
		diff $0.old-version $0
		chmod 755 $0
		echo "$LINENO:PW is now up-to-date"
	else
		mv $0.old-version $0
		echo "$LINENO:Failed to download $UPDATE_SOURCE"
		exit 1
	fi
	exit 0
	;;
#-------------------------------------------------------------------------
--version)
	echo "PW :	$MYVERSION - $REVISION"
	exit 0
	;;
#-------------------------------------------------------------------------
--help|-h|help)
	echo "
PW --single_command

PW [long_options][long_option_and_reference]][short_options][parameters]


options

Single commands
--help
--version
--update
--history	[reference]

These commands and parameters can be combined
--get		reference	#get a registered password if exists, else create a new one
--save		reference	#create a password and register it
--forget	reference	#delete a registered password
--remove			#remove registration file
--prefix	prefix_string	#add a prefix to a new password if generated
--log				#detailled log in pw/pw.log
--verbose			#detailled trace of generation steps, for debug or training

these short options can be combines
-l				#small letters
-L				#capitals
-n				#numbers
-s				#special characters
-a				#equivalent to -lLns
défault is -lLn
short options cover next parameters

parameters
liste of segment lengths
default is 9 3 3

examples:
PW				#print a new password according to defaults
PW -lL				#print a password with small letters and capitals
PW 3 37 5			#print a password made of 3, and 37 and 5 characters separated by _
PW --save test1 -n 6 6		#print a password made of 6 and 6 numbers and register it under test1 name
PW -n --get test1 6 6		#print last registered password of test1 or make it with 6 and 6 numbers
PW --forget test1 --save test1	#erase registered passwords of test1 and make a new one
PW --remove --save test1 -L	#erase all registered passwords, print a new one with capitals and save it for test1
PW --prefix test1 --save test1	#print an new password with test1. as a prefix and save it

What is the expected result of:
PW -L 5 --prefix test1 -l 4 4 -ns 7 --verbose"
	exit 0
	;;
#-------------------------------------------------------------------------
esac
#-------------------------------------------------------------------------

CHECK_OPTIONS $*
NEW_PASSWORD $PARAMETERS
echo "$NEW_PWD"
#-------------------------------------------------------------------------
exit 0
