#!/bin/bash
trap "exit 1" TERM
export TOP_PID=$$
##################################################################################################################
# GREP Classes https://www.gnu.org/software/grep/manual/html_node/Character-Classes-and-Bracket-Expressions.html #
##################################################################################################################

upper='[[:upper:]]'
lower='[[:lower:]]'
digit='[[:digit:]]'
alnum='[[:alnum:]]'
alpha='[[:alpha:]]'
punct='[[:punct:]]'
space='[[:space:]]'

############################################################
# Colors                                                   #
############################################################

cecho() {
	# Reset
	Color_Off='\033[0m'       # Text Reset

	# Regular Colors
	#Black='\033[0;30m'        # Black
	Red='\033[0;31m'          # Red
	Green='\033[0;32m'        # Green
	Yellow='\033[0;33m'       # Yellow
	Blue='\033[0;34m'         # Blue
	Purple='\033[0;35m'       # Purple
	Cyan='\033[0;36m'         # Cyan
	White='\033[0;37m'        # White

	# Bold
	#BBlack='\033[1;30m'       # Black
	BRed='\033[1;31m'         # Red
	BGreen='\033[1;32m'       # Green
	BYellow='\033[1;33m'      # Yellow
	BBlue='\033[1;34m'        # Blue
	BPurple='\033[1;35m'      # Purple
	BCyan='\033[1;36m'        # Cyan
	BWhite='\033[1;37m'       # White

	COLOURS=($Color_Off $Black $Red $Green $Yellow $Blue $Purple $Cyan $White $BBlack $BRed $BGreen $BYellow $BBlue $BPurple $BCyan $BWhite)

	rand=$(( RANDOM % 17 ))

    echo -e "${COLOURS[$rand]}"
}

############################################################
# Help                                                     #
############################################################
Help()
{
   # Display Help
   echo "CATANA filters your wordlist according to the specified password policy."
   echo
   echo "$(basename "$0") [-h] [-i <wordlist.txt>] [-o <filename.txt>]"
   echo
   echo "Options:"
   echo "c     Random colored output."
   echo "h     Print this Help."
   echo "i     Input wordlist."
   echo "o     Print to a file."
   echo
   echo "Usage Examples:"
   echo "catana -i rockyou.txt"
   echo "catana -i rockyou.txt -o wl.txt"
   echo
   echo "Reference to character classes: https://www.gnu.org/software/grep/manual/html_node/Character-Classes-and-Bracket-Expressions.html"
}

charset_flt () {
    if [ $2 = "first" ]; then
        filter=$(echo "$1" | grep --text "^$3")
    elif [ $2 = "last" ]; then
        filter=$(echo "$1" | grep --text "$3$")
    elif [ $2 = "rm" ]; then
        filter=$(echo "$1" | grep -v --text "$3")
    fi
    echo "$filter"
}

Menu () {
wl="$1"
echo "$2" > /dev/stderr
PS3="$3"
pos="$4"
options=("Uppercase" "Lowercase" "Digit" "Alphanumeric" "Alphabetic" "Special" "Space" "Specific" "Skip" "Quit")
select opt in "${options[@]}"
do
    case $opt in
        "Uppercase")
            wl_flt=$(charset_flt "$wl" "$pos" "$upper")
            break
            ;;
        "Lowercase")
            wl_flt=$(charset_flt "$wl" "$pos" "$lower")
            break
            ;;
        "Digit")
            wl_flt=$(charset_flt "$wl" "$pos" "$digit")
            break
            ;;
        "Alphanumeric")
            wl_flt=$(charset_flt "$wl" "$pos" "$alnum")
            break
            ;;
        "Alphabetic")
            wl_flt=$(charset_flt "$wl" "$pos" "$alpha")
            break
            ;;
        "Special")
            wl_flt=$(charset_flt "$wl" "$pos" "$punct")
            break
            ;;
        "Space")
            wl_flt=$(charset_flt "$wl" "$pos" "$space")
            break
            ;;
        "Specific")
            echo "Type the characters or regex:" > /dev/stderr
            read spechar
            wl_flt=$(charset_flt "$wl" "$pos" "$spechar")
            break
            ;;
        "Skip")
            wl_flt=$wl
            break
            ;;
        "Quit")
            kill -s TERM $TOP_PID
            break
	    ;;
        *) echo "Invalid option" > /dev/stderr;;
    esac
done
echo "$wl_flt"
}

############################################################
# Process the input options. Add options as needed.        #
############################################################
# Get the options
while getopts ":chi:o:" option; do #When using getopts, putting : after an option character means that it requires an argument (i.e., 'i:' requires arg).
   case "${option}" in
      c) # colored output
         cecho
         ;;
      h) # display Help
         Help >&2
         exit 0
         ;;
      i) # Enter a command
         wl=$OPTARG
         ;;
      o) # Enter an output filename
         out=$OPTARG
         if [ -f ${out} ]; then
            while true; do
               echo "${out} already exist! Do you want to overwrite it?"
               read -p "Answer [Yes/No]: " yn
               case $yn in
                  [Yy]* ) rm -rf ${out}; break;;
                  [Nn]* ) break;;
                  * ) echo "Please answer yes or no.";;
               esac
            done
         fi
         ;;
      : )
        echo "Missing option argument for -$OPTARG" >&2; exit 0;;
      *  )
        echo "Unimplemented option: -$OPTARG" >&2; exit 0;;
     \?) # Invalid option
         echo "Error: Invalid option" >&2
         ;;
   esac
done

############################################################
# Banner                                                     #
############################################################
#cat banner.txt | gzip | base64
base64 -d <<<"H4sIAAAAAAAAA61QuQ3DQAzrPYVKKUWuT5U9IoAeI0C0U3bIZJHuVZHiiugAWhRJnW2ivZLZHWnKE4gu3cVdKTylHBEdcIY9XI06skjvU4SZYQFSF4o3g1YcUoqIAvBFiJ3w0/aiQth7vyLMheBOgQb4BEaDkqZ+3RJDkOdIK7MYNmp0PcmGlD4/Xqyg+NMFQ0Q6daJL+vGzsVURuD+9Hq/bVmm64vP+3zm+7/tQm1oCAAA=" | gunzip

echo
echo "CATANA - CUT your Wordlist!"
echo
############################################################
############################################################
# Main program                                             #
############################################################
############################################################

# mandatory arguments
if [ ! "$wl" ]; then
  Help >&2
  echo "catana: error: missing a mandatory option (-i). Use -h for help"
  exit 0
fi


echo "Wordlist: $wl"
echo
#Set variables
echo "Loading Wordlist..."
flt_wl=$(cat $wl)
echo
echo "Note: remember to use escape characters against regex special characters (like $ or ?)"
echo
echo "Gimme some information about the Password Policy"
echo

quest="What kind is the first character?"
prmpt="First character:"
pos="first"
flt_wl=$(Menu "$flt_wl" "$quest" "$prmpt" "$pos")
echo

quest="What kind is the last character?"
prmpt="Last character:"
pos="last"
flt_wl=$(Menu "$flt_wl" "$quest" "$prmpt" "$pos")
echo

quest="Do you wish some characters to be removed?"
prmpt="Chars to remove:"
pos="rm"
flt_wl=$(Menu "$flt_wl" "$quest" "$prmpt" "$pos")
echo
while true; do
    echo "Do you wish some characters to be present?"
    read -p "Answer [Yes/No]: " yn
    case $yn in
        [Yy]* ) echo "Type the characters or regex [i.e., @|\\$|#|\?]:"; read spechar; flt_wl=$(echo "$flt_wl" | grep -P --text "$spechar"); break;;
        [Nn]* ) break;;
        * ) echo "Please answer yes or no.";;
    esac
done
echo

echo "Specify the minimum length:"
read min
echo "Specify the maximum length:"
read max
echo

flt_wl=$(echo "$flt_wl" | grep -E '^.{'$min','$max'}$')

if [ ! "$out" ]; then
    echo "$flt_wl"
    echo
else
    echo "$flt_wl" > $out
    echo "Result correctly stored in ${out} file"
    echo
fi
