| a | b | |
|---|
| 0 | + | -module(mycaptcha). |
|---|
| 0 | + | -compile(export_all). |
|---|
| 0 | + | |
|---|
| 0 | + | -record(captcha, {key, value}). |
|---|
| 0 | + | |
|---|
| 0 | + | new() -> |
|---|
| 0 | + | CryptKey = crypto:rand_bytes(16), |
|---|
| 0 | + | |
|---|
| 0 | + | ok = try mnesia:dirty_write({captcha, 0, CryptKey}) |
|---|
| 0 | + | catch |
|---|
| 0 | + | _:_ -> |
|---|
| 0 | + | {atomic, ok} = mnesia:create_table(captcha, [{ram_copies, [node()]}, {attributes, record_info(fields, captcha)}]), |
|---|
| 0 | + | mnesia:dirty_write({captcha, 0, CryptKey}) |
|---|
| 0 | + | end, |
|---|
| 0 | + | |
|---|
| 0 | + | FileName = lists:flatmap(fun(Item) -> integer_to_list(Item) end, tuple_to_list(now())), |
|---|
| 0 | + | |
|---|
| 0 | + | Code = generate_rand(5), |
|---|
| 0 | + | |
|---|
| 0 | + | File = io_lib:format("/tmp/~s.png",[FileName]), |
|---|
| 0 | + | |
|---|
| 0 | + | 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]), |
|---|
| 0 | + | os:cmd(Cmd), |
|---|
| 0 | + | |
|---|
| 0 | + | {ok, BinPng} = file:read_file(File), |
|---|
| 0 | + | file:delete(File), |
|---|
| 0 | + | |
|---|
| 0 | + | Sha = crypto:sha_mac(CryptKey, integer_to_list(lists:sum(Code)) ++ Code), |
|---|
| 0 | + | CodeHex = mochihex:to_hex(Sha), |
|---|
| 0 | + | |
|---|
| 0 | + | {CodeHex, BinPng}. |
|---|
| 0 | + | |
|---|
| 0 | + | check(CodeHex, Code) -> |
|---|
| 0 | + | Sha = mochihex:to_bin(CodeHex), |
|---|
| 0 | + | [Rec] = mnesia:dirty_read({captcha, 0}), |
|---|
| 0 | + | CryptKey = Rec#captcha.value, |
|---|
| 0 | + | |
|---|
| 0 | + | case crypto:sha_mac(CryptKey, integer_to_list(lists:sum(Code)) ++ Code) of |
|---|
| 0 | + | Sha -> |
|---|
| 0 | + | true; |
|---|
| 0 | + | |
|---|
| 0 | + | _ -> |
|---|
| 0 | + | false |
|---|
| 0 | + | end. |
|---|
| 0 | + | |
|---|
| 0 | + | generate_rand(Length) -> |
|---|
| 0 | + | Now = now(), |
|---|
| 0 | + | random:seed(element(1, Now), element(2, Now), element(3, Now)), |
|---|
| 0 | + | lists:foldl(fun(_I, Acc) -> [do_rand(0) | Acc] end, [], lists:seq(1, Length)). |
|---|
| 0 | + | |
|---|
| 0 | + | do_rand(R) when R > 46, R < 58; R > 64, R < 91; R > 96 -> |
|---|
| 0 | + | R; |
|---|
| 0 | + | |
|---|
| 0 | + | do_rand(_R) -> |
|---|
| 0 | + | %do_rand(48 + random:uniform(74)). %% exluding zero |
|---|
| 0 | + | do_rand(47 + random:uniform(75)). |
|---|
| ... | |
|---|