-module(mycaptcha). -compile(export_all). -record(captcha, {key, value}). new() -> CryptKey = crypto:rand_bytes(16), ok = try mnesia:dirty_write({captcha, 0, CryptKey}) catch _:_ -> {atomic, ok} = mnesia:create_table(captcha, [{ram_copies, [node()]}, {attributes, record_info(fields, captcha)}]), mnesia:dirty_write({captcha, 0, CryptKey}) end, FileName = lists:flatmap(fun(Item) -> integer_to_list(Item) end, tuple_to_list(now())), Code = generate_rand(5), File = io_lib:format("/tmp/~s.png",[FileName]), Cmd = io_lib:format("convert -background 'none' -fill '#222222' -size 175 -gravity Center -wave 5x100 -swirl 50 -font DejaVu-Serif-Book -pointsize 28 label:~s -draw 'Bezier 10,40 50,35 100,35 150,35 200,50 250,35 300,35' ~s", [Code, File]), os:cmd(Cmd), {ok, BinPng} = file:read_file(File), file:delete(File), Sha = crypto:sha_mac(CryptKey, integer_to_list(lists:sum(Code)) ++ Code), CodeHex = mochihex:to_hex(Sha), {CodeHex, BinPng}. check(CodeHex, Code) -> Sha = mochihex:to_bin(CodeHex), [Rec] = mnesia:dirty_read({captcha, 0}), CryptKey = Rec#captcha.value, case crypto:sha_mac(CryptKey, integer_to_list(lists:sum(Code)) ++ Code) of Sha -> true; _ -> false end. generate_rand(Length) -> Now = now(), random:seed(element(1, Now), element(2, Now), element(3, Now)), lists:foldl(fun(_I, Acc) -> [do_rand(0) | Acc] end, [], lists:seq(1, Length)). do_rand(R) when R > 46, R < 58; R > 64, R < 91; R > 96 -> R; do_rand(_R) -> %do_rand(48 + random:uniform(74)). %% exluding zero do_rand(47 + random:uniform(75)).