#!/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. # 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. # The whole idea of the captcha script is to let server admins adapt it to # their own needs. The goal is to be able to make the captcha generation as # unique as possible, to make the captcha challenge difficult to bypass by # a bot. # Server admins are thus supposed to write and use their own captcha generators. # This script relies on ImageMagick. # It is NOT compliant with ImageMagick forks like GraphicsMagick. 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) # **************************************************************************** # # Tools # # **************************************************************************** # 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} INSTRUCTIONS1="Remplacez les ${DIGITS[FALSENBR]} par des ${DIGITS[TARGET]}" } # 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 ADDNBR="${INPUT:$LENINPUT-1:1}" NAME+="_LAST" NEWINPUT=${NEWINPUT:1:$LENINPUT-1} # Do not show last INPUT NBR INSTRUCTIONS1="Recopiez de DROITE à GAUCHE ←" INSTRUCTIONS2="Terminez par le chiffre ${DIGIT[$ADDNBR]}" fi NAME+="-$ADDNBR" } # Add FALSE NBR to INPUT at three randomized place NOTIN() { NAME="NOTIN" GENERATE__NOTIN PLACE=(`seq 0 $((LENINPUT-1)) | sort -R | head -n 3 | sort -n`) for i in `seq 0 $((LENINPUT-1))` do (( $i == ${PLACE[0]} )) \ && NEWINPUT+="$FALSENBR" (( $i == ${PLACE[1]} )) \ && NEWINPUT+="$FALSENBR" (( $i == ${PLACE[2]} )) \ && NEWINPUT+="$FALSENBR" NEWINPUT="$NEWINPUT${INPUT:$i:1}" done NAME+="-$FALSENBR" INSTRUCTIONS1="Recopiez sans les ${DIGITS[FALSENBR]}" } # Take a random NBR from INPUT. Calculate X CALCUL() { PLACE=`seq 1 $((LENINPUT)) | sort -R | head -n 1` 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/${NAME}_${NEWINPUT}_${INPUT}.png" convert -size 300x70 xc:none -pointsize 20 \ \( -clone 0 -fill black \ -stroke black -strokewidth 1 \ -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ -roll +$ROLL_X+0 \ -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ -roll -$ROLL_X+0 \) \ -flatten -crop 300x70 +repage -quality 500 \ -depth 11 png:"$CHAPRILURI" convert -size 300x70 xc:none -pointsize 20 \ \( -clone 0 -fill black \ -stroke black -strokewidth 1 \ -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ -roll +$ROLL_X+0 \ -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ -roll -$ROLL_X+0 \) \ -flatten -crop 300x70 +repage -quality 500 -depth 11 png:-