24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-20 22:22:09 +02:00

* src/ejabberd_captcha.erl: moved all functions from ejabberd_captcha process. Use mnesia:transaction/1 where it is needed.

SVN Revision: 1994
This commit is contained in:
Evgeniy Khramtsov 2009-03-14 06:27:05 +00:00
parent 9aadefa5b0
commit b789ee630d

View File

@ -37,6 +37,15 @@
-record(state, {}). -record(state, {}).
-record(captcha, {id, pid, key, tref, args}). -record(captcha, {id, pid, key, tref, args}).
-define(T(S),
case catch mnesia:transaction(fun() -> S end) of
{atomic, Res} ->
Res;
{_, Reason} ->
?ERROR_MSG("mnesia transaction failed: ~p", [Reason]),
{error, Reason}
end).
%%==================================================================== %%====================================================================
%% API %% API
%%==================================================================== %%====================================================================
@ -50,28 +59,6 @@ start_link() ->
create_captcha(Id, SID, From, To, Lang, Args) create_captcha(Id, SID, From, To, Lang, Args)
when is_list(Id), is_list(Lang), is_list(SID), when is_list(Id), is_list(Lang), is_list(SID),
is_record(From, jid), is_record(To, jid) -> is_record(From, jid), is_record(To, jid) ->
gen_server:call(?MODULE, {create_captcha, Id, SID, From, To, Lang, Args}).
process_reply({xmlelement, "captcha", _, _} = El) ->
gen_server:call(?MODULE, {process_reply, El});
process_reply(_) ->
{error, malformed}.
process(_Handlers, Request) when is_record(Request, request) ->
gen_server:call(?MODULE, Request).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
mnesia:create_table(captcha,
[{ram_copies, [node()]},
{attributes, record_info(fields, captcha)}]),
mnesia:add_table_copy(captcha, node(), ram_copies),
{ok, #state{}}.
handle_call({create_captcha, Id, SID, From, To, Lang, Args}, {Pid, _}, State) ->
Reply =
case create_image() of case create_image() of
{ok, Type, Key, Image} -> {ok, Type, Key, Image} ->
B64Image = jlib:encode_base64(binary_to_list(Image)), B64Image = jlib:encode_base64(binary_to_list(Image)),
@ -96,26 +83,25 @@ handle_call({create_captcha, Id, SID, From, To, Lang, Args}, {Pid, _}, State) ->
[{xmlcdata, ?CAPTCHA_BODY(Lang, JID, get_url(Id))}]}, [{xmlcdata, ?CAPTCHA_BODY(Lang, JID, get_url(Id))}]},
OOB = {xmlelement, "x", [{"xmlns", ?NS_OOB}], OOB = {xmlelement, "x", [{"xmlns", ?NS_OOB}],
[{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]}, [{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]},
Tref = erlang:send_after(?CAPTCHA_LIFETIME, self(), {remove_id, Id}), Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
mnesia:dirty_write(#captcha{id=Id, pid=Pid, key=Key, ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key,
tref=Tref, args=Args}), tref=Tref, args=Args})),
{ok, [Body, OOB, Captcha, Data]}; {ok, [Body, OOB, Captcha, Data]};
_Err -> _Err ->
error error
end, end.
{reply, Reply, State};
handle_call({process_reply, Challenge}, _, State) -> process_reply({xmlelement, "captcha", _, _} = El) ->
Reply = case xml:get_subtag(Challenge, "x") of case xml:get_subtag(El, "x") of
false -> false ->
{error, malformed}; {error, malformed};
Xdata -> Xdata ->
Fields = jlib:parse_xdata_submit(Xdata), Fields = jlib:parse_xdata_submit(Xdata),
[Id | _] = proplists:get_value("challenge", Fields, [none]), [Id | _] = proplists:get_value("challenge", Fields, [none]),
[OCR | _] = proplists:get_value("ocr", Fields, [none]), [OCR | _] = proplists:get_value("ocr", Fields, [none]),
case mnesia:dirty_read(captcha, Id) of ?T(case mnesia:read(captcha, Id, write) of
[#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] -> [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
mnesia:dirty_delete(captcha, Id), mnesia:delete({captcha, Id}),
erlang:cancel_timer(Tref), erlang:cancel_timer(Tref),
if OCR == Key -> if OCR == Key ->
Pid ! {captcha_succeed, Args}, Pid ! {captcha_succeed, Args},
@ -126,12 +112,13 @@ handle_call({process_reply, Challenge}, _, State) ->
end; end;
_ -> _ ->
{error, not_found} {error, not_found}
end end)
end, end;
{reply, Reply, State}; process_reply(_) ->
{error, malformed}.
handle_call(#request{method='GET', lang=Lang, path=[_, Id]}, _, State) -> process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) ->
Reply = case mnesia:dirty_read(captcha, Id) of case mnesia:dirty_read(captcha, Id) of
[#captcha{}] -> [#captcha{}] ->
Form = Form =
{xmlelement, "div", [{"align", "center"}], {xmlelement, "div", [{"align", "center"}],
@ -152,11 +139,10 @@ handle_call(#request{method='GET', lang=Lang, path=[_, Id]}, _, State) ->
ejabberd_web:make_xhtml([Form]); ejabberd_web:make_xhtml([Form]);
_ -> _ ->
ejabberd_web:error(not_found) ejabberd_web:error(not_found)
end, end;
{reply, Reply, State};
handle_call(#request{method='GET', path=[_, Id, "image"]}, _, State) -> process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) ->
Reply = case mnesia:dirty_read(captcha, Id) of case mnesia:dirty_read(captcha, Id) of
[#captcha{key=Key}] -> [#captcha{key=Key}] ->
case create_image(Key) of case create_image(Key) of
{ok, Type, _, Img} -> {ok, Type, _, Img} ->
@ -170,13 +156,12 @@ handle_call(#request{method='GET', path=[_, Id, "image"]}, _, State) ->
end; end;
_ -> _ ->
ejabberd_web:error(not_found) ejabberd_web:error(not_found)
end, end;
{reply, Reply, State};
handle_call(#request{method='POST', q=Q, path=[_, Id]}, _, State) -> process(_Handlers, #request{method='POST', q=Q, path=[_, Id]}) ->
Reply = case mnesia:dirty_read(captcha, Id) of ?T(case mnesia:read(captcha, Id, write) of
[#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] -> [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
mnesia:dirty_delete(captcha, Id), mnesia:delete({captcha, Id}),
erlang:cancel_timer(Tref), erlang:cancel_timer(Tref),
Input = proplists:get_value("key", Q, none), Input = proplists:get_value("key", Q, none),
if Input == Key -> if Input == Key ->
@ -188,8 +173,17 @@ handle_call(#request{method='POST', q=Q, path=[_, Id]}, _, State) ->
end; end;
_ -> _ ->
ejabberd_web:error(not_found) ejabberd_web:error(not_found)
end, end).
{reply, Reply, State};
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
mnesia:create_table(captcha,
[{ram_copies, [node()]},
{attributes, record_info(fields, captcha)}]),
mnesia:add_table_copy(captcha, node(), ram_copies),
{ok, #state{}}.
handle_call(_Request, _From, State) -> handle_call(_Request, _From, State) ->
{reply, bad_request, State}. {reply, bad_request, State}.
@ -198,16 +192,14 @@ handle_cast(_Msg, State) ->
{noreply, State}. {noreply, State}.
handle_info({remove_id, Id}, State) -> handle_info({remove_id, Id}, State) ->
F = fun() -> ?DEBUG("captcha ~p timed out", [Id]),
case mnesia:read(captcha, Id, write) of ?T(case mnesia:read(captcha, Id, write) of
[#captcha{args=Args, pid=Pid}] -> [#captcha{args=Args, pid=Pid}] ->
Pid ! {captcha_failed, Args}, Pid ! {captcha_failed, Args},
mnesia:delete({captcha, Id}); mnesia:delete({captcha, Id});
_ -> _ ->
ok ok
end end),
end,
mnesia:transaction(F),
{noreply, State}; {noreply, State};
handle_info(_Info, State) -> handle_info(_Info, State) ->