From e4c5172b223a78a118bf313ef5e4758780d0960e Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 12 Mar 2015 13:41:44 +0100 Subject: [PATCH 1/4] Update mod_multicast to work with ejabberd 14.12 --- mod_multicast/src/ejabberd_c2s.erl | 131 +++++++++++++++++++---------- mod_multicast/src/mod_muc_room.erl | 33 ++++---- 2 files changed, 103 insertions(+), 61 deletions(-) diff --git a/mod_multicast/src/ejabberd_c2s.erl b/mod_multicast/src/ejabberd_c2s.erl index 6fdbcb7..ee626c6 100644 --- a/mod_multicast/src/ejabberd_c2s.erl +++ b/mod_multicast/src/ejabberd_c2s.erl @@ -45,6 +45,7 @@ set_aux_field/3, del_aux_field/2, get_subscription/2, + send_filtered/5, broadcast/4, get_subscribed/1, transform_listen_option/2]). @@ -94,12 +95,12 @@ tls_options = [], authenticated = false, jid, - user = "", server = <<"">>, resource = <<"">>, + user = <<"">>, server = <<"">>, resource = <<"">>, sid, pres_t = ?SETS:new(), pres_f = ?SETS:new(), pres_a = ?SETS:new(), - pres_last, pres_pri, + pres_last, pres_timestamp, privacy_list = #userlist{}, conn = unknown, @@ -247,6 +248,9 @@ get_subscription(LFrom, StateData) -> true -> none end. +send_filtered(FsmRef, Feature, From, To, Packet) -> + FsmRef ! {send_filtered, Feature, From, To, Packet}. + broadcast(FsmRef, Type, From, Packet) -> FsmRef ! {broadcast, Type, From, Packet}. @@ -1690,12 +1694,23 @@ handle_info({route, From, To, jlib:replace_from_to_attrs(jlib:jid_to_string(From), jlib:jid_to_string(To), NewAttrs), FixedPacket = #xmlel{name = Name, attrs = Attrs2, children = Els}, - SentStateData = send_packet(NewState, FixedPacket), - ejabberd_hooks:run(user_receive_packet, - SentStateData#state.server, - [SentStateData#state.jid, From, To, FixedPacket]), + FinalState = + case ejabberd_hooks:run_fold(c2s_filter_packet_in, + NewState#state.server, FixedPacket, + [NewState#state.jid, From, To]) + of + drop -> + NewState; + FinalPacket = #xmlel{} -> + SentState = send_packet(NewState, FinalPacket), + ejabberd_hooks:run(user_receive_packet, + SentState#state.server, + [SentState#state.jid, From, To, + FinalPacket]), + SentState + end, ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]), - fsm_next_state(StateName, SentStateData); + fsm_next_state(StateName, FinalState); true -> ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]), fsm_next_state(StateName, NewState) @@ -1738,6 +1753,32 @@ handle_info({force_update_presence, LUser}, StateName, _ -> StateData end, fsm_next_state(StateName, NewStateData); +handle_info({send_filtered, Feature, From, To, Packet}, StateName, StateData) -> + Drop = ejabberd_hooks:run_fold(c2s_filter_packet, StateData#state.server, + true, [StateData#state.server, StateData, + Feature, To, Packet]), + NewStateData = if Drop -> + ?DEBUG("Dropping packet from ~p to ~p", + [jlib:jid_to_string(From), + jlib:jid_to_string(To)]), + StateData; + true -> + FinalPacket = jlib:replace_from_to(From, To, Packet), + case StateData#state.jid of + To -> + case privacy_check_packet(StateData, From, To, + FinalPacket, in) of + deny -> + StateData; + allow -> + send_stanza(StateData, FinalPacket) + end; + _ -> + ejabberd_router:route(From, To, FinalPacket), + StateData + end + end, + fsm_next_state(StateName, NewStateData); handle_info({broadcast, Type, From, Packet}, StateName, StateData) -> Recipients = ejabberd_hooks:run_fold( c2s_broadcast_recipients, StateData#state.server, @@ -2008,13 +2049,9 @@ process_presence_probe(From, To, StateData) -> ?SETS:is_element(LBFrom, StateData#state.pres_f)), if Cond -> - Timestamp = StateData#state.pres_timestamp, - Packet = xml:append_subtags( - StateData#state.pres_last, - %% To is the one sending the presence (the target of the probe) - [jlib:timestamp_to_xml(Timestamp, utc, To, <<"">>), - %% TODO: Delete the next line once XEP-0091 is Obsolete - jlib:timestamp_to_xml(Timestamp)]), + %% To is the one sending the presence (the probe target) + Packet = jlib:add_delay_info(StateData#state.pres_last, To, + StateData#state.pres_timestamp), case privacy_check_packet(StateData, To, From, Packet, out) of deny -> ok; @@ -2066,12 +2103,11 @@ presence_update(From, Packet, StateData) -> OldPresence -> get_priority_from_presence(OldPresence) end, NewPriority = get_priority_from_presence(Packet), - Timestamp = calendar:now_to_universal_time(now()), update_priority(NewPriority, Packet, StateData), FromUnavail = (StateData#state.pres_last == undefined), ?DEBUG("from unavail = ~p~n", [FromUnavail]), NewStateData = StateData#state{pres_last = Packet, - pres_timestamp = Timestamp}, + pres_timestamp = now()}, NewState = if FromUnavail -> ejabberd_hooks:run(user_available_hook, NewStateData#state.server, @@ -2757,7 +2793,10 @@ handle_resume(StateData, Attrs) -> {<<"h">>, AttrH}, {<<"previd">>, AttrId}], children = []}), - SendFun = fun(_F, _T, El) -> send_element(NewState, El) end, + SendFun = fun(_F, _T, El, Time) -> + NewEl = add_resent_delay_info(NewState, El, Time), + send_element(NewState, NewEl) + end, handle_unacked_stanzas(NewState, SendFun), send_element(NewState, #xmlel{name = <<"r">>, @@ -2813,13 +2852,13 @@ mgmt_queue_add(StateData, El) -> Num -> Num + 1 end, - NewQueue = queue:in({NewNum, El}, StateData#state.mgmt_queue), + NewQueue = queue:in({NewNum, now(), El}, StateData#state.mgmt_queue), NewState = StateData#state{mgmt_queue = NewQueue, mgmt_stanzas_out = NewNum}, check_queue_length(NewState). mgmt_queue_drop(StateData, NumHandled) -> - NewQueue = jlib:queue_drop_while(fun({N, _Stanza}) -> N =< NumHandled end, + NewQueue = jlib:queue_drop_while(fun({N, _T, _E}) -> N =< NumHandled end, StateData#state.mgmt_queue), StateData#state{mgmt_queue = NewQueue}. @@ -2847,12 +2886,12 @@ handle_unacked_stanzas(StateData, F) ?INFO_MSG("~B stanzas were not acknowledged by ~s", [N, jlib:jid_to_string(StateData#state.jid)]), lists:foreach( - fun({_, #xmlel{attrs = Attrs} = El}) -> + fun({_, Time, #xmlel{attrs = Attrs} = El}) -> From_s = xml:get_attr_s(<<"from">>, Attrs), From = jlib:string_to_jid(From_s), To_s = xml:get_attr_s(<<"to">>, Attrs), To = jlib:string_to_jid(To_s), - F(From, To, El) + F(From, To, El, Time) end, queue:to_list(Queue)) end; handle_unacked_stanzas(_StateData, _F) -> @@ -2871,16 +2910,19 @@ handle_unacked_stanzas(StateData) end, ReRoute = case ResendOnTimeout of true -> - fun ejabberd_router:route/3; + fun(From, To, El, Time) -> + NewEl = add_resent_delay_info(StateData, El, Time), + ejabberd_router:route(From, To, NewEl) + end; false -> - fun(From, To, El) -> + fun(From, To, El, _Time) -> Err = jlib:make_error_reply(El, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end end, - F = fun(From, To, El) -> + F = fun(From, To, El, Time) -> %% We'll drop the stanza if it was by some %% encapsulating protocol as per XEP-0297. One such protocol is %% XEP-0280, which says: "When a receiving server attempts to @@ -2893,7 +2935,7 @@ handle_unacked_stanzas(StateData) ?DEBUG("Dropping forwarded stanza from ~s", [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); false -> - ReRoute(From, To, El) + ReRoute(From, To, El, Time) end end, handle_unacked_stanzas(StateData, F); @@ -2956,7 +2998,6 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> pres_f = OldStateData#state.pres_f, pres_a = OldStateData#state.pres_a, pres_last = OldStateData#state.pres_last, - pres_pri = OldStateData#state.pres_pri, pres_timestamp = OldStateData#state.pres_timestamp, privacy_list = OldStateData#state.privacy_list, aux_fields = OldStateData#state.aux_fields, @@ -2985,6 +3026,9 @@ make_resume_id(StateData) -> {Time, _} = StateData#state.sid, jlib:term_to_base64({StateData#state.resource, Time}). +add_resent_delay_info(#state{server = From}, El, Time) -> + jlib:add_delay_info(El, From, Time, <<"Resent">>). + %%%---------------------------------------------------------------------- %%% XEP-0352 %%%---------------------------------------------------------------------- @@ -3007,37 +3051,36 @@ csi_filter_stanza(#state{csi_state = CsiState, jid = JID} = StateData, StateData2#state{csi_state = CsiState} end. -csi_queue_add(#state{csi_queue = Queue, server = Host} = StateData, - #xmlel{children = Els} = Stanza) -> - From = xml:get_tag_attr_s(<<"from">>, Stanza), - Time = calendar:now_to_universal_time(os:timestamp()), - DelayTag = [jlib:timestamp_to_xml(Time, utc, - jlib:make_jid(<<"">>, Host, <<"">>), - <<"Client Inactive">>)], - NewStanza = Stanza#xmlel{children = Els ++ DelayTag}, +csi_queue_add(#state{csi_queue = Queue} = StateData, Stanza) -> case length(StateData#state.csi_queue) >= csi_max_queue(StateData) of - true -> csi_queue_add(csi_queue_flush(StateData), NewStanza); + true -> csi_queue_add(csi_queue_flush(StateData), Stanza); false -> - NewQueue = lists:keystore(From, 1, Queue, {From, NewStanza}), + From = xml:get_tag_attr_s(<<"from">>, Stanza), + NewQueue = lists:keystore(From, 1, Queue, {From, now(), Stanza}), StateData#state{csi_queue = NewQueue} end. -csi_queue_send(#state{csi_queue = Queue, csi_state = CsiState} = StateData, - From) -> +csi_queue_send(#state{csi_queue = Queue, csi_state = CsiState, server = Host} = + StateData, From) -> case lists:keytake(From, 1, Queue) of - {value, {From, Stanza}, NewQueue} -> + {value, {From, Time, Stanza}, NewQueue} -> + NewStanza = jlib:add_delay_info(Stanza, Host, Time, + <<"Client Inactive">>), NewStateData = send_stanza(StateData#state{csi_state = active}, - Stanza), + NewStanza), NewStateData#state{csi_queue = NewQueue, csi_state = CsiState}; false -> StateData end. -csi_queue_flush(#state{csi_queue = Queue, csi_state = CsiState, jid = JID} = - StateData) -> +csi_queue_flush(#state{csi_queue = Queue, csi_state = CsiState, jid = JID, + server = Host} = StateData) -> ?DEBUG("Flushing CSI queue for ~s", [jlib:jid_to_string(JID)]), NewStateData = - lists:foldl(fun({_From, Stanza}, AccState) -> - send_stanza(AccState, Stanza) + lists:foldl(fun({_From, Time, Stanza}, AccState) -> + NewStanza = + jlib:add_delay_info(Stanza, Host, Time, + <<"Client Inactive">>), + send_stanza(AccState, NewStanza) end, StateData#state{csi_state = active}, Queue), NewStateData#state{csi_queue = [], csi_state = CsiState}. diff --git a/mod_multicast/src/mod_muc_room.erl b/mod_multicast/src/mod_muc_room.erl index 3ea7f34..e27549d 100644 --- a/mod_multicast/src/mod_muc_room.erl +++ b/mod_multicast/src/mod_muc_room.erl @@ -174,7 +174,7 @@ normal_state({route, From, <<"">>, Now = now_to_usec(now()), MinMessageInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, - mod_muc, min_message_interval, fun(MMI) when is_integer(MMI) -> MMI end, 0) + mod_muc, min_message_interval, fun(MMI) when is_number(MMI) -> MMI end, 0) * 1000000), Size = element_size(Packet), {MessageShaper, MessageShaperInterval} = @@ -1509,15 +1509,17 @@ get_user_activity(JID, StateData) -> store_user_activity(JID, UserActivity, StateData) -> MinMessageInterval = - gen_mod:get_module_opt(StateData#state.server_host, - mod_muc, min_message_interval, - fun(I) when is_integer(I), I>=0 -> I end, - 0), + trunc(gen_mod:get_module_opt(StateData#state.server_host, + mod_muc, min_message_interval, + fun(I) when is_number(I), I>=0 -> I end, + 0) + * 1000), MinPresenceInterval = - gen_mod:get_module_opt(StateData#state.server_host, - mod_muc, min_presence_interval, - fun(I) when is_integer(I), I>=0 -> I end, - 0), + trunc(gen_mod:get_module_opt(StateData#state.server_host, + mod_muc, min_presence_interval, + fun(I) when is_number(I), I>=0 -> I end, + 0) + * 1000), Key = jlib:jid_tolower(JID), Now = now_to_usec(now()), Activity1 = clean_treap(StateData#state.activity, @@ -1548,8 +1550,8 @@ store_user_activity(JID, UserActivity, StateData) -> 100000), Delay = lists:max([MessageShaperInterval, PresenceShaperInterval, - MinMessageInterval * 1000, - MinPresenceInterval * 1000]) + MinMessageInterval, + MinPresenceInterval]) * 1000, Priority = {1, -(Now + Delay)}, StateData#state{activity = @@ -2428,24 +2430,21 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> false -> false; _ -> true end, - TimeStamp = calendar:now_to_universal_time(now()), + TimeStamp = now(), SenderJid = case (StateData#state.config)#config.anonymous of true -> StateData#state.jid; false -> FromJID end, - TSPacket = xml:append_subtags(Packet, - [jlib:timestamp_to_xml(TimeStamp, utc, - SenderJid, <<"">>), - jlib:timestamp_to_xml(TimeStamp)]), + TSPacket = jlib:add_delay_info(Packet, SenderJid, TimeStamp), SPacket = jlib:replace_from_to(jlib:jid_replace_resource(StateData#state.jid, FromNick), StateData#state.jid, TSPacket), Size = element_size(SPacket), Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, - TimeStamp, Size}, + calendar:now_to_universal_time(TimeStamp), Size}, StateData#state.history), add_to_log(text, {FromNick, Packet}, StateData), StateData#state{history = Q1}. From e87dee1a00970d0864c6f382ac3dae9eee4b5873 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 12 Mar 2015 13:42:37 +0100 Subject: [PATCH 2/4] Add mod_privacy.hrl as it's needed to compile mod_multicast/src/ejabberd_c2s.erl --- ejabberd-dev/include/mod_privacy.hrl | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 ejabberd-dev/include/mod_privacy.hrl diff --git a/ejabberd-dev/include/mod_privacy.hrl b/ejabberd-dev/include/mod_privacy.hrl new file mode 100644 index 0000000..848de86 --- /dev/null +++ b/ejabberd-dev/include/mod_privacy.hrl @@ -0,0 +1,43 @@ +%%%---------------------------------------------------------------------- +%%% +%%% ejabberd, Copyright (C) 2002-2014 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License along +%%% with this program; if not, write to the Free Software Foundation, Inc., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-record(privacy, {us = {<<"">>, <<"">>} :: {binary(), binary()}, + default = none :: none | binary(), + lists = [] :: [{binary(), [listitem()]}]}). + +-record(listitem, {type = none :: none | jid | group | subscription, + value = none :: none | both | from | to | ljid() | binary(), + action = allow :: allow | deny, + order = 0 :: integer(), + match_all = false :: boolean(), + match_iq = false :: boolean(), + match_message = false :: boolean(), + match_presence_in = false :: boolean(), + match_presence_out = false :: boolean()}). + +-type listitem() :: #listitem{}. + +-record(userlist, {name = none :: none | binary(), + list = [] :: [listitem()], + needdb = false :: boolean()}). + +-type userlist() :: #userlist{}. + +-export_type([userlist/0]). From 7870f773928c5f0c971feedeef0f8fe548a0e7e9 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 13 Mar 2015 11:13:21 +0100 Subject: [PATCH 3/4] binarize mod_profile --- mod_profile/README.txt | 2 - mod_profile/src/mod_profile.erl | 248 ++++++++++++++++---------------- 2 files changed, 126 insertions(+), 124 deletions(-) diff --git a/mod_profile/README.txt b/mod_profile/README.txt index 1f690e1..2892042 100644 --- a/mod_profile/README.txt +++ b/mod_profile/README.txt @@ -5,8 +5,6 @@ Author: Magnus Henoch mailto:henoch@dtek.chalmers.se xmpp:legoscia@jabber.cd.chalmers.se - Requirements: ejabberd 2.x.x - Does NOT work with ejabberd 13 or newer. This module supports storing and retrieving a profile according to diff --git a/mod_profile/src/mod_profile.erl b/mod_profile/src/mod_profile.erl index a0e9866..5be3faf 100644 --- a/mod_profile/src/mod_profile.erl +++ b/mod_profile/src/mod_profile.erl @@ -54,9 +54,9 @@ %%% %%% %%% -%%% +%%% %%% The server will return only the fields that were requested and the user had defined previously: -%%% +%%% %%% %%% %%% @@ -76,141 +76,143 @@ %%%% Headers -module(mod_profile). + -author('henoch@dtek.chalmers.se'). -behaviour(gen_mod). --export([start/2, stop/1, - process_sm_iq/3, - get_sm_features/5, - remove_user/2]). +-export([start/2, stop/1, process_sm_iq/3, + get_sm_features/5, remove_user/2]). -include("ejabberd.hrl"). + -include("jlib.hrl"). + -include("logger.hrl"). -record(profile, {us, fields}). --define(NS_PROFILE, "urn:xmpp:tmp:profile"). +-define(NS_PROFILE, <<"urn:xmpp:tmp:profile">>). %%%======================= %%%% gen_mod start(Host, Opts) -> - mnesia:create_table(profile, [{disc_only_copies, [node()]}, - {attributes, record_info(fields, profile)}]), - ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), - ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), + mnesia:create_table(profile, + [{disc_only_copies, [node()]}, + {attributes, record_info(fields, profile)}]), + ejabberd_hooks:add(remove_user, Host, ?MODULE, + remove_user, 50), + ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, + get_sm_features, 50), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PROFILE, - ?MODULE, process_sm_iq, IQDisc). + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_PROFILE, ?MODULE, process_sm_iq, IQDisc). stop(Host) -> - ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), - ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features,50), - gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PROFILE). + ejabberd_hooks:delete(remove_user, Host, ?MODULE, + remove_user, 50), + ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, + get_sm_features, 50), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, + ?NS_PROFILE). %%%======================= %%%% Hooks -get_sm_features({error, _} = Acc, _From, _To, _Node, _Lang) -> +get_sm_features({error, _} = Acc, _From, _To, _Node, + _Lang) -> Acc; get_sm_features(Acc, _From, _To, Node, _Lang) -> - %% XXX: this will make nonexistent users seem to exist. But - %% mod_adhoc and mod_vcard do that already. case Node of - [] -> - case Acc of - {result, Features} -> - {result, [?NS_PROFILE | Features]}; - empty -> - {result, [?NS_PROFILE]} - end; - _ -> - Acc + [] -> + case Acc of + {result, Features} -> + {result, [?NS_PROFILE | Features]}; + empty -> {result, [?NS_PROFILE]} + end; + _ -> Acc end. remove_user(User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), US = {LUser, LServer}, - F = fun() -> - mnesia:delete({profile, US}) - end, + F = fun () -> mnesia:delete({profile, US}) end, mnesia:transaction(F). %%%======================= %%%% IQ handler -process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> +process_sm_iq(From, To, + #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of - set -> - #jid{luser = LUser, lserver = LServer} = From, - process_sm_iq_set(LUser, LServer, SubEl, IQ); - get -> - #jid{luser = LUser, lserver = LServer} = To, - process_sm_iq_get(LUser, LServer, SubEl, IQ) + set -> + #jid{luser = LUser, lserver = LServer} = From, + process_sm_iq_set(LUser, LServer, SubEl, IQ); + get -> + #jid{luser = LUser, lserver = LServer} = To, + process_sm_iq_get(LUser, LServer, SubEl, IQ) end. process_sm_iq_set(LUser, LServer, SubEl, IQ) -> case lists:member(LServer, ?MYHOSTS) of - true -> - {xmlelement, _, _, SubSubEls} = SubEl, - ElsList = [El || {xmlelement, Name, _Attrs, _Els} = El - <- xml:remove_cdata(SubSubEls), - Name == "x"], - case ElsList of - [XData] -> - case set_profile(LUser, LServer, XData) of - ok -> - IQ#iq{type = result, sub_el = []}; - {error, Error} -> - IQ#iq{type = error, sub_el = [SubEl, Error]} - end; - _ -> - IQ#iq{type = error, - sub_el = [SubEl, ?ERR_BAD_REQUEST]} - end; - false -> - IQ#iq{type = error, - sub_el = [SubEl, ?ERR_NOT_ALLOWED]} + true -> + #xmlel{children = SubSubEls} = SubEl, + ElsList = [El + || #xmlel{name = Name} = El + <- xml:remove_cdata(SubSubEls), + Name == <<"x">>], + case ElsList of + [XData] -> + case set_profile(LUser, LServer, XData) of + ok -> IQ#iq{type = result, sub_el = []}; + {error, Error} -> + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + _ -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + end; + false -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} end. process_sm_iq_get(LUser, LServer, SubEl, IQ) -> ReqFields = get_requested_fields(SubEl), case get_profile(LUser, LServer, ReqFields) of - {ok, Fields} -> - XEl = {xmlelement, "x", [{"xmlns", "jabber:x:data"}, - {"type", "result"}], Fields}, - ProfileEl = {xmlelement, "profile", - [{"xmlns", ?NS_PROFILE}], [XEl]}, - IQ#iq{type = result, - sub_el = - [ProfileEl] - }; - {error, user_not_found} -> - IQ#iq{type = error, - sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; - {error, OtherError} -> - ?ERROR_MSG("Problem found when getting profile of ~p@~p:~n~p", - [LUser, LServer, OtherError]), - IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + {ok, Fields} -> + XEl = #xmlel{name = <<"x">>, + attrs = + [{<<"xmlns">>, <<"jabber:x:data">>}, + {<<"type">>, <<"result">>}], + children = Fields}, + ProfileEl = #xmlel{name = <<"profile">>, + attrs = [{<<"xmlns">>, ?NS_PROFILE}], + children = [XEl]}, + IQ#iq{type = result, sub_el = [ProfileEl]}; + {error, user_not_found} -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; + {error, OtherError} -> + ?ERROR_MSG("Problem found when getting profile of " + "~p@~p:~n~p", + [LUser, LServer, OtherError]), + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end. %%%======================= %%%% Set profile -set_profile(LUser, LServer, {xmlelement, "x", _Attrs, Els}) -> +set_profile(LUser, LServer, + #xmlel{name = <<"x">>, children = Els}) -> US = {LUser, LServer}, - F = fun() -> + F = fun () -> mnesia:write(#profile{us = US, fields = Els}) end, case mnesia:transaction(F) of - {atomic, _} -> - ok; - _ -> - {error, ?ERR_INTERNAL_SERVER_ERROR} + {atomic, _} -> ok; + _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end. %%%======================= @@ -218,87 +220,89 @@ set_profile(LUser, LServer, {xmlelement, "x", _Attrs, Els}) -> get_profile(LUser, LServer, []) -> US = {LUser, LServer}, - F = fun() -> - mnesia:read({profile, US}) - end, + F = fun () -> mnesia:read({profile, US}) end, case mnesia:transaction(F) of - {atomic, [#profile{fields = Fields}]} -> - {ok, Fields}; - {atomic, []} -> - {error, user_not_found}; - OtherResult -> - {error, OtherResult} + {atomic, [#profile{fields = Fields}]} -> {ok, Fields}; + {atomic, []} -> {error, user_not_found}; + OtherResult -> {error, OtherResult} end; - get_profile(LUser, LServer, ReqFields) -> case get_profile(LUser, LServer, []) of - {ok, Fields} -> - filter_profile_fields(Fields, ReqFields); - Other -> Other + {ok, Fields} -> + filter_profile_fields(Fields, ReqFields); + Other -> Other end. filter_profile_fields(Fields, ReqFields) -> filter_profile_fields(Fields, ReqFields, []). -%% Probably there are many stored fields and the requested fields are few, -%% so it's optimal to traverse the requested fields instead of stored fields -filter_profile_fields(StoredFields, [{xmlelement, "field", Attrs, []} | ReqFields], ResFields) -> +filter_profile_fields(StoredFields, + [#xmlel{name = <<"field">>, attrs = Attrs, + children = []} + | ReqFields], + ResFields) -> case lists:keysearch(Attrs, 3, StoredFields) of - {value, StoredField} -> - filter_profile_fields(StoredFields, ReqFields, [StoredField | ResFields]); - false -> - filter_profile_fields(StoredFields, ReqFields, ResFields) + {value, StoredField} -> + filter_profile_fields(StoredFields, ReqFields, + [StoredField | ResFields]); + false -> + filter_profile_fields(StoredFields, ReqFields, + ResFields) end; -filter_profile_fields(StoredFields, [_FieldForm | ReqFields], ResFields) -> - filter_profile_fields(StoredFields, ReqFields, ResFields); +filter_profile_fields(StoredFields, + [_FieldForm | ReqFields], ResFields) -> + filter_profile_fields(StoredFields, ReqFields, + ResFields); filter_profile_fields(_StoredFields, [], ResFields) -> - FieldFormType = {xmlelement, "field", [{"var", "FORM_TYPE"}, {"type", "hidden"}], - [{xmlelement, "value",[], [{xmlcdata, <<"urn:xmpp:tmp:profile">>}]}]}, - %% NOTE: This list reverse is not necessary, it just ensure the returned fields are in the same order than the request + FieldFormType = #xmlel{name = <<"field">>, + attrs = + [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"urn:xmpp:tmp:profile">>}]}]}, {ok, [FieldFormType | lists:reverse(ResFields)]}. - %% TODO: la respuesta a una iq query de fields especificos ha de incluir %%%======================= %%%% Mnesia storage - %%%======================= %%%% PubSub storage - %%%======================= %%%% XML processing %% Copied from exmpp_xml.erl, then customized get_requested_fields(SubEl) -> - case xml:get_subtag(SubEl, "x") of - false -> []; - XEl -> get_elements(XEl, "field") + case xml:get_subtag(SubEl, <<"x">>) of + false -> []; + XEl -> get_elements(XEl, <<"field">>) end. -get_elements({xmlelement, "x", _, Children}, Name) -> +get_elements(#xmlel{name = <<"x">>, + children = Children}, + Name) -> get_elements2(Children, Name); -get_elements(_, _Name) -> - []. +get_elements(_, _Name) -> []. -get_elements2([], _Name) -> - []; +get_elements2([], _Name) -> []; get_elements2(Children, Name) -> lists:filter(filter_by_name(Name), Children). filter_by_name(Searched_Name) -> - fun(XML_Element) -> + fun (XML_Element) -> element_matches(XML_Element, Searched_Name) end. -element_matches({xmlelement, Name, _, _}, Name) -> - true; -element_matches(_XML_Element, _Name) -> - false. +element_matches(#xmlel{name = Name}, Name) -> true; +element_matches(_XML_Element, _Name) -> false. %%%================ %%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: + From bdfe82ce795c66c47427a2695882fdc0095736d4 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 13 Mar 2015 11:54:26 +0100 Subject: [PATCH 4/4] Update README files to show configuration file as YAML (#86) --- ejabberd_auth_http/README.md | 10 ++++---- mod_admin_extra/README.txt | 35 +++++++++++-------------- mod_cron/README.txt | 1 - mod_logsession/README.txt | 2 +- mod_message_log/README.txt | 1 - mod_muc_admin/README.txt | 10 +++----- mod_muc_log_http/README.txt | 1 - mod_multicast/README.txt | 50 +++++++++++++++++++----------------- mod_rest/README.txt | 32 +++++++++-------------- mod_s2s_log/README.txt | 8 +++--- mod_shcommands/README.txt | 2 +- mod_statsdx/README.txt | 41 ++++++++++++----------------- mod_webpresence/README.txt | 7 +---- 13 files changed, 83 insertions(+), 117 deletions(-) diff --git a/ejabberd_auth_http/README.md b/ejabberd_auth_http/README.md index fe61320..dc959a0 100644 --- a/ejabberd_auth_http/README.md +++ b/ejabberd_auth_http/README.md @@ -21,7 +21,7 @@ ejabberd has to validate it externally. ### How to enable The simplest way is to just replace default `auth_method` option in -`ejabberd.cfg` with `{auth_method, http}`. +`ejabberd.yml` with `auth_method: http`. However, enabling the module **is not enough!** Please follow instructions below. @@ -29,12 +29,12 @@ instructions below. ### Configuration options `ejabberd_auth_http` requires some parameters to function -properly. The following options can be set in `auth_opts` tuple in -`ejabberd.cfg`: +properly. The following options can be set in `auth_opts` in +`ejabberd.yml`: * `host` (mandatory, `string`) - consists of protocol, hostname (or IP) and port (optional). Examples: - * `{host, "http://localhost:12000"}` - * `{host, "https://10.20.30.40"}` + * `host: "http://localhost:12000"` + * `host: "https://10.20.30.40"` * `connection_pool_size` (optional, `integer`, default: 10) - the number of connections open to auth service * `connection_opts` (optional, default: `[]`) - extra options for diff --git a/mod_admin_extra/README.txt b/mod_admin_extra/README.txt index 5453bb3..bc3dd6f 100644 --- a/mod_admin_extra/README.txt +++ b/mod_admin_extra/README.txt @@ -4,21 +4,14 @@ Author: Badlop Homepage: http://www.ejabberd.im/mod_admin_extra - Requirements: ejabberd 2.1.10 newer - - This module DOES NOT WORK with any ejabberd 2.0.x or older. - If you have some ejabberd 2.0.x, you can still use mod_ctlextra. CONFIGURATION ============= -Add the module to your ejabberd.cfg, on the modules section: -{modules, [ - ... - {mod_admin_extra, []}, - ... -]}. +Add the module to your ejabberd.yml, on the modules section: +modules: + mod_admin_extra: {} The configurable options are: - module_resource: @@ -30,16 +23,18 @@ In this example configuration, the users vcards can only be modified by executing mod_admin_extra commands. Notice that this needs the patch https://support.process-one.net/browse/EJAB-797 -{acl, adminextraresource, {resource, "modadminextraf8x,31ad"}}. -{access, vcard_set, [ - {allow, adminextraresource}, - {deny, all}] -}. -{modules, [ - {mod_admin_extra, [ {module_resource, "modadminextraf8x,31ad"} ]}, - {mod_vcard, [ {access_set, vcard_set} ]}, - ... -]}. +acl: + adminextraresource: + resource: "modadminextraf8x,31ad" +access: + vcard_set: + adminextraresource: allow + all: deny +modules: + mod_admin_extra: + module_resource: "modadminextraf8x,31ad" + mod_vcard: + access_set: vcard_set USAGE diff --git a/mod_cron/README.txt b/mod_cron/README.txt index 483b332..15af70b 100644 --- a/mod_cron/README.txt +++ b/mod_cron/README.txt @@ -3,7 +3,6 @@ http://www.ejabberd.im/mod_cron Author: Badlop - Requirements: ejabberd git master This module allows advanced ejabberd administrators to schedule commands for diff --git a/mod_logsession/README.txt b/mod_logsession/README.txt index 033fdf0..262fce8 100644 --- a/mod_logsession/README.txt +++ b/mod_logsession/README.txt @@ -22,7 +22,7 @@ Note: to log the failed authentication attempts, you need to patch ejabberd. 1 Copy this file to ejabberd/src/mod_logsession.erl 2 Recompile ejabberd -3 Add to ejabberd.cfg, 'modules' section the basic configuration: +3 Add to ejabberd.yml, 'modules' section the basic configuration: mod_logsession: {} 4 With this configuration, the log files are: /tmp/ejabberd_logsession_@HOST@.log diff --git a/mod_message_log/README.txt b/mod_message_log/README.txt index e8b052e..e9c55f7 100644 --- a/mod_message_log/README.txt +++ b/mod_message_log/README.txt @@ -2,7 +2,6 @@ mod_message_log - Log one line per message transmission Author: Holger Weiss - Requirements: ejabberd 13.x or newer DESCRIPTION diff --git a/mod_muc_admin/README.txt b/mod_muc_admin/README.txt index c70fbf8..7f4fafb 100644 --- a/mod_muc_admin/README.txt +++ b/mod_muc_admin/README.txt @@ -4,7 +4,6 @@ Homepage: http://www.ejabberd.im/mod_muc_admin Author: Badlop - Requirements: ejabberd trunk SVN 1699 or newer This module implements several ejabberd commands that can be @@ -17,12 +16,9 @@ rooms. CONFIGURATION ============= -Add the module to your ejabberd.cfg, on the modules section: -{modules, [ - ... - {mod_muc_admin, []}, - ... -]}. +Add the module to your ejabberd.yml, on the modules section: +modules: + mod_muc_admin: {} EJABBERD COMMANDS diff --git a/mod_muc_log_http/README.txt b/mod_muc_log_http/README.txt index b97d556..4bec37f 100644 --- a/mod_muc_log_http/README.txt +++ b/mod_muc_log_http/README.txt @@ -4,7 +4,6 @@ Homepage: http://ejabberd.im/mod_muc_log_http Author: Badlop - Requirement: ejabberd git master DESCRIPTION diff --git a/mod_multicast/README.txt b/mod_multicast/README.txt index b0bed55..44dca53 100644 --- a/mod_multicast/README.txt +++ b/mod_multicast/README.txt @@ -4,7 +4,6 @@ Homepage: http://ejabberd.jabber.ru/mod_multicast Author: Badlop - Module for ejabberd master branch DESCRIPTION @@ -20,8 +19,8 @@ The development of this module is included on a Google Summer of Code 2007 proje 1. Compile the module. 2. Copy the binary files to ejabberd ebin directory. -3. Edit ejabberd.cfg and add the module to the list of modules: - {mod_multicast, []}, +3. Edit ejabberd.yml and add the module to the list of modules: + mod_multicast: {} 4. Start ejabberd. @@ -48,31 +47,34 @@ limits: EXAMPLE CONFIGURATION --------------------- -% Only admins can send packets to multicast service -{access, multicast, [{allow, admin}, {deny, all}]}. +# Only admins can send packets to multicast service +access: + multicast: + admin: allow + all: deny -% If you want to allow all your users: -%{access, multicast, [{allow, all}]}. +# If you want to allow all your users: +access: + multicast: + all: allow -% This allows both admins and remote users to send packets, -% but does not allow local users -%{acl, allservers, {server_glob, "*"}}. -%{access, multicast, [{allow, admin}, {deny, local}, {allow, allservers}]}. +# This allows both admins and remote users to send packets, +# but does not allow local users +acl: + allservers: + server_glob: "*" +access: + multicast: + admin: allow + local: deny + allservers: allow -{modules, [ - ... - {mod_multicast, [ - %{host, "multicast.example.org"}, - {access, multicast}, - {limits, [ - {local, message, 40}, - {local, presence, infinite}, - {remote, message, 150} - ]} - ]}, - ... -]}. +modules: + mod_multicast: + host: "multicast.example.org" + access: multicast + limits, "> [ {local,message,40}, {local,presence,infinite}, {remote,message,150} ]." TO DO diff --git a/mod_rest/README.txt b/mod_rest/README.txt index 1e47510..7de9551 100644 --- a/mod_rest/README.txt +++ b/mod_rest/README.txt @@ -4,8 +4,6 @@ Author: Nolan Eakins Copyright (C) 2008 Nolan Eakins - Requirements: ejabberd trunk SVN 2025 (ejabberd 2.1.0, once released) - This is an ejabberd module that adds an HTTP handler that allows HTTP @@ -20,27 +18,21 @@ This module can also be used as a frontend to execute ejabberd commands. ============= To use this module, follow the general build instructions, and configure -in ejabberd.cfg as described. +in ejabberd.yml as described. Enable the module: -{modules, - [ - {mod_rest, [ {allowed_ips, [ {127,0,0,1} ]} ]}, - ... - ] -}. +modules: + mod_rest: + allowed_ips: + - "> {127,0,0,1} ." And enable the HTTP request handler in the listen section: -{listen, - [ - ... - {5285, ejabberd_http, [ - {request_handlers, [ - {["rest"], mod_rest} - ]} - ]} - ] -}. +listen: + - + port: 5285 + module: ejabberd_http + request_handlers: + "/rest": mod_rest With that configuration, you can send HTTP POST requests to the URL: http://localhost:5285/rest @@ -70,7 +62,7 @@ Configurable options: There is more information about AccessCommands in the ejabberd Guide. Default value: [] -Complex example configuration: +Complex example configuration (works only when set in an old-format ejabberd.cfg file: {modules, [ {mod_rest, [ diff --git a/mod_s2s_log/README.txt b/mod_s2s_log/README.txt index 8fab2e7..b7bc129 100644 --- a/mod_s2s_log/README.txt +++ b/mod_s2s_log/README.txt @@ -2,13 +2,11 @@ mod_s2s_log ----------- - Requirements: ejabberd SVN r1235 trunk or 2.0.x branch - (ejabberd 2.0.1 or newer is required) - This module can be use to keep a track of other XMPP servers your server has been connected with. You can use it by adding the following line in the modules section of -ejabberd.cfg: - {mod_s2s_log, [{filename, "/path/to/s2s.log"}]} +ejabberd.yml: + mod_s2s_log: + filename: "/path/to/s2s.log" diff --git a/mod_shcommands/README.txt b/mod_shcommands/README.txt index 8d838d0..b2acf3e 100644 --- a/mod_shcommands/README.txt +++ b/mod_shcommands/README.txt @@ -62,6 +62,6 @@ administrators. BASIC CONFIGURATION =================== -Add the module to your ejabberd.cfg, on the modules section: +Add the module to your ejabberd.yml, on the modules section: modules: mod_shcommands: {} diff --git a/mod_statsdx/README.txt b/mod_statsdx/README.txt index e736035..6111b56 100644 --- a/mod_statsdx/README.txt +++ b/mod_statsdx/README.txt @@ -3,7 +3,6 @@ Homepage: http://www.ejabberd.im/mod_statsdx Author: Badlop - Requirements: ejabberd 2.1.x mod_statsdx @@ -16,11 +15,9 @@ Web Admin and two ejabberd commands to view the information. CONFIGURE --------- -Enable the module in ejabberd.cfg for example with a basic configuration: -{modules, [ - ... - {mod_statsdx, []} - ]}. +Enable the module in ejabberd.yml for example with a basic configuration: +modules: + mod_statsdx: {} Configurable options: hooks: Set to 'true' to enable hooks and related statistics. @@ -32,10 +29,9 @@ Configurable options: EXAMPLE CONFIGURATION --------------------- -{modules, [ - ... - {mod_statsdx, [{hooks, true}]} - ]}. +modules: + mod_statsdx: + hooks: true FEATURE REQUESTS @@ -65,11 +61,9 @@ text file with descriptions and raw text file (for MRTG, RRDTool...). This module requires mod_statsdx. -Enable the module in ejabberd.cfg for example with a basic configuration: -{modules, [ - ... - {mod_stats2file, []} - ]}. +Enable the module in ejabberd.yml for example with a basic configuration: +modules: + mod_stats2file: {} Configurable options: interval: Time between updates, in minutes (default: 5) @@ -82,14 +76,11 @@ Configurable options: EXAMPLE CONFIGURATION --------------------- -{modules, [ - ... - {mod_stats2file, [{interval, 60}, - {type, txt}, - {split, true}, - {basefilename, "/var/www/stats"}, - {hosts, ["localhost", "server3.com"]} - ]} - ]}. - +modules: + mod_stats2file: + interval: 60 + type: txt + split: true + basefilename: "/var/www/stats" + hosts: ["localhost", "server3.com"] diff --git a/mod_webpresence/README.txt b/mod_webpresence/README.txt index 3d4cb3b..68284af 100644 --- a/mod_webpresence/README.txt +++ b/mod_webpresence/README.txt @@ -32,7 +32,7 @@ No web server, database, additional libraries or programs are required. 3. Copy the directory data/pixmaps to a directory you prefer. -4. Edit ejabberd.cfg and add the HTTP and module definitions: +4. Edit ejabberd.yml and add the HTTP and module definitions: listen: - @@ -43,7 +43,6 @@ listen: "presence": mod_webpresence modules: - [...] mod_webpresence: pixmaps_path: "/path/to/pixmaps" @@ -122,12 +121,10 @@ listen: - port: 5280 module: ejabberd_http - [...] request_handlers: "presence": mod_webpresence modules: - [...] mod_webpresence: pixmaps_path: "/path/to/pixmaps" @@ -139,12 +136,10 @@ listen: - port: 80 module: ejabberd_http - [...] request_handlers: "status": mod_webpresence modules: - [...] mod_webpresence: host: "webstatus.@HOST@" access: local