rpms/ejabberd/F-10 ejabberd-captcha.patch, NONE, 1.1 .cvsignore, 1.13, 1.14 ejabberd.spec, 1.33, 1.34 import.log, 1.8, 1.9 mod_ctlextra.erl, 1.4, 1.5 sources, 1.15, 1.16
Peter Lemenkov
peter at fedoraproject.org
Fri Apr 3 20:14:16 UTC 2009
- Previous message: rpms/nemiver/F-9 nemiver.spec,1.15,1.16
- Next message: rpms/ejabberd/F-9 ejabberd-captcha.patch, NONE, 1.1 .cvsignore, 1.12, 1.13 ejabberd.spec, 1.30, 1.31 import.log, 1.6, 1.7 mod_ctlextra.erl, 1.4, 1.5 sources, 1.14, 1.15
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: peter
Update of /cvs/pkgs/rpms/ejabberd/F-10
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv9779/F-10
Modified Files:
.cvsignore ejabberd.spec import.log mod_ctlextra.erl sources
Added Files:
ejabberd-captcha.patch
Log Message:
Ver. 2.0.5
ejabberd-captcha.patch:
--- NEW FILE ejabberd-captcha.patch ---
Binary files ejabberd-2.0.4/src/.DS_Store and ejabberd-2.0.4-new/src/.DS_Store differ
diff -urN ejabberd-2.0.4/src/ejabberd_captcha.erl ejabberd-2.0.4-new/src/ejabberd_captcha.erl
--- ejabberd-2.0.4/src/ejabberd_captcha.erl 1970-01-01 01:00:00.000000000 +0100
+++ ejabberd-2.0.4-new/src/ejabberd_captcha.erl 2009-03-14 07:27:05.000000000 +0100
@@ -0,0 +1,312 @@
+%%%-------------------------------------------------------------------
+%%% File : ejabberd_captcha.erl
+%%% Author : Evgeniy Khramtsov <xramtsov at gmail.com>
+%%% Description : CAPTCHA processing.
+%%%
+%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov at gmail.com>
+%%%-------------------------------------------------------------------
+-module(ejabberd_captcha).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-export([create_captcha/6, process_reply/1, process/2]).
+
+-include("jlib.hrl").
+-include("ejabberd.hrl").
+-include("web/ejabberd_http.hrl").
+
+-define(VFIELD(Type, Var, Value),
+ {xmlelement, "field", [{"type", Type}, {"var", Var}],
+ [{xmlelement, "value", [], [Value]}]}).
+
+-define(CAPTCHA_BODY(Lang, Room, URL),
+ translate:translate(Lang, "Your messages to ") ++ Room
+ ++ translate:translate(Lang, " are being blocked. To unblock them, visit ")
+ ++ URL).
+
+-define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")).
+-define(CAPTCHA_LIFETIME, 120000). % two minutes
+
+-record(state, {}).
+-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
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+create_captcha(Id, SID, From, To, Lang, Args)
+ when is_list(Id), is_list(Lang), is_list(SID),
+ is_record(From, jid), is_record(To, jid) ->
+ case create_image() of
+ {ok, Type, Key, Image} ->
+ B64Image = jlib:encode_base64(binary_to_list(Image)),
+ JID = jlib:jid_to_string(From),
+ CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org",
+ Data = {xmlelement, "data",
+ [{"xmlns", ?NS_BOB}, {"cid", CID},
+ {"max-age", "0"}, {"type", Type}],
+ [{xmlcdata, B64Image}]},
+ Captcha =
+ {xmlelement, "captcha", [{"xmlns", ?NS_CAPTCHA}],
+ [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
+ [?VFIELD("hidden", "FORM_TYPE", {xmlcdata, ?NS_CAPTCHA}),
+ ?VFIELD("hidden", "from", {xmlcdata, jlib:jid_to_string(To)}),
+ ?VFIELD("hidden", "challenge", {xmlcdata, Id}),
+ ?VFIELD("hidden", "sid", {xmlcdata, SID}),
+ {xmlelement, "field", [{"var", "ocr"}],
+ [{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
+ [{xmlelement, "uri", [{"type", Type}],
+ [{xmlcdata, "cid:" ++ CID}]}]}]}]}]},
+ Body = {xmlelement, "body", [],
+ [{xmlcdata, ?CAPTCHA_BODY(Lang, JID, get_url(Id))}]},
+ OOB = {xmlelement, "x", [{"xmlns", ?NS_OOB}],
+ [{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]},
+ Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
+ ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key,
+ tref=Tref, args=Args})),
+ {ok, [Body, OOB, Captcha, Data]};
+ _Err ->
+ error
+ end.
+
+process_reply({xmlelement, "captcha", _, _} = El) ->
+ case xml:get_subtag(El, "x") of
+ false ->
+ {error, malformed};
+ Xdata ->
+ Fields = jlib:parse_xdata_submit(Xdata),
+ [Id | _] = proplists:get_value("challenge", Fields, [none]),
+ [OCR | _] = proplists:get_value("ocr", Fields, [none]),
+ ?T(case mnesia:read(captcha, Id, write) of
+ [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
+ mnesia:delete({captcha, Id}),
+ erlang:cancel_timer(Tref),
+ if OCR == Key ->
+ Pid ! {captcha_succeed, Args},
+ ok;
+ true ->
+ Pid ! {captcha_failed, Args},
+ {error, bad_match}
+ end;
+ _ ->
+ {error, not_found}
+ end)
+ end;
+process_reply(_) ->
+ {error, malformed}.
+
+process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) ->
+ case mnesia:dirty_read(captcha, Id) of
+ [#captcha{}] ->
+ Form =
+ {xmlelement, "div", [{"align", "center"}],
+ [{xmlelement, "form", [{"action", get_url(Id)},
+ {"name", "captcha"},
+ {"method", "POST"}],
+ [{xmlelement, "img", [{"src", get_url(Id ++ "/image")}], []},
+ {xmlelement, "br", [], []},
+ {xmlcdata, ?CAPTCHA_TEXT(Lang)},
+ {xmlelement, "br", [], []},
+ {xmlelement, "input", [{"type", "text"},
+ {"name", "key"},
+ {"size", "10"}], []},
+ {xmlelement, "br", [], []},
+ {xmlelement, "input", [{"type", "submit"},
+ {"name", "enter"},
+ {"value", "OK"}], []}]}]},
+ ejabberd_web:make_xhtml([Form]);
+ _ ->
+ ejabberd_web:error(not_found)
+ end;
+
+process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) ->
+ case mnesia:dirty_read(captcha, Id) of
+ [#captcha{key=Key}] ->
+ case create_image(Key) of
+ {ok, Type, _, Img} ->
+ {200,
+ [{"Content-Type", Type},
+ {"Cache-Control", "no-cache"},
+ {"Last-Modified", httpd_util:rfc1123_date()}],
+ Img};
+ _ ->
+ ejabberd_web:error(not_found)
+ end;
+ _ ->
+ ejabberd_web:error(not_found)
+ end;
+
+process(_Handlers, #request{method='POST', q=Q, path=[_, Id]}) ->
+ ?T(case mnesia:read(captcha, Id, write) of
+ [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
+ mnesia:delete({captcha, Id}),
+ erlang:cancel_timer(Tref),
+ Input = proplists:get_value("key", Q, none),
+ if Input == Key ->
+ Pid ! {captcha_succeed, Args},
+ ejabberd_web:make_xhtml([]);
+ true ->
+ Pid ! {captcha_failed, Args},
+ ejabberd_web:error(not_allowed)
+ end;
+ _ ->
+ ejabberd_web:error(not_found)
+ end).
+
+%%====================================================================
+%% 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) ->
+ {reply, bad_request, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info({remove_id, Id}, State) ->
+ ?DEBUG("captcha ~p timed out", [Id]),
+ ?T(case mnesia:read(captcha, Id, write) of
+ [#captcha{args=Args, pid=Pid}] ->
+ Pid ! {captcha_failed, Args},
+ mnesia:delete({captcha, Id});
+ _ ->
+ ok
+ end),
+ {noreply, State};
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%% Function: create_image() -> {ok, Type, Key, Image} | {error, Reason}
+%% Type = "image/png" | "image/jpeg" | "image/gif"
+%% Key = string()
+%% Image = binary()
+%% Reason = atom()
+%%--------------------------------------------------------------------
+create_image() ->
+ %% Six numbers from 1 to 9.
+ Key = string:substr(randoms:get_string(), 1, 6),
+ create_image(Key).
+
+create_image(Key) ->
+ FileName = get_prog_name(),
+ Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])),
+ case cmd(Cmd) of
+ {ok, <<16#89, $P, $N, $G, $\r, $\n, 16#1a, $\n, _/binary>> = Img} ->
+ {ok, "image/png", Key, Img};
+ {ok, <<16#ff, 16#d8, _/binary>> = Img} ->
+ {ok, "image/jpeg", Key, Img};
+ {ok, <<$G, $I, $F, $8, X, $a, _/binary>> = Img} when X==$7; X==$9 ->
+ {ok, "image/gif", Key, Img};
+ {error, Reason} ->
+ ?ERROR_MSG("Failed to process an output from \"~s\": ~p",
+ [Cmd, Reason]),
+ {error, Reason};
+ _ ->
+ Reason = malformed_image,
+ ?ERROR_MSG("Failed to process an output from \"~s\": ~p",
+ [Cmd, Reason]),
+ {error, Reason}
+ end.
+
+get_prog_name() ->
+ case ejabberd_config:get_local_option(captcha_cmd) of
+ FileName when is_list(FileName) ->
+ FileName;
+ _ ->
+ ""
+ end.
+
+get_url(Str) ->
+ case ejabberd_config:get_local_option(captcha_host) of
+ Host when is_list(Host) ->
+ "http://" ++ Host ++ "/captcha/" ++ Str;
+ _ ->
+ "http://" ++ ?MYNAME ++ "/captcha/" ++ Str
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: cmd(Cmd) -> Data | {error, Reason}
+%% Cmd = string()
+%% Data = binary()
+%% Description: os:cmd/1 replacement
+%%--------------------------------------------------------------------
+-define(CMD_TIMEOUT, 5000).
+-define(MAX_FILE_SIZE, 64*1024).
+
+cmd(Cmd) ->
+ Port = open_port({spawn, Cmd}, [stream, eof, binary]),
+ TRef = erlang:start_timer(?CMD_TIMEOUT, self(), timeout),
+ recv_data(Port, TRef, <<>>).
+
+recv_data(Port, TRef, Buf) ->
+ receive
+ {Port, {data, Bytes}} ->
+ NewBuf = <<Buf/binary, Bytes/binary>>,
+ if size(NewBuf) > ?MAX_FILE_SIZE ->
+ return(Port, TRef, {error, efbig});
+ true ->
+ recv_data(Port, TRef, NewBuf)
+ end;
+ {Port, {data, _}} ->
+ return(Port, TRef, {error, efbig});
+ {Port, eof} when Buf /= <<>> ->
+ return(Port, TRef, {ok, Buf});
+ {Port, eof} ->
+ return(Port, TRef, {error, enodata});
+ {timeout, TRef, _} ->
+ return(Port, TRef, {error, timeout})
+ end.
+
+return(Port, TRef, Result) ->
+ case erlang:cancel_timer(TRef) of
+ false ->
+ receive
+ {timeout, TRef, _} ->
+ ok
+ after 0 ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ catch port_close(Port),
+ Result.
diff -urN ejabberd-2.0.4/src/ejabberd_config.erl ejabberd-2.0.4-new/src/ejabberd_config.erl
--- ejabberd-2.0.4/src/ejabberd_config.erl 2009-03-12 09:41:02.000000000 +0100
+++ ejabberd-2.0.4-new/src/ejabberd_config.erl 2009-03-14 11:43:35.000000000 +0100
@@ -164,6 +164,10 @@
add_option(watchdog_admins, Admins, State);
{registration_timeout, Timeout} ->
add_option(registration_timeout, Timeout, State);
+ {captcha_cmd, Cmd} ->
+ add_option(captcha_cmd, Cmd, State);
+ {captcha_host, Host} ->
+ add_option(captcha_host, Host, State);
{loglevel, Loglevel} ->
ejabberd_loglevel:set(Loglevel),
State;
diff -urN ejabberd-2.0.4/src/ejabberd_sup.erl ejabberd-2.0.4-new/src/ejabberd_sup.erl
--- ejabberd-2.0.4/src/ejabberd_sup.erl 2009-03-12 09:41:02.000000000 +0100
+++ ejabberd-2.0.4-new/src/ejabberd_sup.erl 2009-03-14 12:36:43.000000000 +0100
@@ -84,6 +84,13 @@
brutal_kill,
worker,
[ejabberd_local]},
+ Captcha =
+ {ejabberd_captcha,
+ {ejabberd_captcha, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ [ejabberd_captcha]},
Listener =
{ejabberd_listener,
{ejabberd_listener, start_link, []},
@@ -170,6 +177,7 @@
SM,
S2S,
Local,
+ Captcha,
ReceiverSupervisor,
C2SSupervisor,
S2SInSupervisor,
diff -urN ejabberd-2.0.4/src/jlib.hrl ejabberd-2.0.4-new/src/jlib.hrl
--- ejabberd-2.0.4/src/jlib.hrl 2009-03-12 09:41:02.000000000 +0100
+++ ejabberd-2.0.4-new/src/jlib.hrl 2009-03-14 11:41:46.000000000 +0100
@@ -74,6 +74,12 @@
-define(NS_CAPS, "http://jabber.org/protocol/caps").
+%% CAPTCHA related NSes.
+-define(NS_OOB, "jabber:x:oob").
+-define(NS_CAPTCHA, "urn:xmpp:captcha").
+-define(NS_MEDIA, "urn:xmpp:media-element").
+-define(NS_BOB, "urn:xmpp:bob").
+
% TODO: remove "code" attribute (currently it used for backward-compatibility)
-define(STANZA_ERROR(Code, Type, Condition),
{xmlelement, "error",
diff -urN ejabberd-2.0.4/src/mod_muc/mod_muc_room.erl ejabberd-2.0.4-new/src/mod_muc/mod_muc_room.erl
--- ejabberd-2.0.4/src/mod_muc/mod_muc_room.erl 2009-03-12 09:41:02.000000000 +0100
+++ ejabberd-2.0.4-new/src/mod_muc/mod_muc_room.erl 2009-03-14 11:40:40.000000000 +0100
@@ -69,6 +69,7 @@
public_list = true,
persistent = false,
moderated = true,
+ captcha_protected = false,
members_by_default = true,
members_only = false,
allow_user_invites = false,
@@ -98,6 +99,7 @@
jid,
config = #config{},
users = ?DICT:new(),
+ robots = ?DICT:new(),
affiliations = ?DICT:new(),
history = lqueue_new(20),
subject = "",
@@ -382,7 +384,8 @@
(XMLNS == ?NS_MUC_ADMIN) or
(XMLNS == ?NS_MUC_OWNER) or
(XMLNS == ?NS_DISCO_INFO) or
- (XMLNS == ?NS_DISCO_ITEMS) ->
+ (XMLNS == ?NS_DISCO_ITEMS) or
+ (XMLNS == ?NS_CAPTCHA) ->
Res1 = case XMLNS of
?NS_MUC_ADMIN ->
process_iq_admin(From, Type, Lang, SubEl, StateData);
@@ -391,7 +394,9 @@
?NS_DISCO_INFO ->
process_iq_disco_info(From, Type, Lang, StateData);
?NS_DISCO_ITEMS ->
- process_iq_disco_items(From, Type, Lang, StateData)
+ process_iq_disco_items(From, Type, Lang, StateData);
+ ?NS_CAPTCHA ->
+ process_iq_captcha(From, Type, Lang, SubEl, StateData)
end,
{IQRes, NewStateData} =
case Res1 of
@@ -761,6 +766,30 @@
{empty, _} ->
{next_state, StateName, StateData}
end;
+handle_info({captcha_succeed, From}, normal_state, StateData) ->
+ NewState = case ?DICT:find(From, StateData#state.robots) of
+ {ok, {Nick, Packet}} ->
+ Robots = ?DICT:store(From, passed, StateData#state.robots),
+ add_new_user(From, Nick, Packet, StateData#state{robots=Robots});
+ _ ->
+ StateData
+ end,
+ {next_state, normal_state, NewState};
+handle_info({captcha_failed, From}, normal_state, StateData) ->
+ NewState = case ?DICT:find(From, StateData#state.robots) of
+ {ok, {Nick, Packet}} ->
+ Robots = ?DICT:erase(From, StateData#state.robots),
+ Err = jlib:make_error_reply(
+ Packet, ?ERR_NOT_AUTHORIZED),
+ ejabberd_router:route( % TODO: s/Nick/""/
+ jlib:jid_replace_resource(
+ StateData#state.jid, Nick),
+ From, Err),
+ StateData#state{robots=Robots};
+ _ ->
+ StateData
+ end,
+ {next_state, normal_state, NewState};
handle_info(_Info, StateName, StateData) ->
{next_state, StateName, StateData}.
@@ -1461,7 +1490,8 @@
From, Err),
StateData;
{_, _, _, Role} ->
- case check_password(ServiceAffiliation, Els, StateData) of
+ case check_password(ServiceAffiliation, Affiliation,
+ Els, From, StateData) of
true ->
NewState =
add_user_presence(
@@ -1494,7 +1524,8 @@
true ->
NewState#state{just_created = false};
false ->
- NewState
+ Robots = ?DICT:erase(From, StateData#state.robots),
+ NewState#state{robots = Robots}
end;
nopass ->
ErrText = "Password required to enter this room",
@@ -1505,6 +1536,29 @@
StateData#state.jid, Nick),
From, Err),
StateData;
+ captcha_required ->
+ ID = randoms:get_string(),
+ SID = xml:get_attr_s("id", Attrs),
+ RoomJID = StateData#state.jid,
+ To = jlib:jid_replace_resource(RoomJID, Nick),
+ case ejabberd_captcha:create_captcha(
+ ID, SID, RoomJID, To, Lang, From) of
+ {ok, CaptchaEls} ->
+ MsgPkt = {xmlelement, "message", [{"id", ID}], CaptchaEls},
+ Robots = ?DICT:store(From,
+ {Nick, Packet}, StateData#state.robots),
+ ejabberd_router:route(RoomJID, From, MsgPkt),
+ StateData#state{robots = Robots};
+ error ->
+ ErrText = "Unable to generate a captcha",
+ Err = jlib:make_error_reply(
+ Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)),
+ ejabberd_router:route( % TODO: s/Nick/""/
+ jlib:jid_replace_resource(
+ StateData#state.jid, Nick),
+ From, Err),
+ StateData
+ end;
_ ->
ErrText = "Incorrect password",
Err = jlib:make_error_reply(
@@ -1517,13 +1571,13 @@
end
end.
-check_password(owner, _Els, _StateData) ->
+check_password(owner, _Affiliation, _Els, _From, _StateData) ->
%% Don't check pass if user is owner in MUC service (access_admin option)
true;
-check_password(_ServiceAffiliation, Els, StateData) ->
+check_password(_ServiceAffiliation, Affiliation, Els, From, StateData) ->
case (StateData#state.config)#config.password_protected of
false ->
- true;
+ check_captcha(Affiliation, From, StateData);
true ->
Pass = extract_password(Els),
case Pass of
@@ -1539,6 +1593,19 @@
end
end.
+check_captcha(Affiliation, From, StateData) ->
+ case (StateData#state.config)#config.captcha_protected of
+ true when Affiliation == none ->
+ case ?DICT:find(From, StateData#state.robots) of
+ {ok, passed} ->
+ true;
+ _ ->
+ captcha_required
+ end;
+ _ ->
+ true
+ end.
+
extract_password([]) ->
false;
extract_password([{xmlelement, _Name, Attrs, _SubEls} = El | Els]) ->
@@ -2713,6 +2780,9 @@
?BOOLXFIELD("Make room members-only",
"muc#roomconfig_membersonly",
Config#config.members_only),
+ ?BOOLXFIELD("Make room captcha protected",
+ "captcha_protected",
+ Config#config.captcha_protected),
?BOOLXFIELD("Make room moderated",
"muc#roomconfig_moderatedroom",
Config#config.moderated),
@@ -2823,6 +2893,8 @@
?SET_BOOL_XOPT(members_by_default, Val);
set_xoption([{"muc#roomconfig_membersonly", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(members_only, Val);
+set_xoption([{"captcha_protected", [Val]} | Opts], Config) ->
+ ?SET_BOOL_XOPT(captcha_protected, Val);
set_xoption([{"muc#roomconfig_allowinvites", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(allow_user_invites, Val);
set_xoption([{"muc#roomconfig_passwordprotectedroom", [Val]} | Opts], Config) ->
@@ -2913,6 +2985,7 @@
?CASE_CONFIG_OPT(members_only);
?CASE_CONFIG_OPT(allow_user_invites);
?CASE_CONFIG_OPT(password_protected);
+ ?CASE_CONFIG_OPT(captcha_protected);
?CASE_CONFIG_OPT(password);
?CASE_CONFIG_OPT(anonymous);
?CASE_CONFIG_OPT(logging);
@@ -2954,6 +3027,7 @@
?MAKE_CONFIG_OPT(members_only),
?MAKE_CONFIG_OPT(allow_user_invites),
?MAKE_CONFIG_OPT(password_protected),
+ ?MAKE_CONFIG_OPT(captcha_protected),
?MAKE_CONFIG_OPT(password),
?MAKE_CONFIG_OPT(anonymous),
?MAKE_CONFIG_OPT(logging),
@@ -3074,6 +3148,17 @@
{error, ?ERR_FORBIDDEN}
end.
+process_iq_captcha(_From, get, _Lang, _SubEl, _StateData) ->
+ {error, ?ERR_NOT_ALLOWED};
+
+process_iq_captcha(_From, set, _Lang, SubEl, StateData) ->
+ case ejabberd_captcha:process_reply(SubEl) of
+ ok ->
+ {result, [], StateData};
+ _ ->
+ {error, ?ERR_NOT_ACCEPTABLE}
+ end.
+
get_title(StateData) ->
case (StateData#state.config)#config.title of
"" ->
diff -urN ejabberd-2.0.4/src/web/ejabberd_http.erl ejabberd-2.0.4-new/src/web/ejabberd_http.erl
--- ejabberd-2.0.4/src/web/ejabberd_http.erl 2009-03-12 09:41:02.000000000 +0100
+++ ejabberd-2.0.4-new/src/web/ejabberd_http.erl 2009-03-14 10:57:34.000000000 +0100
@@ -106,6 +106,10 @@
{value, {request_handlers, H}} -> H;
false -> []
end ++
+ case lists:member(captcha, Opts) of
+ true -> [{["captcha"], ejabberd_captcha}];
+ false -> []
+ end ++
case lists:member(web_admin, Opts) of
true -> [{["admin"], ejabberd_web_admin}];
false -> []
Binary files ejabberd-2.0.4/tools/.DS_Store and ejabberd-2.0.4-new/tools/.DS_Store differ
diff -urN ejabberd-2.0.4/tools/captcha.sh ejabberd-2.0.4-new/tools/captcha.sh
--- ejabberd-2.0.4/tools/captcha.sh 1970-01-01 01:00:00.000000000 +0100
+++ ejabberd-2.0.4-new/tools/captcha.sh 2009-03-14 11:46:42.000000000 +0100
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+SIGN=$(($RANDOM % 2))
+
+R1=$(($RANDOM % 20))
+R2=$(($RANDOM % 10 + 40))
+
+if [ $SIGN -eq "0" ]; then
+ S1=$(( -1*($RANDOM % 20 + 50) ))
+ S2=$(( $RANDOM % 20 + 50 ))
+else
+ S2=$(( -1*($RANDOM % 20 + 50) ))
+ S1=$(( $RANDOM % 20 + 50 ))
+fi
+
+convert -size 140x60 xc:white \
+ -pointsize 30 -draw "text 20,30 '$1'" \
+ -roll -$R2+$R1 -swirl $S1 \
+ -roll +$R2-$R1 -swirl $S2 \
+ +repage -resize 120x60 \
+ -quality 90 -depth 8 png:-
--- ejabberd-2.0.5/ChangeLog~ 2009-04-01 19:23:52.000000000 +0400
+++ ejabberd-2.0.5/ChangeLog 2009-04-03 23:45:03.174979944 +0400
@@ -15,6 +15,15 @@
stanza (EJAB-300).
* src/ejabberd_c2s.erl: Likewise
+2009-03-13 Evgeniy Khramtsov <ekhramtsov at process-one.net>
+
+ * src/ejabberd_captcha.erl: XEP-158 (CAPTCHA Forms).
+ * src/ejabberd_config.erl: likewise.
+ * src/ejabberd_sup.erl: likewise.
+ * src/jlib.hrl: likewise.
+ * src/web/ejabberd_http.erl: likewise.
+ * src/mod_muc/mod_muc_room.erl: CAPTCHA support.
+
2009-03-10 Badlop <badlop at process-one.net>
* doc/release_notes_2.0.4.txt: Added file for new release
Index: .cvsignore
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-10/.cvsignore,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- .cvsignore 15 Mar 2009 11:36:41 -0000 1.13
+++ .cvsignore 3 Apr 2009 20:13:45 -0000 1.14
@@ -1 +1 @@
-ejabberd-2.0.4.tar.gz
+ejabberd-2.0.5.tar.gz
Index: ejabberd.spec
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-10/ejabberd.spec,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- ejabberd.spec 15 Mar 2009 11:36:41 -0000 1.33
+++ ejabberd.spec 3 Apr 2009 20:13:45 -0000 1.34
@@ -1,5 +1,5 @@
Name: ejabberd
-Version: 2.0.4
+Version: 2.0.5
Release: 1%{?dist}
Summary: A distributed, fault-tolerant Jabber/XMPP server
@@ -12,7 +12,7 @@
Source3: ejabberd.sysconfig
# http://www.ejabberd.im/mod_ctlextra
-# svn export -r 557 https://svn.process-one.net/ejabberd-modules/mod_ctlextra/trunk/src/mod_ctlextra.erl
+# svn export -r 873 https://svn.process-one.net/ejabberd-modules/mod_ctlextra/trunk/src/mod_ctlextra.erl
Source4: mod_ctlextra.erl
# The following were extracted from a patch found on http://realloc.spb.ru/share/ejabberdad.html
@@ -31,6 +31,10 @@
Patch2: ejabberd-ejabberdctl_fix.diff
# Use ejabberd as an example for PAM service name
Patch3: ejabberd-ejabberd_cfg_pam_name.diff
+# CAPTCHA support, see https://support.process-one.net/doc/display/XAAI/Fighting+Multi-User+Chat+SPAM+with+CAPTCHA
+# wget https://support.process-one.net/secure/attachment/13851/XEP-0158_ejabberd-2.0.4.patch -O ejabberd-captcha.patch
+Patch4: ejabberd-captcha.patch
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -113,6 +117,7 @@
%patch1 -p0 -b .fix_paths
%patch2 -p0 -b .fix_user
%patch3 -p0 -b .pam_name
+#%patch4 -p1 -b .captcha
dos2unix src/odbc/mssql.sql
cp %{S:4} src
@@ -172,7 +177,7 @@
%files
%defattr(-,root,root,-)
-%doc COPYING src/odbc/mysql.sql src/odbc/mssql.sql src/odbc/pg.sql
+%doc COPYING src/odbc/mysql.sql src/odbc/mssql.sql src/odbc/pg.sql tools/captcha.sh
%attr(750,ejabberd,ejabberd) %dir %{_sysconfdir}/ejabberd
%attr(640,ejabberd,ejabberd) %config(noreplace) %{_sysconfdir}/ejabberd/ejabberd.cfg
@@ -214,6 +219,14 @@
%endif
%changelog
+* Fri Apr 3 2009 Peter Lemenkov <lemenkov at gmail.com> 2.0.5-1
+- Ver. 2.0.5
+- Temporarily disabled CAPTCHA support
+
+* Sun Mar 15 2009 Peter Lemenkov <lemenkov at gmail.com> 2.0.4-2
+- Support for CAPTCHA (XEP-0158)
+- Updated mod_ctlextra.erl (fixed EJAB-789, EJAB-864)
+
* Sun Mar 15 2009 Peter Lemenkov <lemenkov at gmail.com> 2.0.4-1
- Ver. 2.0.4
Index: import.log
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-10/import.log,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- import.log 15 Mar 2009 11:36:41 -0000 1.8
+++ import.log 3 Apr 2009 20:13:46 -0000 1.9
@@ -6,3 +6,4 @@
ejabberd-2_0_2-3_fc9:HEAD:ejabberd-2.0.2-3.fc9.src.rpm:1222925272
ejabberd-2_0_3-1_fc10:F-10:ejabberd-2.0.3-1.fc10.src.rpm:1232988288
ejabberd-2_0_4-1_fc10:F-10:ejabberd-2.0.4-1.fc10.src.rpm:1237116924
+ejabberd-2_0_5-1_fc10:F-10:ejabberd-2.0.5-1.fc10.src.rpm:1238789573
Index: mod_ctlextra.erl
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-10/mod_ctlextra.erl,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- mod_ctlextra.erl 29 Aug 2008 20:16:17 -0000 1.4
+++ mod_ctlextra.erl 3 Apr 2009 20:13:46 -0000 1.5
@@ -47,14 +47,12 @@
%% ejabberd_auth
{"delete-older-users days", "delete users that have not logged in the last 'days'"},
+ {"delete-older-users-vhost host days", "delete users that not logged in last 'days' in 'host'"},
{"set-password user server password", "set password to user at server"},
%% ejd2odbc
{"export2odbc server output", "export Mnesia tables on server to files on output directory"},
- %% mod_offline
- {"delete-older-messages days", "delete offline messages older than 'days'"},
-
%% mod_shared_roster
{"srg-create group host name description display", "create the group with options"},
{"srg-delete group host", "delete the group"},
@@ -113,15 +111,16 @@
%% Commands global
%%-------------
-ctl_process(_Val, ["delete-older-messages", Days]) ->
- mod_offline:remove_old_messages(list_to_integer(Days)),
- ?STATUS_SUCCESS;
-
ctl_process(_Val, ["delete-older-users", Days]) ->
{removed, N, UR} = delete_older_users(list_to_integer(Days)),
io:format("Deleted ~p users: ~p~n", [N, UR]),
?STATUS_SUCCESS;
+ctl_process(_Val, ["delete-older-users-vhost", Host, Days]) ->
+ {removed, N, UR} = delete_older_users_vhost(Host, list_to_integer(Days)),
+ io:format("Deleted ~p users: ~p~n", [N, UR]),
+ ?STATUS_SUCCESS;
+
ctl_process(_Val, ["export2odbc", Server, Output]) ->
Tables = [
{export_last, last},
@@ -357,7 +356,7 @@
ctl_process(_Val, ["stats", Stat]) ->
Res = case Stat of
"uptime-seconds" -> uptime_seconds();
- "registeredusers" -> mnesia:table_info(passwd, size);
+ "registeredusers" -> length(ejabberd_auth:dirty_get_registered_users());
"onlineusersnode" -> length(ejabberd_sm:dirty_get_my_sessions_list());
"onlineusers" -> length(ejabberd_sm:dirty_get_sessions_list())
end,
@@ -752,6 +751,16 @@
-record(last_activity, {us, timestamp, status}).
delete_older_users(Days) ->
+ %% Get the list of registered users
+ Users = ejabberd_auth:dirty_get_registered_users(),
+ delete_older_users(Days, Users).
+
+delete_older_users_vhost(Host, Days) ->
+ %% Get the list of registered users
+ Users = ejabberd_auth:get_vh_registered_users(Host),
+ delete_older_users(Days, Users).
+
+delete_older_users(Days, Users) ->
%% Convert older time
SecOlder = Days*24*60*60,
@@ -759,9 +768,6 @@
{MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp_now = MegaSecs * 1000000 + Secs,
- %% Get the list of registered users
- Users = ejabberd_auth:dirty_get_registered_users(),
-
%% For a user, remove if required and answer true
F = fun({LUser, LServer}) ->
%% Check if the user is logged
Index: sources
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-10/sources,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- sources 15 Mar 2009 11:36:41 -0000 1.15
+++ sources 3 Apr 2009 20:13:46 -0000 1.16
@@ -1 +1 @@
-1ff37c329e9bc1ddf3c458e051b81d63 ejabberd-2.0.4.tar.gz
+2d85b47df969daf0a78ed3b16562d731 ejabberd-2.0.5.tar.gz
- Previous message: rpms/nemiver/F-9 nemiver.spec,1.15,1.16
- Next message: rpms/ejabberd/F-9 ejabberd-captcha.patch, NONE, 1.1 .cvsignore, 1.12, 1.13 ejabberd.spec, 1.30, 1.31 import.log, 1.6, 1.7 mod_ctlextra.erl, 1.4, 1.5 sources, 1.14, 1.15
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the scm-commits
mailing list