New captcha in prod

This commit is contained in:
Adrien Bourmault 2021-08-31 20:37:06 +02:00
parent b63d626d4f
commit bd635ae2a1
No known key found for this signature in database
GPG Key ID: 6EB408FE0ACEC664
2 changed files with 144 additions and 98 deletions

View File

@ -1,5 +1,13 @@
#!/bin/bash #!/bin/bash
# Copyright © 2021 Adrien Bourmault (neox@a-lec.org)
# Copyright © 2021 Echolib (echolib@dismail.de)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This script is an example captcha script. # This script is an example captcha script.
# It takes the text to recognize in the captcha image as a parameter. # It takes the text to recognize in the captcha image as a parameter.
# It return the image binary as a result. ejabberd support PNG, JPEG and GIF. # It return the image binary as a result. ejabberd support PNG, JPEG and GIF.
@ -14,104 +22,140 @@
# It is NOT compliant with ImageMagick forks like GraphicsMagick. # It is NOT compliant with ImageMagick forks like GraphicsMagick.
INPUT=$1 INPUT=$1
LENINPUT=${#INPUT}
DIGITS=(zéros uns deux trois quatres cinqs six septs huits neufs dix)
DIGIT=(zéro un deux trois quatre cinq six sept huit neuf dix)
TRANSFORMATIONS=(INTRUS SOMME)
DIGIT=(zéros uns deux trois quatres cinqs six septs huits neufs dix)
if test -n ${BASH_VERSION:-''} ; then # ****************************************************************************
get_random () #
{ # Tools
R=$RANDOM #
} # ****************************************************************************
# Loops 10 times (should be enough) to check if a TARGET number is in INPUT
GENERATE__NOTIN() {
for i in {1..10}
do
FALSENBR=`seq 1 9 | sort -R | head -n 1`
! [[ $INPUT =~ $FALSENBR ]] \
&& break
done
}
# ****************************************************************************
#
# Captcha shapes
#
# ****************************************************************************
# REPLACEs a random number in INPUT by another one randomized
REPLACE() {
NAME="REPLACE"
PLACE=`seq 1 6 | sort -R | head -n 1`
TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1`
GENERATE__NOTIN
NAME+="-$FALSENBR-$TARGET"
NEWINPUT=${INPUT//$TARGET/$FALSENBR}
INSTRUCTIONS2="en changeant les ${DIGITS[FALSENBR]} en ${DIGITS[TARGET]}"
INSTRUCTIONS1="Recopiez"
}
# REVERSEs INPUT. Ask to Add first or last number in random.
REVERSE() {
NAME="REVERSE"
RFL=`seq 1 2 | sort -R | head -n 1` # Rand First (1) or Last (2)
ADDNBR=${DIGITS[ADDNBR]}
for ((i=$LENINPUT-1;i>=0;i--))
do
NEWINPUT="$NEWINPUT${INPUT:$i:1}"
done
if (( $RFL == 1 ));then
ADDNBR="${INPUT:0:1}"
NAME+="_FIRST"
NEWINPUT=${NEWINPUT:0:$LENINPUT-1} # Do not show first INPUT NBR
INSTRUCTIONS1="Écrivez le chiffre ${DIGIT[$ADDNBR]} puis"
INSTRUCTIONS2="Recopiez de DROITE à GAUCHE ←"
else else
for n in `od -A n -t u2 -N 64 /dev/urandom`; do RL="$RL$n "; done ADDNBR="${INPUT:$LENINPUT-1:1}"
get_random () NAME+="_LAST"
{ NEWINPUT=${NEWINPUT:1:$LENINPUT-1} # Do not show last INPUT NBR
R=${RL%% *} INSTRUCTIONS1="Recopiez de DROITE à GAUCHE ←"
RL=${RL#* } INSTRUCTIONS2="Terminez par le chiffre ${DIGIT[$ADDNBR]}"
}
fi fi
NAME+="-$ADDNBR"
INTRUS()
{
LENGTH=${#INPUT}
NUMBERS=$(echo $INPUT | grep -o . | tr '\n' ' ')
SORTED_UNIQ_NUM=$(echo "${NUMBERS[@]}" | sort -u | tr '\n' ' ')
INTRUS=-1
for i in 1 2 3 4 5 6 7 8 9
do
if [[ ! " ${SORTED_UNIQ_NUM[@]} " =~ " ${i} " ]]; then
INTRUS=$i
break
fi
done
# Worst case
if [[ $INTRUS -eq "-1" ]]
then
echo Tapez "$INPUT |sans changement"
return
fi
for num in ${NUMBERS[@]}
do
get_random
R=$(($R % 100))
if [[ $R -lt 60 ]]; then
NEWINPUT=${NEWINPUT}${num}${INTRUS}
else
NEWINPUT=${NEWINPUT}${num}
fi
done
get_random
R=$(($R % 100))
if [[ $R -lt 50 ]]; then
echo "Tapez ce nombre en enlevant les ${DIGIT[$INTRUS]} | $NEWINPUT"
else
echo "Saisissez ce nombre sans les ${DIGIT[$INTRUS]} | $NEWINPUT"
fi
} }
SOMME()
{
get_random
RB=$(($R % 5))
get_random
RA=$(($R % 10 * (10 ** $RB)))
if [[ $(($INPUT % 2)) -eq 0 ]]; then # Add FALSE NBR to INPUT at three randomized place
A=$(($INPUT - $RA)) NOTIN() {
B=$RA NAME="NOTIN"
else GENERATE__NOTIN
B=$(($INPUT - $RA)) PLACE=(`seq 0 $((LENINPUT-1)) | sort -R | head -n 3 | sort -n`)
A=$RA for i in `seq 0 $((LENINPUT-1))`
fi do
(( $i == ${PLACE[0]} )) \
get_random && NEWINPUT+="$FALSENBR"
R=$(($R % 100)) (( $i == ${PLACE[1]} )) \
&& NEWINPUT+="$FALSENBR"
if [[ $R -lt 25 ]]; then (( $i == ${PLACE[2]} )) \
echo "Tapez le résultat de | $A + $B" && NEWINPUT+="$FALSENBR"
elif [[ $R -lt 50 ]]; then NEWINPUT="$NEWINPUT${INPUT:$i:1}"
echo "Sommez | $A et $B" done
elif [[ $R -lt 75 ]]; then NAME+="-$FALSENBR"
echo "Additionnez | $A et $B" INSTRUCTIONS1="Recopiez sans les ${DIGITS[FALSENBR]}"
else
echo "Saisissez le résultat de | $A + $B"
fi
} }
get_random
RAND_INDEX=$(($R % ${#TRANSFORMATIONS[@]}))
INSTRUCTIONS0=$(echo "$(${TRANSFORMATIONS[$RAND_INDEX]})") # Take a random NBR from INPUT. Calculate X
INSTRUCTIONS1=$(echo $INSTRUCTIONS0 | cut -d "|" -f 1) CALCUL() {
INSTRUCTIONS2=$(echo $INSTRUCTIONS0 | cut -d "|" -f 3) PLACE=`seq 1 $((LENINPUT)) | sort -R | head -n 1`
TEXT=$(echo $INSTRUCTIONS0 | cut -d "|" -f 2) TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1`
NEWINPUT=${INPUT//$TARGET/X}
RC=`seq 1 2 | sort -R | head -n 1` # 1 = - | 2 = +
if (( $RC == 1 ));then
FALSENBR=`seq $TARGET 10 | sort -R | head -n 1`
RESUME=$(( FALSENBR - TARGET ))
INSTRUCTIONS1="Calculez: $FALSENBR moins $RESUME. Copiez..."
NAME="CALCULM-$FALSENBR-$RESUME"
else
FALSENBR=`seq 1 4 | sort -R | head -n 1`
if (( $FALSENBR <= $TARGET ));then
RESULT=$(( TARGET + FALSENBR ))
RESUME=$(( TARGET - FALSENBR ))
INSTRUCTIONS1="Calculez: ${DIGIT[FALSENBR]} + ${DIGIT[RESUME]}. Copiez..."
NAME="CALCULP-$FALSENBR-$RESUME"
else
RESULT=$(( FALSENBR - TARGET ))
RESUME=$(( TARGET - RESULT ))
INSTRUCTIONS1="Calculez: ${DIGIT[RESULT]} + ${DIGIT[RESUME]}. Copiez..."
NAME="CALCULP-$RESULT-$RESUME"
fi
fi
INSTRUCTIONS2="...en remplaçant chaque X par la somme"
}
# ****************************************************************************
#
# Random captcha shape choice (aka main)
#
# ****************************************************************************
MODULES=(CALCUL NOTIN REPLACE REVERSE)
RMODULE=`seq 0 $(( ${#MODULES[@]} - 1)) | sort -R | head -n 1`
eval "${MODULES[RMODULE]}"
TEXT="$NEWINPUT"
CHAPRILURI="/var/lib/ejabberd/chapril_captchas_experimental/$(date "+%Y-%m-%d-%H%M%S")_${NAME}_${INPUT}.png"
convert -size 300x70 xc:none -pointsize 20 \ convert -size 300x70 xc:none -pointsize 20 \
\( -clone 0 -fill black \ \( -clone 0 -fill black \
@ -122,7 +166,8 @@ convert -size 300x70 xc:none -pointsize 20 \
-roll +$ROLL_X+0 \ -roll +$ROLL_X+0 \
-wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \
-roll -$ROLL_X+0 \) \ -roll -$ROLL_X+0 \) \
-flatten -crop 300x70 +repage -quality 500 -depth 11 png:"/var/lib/ejabberd/chapril_captchas/$(date "+%Y-%m-%d-%H%M%S")_${INPUT}.png" -flatten -crop 300x70 +repage -quality 500 \
-depth 11 png:"$CHAPRILURI"
convert -size 300x70 xc:none -pointsize 20 \ convert -size 300x70 xc:none -pointsize 20 \
\( -clone 0 -fill black \ \( -clone 0 -fill black \

View File

@ -61,7 +61,8 @@ TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1`
GENERATE__NOTIN GENERATE__NOTIN
NAME+="-$FALSENBR-$TARGET" NAME+="-$FALSENBR-$TARGET"
NEWINPUT=${INPUT//$TARGET/$FALSENBR} NEWINPUT=${INPUT//$TARGET/$FALSENBR}
INSTRUCTIONS1="Remplacez les ${DIGITS[FALSENBR]} par des ${DIGITS[TARGET]}" INSTRUCTIONS2="en changeant les ${DIGITS[FALSENBR]} en ${DIGITS[TARGET]}"
INSTRUCTIONS1="Recopiez"
} }
@ -154,7 +155,7 @@ RMODULE=`seq 0 $(( ${#MODULES[@]} - 1)) | sort -R | head -n 1`
eval "${MODULES[RMODULE]}" eval "${MODULES[RMODULE]}"
TEXT="$NEWINPUT" TEXT="$NEWINPUT"
CHAPRILURI="/var/lib/ejabberd/chapril_captchas_experimental/${NAME}_${NEWINPUT}_${INPUT}.png" CHAPRILURI="/var/lib/ejabberd/chapril_captchas_experimental/$(date "+%Y-%m-%d-%H%M%S")_${NAME}_${INPUT}.png"
convert -size 300x70 xc:none -pointsize 20 \ convert -size 300x70 xc:none -pointsize 20 \
\( -clone 0 -fill black \ \( -clone 0 -fill black \