From 4f49b16079b27d7ce633619e4cddfdf2bffbc952 Mon Sep 17 00:00:00 2001 From: cashmere Date: Fri, 4 Sep 2026 09:05:24 +0200 Subject: initial commit --- src/captcha.c | 926 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 926 insertions(+) create mode 100644 src/captcha.c (limited to 'src/captcha.c') diff --git a/src/captcha.c b/src/captcha.c new file mode 100644 index 0000000..8e768ce --- /dev/null +++ b/src/captcha.c @@ -0,0 +1,926 @@ +/* +** Copyright (c) 2009 D. Richard Hipp +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the Simplified BSD License (also +** known as the "2-Clause License" or "FreeBSD License".) + +** This program is distributed in the hope that it will be useful, +** but without any warranty; without even the implied warranty of +** merchantability or fitness for a particular purpose. +** +** Author contact information: +** drh@hwaci.com +** http://www.hwaci.com/drh/ +** +******************************************************************************* +** +** This file contains code to a simple text-based CAPTCHA. Though easily +** defeated by a sophisticated attacker, this CAPTCHA does at least make +** scripting attacks more difficult. +*/ +#include "config.h" +#include +#include "captcha.h" + +#if INTERFACE +#define CAPTCHA 2 /* Which captcha rendering to use */ +#endif + +/* +** Convert a hex digit into a value between 0 and 15 +*/ +int hex_digit_value(char c){ + if( c>='0' && c<='9' ){ + return c - '0'; + }else if( c>='a' && c<='f' ){ + return c - 'a' + 10; + }else if( c>='A' && c<='F' ){ + return c - 'A' + 10; + }else{ + return 0; + } +} + +#if CAPTCHA==1 +/* +** A 4x6 pixel bitmap font for hexadecimal digits +*/ +static const unsigned int aFont1[] = { + 0x699996, + 0x262227, + 0x69124f, + 0xf16196, + 0x26af22, + 0xf8e196, + 0x68e996, + 0xf12244, + 0x696996, + 0x699716, + 0x699f99, + 0xe9e99e, + 0x698896, + 0xe9999e, + 0xf8e88f, + 0xf8e888, +}; + +/* +** Render an 8-character hexadecimal string as ascii art. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = fossil_malloc( 9*12*3*strlen(zPw) + 8 ); + int i, j, k, m; + + k = 0; + for(i=0; i<6; i++){ + for(j=0; zPw[j]; j++){ + unsigned char v = hex_digit_value(zPw[j]); + v = (aFont1[v] >> ((5-i)*4)) & 0xf; + for(m=8; m>=1; m = m>>1){ + if( v & m ){ + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x88; + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x88; + }else{ + z[k++] = ' '; + z[k++] = ' '; + } + } + z[k++] = ' '; + z[k++] = ' '; + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==1 */ + +#if CAPTCHA==2 +/* +** A 5x7 pixel bitmap font for hexadecimal digits +*/ +static const unsigned char aFont2[] = { + /* 0 */ 0x0e, 0x13, 0x15, 0x19, 0x11, 0x11, 0x0e, + /* 1 */ 0x02, 0x06, 0x0A, 0x02, 0x02, 0x02, 0x02, + /* 2 */ 0x0e, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1f, + /* 3 */ 0x0e, 0x11, 0x01, 0x06, 0x01, 0x11, 0x0e, + /* 4 */ 0x02, 0x06, 0x0A, 0x12, 0x1f, 0x02, 0x02, + /* 5 */ 0x1f, 0x10, 0x1e, 0x01, 0x01, 0x11, 0x0e, + /* 6 */ 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x0e, + /* 7 */ 0x1f, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08, + /* 8 */ 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e, + /* 9 */ 0x0e, 0x11, 0x11, 0x0f, 0x01, 0x11, 0x0e, + /* A */ 0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, + /* B */ 0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e, + /* C */ 0x0e, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0e, + /* D */ 0x1c, 0x12, 0x11, 0x11, 0x11, 0x12, 0x1c, + /* E */ 0x1f, 0x10, 0x10, 0x1c, 0x10, 0x10, 0x1f, + /* F */ 0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10, +}; + +/* +** Render an 8-character hexadecimal string as ascii art. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = fossil_malloc( 224*strlen(zPw) + 9 ); + int i, j, k, m; + + k = 0; + for(i=0; i<7; i++){ + for(j=0; zPw[j]; j++){ + unsigned char v = hex_digit_value(zPw[j]); + v = aFont2[v*7+i]; + for(m=16; m>=1; m = m>>1){ + if( v & m ){ + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x88; + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x88; + }else{ + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x91; + z[k++] = 0xe2; + z[k++] = 0x96; + z[k++] = 0x91; + } + } + z[k++] = ' '; + z[k++] = ' '; + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==2 */ + + +#if CAPTCHA==3 +static const char *const azFont3[] = { + /* 0 */ + " __ ", + " / \\ ", + "| () |", + " \\__/ ", + + /* 1 */ + " _ ", + "/ |", + "| |", + "|_|", + + /* 2 */ + " ___ ", + "|_ )", + " / / ", + "/___|", + + /* 3 */ + " ____", + "|__ /", + " |_ \\", + "|___/", + + /* 4 */ + " _ _ ", + "| | | ", + "|_ _|", + " |_| ", + + /* 5 */ + " ___ ", + "| __|", + "|__ \\", + "|___/", + + /* 6 */ + " __ ", + " / / ", + "/ _ \\", + "\\___/", + + /* 7 */ + " ____ ", + "|__ |", + " / / ", + " /_/ ", + + /* 8 */ + " ___ ", + "( _ )", + "/ _ \\", + "\\___/", + + /* 9 */ + " ___ ", + "/ _ \\", + "\\_, /", + " /_/ ", + + /* A */ + " ", + " /\\ ", + " / \\ ", + "/_/\\_\\", + + /* B */ + " ___ ", + "| _ )", + "| _ \\", + "|___/", + + /* C */ + " ___ ", + " / __|", + "| (__ ", + " \\___|", + + /* D */ + " ___ ", + "| \\ ", + "| |) |", + "|___/ ", + + /* E */ + " ___ ", + "| __|", + "| _| ", + "|___|", + + /* F */ + " ___ ", + "| __|", + "| _| ", + "|_| ", +}; + +/* +** Render an 8-digit hexadecimal string as ascii arg. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = fossil_malloc( 7*4*strlen(zPw) + 5 ); + int i, j, k, m; + const char *zChar; + + k = 0; + for(i=0; i<4; i++){ + for(j=0; zPw[j]; j++){ + unsigned char v = hex_digit_value(zPw[j]); + zChar = azFont3[4*v + i]; + for(m=0; zChar[m]; m++){ + z[k++] = zChar[m]; + } + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==3 */ + +#if CAPTCHA==4 +static const char *const azFont4[] = { + /* 0 */ + " ___ ", + " / _ \\ ", + "| | | |", + "| | | |", + "| |_| |", + " \\___/ ", + + /* 1 */ + " __ ", + "/_ |", + " | |", + " | |", + " | |", + " |_|", + + /* 2 */ + " ___ ", + "|__ \\ ", + " ) |", + " / / ", + " / /_ ", + "|____|", + + /* 3 */ + " ____ ", + "|___ \\ ", + " __) |", + " |__ < ", + " ___) |", + "|____/ ", + + /* 4 */ + " _ _ ", + "| || | ", + "| || |_ ", + "|__ _|", + " | | ", + " |_| ", + + /* 5 */ + " _____ ", + "| ____|", + "| |__ ", + "|___ \\ ", + " ___) |", + "|____/ ", + + /* 6 */ + " __ ", + " / / ", + " / /_ ", + "| '_ \\ ", + "| (_) |", + " \\___/ ", + + /* 7 */ + " ______ ", + "|____ |", + " / / ", + " / / ", + " / / ", + " /_/ ", + + /* 8 */ + " ___ ", + " / _ \\ ", + "| (_) |", + " > _ < ", + "| (_) |", + " \\___/ ", + + /* 9 */ + " ___ ", + " / _ \\ ", + "| (_) |", + " \\__, |", + " / / ", + " /_/ ", + + /* A */ + " ", + " /\\ ", + " / \\ ", + " / /\\ \\ ", + " / ____ \\ ", + "/_/ \\_\\", + + /* B */ + " ____ ", + "| _ \\ ", + "| |_) |", + "| _ < ", + "| |_) |", + "|____/ ", + + /* C */ + " _____ ", + " / ____|", + "| | ", + "| | ", + "| |____ ", + " \\_____|", + + /* D */ + " _____ ", + "| __ \\ ", + "| | | |", + "| | | |", + "| |__| |", + "|_____/ ", + + /* E */ + " ______ ", + "| ____|", + "| |__ ", + "| __| ", + "| |____ ", + "|______|", + + /* F */ + " ______ ", + "| ____|", + "| |__ ", + "| __| ", + "| | ", + "|_| ", +}; + +/* +** Render an 8-digit hexadecimal string as ascii arg. +** Space to hold the result is obtained from malloc() and should be freed +** by the caller. +*/ +char *captcha_render(const char *zPw){ + char *z = fossil_malloc( 10*6*strlen(zPw) + 7 ); + int i, j, k, m; + const char *zChar; + unsigned char x; + int y; + + k = 0; + for(i=0; i<6; i++){ + x = 0; + for(j=0; zPw[j]; j++){ + unsigned char v = hex_digit_value(zPw[j]); + x = (x<<4) + v; + switch( x ){ + case 0x7a: + case 0xfa: + y = 3; + break; + case 0x47: + y = 2; + break; + case 0xf6: + case 0xa9: + case 0xa4: + case 0xa1: + case 0x9a: + case 0x76: + case 0x61: + case 0x67: + case 0x69: + case 0x41: + case 0x42: + case 0x43: + case 0x4a: + y = 1; + break; + default: + y = 0; + break; + } + zChar = azFont4[6*v + i]; + while( y && zChar[0]==' ' ){ y--; zChar++; } + while( y && z[k-1]==' ' ){ y--; k--; } + for(m=0; zChar[m]; m++){ + z[k++] = zChar[m]; + } + } + z[k++] = '\n'; + } + z[k] = 0; + return z; +} +#endif /* CAPTCHA==4 */ + +/* +** COMMAND: test-captcha +** +** Render an ASCII-art captcha for numbers given on the command line. +*/ +void test_captcha(void){ + int i; + sqlite3_uint64 v; + char *z; + + for(i=2; i