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

Merge from trunk (r1709 to r1730).

Ejabberd should be usable again.

PR:		EJABP-1

SVN Revision: 1731
This commit is contained in:
Jean-Sébastien Pédron 2008-12-16 13:16:56 +00:00
parent 62f9f6e6c5
commit 6a3436b1c4
4 changed files with 106 additions and 85 deletions

View File

@ -1,3 +1,9 @@
2008-12-16 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
Merge from trunk (r1709 to r1730).
Ejabberd should be usable again.
2008-12-16 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-12-16 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_pubsub/mod_pubsub.erl: Convert to exmpp the parts recently * src/mod_pubsub/mod_pubsub.erl: Convert to exmpp the parts recently
@ -9,6 +15,10 @@
* src/mod_pubsub/mod_pubsub.erl: Fix get_item_name deadlock on * src/mod_pubsub/mod_pubsub.erl: Fix get_item_name deadlock on
transaction transaction
2008-12-12 Alexey Shchepin <alexey@process-one.net>
* src/ejabberd_c2s.erl: Bugfix in "from" attribute checking
2008-12-10 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-12-10 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/eldap/eldap_utils.erl (case_insensitive_match/2): Replace * src/eldap/eldap_utils.erl (case_insensitive_match/2): Replace
@ -18,9 +28,46 @@
* src/mod_pubsub: Merge from latest trunk (r1716). * src/mod_pubsub: Merge from latest trunk (r1716).
2008-12-09 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: prevent publish items with invalid
XML schema bugfix (EJAB-699) (previous commit was uncomplete)
and fix bug injected in previous commit
2008-12-08 Christophe Romain <christophe.romain@process-one.net>
* src/ejabberd_c2s.erl: Reduce memory consumption due to caps handling
* src/mod_pubsub/mod_pubsub.erl: Likewise
* src/mod_caps.erl: Likewise
* src/mod_pubsub/mod_pubsub.erl: ignore unknown configuration fields
(EJAB-762) (thanks to Jack Moffitt)
* src/mod_pubsub/mod_pubsub.erl: fix node authorization bug (EJAB-798)
send authorization update event (EJAB-799) (thanks to Brian Cully)
* src/mod_pubsub/mod_pubsub.erl: add nodetree filtering and
authorization (EJAB-813) (thanks to Brian Cully)
* src/mod_pubsub/nodetree_default.erl: Likewise
* src/mod_pubsub/nodetree_virtual.erl: Likewise
* src/mod_pubsub/gen_pubsub_nodetree.erl: Likewise
* src/mod_pubsub/mod_pubsub.erl: prevent publish items with invalid
XML schema (EJAB-699)
* src/mod_pubsub/pubsub.hrl: remove unused pubsub_presence record
* src/mod_pubsub/node_flat.erl: renamed from node_zoo
* src/mod_pubsub/mod_pubsub.erl: reply to suscriptions options queries
with unsupported feature error (EJAB-713)
* src/mod_pubsub/node_default.erl: remove pubsub_state record when
unsubscribing node without affiliation (EJAB-776)
2008-12-08 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-12-08 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_pubsub: Merge from trunk (r1692 to r1709). Merge from trunk (r1692 to r1709).
2008-12-08 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-12-08 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>

View File

@ -37,8 +37,7 @@
send_element/2, send_element/2,
socket_type/0, socket_type/0,
get_presence/1, get_presence/1,
get_subscribed/1, get_subscribed/1]).
get_subscribed_and_online/1]).
%% gen_fsm callbacks %% gen_fsm callbacks
-export([init/1, -export([init/1,
@ -85,7 +84,6 @@
pres_f = ?SETS:new(), pres_f = ?SETS:new(),
pres_a = ?SETS:new(), pres_a = ?SETS:new(),
pres_i = ?SETS:new(), pres_i = ?SETS:new(),
pres_available = ?DICT:new(),
pres_last, pres_pri, pres_last, pres_pri,
pres_timestamp, pres_timestamp,
pres_invis = false, pres_invis = false,
@ -205,14 +203,8 @@ init([{SockMod, Socket}, Opts]) ->
end. end.
%% Return list of all available resources of contacts, %% Return list of all available resources of contacts,
%% in form [{JID, Caps}].
get_subscribed(FsmRef) -> get_subscribed(FsmRef) ->
gen_fsm:sync_send_all_state_event( gen_fsm:sync_send_all_state_event(FsmRef, get_subscribed, 1000).
FsmRef, get_subscribed, 1000).
get_subscribed_and_online(FsmRef) ->
gen_fsm:sync_send_all_state_event(
FsmRef, get_subscribed_and_online, 1000).
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%% Func: StateName/2 %% Func: StateName/2
@ -951,29 +943,8 @@ handle_sync_event({get_presence}, _From, StateName, StateData) ->
fsm_reply(Reply, StateName, StateData); fsm_reply(Reply, StateName, StateData);
handle_sync_event(get_subscribed, _From, StateName, StateData) -> handle_sync_event(get_subscribed, _From, StateName, StateData) ->
Subscribed = StateData#state.pres_f, Subscribed = ?SETS:to_list(StateData#state.pres_f),
Online = StateData#state.pres_available, {reply, Subscribed, StateName, StateData};
Pred = fun({U, S, _} = User, _Caps) ->
?SETS:is_element({U, S, undefined},
Subscribed) orelse
?SETS:is_element(User, Subscribed)
end,
SubscribedAndOnline = ?DICT:filter(Pred, Online),
SubscribedWithCaps = ?SETS:fold(fun(User, Acc) ->
[{User, undefined}|Acc]
end, ?DICT:to_list(SubscribedAndOnline), Subscribed),
{reply, SubscribedWithCaps, StateName, StateData};
handle_sync_event(get_subscribed_and_online, _From, StateName, StateData) ->
Subscribed = StateData#state.pres_f,
Online = StateData#state.pres_available,
Pred = fun({U, S, _R} = User, _Caps) ->
?SETS:is_element({U, S, undefined},
Subscribed) orelse
?SETS:is_element(User, Subscribed)
end,
SubscribedAndOnline = ?DICT:filter(Pred, Online),
{reply, ?DICT:to_list(SubscribedAndOnline), StateName, StateData};
handle_sync_event(_Event, _From, StateName, StateData) -> handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok, Reply = ok,
@ -1065,42 +1036,39 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
LFrom = jlib:short_prepd_jid(From), LFrom = jlib:short_prepd_jid(From),
LBFrom = jlib:short_prepd_bare_jid(From), LBFrom = jlib:short_prepd_bare_jid(From),
%% Note contact availability %% Note contact availability
Els = Packet#xmlel.children, case exmpp_presence:get_type(Packet) of
Caps = mod_caps:read_caps(Els), 'unavailable' ->
mod_caps:note_caps(StateData#state.server, From, Caps), mod_caps:clear_caps(From);
NewAvailable = case exmpp_presence:get_type(Packet) of _ ->
'unavailable' -> Caps = mod_caps:read_caps(Packet#xmlel.children),
?DICT:erase(LFrom, StateData#state.pres_available); mod_caps:note_caps(StateData#state.server, From, Caps)
_ -> end,
?DICT:store(LFrom, Caps, StateData#state.pres_available)
end,
NewStateData = StateData#state{pres_available = NewAvailable},
case ?SETS:is_element( case ?SETS:is_element(
LFrom, NewStateData#state.pres_a) orelse LFrom, StateData#state.pres_a) orelse
?SETS:is_element( ?SETS:is_element(
LBFrom, NewStateData#state.pres_a) of LBFrom, StateData#state.pres_a) of
true -> true ->
{true, Attrs, NewStateData}; {true, Attrs, StateData};
false -> false ->
case ?SETS:is_element( case ?SETS:is_element(
LFrom, NewStateData#state.pres_f) of LFrom, StateData#state.pres_f) of
true -> true ->
A = ?SETS:add_element( A = ?SETS:add_element(
LFrom, LFrom,
NewStateData#state.pres_a), StateData#state.pres_a),
{true, Attrs, {true, Attrs,
NewStateData#state{pres_a = A}}; StateData#state{pres_a = A}};
false -> false ->
case ?SETS:is_element( case ?SETS:is_element(
LBFrom, NewStateData#state.pres_f) of LBFrom, StateData#state.pres_f) of
true -> true ->
A = ?SETS:add_element( A = ?SETS:add_element(
LBFrom, LBFrom,
NewStateData#state.pres_a), StateData#state.pres_a),
{true, Attrs, {true, Attrs,
NewStateData#state{pres_a = A}}; StateData#state{pres_a = A}};
false -> false ->
{true, Attrs, NewStateData} {true, Attrs, StateData}
end end
end end
end; end;
@ -1907,28 +1875,15 @@ is_ip_blacklisted({IP,_Port}) ->
check_from(El, FromJID) -> check_from(El, FromJID) ->
case exmpp_stanza:get_sender(El) of case exmpp_stanza:get_sender(El) of
undefined -> undefined ->
exmpp_stanza:set_sender(El, FromJID); El;
JIDElString -> SJID ->
try try
JIDEl = exmpp_jid:list_to_jid(JIDElString), JID = exmpp_jid:list_to_jid(SJID),
case JIDEl#jid.lresource of case exmpp_jid:compare_jids(JID, FromJID) of
undefined -> true ->
%% Matching JID: The stanza is ok El;
if JIDEl#jid.lnode == FromJID#jid.lnode andalso false ->
JIDEl#jid.ldomain == FromJID#jid.ldomain -> 'invalid-from'
El;
true ->
'invalid-from'
end;
_ ->
%% Matching JID: The stanza is ok
if JIDEl#jid.lnode == FromJID#jid.lnode andalso
JIDEl#jid.ldomain == FromJID#jid.ldomain andalso
JIDEl#jid.lresource == FromJID#jid.lresource ->
El;
true ->
'invalid-from'
end
end end
catch catch
_:_ -> _:_ ->

View File

@ -31,7 +31,9 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([read_caps/1, -export([read_caps/1,
get_caps/1,
note_caps/3, note_caps/3,
clear_caps/1,
get_features/2, get_features/2,
handle_disco_response/3]). handle_disco_response/3]).
@ -58,6 +60,7 @@
-record(caps, {node, version, exts}). -record(caps, {node, version, exts}).
-record(caps_features, {node_pair, features}). -record(caps_features, {node_pair, features}).
-record(user_caps, {jid, caps}).
-record(state, {host, -record(state, {host,
disco_requests = ?DICT:new(), disco_requests = ?DICT:new(),
feature_queries = []}). feature_queries = []}).
@ -80,12 +83,26 @@ read_caps([_ | Tail], Result) ->
read_caps([], Result) -> read_caps([], Result) ->
Result. Result.
%% get_caps reads user caps from database
get_caps(JID) ->
case catch mnesia:dirty_read({user_caps, list_to_binary(exmpp_jid:jid_to_list(JID))}) of
[#user_caps{caps=Caps}] ->
Caps;
_ ->
nothing
end.
%% clear_caps removes user caps from database
clear_caps(JID) ->
catch mnesia:dirty_delete({user_caps, list_to_binary(exmpp_jid:jid_to_list(JID))}).
%% note_caps should be called to make the module request disco %% note_caps should be called to make the module request disco
%% information. Host is the host that asks, From is the full JID that %% information. Host is the host that asks, From is the full JID that
%% sent the caps packet, and Caps is what read_caps returned. %% sent the caps packet, and Caps is what read_caps returned.
note_caps(Host, From, Caps) -> note_caps(Host, From, Caps) ->
case Caps of case Caps of
nothing -> ok; nothing ->
ok;
_ -> _ ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
gen_server:cast(Proc, {note_caps, From, Caps}) gen_server:cast(Proc, {note_caps, From, Caps})
@ -129,7 +146,9 @@ init([Host, _Opts]) ->
mnesia:create_table(caps_features, mnesia:create_table(caps_features,
[{ram_copies, [node()]}, [{ram_copies, [node()]},
{attributes, record_info(fields, caps_features)}]), {attributes, record_info(fields, caps_features)}]),
mnesia:add_table_copy(caps_features, node(), ram_copies), mnesia:create_table(user_caps,
[{disc_copies, [node()]},
{attributes, record_info(fields, user_caps)}]),
{ok, #state{host = Host}}. {ok, #state{host = Host}}.
maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) -> maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) ->
@ -177,10 +196,12 @@ handle_call(stop, _From, State) ->
{stop, normal, ok, State}. {stop, normal, ok, State}.
handle_cast({note_caps, From, handle_cast({note_caps, From,
#caps{node = Node, version = Version, exts = Exts}}, #caps{node = Node, version = Version, exts = Exts} = Caps},
#state{host = Host, disco_requests = Requests} = State) -> #state{host = Host, disco_requests = Requests} = State) ->
%% XXX: this leads to race conditions where ejabberd will send %% XXX: this leads to race conditions where ejabberd will send
%% lots of caps disco requests. %% lots of caps disco requests.
mnesia:dirty_write(#user_caps{jid = list_to_binary(exmpp_jid:jid_to_list(From)),
caps = Caps}),
SubNodes = [Version | Exts], SubNodes = [Version | Exts],
%% Now, find which of these are not already in the database. %% Now, find which of these are not already in the database.
Fun = fun() -> Fun = fun() ->
@ -195,11 +216,9 @@ handle_cast({note_caps, From,
end, end,
case mnesia:transaction(Fun) of case mnesia:transaction(Fun) of
{atomic, Missing} -> {atomic, Missing} ->
%% For each unknown caps "subnode", we send a disco %% For each unknown caps "subnode", we send a disco request.
%% request. NewRequests = lists:foldl(
NewRequests = fun(SubNode, Dict) ->
lists:foldl(
fun(SubNode, Dict) ->
ID = randoms:get_string(), ID = randoms:get_string(),
Query = exmpp_xml:set_attribute( Query = exmpp_xml:set_attribute(
#xmlel{ns = ?NS_DISCO_INFO, name = 'query'}, #xmlel{ns = ?NS_DISCO_INFO, name = 'query'},

View File

@ -480,9 +480,9 @@ handle_cast({presence, JID, Pid}, State) ->
case catch ejabberd_c2s:get_subscribed(Pid) of case catch ejabberd_c2s:get_subscribed(Pid) of
Contacts when is_list(Contacts) -> Contacts when is_list(Contacts) ->
lists:foreach( lists:foreach(
fun({{User, Server, _}, _}) -> fun({User, Server, _}) ->
Owner = {User, Server, undefined}, Owner = {User, Server, undefined},
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options} = PN) -> lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) ->
case get_option(Options, send_last_published_item) of case get_option(Options, send_last_published_item) of
on_sub_and_presence -> on_sub_and_presence ->
case is_caps_notify(ServerHost, Node, LJID) of case is_caps_notify(ServerHost, Node, LJID) of