public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Peter Lemenkov <peter@fedoraproject.org>
To: git-commits@fedoraproject.org
Subject: [rpms/ejabberd] f45: Ver. 2.0.5
Date: Wed, 23 Sep 2026 19:06:47 GMT [thread overview]
Message-ID: <179019040730.1.541962217257319369.rpms-ejabberd-b83959148a90@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/ejabberd
Branch : f45
Commit : b83959148a9053fe57327981bbf1cfca742b2c8b
Author : Peter Lemenkov <peter@fedoraproject.org>
Date : 2009-04-03T20:09:33+00:00
Stats : +678/-17 in 6 file(s)
URL : https://src.fedoraproject.org/rpms/ejabberd/c/b83959148a9053fe57327981bbf1cfca742b2c8b?branch=f45
Log:
Ver. 2.0.5
---
diff --git a/.cvsignore b/.cvsignore
index 7a2baca..7182d06 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1 +1 @@
-ejabberd-2.0.4.tar.gz
+ejabberd-2.0.5.tar.gz
diff --git a/ejabberd-captcha.patch b/ejabberd-captcha.patch
new file mode 100644
index 0000000..4e9334b
--- /dev/null
+++ b/ejabberd-captcha.patch
@@ -0,0 +1,641 @@
+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@gmail.com>
++%%% Description : CAPTCHA processing.
++%%%
++%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@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@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@process-one.net>
+
+ * doc/release_notes_2.0.4.txt: Added file for new release
diff --git a/ejabberd.spec b/ejabberd.spec
index 386d8b6..a420d6e 100644
--- a/ejabberd.spec
+++ b/ejabberd.spec
@@ -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 @@ Source2: ejabberd.logrotate
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 @@ Patch1: ejabberd-build.patch
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 @@ fi
%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 @@ rm -rf %{buildroot}
%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 @@ rm -rf %{buildroot}
%endif
%changelog
+* Fri Apr 3 2009 Peter Lemenkov <lemenkov@gmail.com> 2.0.5-1
+- Ver. 2.0.5
+- Temporarily disabled CAPTCHA support
+
+* Sun Mar 15 2009 Peter Lemenkov <lemenkov@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@gmail.com> 2.0.4-1
- Ver. 2.0.4
diff --git a/import.log b/import.log
index bad8533..0f0c5a2 100644
--- a/import.log
+++ b/import.log
@@ -6,3 +6,4 @@ ejabberd-2_0_2-1_fc9:HEAD:ejabberd-2.0.2-1.fc9.src.rpm:1220040866
ejabberd-2_0_2-3_fc9:HEAD:ejabberd-2.0.2-3.fc9.src.rpm:1222925272
ejabberd-2_0_3-1_fc10:HEAD:ejabberd-2.0.3-1.fc10.src.rpm:1232988133
ejabberd-2_0_4-1_fc10:HEAD:ejabberd-2.0.4-1.fc10.src.rpm:1237116778
+ejabberd-2_0_5-1_fc10:HEAD:ejabberd-2.0.5-1.fc10.src.rpm:1238789339
diff --git a/mod_ctlextra.erl b/mod_ctlextra.erl
index 8753057..5c6c6c8 100644
--- a/mod_ctlextra.erl
+++ b/mod_ctlextra.erl
@@ -3,7 +3,7 @@
%%% Author : Badlop <badlop@ono.com>
%%% Purpose : Adds more commands to ejabberd_ctl
%%% Created : 30 Nov 2006 by Badlop <badlop@ono.com>
-%%% Id : $Id: mod_ctlextra.erl 557 2008-04-25 22:01:13Z badlop $
+%%% Id : $Id: mod_ctlextra.erl 873 2009-02-09 18:30:21Z badlop $
%%%----------------------------------------------------------------------
-module(mod_ctlextra).
@@ -47,14 +47,12 @@ commands_global() ->
%% 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@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_host() ->
%% 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, ["load-config", Path]) ->
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 @@ update_vcard_els(Data, Content, Els1) ->
-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 @@ delete_older_users(Days) ->
{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
diff --git a/sources b/sources
index 26b2103..77e1427 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-1ff37c329e9bc1ddf3c458e051b81d63 ejabberd-2.0.4.tar.gz
+2d85b47df969daf0a78ed3b16562d731 ejabberd-2.0.5.tar.gz
reply other threads:[~2026-09-23 19:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=179019040730.1.541962217257319369.rpms-ejabberd-b83959148a90@fedoraproject.org \
--to=peter@fedoraproject.org \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox