public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/ejabberd] f45: Ver. 2.1.0
@ 2026-09-23 19:06 Peter Lemenkov
  0 siblings, 0 replies; only message in thread
From: Peter Lemenkov @ 2026-09-23 19:06 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/ejabberd
Branch : f45
Commit : 63ecd49025a9416f9d058ca62ef9e31b816691fe
Author : Peter Lemenkov <peter@fedoraproject.org>
Date   : 2009-11-21T08:01:19+00:00
Stats  : +166/-1597 in 13 file(s)
URL    : https://src.fedoraproject.org/rpms/ejabberd/c/63ecd49025a9416f9d058ca62ef9e31b816691fe?branch=f45

Log:
Ver. 2.1.0

---
diff --git a/.cvsignore b/.cvsignore
index 7182d06..1a0dda1 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1 +1 @@
-ejabberd-2.0.5.tar.gz
+ejabberd-2.1.0.tar.gz

diff --git a/ejabberd-build.patch b/ejabberd-build.patch
deleted file mode 100644
index f0e02dd..0000000
--- a/ejabberd-build.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- src/Makefile.in.fix_paths	2008-08-01 16:34:28.000000000 +0400
-+++ src/Makefile.in	2008-08-09 19:54:03.000000000 +0400
-@@ -58,7 +58,7 @@
- 
- DESTDIR =
- 
--EJABBERDDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
-+EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd
- BEAMDIR = $(EJABBERDDIR)/ebin
- SPOOLDIR = $(EJABBERDDIR)/db
- PRIVDIR = $(EJABBERDDIR)/priv

diff --git a/ejabberd-captcha.patch b/ejabberd-captcha.patch
deleted file mode 100644
index 4e9334b..0000000
--- a/ejabberd-captcha.patch
+++ /dev/null
@@ -1,641 +0,0 @@
-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-decrease_buffers_in_mod_proxy65.patch b/ejabberd-decrease_buffers_in_mod_proxy65.patch
deleted file mode 100644
index 2bcb135..0000000
--- a/ejabberd-decrease_buffers_in_mod_proxy65.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-Patch by Evgeniy Khramtsov decreases proxy65 buffer sizes (size 65535 is known
-to confuse users with tight shapers).
-
-Index: src/mod_proxy65/mod_proxy65_stream.erl
-===================================================================
---- src/mod_proxy65/mod_proxy65_stream.erl	2009-04-01 17:23:51.000000000 +0200
-+++ src/mod_proxy65/mod_proxy65_stream.erl	2009-04-05 22:51:20.000000000 +0200
-@@ -89,8 +89,8 @@
-     process_flag(trap_exit, true),
-     AuthType = gen_mod:get_opt(auth_type, Opts, anonymous),
-     Shaper = gen_mod:get_opt(shaper, Opts, none),
--    RecvBuf = gen_mod:get_opt(recbuf, Opts, 65535),
--    SendBuf = gen_mod:get_opt(sndbuf, Opts, 65535),
-+    RecvBuf = gen_mod:get_opt(recbuf, Opts, 8192),
-+    SendBuf = gen_mod:get_opt(sndbuf, Opts, 8192),
-     TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop),
-     inet:setopts(Socket, [{active, true}, {recbuf, RecvBuf}, {sndbuf, SendBuf}]),
-     {ok, wait_for_init, #state{host      = Host,

diff --git a/ejabberd-dynamic_compile_loglevel.patch b/ejabberd-dynamic_compile_loglevel.patch
deleted file mode 100644
index 62083a0..0000000
--- a/ejabberd-dynamic_compile_loglevel.patch
+++ /dev/null
@@ -1,768 +0,0 @@
---- /dev/null	1994-03-08 01:27:08.504001460 +0300
-+++ src/dynamic_compile.erl	2009-11-05 16:25:27.647417513 +0300
-@@ -0,0 +1,269 @@
-+%% Copyright (c) 2007
-+%%          Mats Cronqvist <mats.cronqvist@ericsson.com>
-+%%          Chris Newcombe <chris.newcombe@gmail.com> 
-+%%          Jacob Vorreuter <jacob.vorreuter@gmail.com>
-+%% 
-+%% Permission is hereby granted, free of charge, to any person
-+%% obtaining a copy of this software and associated documentation
-+%% files (the "Software"), to deal in the Software without
-+%% restriction, including without limitation the rights to use,
-+%% copy, modify, merge, publish, distribute, sublicense, and/or sell
-+%% copies of the Software, and to permit persons to whom the
-+%% Software is furnished to do so, subject to the following
-+%% conditions:
-+%% 
-+%% The above copyright notice and this permission notice shall be
-+%% included in all copies or substantial portions of the Software.
-+%% 
-+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-+%% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+%% OTHER DEALINGS IN THE SOFTWARE.
-+
-+%%%-------------------------------------------------------------------
-+%%% File : dynamic_compile.erl
-+%%% Description :
-+%%% Authors : Mats Cronqvist <mats.cronqvist@ericsson.com>
-+%%%           Chris Newcombe <chris.newcombe@gmail.com> 
-+%%%           Jacob Vorreuter <jacob.vorreuter@gmail.com>
-+%%% TODO :
-+%%% - add support for limit include-file depth (and prevent circular references)
-+%%%   prevent circular macro expansion set FILE correctly when -module() is found
-+%%% -include_lib support $ENVVAR in include filenames
-+%%%  substitute-stringize (??MACRO)
-+%%% -undef/-ifdef/-ifndef/-else/-endif
-+%%% -file(File, Line)
-+%%%-------------------------------------------------------------------
-+-module(dynamic_compile).
-+
-+%% API
-+-export([from_string/1, from_string/2]).
-+
-+-import(lists, [reverse/1, keyreplace/4]).
-+
-+%%====================================================================
-+%% API
-+%%====================================================================
-+%%--------------------------------------------------------------------
-+%% Function:
-+%% Description:
-+%%   Returns a binary that can be used with
-+%%           code:load_binary(Module, ModuleFilenameForInternalRecords, Binary).
-+%%--------------------------------------------------------------------
-+from_string(CodeStr) ->
-+    from_string(CodeStr, []).
-+
-+% takes Options as for compile:forms/2
-+from_string(CodeStr, CompileFormsOptions) ->
-+    %% Initialise the macro dictionary with the default predefined macros,
-+    %% (adapted from epp.erl:predef_macros/1
-+    Filename = "compiled_from_string",
-+    %%Machine  = list_to_atom(erlang:system_info(machine)),
-+    Ms0    = dict:new(),
-+    % Ms1    = dict:store('FILE',          {[], "compiled_from_string"}, Ms0),
-+    % Ms2    = dict:store('LINE',          {[], 1}, Ms1),  % actually we might add special code for this
-+    % Ms3    = dict:store('MODULE',        {[], undefined},              Ms2),
-+    % Ms4    = dict:store('MODULE_STRING', {[], undefined},              Ms3),
-+    % Ms5    = dict:store('MACHINE',       {[], Machine},                Ms4),
-+    % InitMD = dict:store(Machine,         {[], true},                   Ms5),
-+    InitMD = Ms0,
-+
-+    %% From the docs for compile:forms:
-+    %%    When encountering an -include or -include_dir directive, the compiler searches for header files in the following directories:
-+    %%      1. ".", the current working directory of the file server;
-+    %%      2. the base name of the compiled file;
-+    %%      3. the directories specified using the i option. The directory specified last is searched first.
-+    %% In this case, #2 is meaningless.
-+    IncludeSearchPath = ["." | reverse([Dir || {i, Dir} <- CompileFormsOptions])],
-+    {RevForms, _OutMacroDict} = scan_and_parse(CodeStr, Filename, 1, [], InitMD, IncludeSearchPath),
-+    Forms = reverse(RevForms),
-+
-+    %% note: 'binary' is forced as an implicit option, whether it is provided or not.
-+    case compile:forms(Forms, CompileFormsOptions) of
-+        {ok, ModuleName, CompiledCodeBinary} when is_binary(CompiledCodeBinary) ->
-+            {ModuleName, CompiledCodeBinary};
-+        {ok, ModuleName, CompiledCodeBinary, []} when is_binary(CompiledCodeBinary) ->  % empty warnings list
-+            {ModuleName, CompiledCodeBinary};
-+        {ok, _ModuleName, _CompiledCodeBinary, Warnings} ->
-+            throw({?MODULE, warnings, Warnings});
-+        Other ->
-+            throw({?MODULE, compile_forms, Other})
-+    end.
-+
-+%%====================================================================
-+%% Internal functions
-+%%====================================================================
-+%%% Code from Mats Cronqvist
-+%%% See http://www.erlang.org/pipermail/erlang-questions/2007-March/025507.html
-+%%%## 'scan_and_parse'
-+%%%
-+%%% basically we call the OTP scanner and parser (erl_scan and
-+%%% erl_parse) line-by-line, but check each scanned line for (or
-+%%% definitions of) macros before parsing.
-+%% returns {ReverseForms, FinalMacroDict}
-+scan_and_parse([], _CurrFilename, _CurrLine, RevForms, MacroDict, _IncludeSearchPath) ->
-+    {RevForms, MacroDict};
-+
-+scan_and_parse(RemainingText, CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath) ->
-+    case scanner(RemainingText, CurrLine, MacroDict) of
-+	    {tokens, NLine, NRemainingText, Toks} ->
-+	        {ok, Form} = erl_parse:parse_form(Toks),
-+	        scan_and_parse(NRemainingText, CurrFilename, NLine, [Form | RevForms], MacroDict, IncludeSearchPath);
-+	    {macro, NLine, NRemainingText, NMacroDict} ->
-+	        scan_and_parse(NRemainingText, CurrFilename, NLine, RevForms,NMacroDict, IncludeSearchPath);
-+        {include, NLine, NRemainingText, IncludeFilename} ->
-+            IncludeFileRemainingTextents = read_include_file(IncludeFilename, IncludeSearchPath),
-+            %%io:format("include file ~p contents: ~n~p~nRemainingText = ~p~n", [IncludeFilename,IncludeFileRemainingTextents, RemainingText]),
-+            %% Modify the FILE macro to reflect the filename
-+            %%IncludeMacroDict = dict:store('FILE', {[],IncludeFilename}, MacroDict),
-+            IncludeMacroDict = MacroDict,
-+
-+            %% Process the header file (inc. any nested header files)
-+            {RevIncludeForms, IncludedMacroDict} = scan_and_parse(IncludeFileRemainingTextents, IncludeFilename, 1, [], IncludeMacroDict, IncludeSearchPath),
-+            %io:format("include file results = ~p~n", [R]),
-+            %% Restore the FILE macro in the NEW MacroDict (so we keep any macros defined in the header file)
-+            %%NMacroDict = dict:store('FILE', {[],CurrFilename}, IncludedMacroDict),
-+            NMacroDict = IncludedMacroDict,
-+
-+            %% Continue with the original file
-+	        scan_and_parse(NRemainingText, CurrFilename, NLine, RevIncludeForms ++ RevForms, NMacroDict, IncludeSearchPath);
-+        done ->
-+	        scan_and_parse([], CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath)
-+    end.
-+
-+scanner(Text, Line, MacroDict) ->
-+    case erl_scan:tokens([],Text,Line) of
-+        {done, {ok,Toks,NLine}, LeftOverChars} ->
-+            case pre_proc(Toks, MacroDict) of
-+                {tokens,  NToks}      -> {tokens,  NLine, LeftOverChars, NToks};
-+                {macro,   NMacroDict} -> {macro,   NLine, LeftOverChars, NMacroDict};
-+                {include, Filename}   -> {include, NLine, LeftOverChars, Filename}
-+            end;
-+        {more, _Continuation} ->
-+            %% This is supposed to mean "term is not yet complete" (i.e. a '.' has
-+            %% not been reached yet).
-+            %% However, for some bizarre reason we also get this if there is a comment after the final '.' in a file.
-+            %% So we check to see if Text only consists of comments.
-+            case is_only_comments(Text) of
-+                true  ->
-+                    done;
-+                false ->
-+                    throw({incomplete_term, Text, Line})
-+            end
-+    end.
-+
-+is_only_comments(Text) -> is_only_comments(Text, not_in_comment).
-+
-+is_only_comments([],       _)              -> true;
-+is_only_comments([$   |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
-+is_only_comments([$\t |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
-+is_only_comments([$\n |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
-+is_only_comments([$%  |T], not_in_comment) -> is_only_comments(T, in_comment);     % found start of a comment
-+is_only_comments(_,        not_in_comment) -> false;
-+% found any significant char NOT in a comment
-+is_only_comments([$\n |T], in_comment)     -> is_only_comments(T, not_in_comment); % found end of a comment
-+is_only_comments([_   |T], in_comment)     -> is_only_comments(T, in_comment).     % skipping over in-comment chars
-+
-+%%%## 'pre-proc'
-+%%%
-+%%% have to implement a subset of the pre-processor, since epp insists
-+%%% on running on a file.
-+%%% only handles 2 cases;
-+%% -define(MACRO, something).
-+%% -define(MACRO(VAR1,VARN),{stuff,VAR1,more,stuff,VARN,extra,stuff}).
-+pre_proc([{'-',_},{atom,_,define},{'(',_},{_,_,Name}|DefToks],MacroDict) ->
-+    false = dict:is_key(Name, MacroDict),
-+    case DefToks of
-+    	[{',',_} | Macro] ->
-+    	    {macro, dict:store(Name, {[], macro_body_def(Macro, [])},  MacroDict)};
-+    	[{'(',_} | Macro] ->
-+    	    {macro, dict:store(Name, macro_params_body_def(Macro, []), MacroDict)}
-+    end;
-+
-+pre_proc([{'-',_}, {atom,_,include}, {'(',_}, {string,_,Filename}, {')',_}, {dot,_}], _MacroDict) ->
-+    {include, Filename};
-+
-+pre_proc(Toks,MacroDict) ->
-+    {tokens, subst_macros(Toks, MacroDict)}.
-+
-+macro_params_body_def([{')',_},{',',_} | Toks], RevParams) ->
-+    {reverse(RevParams), macro_body_def(Toks, [])};
-+macro_params_body_def([{var,_,Param} | Toks], RevParams) ->
-+    macro_params_body_def(Toks, [Param | RevParams]);
-+macro_params_body_def([{',',_}, {var,_,Param} | Toks], RevParams) ->
-+    macro_params_body_def(Toks, [Param | RevParams]).
-+
-+macro_body_def([{')',_}, {dot,_}], RevMacroBodyToks) ->
-+    reverse(RevMacroBodyToks);
-+macro_body_def([Tok|Toks], RevMacroBodyToks) ->
-+    macro_body_def(Toks, [Tok | RevMacroBodyToks]).
-+
-+subst_macros(Toks, MacroDict) ->
-+    reverse(subst_macros_rev(Toks, MacroDict, [])).
-+
-+%% returns a reversed list of tokes
-+subst_macros_rev([{'?',_}, {_,LineNum,'LINE'} | Toks], MacroDict, RevOutToks) ->
-+    %% special-case for ?LINE, to avoid creating a new MacroDict for every line in the source file
-+    subst_macros_rev(Toks, MacroDict, [{integer,LineNum,LineNum}] ++ RevOutToks);
-+
-+subst_macros_rev([{'?',_}, {_,_,Name}, {'(',_} = Paren | Toks], MacroDict, RevOutToks) ->
-+    case dict:fetch(Name, MacroDict) of
-+        {[], MacroValue} ->
-+            %% This macro does not have any vars, so ignore the fact that the invocation is followed by "(...stuff"
-+            %% Recursively expand any macro calls inside this macro's value
-+            %% TODO: avoid infinite expansion due to circular references (even indirect ones)
-+            RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
-+            subst_macros_rev([Paren|Toks], MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
-+        ParamsAndBody ->
-+            %% This macro does have vars.
-+            %% Collect all of the passe arguments, in an ordered list
-+            {NToks, Arguments} = subst_macros_get_args(Toks, []),
-+            %% Expand the varibles
-+            ExpandedParamsToks = subst_macros_subst_args_for_vars(ParamsAndBody, Arguments),
-+            %% Recursively expand any macro calls inside this macro's value
-+            %% TODO: avoid infinite expansion due to circular references (even indirect ones)
-+            RevExpandedOtherMacrosToks = subst_macros_rev(ExpandedParamsToks, MacroDict, []),
-+            subst_macros_rev(NToks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks)
-+    end;
-+
-+subst_macros_rev([{'?',_}, {_,_,Name} | Toks], MacroDict, RevOutToks) ->
-+    %% This macro invocation does not have arguments.
-+    %% Therefore the definition should not have parameters
-+    {[], MacroValue} = dict:fetch(Name, MacroDict),
-+
-+    %% Recursively expand any macro calls inside this macro's value
-+    %% TODO: avoid infinite expansion due to circular references (even indirect ones)
-+    RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
-+    subst_macros_rev(Toks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
-+
-+subst_macros_rev([Tok|Toks], MacroDict,  RevOutToks) ->
-+subst_macros_rev(Toks, MacroDict, [Tok|RevOutToks]);
-+subst_macros_rev([], _MacroDict, RevOutToks) -> RevOutToks.
-+
-+subst_macros_get_args([{')',_} | Toks], RevArgs) ->
-+    {Toks, reverse(RevArgs)};
-+subst_macros_get_args([{',',_}, {var,_,ArgName} | Toks], RevArgs) ->
-+    subst_macros_get_args(Toks, [ArgName| RevArgs]);
-+subst_macros_get_args([{var,_,ArgName} | Toks], RevArgs) ->
-+    subst_macros_get_args(Toks, [ArgName | RevArgs]).
-+
-+subst_macros_subst_args_for_vars({[], BodyToks}, []) ->
-+    BodyToks;
-+subst_macros_subst_args_for_vars({[Param | Params], BodyToks}, [Arg|Args]) ->
-+    NBodyToks = keyreplace(Param, 3, BodyToks, {var,1,Arg}),
-+    subst_macros_subst_args_for_vars({Params, NBodyToks}, Args).
-+
-+read_include_file(Filename, IncludeSearchPath) ->
-+    case file:path_open(IncludeSearchPath, Filename, [read, raw, binary]) of
-+        {ok, IoDevice, FullName} ->
-+            {ok, Data} = file:read(IoDevice, filelib:file_size(FullName)),
-+            file:close(IoDevice),
-+            binary_to_list(Data);
-+        {error, Reason} ->
-+            throw({failed_to_read_include_file, Reason, Filename, IncludeSearchPath})
-+    end.
-+
---- src/ejabberd.app	2009-04-01 19:23:51.000000000 +0400
-+++ src/ejabberd.app	2009-11-05 16:27:10.081417222 +0300
-@@ -115,7 +115,6 @@
- 	     nodetree_virtual,
- 	     p1_fsm,
- 	     p1_mnesia,
--	     ram_file_io_server,
- 	     randoms,
- 	     sha,
- 	     shaper,
---- src/ejabberd_loglevel.erl	2009-04-01 19:23:52.000000000 +0400
-+++ src/ejabberd_loglevel.erl	2009-11-05 16:27:47.816415376 +0300
-@@ -38,51 +38,30 @@
- -define(LOGMODULE, "error_logger").
- 
- %% Error levels:
--%% 0 -> No log
--%% 1 -> Critical
--%% 2 -> Error
--%% 3 -> Warning
--%% 4 -> Info
--%% 5 -> Debug
-+-define(LOG_LEVELS,[ {0, no_log, "No log"}
-+                    ,{1, critical, "Critical"}
-+                    ,{2, error, "Error"}
-+                    ,{3, warning, "Warning"}
-+                    ,{4, info, "Info"}
-+                    ,{5, debug, "Debug"}
-+                    ]).
-+
-+set(LogLevel) when is_atom(LogLevel) ->
-+    set(level_to_integer(LogLevel));
- set(Loglevel) when is_integer(Loglevel) ->
--   Forms = compile_string(?LOGMODULE, ejabberd_logger_src(Loglevel)),
--   load_logger(Forms, ?LOGMODULE, Loglevel);
-+    try
-+        {Mod,Code} = dynamic_compile:from_string(ejabberd_logger_src(Loglevel)),
-+        code:load_binary(Mod, ?LOGMODULE ++ ".erl", Code)
-+    catch
-+        Type:Error -> ?CRITICAL_MSG("Error compiling logger (~p): ~p~n", [Type, Error])
-+    end;
- set(_) ->
-     exit("Loglevel must be an integer").
--                
--%% --------------------------------------------------------------  
--%% Compile a string into a module and returns the binary
--compile_string(Mod, Str) ->
--    Fname = Mod ++ ".erl",
--    {ok, Fd} = open_ram_file(Fname),
--    file:write(Fd, Str),
--    file:position(Fd, 0),
--    case epp_dodger:parse(Fd) of
--	{ok, Tree} ->
--	    Forms = revert_tree(Tree),
--	    close_ram_file(Fd),
--	    Forms;
--	Error ->
--	    close_ram_file(Fd),
--	    Error
--    end.
--   
--open_ram_file(Fname) ->
--    ram_file_io_server:start(self(), Fname, [read,write]).
--
--close_ram_file(Fd) ->
--    file:close(Fd).
--
--revert_tree(Tree) ->
--    [erl_syntax:revert(T) || T <- Tree].
--
--load_logger(Forms, Mod, Loglevel) ->
--    Fname = Mod ++ ".erl",
--    case compile:forms(Forms, [binary, {d,'LOGLEVEL',Loglevel}]) of
--        {ok, M, Bin} ->
--            code:load_binary(M, Fname, Bin);
--        Error ->
--            ?CRITICAL_MSG("Error ~p~n", [Error])
-+
-+level_to_integer(Level) ->
-+    case lists:keyfind(Level, 2, ?LOG_LEVELS) of
-+        {Int, Level, _Desc} -> Int;
-+        _ -> erlang:error({no_such_loglevel, Level})
-     end.
- 
- %% --------------------------------------------------------------
---- src/ram_file_io_server.erl	2009-04-01 19:23:51.000000000 +0400
-+++ /dev/null	1994-03-08 01:27:08.504001460 +0300
-@@ -1,408 +0,0 @@
--%% ``The contents of this file are subject to the Erlang Public License,
--%% Version 1.1, (the "License"); you may not use this file except in
--%% compliance with the License. You should have received a copy of the
--%% Erlang Public License along with this software. If not, it can be
--%% retrieved via the world wide web at http://www.erlang.org/.
--%% 
--%% Software distributed under the License is distributed on an "AS IS"
--%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
--%% the License for the specific language governing rights and limitations
--%% under the License.
--%% 
--%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
--%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
--%% AB. All Rights Reserved.''
--%% 
--%%     $Id: ram_file_io_server.erl 970 2007-11-15 10:33:18Z mremond $
--%% 
--%% This file is mostly copied from Erlang file_io_server.erl
--%% See: http://www.erlang.org/ml-archive/erlang-questions/200607/msg00080.html
--%% for details on ram_file_io_server.erl (Erlang OTP R11B-2)
---module(ram_file_io_server).
--
--%% A simple file server for io to one file instance per server instance.
--
---export([format_error/1]).
---export([start/3, start_link/3]).
--
---record(state, {handle,owner,mref,buf,read_mode}).
--
---define(PRIM_FILE, ram_file).
---define(READ_SIZE_LIST, 128).
---define(READ_SIZE_BINARY, (8*1024)).
--
---define(eat_message(M, T), receive M -> M after T -> timeout end).
--
--%%%-----------------------------------------------------------------
--%%% Exported functions
--
--format_error({_Line, ?MODULE, Reason}) ->
--    io_lib:format("~w", [Reason]);
--format_error({_Line, Mod, Reason}) ->
--    Mod:format_error(Reason);
--format_error(ErrorId) ->
--    erl_posix_msg:message(ErrorId).
--
--start(Owner, FileName, ModeList) 
--  when pid(Owner), list(FileName), list(ModeList) ->
--    do_start(spawn, Owner, FileName, ModeList).
--
--start_link(Owner, FileName, ModeList) 
--  when pid(Owner), list(FileName), list(ModeList) ->
--    do_start(spawn_link, Owner, FileName, ModeList).
--
--%%%-----------------------------------------------------------------
--%%% Server starter, dispatcher and helpers
--
--do_start(Spawn, Owner, FileName, ModeList) ->
--    Self = self(),
--    Ref = make_ref(),
--    Pid = 
--	erlang:Spawn(
--	  fun() ->
--		  %% process_flag(trap_exit, true),
--		  {ReadMode,Opts} = 
--		      case lists:member(binary, ModeList) of
--			  true ->
--			      {binary,ModeList};
--			  false ->
--			      {list,[binary|ModeList]}
--		      end,
--		  case ?PRIM_FILE:open(FileName, Opts) of
--		      {error, Reason} = Error ->
--			  Self ! {Ref, Error},
--			  exit(Reason);
--		      {ok, Handle} ->
--			  %% XXX must I handle R6 nodes here?
--			  M = erlang:monitor(process, Owner),
--			  Self ! {Ref, ok},
--			  server_loop(
--			    #state{handle    = Handle,
--				   owner     = Owner, 
--				   mref      = M, 
--				   buf       = <<>>,
--				   read_mode = ReadMode})
--		  end
--	  end),
--    Mref = erlang:monitor(process, Pid),
--    receive
--	{Ref, {error, _Reason} = Error} ->
--	    erlang:demonitor(Mref),
--	    receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end,
--	    Error;
--	{Ref, ok} ->
--	    erlang:demonitor(Mref),
--	    receive
--		{'DOWN', Mref, _, _, Reason} ->
--		    {error, Reason}
--	    after 0 ->
--		    {ok, Pid}
--	    end;
--	{'DOWN', Mref, _, _, Reason} ->
--	    {error, Reason}
--    end.
--
--server_loop(#state{mref = Mref} = State) ->
--    receive
--	{file_request, From, ReplyAs, Request} when pid(From) ->
--	    case file_request(Request, State) of
--		{reply, Reply, NewState} ->
--		    file_reply(From, ReplyAs, Reply),
--		    server_loop(NewState);
--		{error, Reply, NewState} ->
--		    %% error is the same as reply, except that
--		    %% it breaks the io_request_loop further down
--		    file_reply(From, ReplyAs, Reply),
--		    server_loop(NewState);
--		{stop, Reason, Reply, _NewState} ->
--		    file_reply(From, ReplyAs, Reply),
--		    exit(Reason)
--	    end;
--	{io_request, From, ReplyAs, Request} when pid(From) ->
--	    case io_request(Request, State) of
--		{reply, Reply, NewState} ->
--		    io_reply(From, ReplyAs, Reply),
--		    server_loop(NewState);
--		{error, Reply, NewState} ->
--		    %% error is the same as reply, except that
--		    %% it breaks the io_request_loop further down
--		    io_reply(From, ReplyAs, Reply),
--		    server_loop(NewState);
--		{stop, Reason, Reply, _NewState} ->
--		    io_reply(From, ReplyAs, Reply),
--		    exit(Reason)
--	    end;
--	{'DOWN', Mref, _, _, Reason} ->
--	    exit(Reason);
--	_ ->
--	    server_loop(State)
--    end.
--
--file_reply(From, ReplyAs, Reply) ->
--    From ! {file_reply, ReplyAs, Reply}.
--
--io_reply(From, ReplyAs, Reply) ->
--    From ! {io_reply, ReplyAs, Reply}.
--
--%%%-----------------------------------------------------------------
--%%% file requests
--
--file_request({pread,At,Sz}, 
--	     #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) ->
--    case position(Handle, At, Buf) of
--	{ok,_Offs} ->
--	    case ?PRIM_FILE:read(Handle, Sz) of
--		{ok,Bin} when ReadMode==list ->
--		    std_reply({ok,binary_to_list(Bin)}, State);
--		Reply ->
--		    std_reply(Reply, State)
--	    end;
--	Reply ->
--	    std_reply(Reply, State)
--    end;
--file_request({pwrite,At,Data}, 
--	     #state{handle=Handle,buf=Buf}=State) ->
--    case position(Handle, At, Buf) of
--	{ok,_Offs} ->
--	    std_reply(?PRIM_FILE:write(Handle, Data), State);
--	Reply ->
--	    std_reply(Reply, State)
--    end;
--file_request(sync, 
--	     #state{handle=Handle}=State) ->
--    case ?PRIM_FILE:sync(Handle) of
--	{error,_}=Reply ->
--	    {stop,normal,Reply,State};
--	Reply ->
--	    {reply,Reply,State}
--    end;
--file_request(close, 
--	     #state{handle=Handle}=State) ->
--    {stop,normal,?PRIM_FILE:close(Handle),State#state{buf= <<>>}};
--file_request({position,At}, 
--	     #state{handle=Handle,buf=Buf}=State) ->
--    std_reply(position(Handle, At, Buf), State);
--file_request(truncate, 
--	     #state{handle=Handle}=State) ->
--    case ?PRIM_FILE:truncate(Handle) of
--	{error,_Reason}=Reply ->
--	    {stop,normal,Reply,State#state{buf= <<>>}};
--	Reply ->
--	    {reply,Reply,State}
--    end;
--file_request(Unknown, 
--	     #state{}=State) ->
--    Reason = {request, Unknown},
--    {error,{error,Reason},State}.
--
--std_reply({error,_}=Reply, State) ->
--    {error,Reply,State#state{buf= <<>>}};
--std_reply(Reply, State) ->
--    {reply,Reply,State#state{buf= <<>>}}.
--
--%%%-----------------------------------------------------------------
--%%% I/O request 
--
--io_request({put_chars,Chars}, % binary(Chars) new in R9C
--	   #state{buf= <<>>}=State) ->
--    put_chars(Chars, State);
--io_request({put_chars,Chars}, % binary(Chars) new in R9C
--	   #state{handle=Handle,buf=Buf}=State) ->
--    case position(Handle, cur, Buf) of
--	{error,_}=Reply ->
--	    {stop,normal,Reply,State#state{buf= <<>>}};
--	_ ->
--	    put_chars(Chars, State#state{buf= <<>>})
--    end;
--io_request({put_chars,Mod,Func,Args}, 
--	   #state{}=State) ->
--    case catch apply(Mod, Func, Args) of
--	Chars when list(Chars); binary(Chars) ->
--	    io_request({put_chars,Chars}, State);
--	_ ->
--	    {error,{error,Func},State}
--    end;
--io_request({get_until,_Prompt,Mod,Func,XtraArgs}, 
--	   #state{}=State) ->
--    get_chars(io_lib, get_until, {Mod, Func, XtraArgs}, State);
--io_request({get_chars,_Prompt,N}, % New in R9C
--	   #state{}=State) ->
--    get_chars(N, State);
--io_request({get_chars,_Prompt,Mod,Func,XtraArg}, % New in R9C
--	   #state{}=State) ->
--    get_chars(Mod, Func, XtraArg, State);
--io_request({get_line,_Prompt}, % New in R9C
--	   #state{}=State) ->
--    get_chars(io_lib, collect_line, [], State);
--io_request({setopts, Opts}, % New in R9C
--	   #state{}=State) when list(Opts) ->
--    setopts(Opts, State);
--io_request({requests,Requests}, 
--	   #state{}=State) when list(Requests) ->
--    io_request_loop(Requests, {reply,ok,State});
--io_request(Unknown, 
--	   #state{}=State) ->
--    Reason = {request,Unknown},
--    {error,{error,Reason},State}.
--
--
--
--%% Process a list of requests as long as the results are ok.
--
--io_request_loop([], Result) ->
--    Result;
--io_request_loop([_Request|_Tail], 
--		{stop,_Reason,_Reply,_State}=Result) ->
--    Result;
--io_request_loop([_Request|_Tail],
--		{error,_Reply,_State}=Result) ->
--    Result;
--io_request_loop([Request|Tail], 
--		{reply,_Reply,State}) ->
--    io_request_loop(Tail, io_request(Request, State)).
--
--
--
--%% I/O request put_chars
--%%
--put_chars(Chars, #state{handle=Handle}=State) ->
--    case ?PRIM_FILE:write(Handle, Chars) of
--	{error,_}=Reply ->
--	    {stop,normal,Reply,State};
--	Reply ->
--	    {reply,Reply,State}
--    end.
--
--
--%% Process the I/O request get_chars
--%%
--get_chars(0, #state{read_mode=ReadMode}=State) ->
--    {reply,cast(<<>>, ReadMode),State};
--get_chars(N, #state{buf=Buf,read_mode=ReadMode}=State) 
--  when integer(N), N > 0, N =< size(Buf) ->
--    {B1,B2} = split_binary(Buf, N),
--    {reply,cast(B1, ReadMode),State#state{buf=B2}};
--get_chars(N, #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) 
--  when integer(N), N > 0 ->
--    BufSize = size(Buf),
--    NeedSize = N-BufSize,
--    Size = max(NeedSize, ?READ_SIZE_BINARY),
--    case ?PRIM_FILE:read(Handle, Size) of
--	{ok, B} ->
--	    if BufSize+size(B) < N ->
--		    std_reply(cat(Buf, B, ReadMode), State);
--	       true ->
--		    {B1,B2} = split_binary(B, NeedSize),
--		    {reply,cat(Buf, B1, ReadMode),State#state{buf=B2}}
--	    end;
--	eof when BufSize==0 ->
--	    {reply,eof,State};
--	eof ->
--	    std_reply(cast(Buf, ReadMode), State);
--	{error,Reason}=Error ->
--	    {stop,Reason,Error,State#state{buf= <<>>}}
--    end;
--get_chars(_N, #state{}=State) ->
--    {error,{error,get_chars},State}.
--
--get_chars(Mod, Func, XtraArg, #state{buf= <<>>}=State) ->
--    get_chars_empty(Mod, Func, XtraArg, start, State);
--get_chars(Mod, Func, XtraArg, #state{buf=Buf}=State) ->
--    get_chars_apply(Mod, Func, XtraArg, start, State#state{buf= <<>>}, Buf).
--
--get_chars_empty(Mod, Func, XtraArg, S, 
--		#state{handle=Handle,read_mode=ReadMode}=State) ->
--    case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of
--	{ok,Bin} ->
--	    get_chars_apply(Mod, Func, XtraArg, S, State, Bin);
--	eof ->
--	    get_chars_apply(Mod, Func, XtraArg, S, State, eof);
--	{error,Reason}=Error ->
--	    {stop,Reason,Error,State}
--    end.
--
--get_chars_apply(Mod, Func, XtraArg, S0, 
--		#state{read_mode=ReadMode}=State, Data0) ->
--    Data1 = case ReadMode of
--	       list when binary(Data0) -> binary_to_list(Data0);
--	       _ -> Data0
--	    end,
--    case catch Mod:Func(S0, Data1, XtraArg) of
--	{stop,Result,Buf} ->
--	    {reply,Result,State#state{buf=cast_binary(Buf)}};
--	{'EXIT',Reason} ->
--	    {stop,Reason,{error,err_func(Mod, Func, XtraArg)},State};
--	S1 ->
--	    get_chars_empty(Mod, Func, XtraArg, S1, State)
--    end.
--
--%% Convert error code to make it look as before
--err_func(io_lib, get_until, {_,F,_}) ->
--    F;
--err_func(_, F, _) ->
--    F.
--
--
--
--%% Process the I/O request setopts
--%%
--%% setopts
--setopts(Opts0, State) ->
--    Opts = proplists:substitute_negations([{list,binary}], Opts0),
--    case proplists:get_value(binary, Opts) of
--	true ->
--	    {ok,ok,State#state{read_mode=binary}};
--	false ->
--	    {ok,ok,State#state{read_mode=list}};
--	_ ->
--	    {error,{error,badarg},State}
--    end.
--
--
--
--%% Concatenate two binaries and convert the result to list or binary
--cat(B1, B2, binary) ->
--    list_to_binary([B1,B2]);
--cat(B1, B2, list) ->
--    binary_to_list(B1)++binary_to_list(B2).
--
--%% Cast binary to list or binary
--cast(B, binary) ->
--    B;
--cast(B, list) ->
--    binary_to_list(B).
--
--%% Convert buffer to binary
--cast_binary(Binary) when binary(Binary) ->
--    Binary;
--cast_binary(List) when list(List) ->
--    list_to_binary(List);
--cast_binary(_EOF) ->
--    <<>>.
--
--%% Read size for different read modes
--read_size(binary) ->
--    ?READ_SIZE_BINARY;
--read_size(list) ->
--    ?READ_SIZE_LIST.
--
--max(A, B) when A >= B ->
--    A;
--max(_, B) ->
--    B.
--
--%%%-----------------------------------------------------------------
--%%% ?PRIM_FILE helpers
--
--%% Compensates ?PRIM_FILE:position/2 for the number of bytes 
--%% we have buffered
--
--position(Handle, cur, Buf) ->
--    position(Handle, {cur, 0}, Buf);
--position(Handle, {cur, Offs}, Buf) when list(Buf) ->
--    ?PRIM_FILE:position(Handle, {cur, Offs-length(Buf)});
--position(Handle, {cur, Offs}, Buf) when binary(Buf) ->
--    ?PRIM_FILE:position(Handle, {cur, Offs-size(Buf)});
--position(Handle, At, _Buf) ->
--    ?PRIM_FILE:position(Handle, At).
--

diff --git a/ejabberd-ejabberd_cfg_pam_name.diff b/ejabberd-ejabberd_cfg_pam_name.diff
index 7c0d519..3b9ed7d 100644
--- a/ejabberd-ejabberd_cfg_pam_name.diff
+++ b/ejabberd-ejabberd_cfg_pam_name.diff
@@ -1,6 +1,6 @@
---- src/ejabberd.cfg.example~	2008-08-01 16:34:28.000000000 +0400
-+++ src/ejabberd.cfg.example	2008-08-09 21:09:07.000000000 +0400
-@@ -214,7 +214,7 @@
+--- src/ejabberd.cfg.example	2009-11-20 15:07:57.317704955 +0300
++++ src/ejabberd.cfg.example	2009-11-20 15:08:11.522704968 +0300
+@@ -235,7 +235,7 @@
  %% Authentication using PAM
  %%
  %%{auth_method, pam}.

diff --git a/ejabberd-ejabberdctl_fix.diff b/ejabberd-ejabberdctl_fix.diff
index 8c8a27b..3bf5419 100644
--- a/ejabberd-ejabberdctl_fix.diff
+++ b/ejabberd-ejabberdctl_fix.diff
@@ -1,6 +1,6 @@
---- src/ejabberdctl.template	2009-04-01 19:23:51.000000000 +0400
-+++ src/ejabberdctl.template	2009-08-25 23:06:19.258685929 +0400
-@@ -9,13 +9,14 @@
+--- src/ejabberdctl.template.fix_ctl	2009-11-06 22:53:19.000000000 +0300
++++ src/ejabberdctl.template	2009-11-21 10:43:17.654686409 +0300
+@@ -9,10 +9,10 @@
  
  # define default environment variables
  NODE=ejabberd
@@ -8,75 +8,25 @@
 +HOST=`hostname -s 2>/dev/null || echo "localhost"`
  ERLANG_NODE=$NODE@$HOST
  ERL=@erl@
--ROOTDIR=@rootdir@
-+ROOTDIR=
-+MAINDIR=
- EJABBERD_CONFIG_PATH=$ROOTDIR/etc/ejabberd/ejabberd.cfg
- LOGS_DIR=$ROOTDIR/var/log/ejabberd/
--EJABBERD_DB=$ROOTDIR/var/lib/ejabberd/db/$NODE
-+EJABBERD_DB=$ROOTDIR/var/lib/ejabberd/spool
+-INSTALLUSER=@installuser@
++INSTALLUSER=ejabberd
  
- # read custom configuration
- CONFIG=$ROOTDIR/etc/ejabberd/ejabberdctl.cfg
-@@ -43,10 +44,10 @@
- ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES"
+ # parse command line parameters
+ ARGS=
+@@ -60,14 +60,14 @@
+ EJID=`id -g $INSTALLUSER`
+ EXEC_CMD="false"
+ if [ $ID -eq 0 ] ; then
+-	EXEC_CMD="su ${INSTALLUSER} -c"
++	EXEC_CMD="/sbin/runuser -s /bin/bash -p ejabberd -c"
+ fi
+ if [ "$ID" -eq "$EJID" ] ; then
+ 	EXEC_CMD="sh -c"
+ fi
+ if [ "$EXEC_CMD" = "false" ] ; then
+ 	echo "This command can only be run by root or the user $INSTALLUSER" >&2
+-	exit 1
++	exit 4
+ fi
  
- # define additional environment variables
--EJABBERD_EBIN=$ROOTDIR/var/lib/ejabberd/ebin
--EJABBERD_MSGS_PATH=$ROOTDIR/var/lib/ejabberd/priv/msgs
--EJABBERD_SO_PATH=$ROOTDIR/var/lib/ejabberd/priv/lib
--EJABBERD_BIN_PATH=$ROOTDIR/var/lib/ejabberd/priv/bin
-+EJABBERD_EBIN=$MAINDIR/ebin
-+EJABBERD_MSGS_PATH=$MAINDIR/priv/msgs
-+EJABBERD_SO_PATH=$MAINDIR/priv/lib
-+EJABBERD_BIN_PATH=$MAINDIR/priv/bin
- EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log
- SASL_LOG_PATH=$LOGS_DIR/sasl.log
- DATETIME=`date "+%Y%m%d-%H%M%S"`
-@@ -75,14 +76,16 @@
- # start server
- start ()
- {
--    $ERL \
-+     ERL_COMMAND="$ERL \
-       $NAME $ERLANG_NODE \
-       -noinput -detached \
-       -pa $EJABBERD_EBIN \
--      -mnesia dir "\"$EJABBERD_DB\"" \
-+      -mnesia dir \\\"$EJABBERD_DB\\\" \
-       -s ejabberd \
--      -sasl sasl_error_logger \{file,\"$SASL_LOG_PATH\"\} \
--      $ERLANG_OPTS $ARGS "$@"
-+      -sasl sasl_error_logger \{file,\\\"$SASL_LOG_PATH\\\"\} \
-+      $ERLANG_OPTS $ARGS "$@" \
-+      "
-+      /sbin/runuser -s /bin/bash -p ejabberd -c "$ERL_COMMAND"
- }
- 
- # attach to server
-@@ -105,7 +108,7 @@
-     read foo
-     echo ""
-     $ERL \
--      $NAME ${NODE}debug \
-+      $NAME debug-${ERLANG_NODE} \
-       -remsh $ERLANG_NODE \
-       $ERLANG_OPTS $ARGS "$@"
- }
-@@ -139,11 +142,13 @@
- # common control function
- ctl ()
- {
--    $ERL \
--      $NAME ejabberdctl \
-+    ERL_COMMAND="$ERL \
-+      $NAME ctl-${ERLANG_NODE} \
-       -noinput \
-       -pa $EJABBERD_EBIN \
--      -s ejabberd_ctl -extra $ERLANG_NODE $@
-+      -s ejabberd_ctl -extra $ERLANG_NODE $@ \
-+      "
-+    /sbin/runuser -s /bin/bash -p ejabberd -c "$ERL_COMMAND"
-     result=$?
-     case $result in
-     0) :;;
+ NAME=-name

diff --git a/ejabberd-fixed_delays_in_s2s.patch b/ejabberd-fixed_delays_in_s2s.patch
index 0090ea7..c520d6f 100644
--- a/ejabberd-fixed_delays_in_s2s.patch
+++ b/ejabberd-fixed_delays_in_s2s.patch
@@ -18,18 +18,18 @@ Index: src/ejabberd_s2s_in.erl
  					    Key, StateData#state.streamid}),
 Index: src/ejabberd_s2s_out.erl
 ===================================================================
---- src/ejabberd_s2s_out.erl	2009-04-01 17:23:51.000000000 +0200
-+++ src/ejabberd_s2s_out.erl	2009-04-05 22:51:20.000000000 +0200
-@@ -93,7 +93,7 @@
- %% Only change this value if you now what your are doing:
- -define(FSMLIMITS,[]).
- %% -define(FSMLIMITS, [{max_queue, 2000}]).
+--- src/ejabberd_s2s_out.erl	2009-11-06 22:53:19.000000000 +0300
++++ src/ejabberd_s2s_out.erl	2009-11-20 15:59:53.445703654 +0300
+@@ -90,7 +90,7 @@
+ 						 [From, Host, Type])).
+ -endif.
+ 
 --define(FSMTIMEOUT, 30000).
 +-define(FSMTIMEOUT, 60000).
  
  %% We do not block on send anymore.
  -define(TCP_SEND_TIMEOUT, 15000).
-@@ -227,8 +227,8 @@
+@@ -226,8 +226,8 @@
  	{error, _Reason} ->
  	    ?INFO_MSG("s2s connection: ~s -> ~s (remote server not found)",
  		      [StateData#state.myname, StateData#state.server]),

diff --git a/ejabberd-turn_off_error_messages_in_mod_caps.patch b/ejabberd-turn_off_error_messages_in_mod_caps.patch
deleted file mode 100644
index dd722ad..0000000
--- a/ejabberd-turn_off_error_messages_in_mod_caps.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-Patch by Sergei Golovan turns unnecessary error messages into debug messages.
-
-Index: src/mod_caps.erl
-===================================================================
---- src/mod_caps.erl	2009-04-01 17:23:51.000000000 +0200
-+++ src/mod_caps.erl	2009-04-05 22:51:20.000000000 +0200
-@@ -301,7 +301,7 @@
- 		      end),
- 		    gen_server:cast(self(), visit_feature_queries);
- 		error ->
--		    ?ERROR_MSG("ID '~s' matches no query", [ID])
-+		    ?DEBUG("ID '~s' matches no query", [ID])
- 	    end;
- 	{error, _} ->
- 	    %% XXX: if we get error, we cache empty feature not to probe the client continuously
-@@ -315,7 +315,7 @@
- 		      end),
- 		    gen_server:cast(self(), visit_feature_queries);
- 		error ->
--		    ?ERROR_MSG("ID '~s' matches no query", [ID])
-+		    ?DEBUG("ID '~s' matches no query", [ID])
- 	    end;
- 	    %gen_server:cast(self(), visit_feature_queries),
- 	    %?DEBUG("Error IQ reponse from ~s:~n~p", [jlib:jid_to_string(From), SubEls]);

diff --git a/ejabberd.init b/ejabberd.init
index 8115600..9670916 100644
--- a/ejabberd.init
+++ b/ejabberd.init
@@ -11,6 +11,8 @@
 # Provides: ejabberd
 # Required-Start: network
 # Required-Stop: network
+# Default-Start:
+# Default-Stop: 0 1 6
 # Short-Description: Start and stop ejabberd
 # Description: A distributed, fault-tolerant Jabber/XMPP server
 ### END INIT INFO

diff --git a/ejabberd.spec b/ejabberd.spec
index 0191087..9086ec0 100644
--- a/ejabberd.spec
+++ b/ejabberd.spec
@@ -1,6 +1,18 @@
+%bcond_without fedora
+%global uid 27
+
+# Currently, hevea available only in Fedora
+%if %{defined fedora}
+# No hevea on Fedora for ppc64
+# see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=250253
+%ifnarch ppc64
+%define with_hevea 1
+%endif
+%endif
+
 Name:           ejabberd
-Version:        2.0.5
-Release:        10%{?dist}
+Version:        2.1.0
+Release:        1%{?dist}
 Summary:        A distributed, fault-tolerant Jabber/XMPP server
 
 Group:          Applications/Internet
@@ -12,10 +24,12 @@ Source2:        ejabberd.logrotate
 Source3:	ejabberd.sysconfig
 
 # http://www.ejabberd.im/mod_ctlextra
+# this module will be removed in the near future in favor of mod_admin_extra
 # svn export -r 1020 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
+# These are unmaintained and will be removed soon (users should use *_ldap.erl instead)
 Source5:        ejabberd_auth_ad.erl
 Source6:        mod_shared_roster_ad.erl
 Source7:        mod_vcard_ad.erl
@@ -25,27 +39,14 @@ Source9:        ejabberdctl.pam
 Source10:       ejabberdctl.apps
 Source11:       ejabberd.pam
 
-# Fedora-specific stuff - fixing paths
-Patch1: ejabberd-build.patch
 # BZ# 439583, 452326, 451554, 465196, 502361
 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
 # Mention mod_ctlextra as an ejabberd module
 Patch5: ejabberd-mod_ctlextra_mentioning_in_ejabberd_app.diff
-# Turn off unnecessary error messages in mod_caps (backport from upstream)
-Patch6: ejabberd-turn_off_error_messages_in_mod_caps.patch
-# Decrease mod_proxy65 send/receive buffers (backport from upstream)
-Patch7: ejabberd-decrease_buffers_in_mod_proxy65.patch
 # fixed delays in s2s connections
 Patch8: ejabberd-fixed_delays_in_s2s.patch
-# Common dynamic compilation facility for Erlang R11/R12/R13 instead of old one
-# See https://support.process-one.net/browse/EJAB-919
-# Fixes BZ# 533021
-Patch9: ejabberd-dynamic_compile_loglevel.patch
 
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -55,22 +56,25 @@ BuildRequires:  openssl-devel
 BuildRequires:  pam-devel
 BuildRequires:  erlang
 BuildRequires:	dos2unix
-%if %{undefined rhel}
+BuildRequires:	fedora-usermgmt-devel
+
+%if 0%{?with_hevea}
 BuildRequires:  hevea
 %endif
 
-Requires:       erlang
-Requires:       usermode
-
-Requires(pre): fedora-usermgmt
+%{?FE_USERADD_REQ}
 Requires(post): /sbin/chkconfig
 Requires(post): /usr/bin/openssl
 Requires(preun): /sbin/chkconfig
 Requires(preun): /sbin/service
 Requires(postun): /sbin/service
 
-# https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=250253
-ExcludeArch: ppc64
+Provides: user(%{name}) = %{uid}
+Provides: group(%{name}) = %{uid}
+
+Requires:       erlang
+Requires:       usermode
+
 
 %description
 ejabberd is a Free and Open Source distributed fault-tolerant
@@ -86,12 +90,12 @@ Group: Documentation
 Documentation for ejabberd.
 
 %pre
-/usr/sbin/fedora-groupadd 27 -r ejabberd &>/dev/null || :
-/usr/sbin/fedora-useradd  27 -r -s /sbin/nologin -d /var/lib/ejabberd -M \
-                             -c 'ejabberd' -g ejabberd ejabberd &>/dev/null || :
+%{__fe_groupadd} %{uid} -r %{name} &>/dev/null || :
+%{__fe_useradd} %{uid} -r -s /sbin/nologin -d /var/lib/ejabberd -M \
+			-c 'ejabberd' -g %{name} %{name} &>/dev/null || :
 
 %post
-/sbin/chkconfig --add ejabberd
+/sbin/chkconfig --add %{name}
 
 (cd /etc/ejabberd
 if [ ! -f ejabberd.pem ]
@@ -115,28 +119,23 @@ fi)
 
 %preun
 if [ $1 = 0 ]; then
-        /sbin/service ejabberd stop >/dev/null 2>&1
-        /sbin/chkconfig --del ejabberd
+        /sbin/service %{name} stop >/dev/null 2>&1
+        /sbin/chkconfig --del %{name}
 fi
 
 %postun
 if [ "$1" -ge "1" ]; then
-        /sbin/service ejabberd condrestart >/dev/null 2>&1
+        /sbin/service %{name} condrestart >/dev/null 2>&1
 fi
 
 %prep
 %setup -q
-%patch1 -p0 -b .fix_paths
 %patch2 -p0 -b .fix_ctl
 %patch3 -p0 -b .pam_name
-%patch4 -p1 -b .captcha
 %patch5 -p0 -b .mod_ctlextra
-%patch6 -p0 -b .error_msg
-%patch7 -p0 -b .decrease_buffers
 %patch8 -p0 -b .s2s
-%patch9 -p0 -b .dyn_compile
 
-dos2unix src/odbc/mssql.sql
+dos2unix src/odbc/mssql2000.sql
 
 cp %{S:4} src
 cp %{S:5} src
@@ -149,8 +148,10 @@ pushd src
 # doesn't builds on SMP currently
 make
 popd
-%if %{undefined rhel}
+%if 0%{?with_hevea}
 pushd doc
+# remove pre-built docs
+rm -f dev.html features.html features.pdf guide.html guide.pdf
 make html pdf
 popd
 %endif
@@ -162,9 +163,11 @@ pushd src
 make install DESTDIR=%{buildroot}
 popd
 
+# surprisingly, generic ejabberd makefile installs libraries with 644 permissions
 chmod a+x %{buildroot}%{_libdir}/%{name}/priv/lib/*.so
 
-%{__perl} -pi -e 's!./ssl.pem!/etc/ejabberd/ejabberd.pem!g' %{buildroot}/etc/ejabberd/ejabberd.cfg
+# fix example SSL certificate path to real one, which we created recently (see above)
+%{__perl} -pi -e 's!/path/to/ssl.pem!/etc/ejabberd/ejabberd.pem!g' %{buildroot}/etc/ejabberd/ejabberd.cfg
 
 mkdir -p %{buildroot}/var/log/ejabberd
 mkdir -p %{buildroot}/var/lib/ejabberd/spool
@@ -184,18 +187,26 @@ install -D -p -m 0644  %{S:2} %{buildroot}%{_sysconfdir}/logrotate.d/ejabberd
 # install sysconfig file
 install -D -p -m 0644  %{S:3} %{buildroot}%{_sysconfdir}/sysconfig/ejabberd
 
-%{__perl} -pi -e 's!\@libdir\@!%{_libdir}!g'  %{buildroot}%{_initrddir}/ejabberd %{buildroot}%{_sysconfdir}/logrotate.d/ejabberd %{buildroot}%{_sbindir}/ejabberdctl
-%{__perl} -pi -e 's!\@version\@!%{version}!g' %{buildroot}%{_initrddir}/ejabberd %{buildroot}%{_sysconfdir}/logrotate.d/ejabberd %{buildroot}%{_sbindir}/ejabberdctl
+# create room for necessary data
+install -d %{buildroot}%{_datadir}/%{name}
+# install sql-scripts for creating db schemes for various RDBMS
+install -p -m 0644 src/odbc/mssql2000.sql %{buildroot}%{_datadir}/%{name}
+install -p -m 0644 src/odbc/mssql2005.sql %{buildroot}%{_datadir}/%{name}
+install -p -m 0644 src/odbc/mysql.sql %{buildroot}%{_datadir}/%{name}
+install -p -m 0644 src/odbc/pg.sql %{buildroot}%{_datadir}/%{name}
+# install example script for CAPTCHA-protection
+install -p -m 0644 tools/captcha.sh %{buildroot}%{_datadir}/%{name}
 
-# BZ# 439583
-%{__perl} -pi -e 's!MAINDIR=!MAINDIR=%{_libdir}/ejabberd!g' %{buildroot}%{_sbindir}/ejabberdctl
+# removed files, which would be packaged later (see 'files' section)
+rm -rf %{buildroot}%{_docdir}/%{name}
+rm -f %{buildroot}%{_libdir}/%{name}/priv/bin/captcha.sh
 
 %clean
 rm -rf %{buildroot}
 
 %files
 %defattr(-,root,root,-)
-%doc COPYING src/odbc/mysql.sql src/odbc/mssql.sql src/odbc/pg.sql tools/captcha.sh
+%doc COPYING
 
 %attr(750,ejabberd,ejabberd) %dir %{_sysconfdir}/ejabberd
 %attr(640,ejabberd,ejabberd) %config(noreplace) %{_sysconfdir}/ejabberd/ejabberd.cfg
@@ -213,30 +224,97 @@ rm -rf %{buildroot}
 
 %dir %{_libdir}/%{name}
 %dir %{_libdir}/%{name}/ebin
+%dir %{_libdir}/%{name}/include
+%dir %{_libdir}/%{name}/include/eldap
+%dir %{_libdir}/%{name}/include/mod_muc
+%dir %{_libdir}/%{name}/include/mod_proxy65
+%dir %{_libdir}/%{name}/include/mod_pubsub
+%dir %{_libdir}/%{name}/include/web
 %dir %{_libdir}/%{name}/priv
 %dir %{_libdir}/%{name}/priv/bin
-%attr(4750,root,ejabberd)    %{_libdir}/%{name}/priv/bin/epam
 %dir %{_libdir}/%{name}/priv/lib
 %dir %{_libdir}/%{name}/priv/msgs
 
-%{_libdir}/%{name}/ebin/*.app
+%{_libdir}/%{name}/ebin/%{name}.app
 %{_libdir}/%{name}/ebin/*.beam
-%{_libdir}/%{name}/priv/lib/*.so
+%{_libdir}/%{name}/include/XmppAddr.hrl
+%{_libdir}/%{name}/include/adhoc.hrl
+%{_libdir}/%{name}/include/ejabberd.hrl
+%{_libdir}/%{name}/include/ejabberd_commands.hrl
+%{_libdir}/%{name}/include/ejabberd_config.hrl
+%{_libdir}/%{name}/include/ejabberd_ctl.hrl
+%{_libdir}/%{name}/include/eldap/ELDAPv3.hrl
+%{_libdir}/%{name}/include/eldap/eldap.hrl
+%{_libdir}/%{name}/include/jlib.hrl
+%{_libdir}/%{name}/include/mod_muc/mod_muc_room.hrl
+%{_libdir}/%{name}/include/mod_privacy.hrl
+%{_libdir}/%{name}/include/mod_proxy65/mod_proxy65.hrl
+%{_libdir}/%{name}/include/mod_pubsub/pubsub.hrl
+%{_libdir}/%{name}/include/mod_roster.hrl
+%{_libdir}/%{name}/include/web/ejabberd_http.hrl
+%{_libdir}/%{name}/include/web/ejabberd_web_admin.hrl
+%attr(4750,root,ejabberd) %{_libdir}/%{name}/priv/bin/epam
+%{_libdir}/%{name}/priv/lib/ejabberd_zlib_drv.so
+%{_libdir}/%{name}/priv/lib/expat_erl.so
+%{_libdir}/%{name}/priv/lib/iconv_erl.so
+%{_libdir}/%{name}/priv/lib/stringprep_drv.so
+%{_libdir}/%{name}/priv/lib/tls_drv.so
 %{_libdir}/%{name}/priv/msgs/*.msg
 
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/captcha.sh
+%{_datadir}/%{name}/mssql2000.sql
+%{_datadir}/%{name}/mssql2005.sql
+%{_datadir}/%{name}/mysql.sql
+%{_datadir}/%{name}/pg.sql
+
 %attr(750,ejabberd,ejabberd) %dir /var/lib/ejabberd
 %attr(750,ejabberd,ejabberd) %dir /var/lib/ejabberd/spool
 %attr(750,ejabberd,ejabberd) %dir /var/log/ejabberd
 
 %files doc
 %defattr(-,root,root,-)
-%if %{undefined rhel}
-%doc ChangeLog COPYING doc/release_notes_* doc/*.pdf doc/*.html doc/*.png
-%else
-%doc ChangeLog COPYING doc/release_notes_*
-%endif
+%doc COPYING
+%doc doc/dev.html
+%doc doc/discorus.png
+%doc doc/features.html
+%doc doc/features.pdf
+%doc doc/guide.html
+%doc doc/guide.pdf
+%doc doc/logo.png
+%doc doc/release_notes_0.9.txt
+%doc doc/release_notes_0.9.1.txt
+%doc doc/release_notes_0.9.8.txt
+%doc doc/release_notes_1.0.0.txt
+%doc doc/release_notes_1.1.0.txt
+%doc doc/release_notes_1.1.1.txt
+%doc doc/release_notes_1.1.2.txt
+%doc doc/release_notes_1.1.3.txt
+%doc doc/release_notes_1.1.4.txt
+%doc doc/release_notes_2.0.0.txt
+%doc doc/release_notes_2.0.1.txt
+%doc doc/release_notes_2.0.2.txt
+%doc doc/release_notes_2.0.3.txt
+%doc doc/release_notes_2.0.4.txt
+%doc doc/release_notes_2.0.5.txt
+%doc doc/release_notes_2.1.0.txt
+%doc doc/webadmmain.png
+%doc doc/webadmmainru.png
+%doc doc/yozhikheader.png
 
 %changelog
+* Fri Nov 20 2009 Peter Lemenkov <lemenkov@gmail.com> 2.1.0-1
+- Ver. 2.1.0
+- Upstream no longer providing ChangeLog
+- Dropped ejabberd-build.patch (upstreamed)
+- Dropped ejabberd-captcha.patch (upstreamed)
+- Dropped ejabberd-decrease_buffers_in_mod_proxy65.patch (upstreamed)
+- Dropped ejabberd-dynamic_compile_loglevel.patch (upstreamed)
+- Dropped ejabberd-turn_off_error_messages_in_mod_caps.patch (upstreamed)
+- Docs reorganized and added ability to rebuild them if possible
+- Added back ppc64 target
+- SQL-scripts moved to %%{_datadir}/%%{name} from %%doc
+
 * Thu Nov  5 2009 Peter Lemenkov <lemenkov@gmail.com> 2.0.5-10
 - mod_ctlextra was updated from r873 to r1020
 - Fix for BZ# 533021

diff --git a/import.log b/import.log
index 548962f..cc1cb86 100644
--- a/import.log
+++ b/import.log
@@ -12,3 +12,4 @@ ejabberd-2_0_5-3_fc10:HEAD:ejabberd-2.0.5-3.fc10.src.rpm:1240304532
 ejabberd-2_0_5-6_fc11:HEAD:ejabberd-2.0.5-6.fc11.src.rpm:1251228870
 ejabberd-2_0_5-8_fc11:HEAD:ejabberd-2.0.5-8.fc11.src.rpm:1252493017
 ejabberd-2_0_5-10_fc11:HEAD:ejabberd-2.0.5-10.fc11.src.rpm:1257428310
+ejabberd-2_1_0-1_fc12:HEAD:ejabberd-2.1.0-1.fc12.src.rpm:1258790332

diff --git a/sources b/sources
index 77e1427..cc4348c 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-2d85b47df969daf0a78ed3b16562d731  ejabberd-2.0.5.tar.gz
+373be6e99acf7c930ab85531489c63c4  ejabberd-2.1.0.tar.gz

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-23 19:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-23 19:06 [rpms/ejabberd] f45: Ver. 2.1.0 Peter Lemenkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox