From 59fd57bc074b31e440734865a371f79fb480e6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Thu, 8 Nov 2012 19:18:12 +0100 Subject: [PATCH] Initial commit --- Makefile | 3 + gcaptchaz.c | 253 ++++++++++++++++++++++++++++++++++++++++++++ generate_captcha.sh | 56 ++++++++++ scrawl.ttf | Bin 0 -> 45080 bytes 4 files changed, 312 insertions(+) create mode 100644 Makefile create mode 100644 gcaptchaz.c create mode 100755 generate_captcha.sh create mode 100644 scrawl.ttf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..609f093 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ + +gcaptchaz: gcaptchaz.c + gcc $^ -o $@ -lm -lfreetype -lpng -lgd -ggdb -Wall diff --git a/gcaptchaz.c b/gcaptchaz.c new file mode 100644 index 0000000..9f5404a --- /dev/null +++ b/gcaptchaz.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include +#include +#include + +/* + This code is only a C implementation (with some minor modifications) of this captcha generator : + http://logz.org/captchaz/ + + Copyright November 2012 Grégory Soutadé + Copyright July 2007 Loz + + LICENCE : Copyleft, Licence Art Libre (http://artlibre.org/licence/lal) + + Modifications : + * Group letters + * Add another layer for letter rendering (more confusing) + * Change start, not appropriate for big fonts + * Change min/max font size + + You need libgd2-xpm-dev package + + It's recommanded the included font "scrawl.ttf" + */ + +#define MAX(a, b) (((a) >= (b)) ? (a) : (b)) + +// If not defined +/* int overflow2(int a, int b) */ +/* { */ +/* if(a < 0 || b < 0) { */ +/* fprintf(stderr, "gd warning: one parameter to a memory allocation multiplication is negative, failing operation gracefully\n"); */ +/* return 1; */ +/* } */ +/* if(b == 0) */ +/* return 0; */ +/* if(a > 0xFFFFFFFF / b) { */ +/* fprintf(stderr, "gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully\n"); */ +/* return 1; */ +/* } */ +/* return 0; */ +/* } */ + +static int my_rand(int min, int max) +{ + int val; + struct timeval tv; + static unsigned int seed = 0; + int interval; + + if (seed == 0) + { + gettimeofday(&tv, NULL); + seed = tv.tv_usec; + } + + val = rand_r(&seed); + + if (min < 0) + { + if (max < 0) + interval = -(min-max); + else + interval = max-min; + } + else + interval = max-min; + + val = (int)(((double)val/(double)RAND_MAX)*(double)(interval)); + + val += min; + + /* printf("rand [%d..%d] %d\n", min, max, val); */ + + return val; +} + +static inline int random_color(gdImagePtr im, int a, int b) { + return gdImageColorAllocate(im, my_rand(a,b), my_rand(a,b), my_rand(a,b)); +} + +static int generate_captcha(int width, int height, int inverse, char* font, char* phrase, char* out) +{ + gdImagePtr im; + int R, c1, c2; + int wd, x, y, w1, w2, limit, n, p, r, g, b; + int size, half, len; + double rotation; + char letter[2] = {0, 0}; + int brect[8]; + char* error; + const double rad = 3.14/(double)180; + +// initialize in-memory image with gd library + im = gdImageCreateTrueColor(width, height); + + R = (inverse) ? 0xFF : 0x00; + + gdImageFilledRectangle(im, 0, 0, width, height, random_color(im, 222^R, 255^R)); + + c1 = my_rand(150^R, 185^R); + c2 = my_rand(195^R, 230^R); + +// encolour bg + wd=20; x=0; + while (x < width) + { + gdImageFilledRectangle(im, x, 0, x+wd, height, random_color(im, 222^R, 255^R)); + x += wd; + wd += MAX(10, my_rand(0, 20) - 10); + } + + // make interesting background I, lines + wd=4; w1=0; w2=0; + for(x=0; x height) && (x > height)) // ??? + break; + } + + // more disturbing II, random letters + limit = my_rand(30, 90); + for(n=0; n /dev/null +if [ ! $? -eq 0 ] ; then + echo $res + exit 1 +fi + +text=`echo $res | cut -d\" -f2` + +# Do verification +if [ $do_check -eq 1 ] ; then + emacs "$out/captcha.png" + + echo -n "Enter CAPTCHA value : " + read user + + if [ "$user" != "$text" ] ; then + echo "CAPTCHA failed" + rm -f "$out/captcha.png" + exit 1 + fi + + echo "CAPTCHA OK" +fi + +# Encrypt captcha's value to generate captcha's name +key=`echo -n $pass | md5sum | cut -d' ' -f1` +enc=`echo -n $text | openssl enc -aes-128-ecb -nosalt -K $key -iv $key` +enc=`echo -n $enc | hexdump -e '"%02x"'` +mv "$out/captcha.png" "$out/$enc.png" diff --git a/scrawl.ttf b/scrawl.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1ef4878bc42be22d5e2d2d5f6a1e21e1cd22fd20 GIT binary patch literal 45080 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 E0&fRmd;kCd literal 0 HcmV?d00001