summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile2
-rw-r--r--src/ejabberd_c2s.erl42
-rw-r--r--src/ejabberd_s2s.erl8
-rw-r--r--src/mod_disco.erl74
-rw-r--r--src/mod_roster.erl5
-rw-r--r--src/msgs/ru.msg3
6 files changed, 112 insertions, 22 deletions
diff --git a/src/Makefile b/src/Makefile
index 12ff0b40..6bee2bb3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -5,7 +5,7 @@ INCLUDES = -I/usr/lib/erlang/usr/include \
LIBDIRS = -L/usr/lib/erlang/lib/erl_interface-3.3.0/lib
-ERLSHLIBS = expat_erl.so sha_erl.so
+ERLSHLIBS = expat_erl.so
all: $(ERLSHLIBS)
erl -make
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 0d7a864d..725390cc 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -298,6 +298,9 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
From,
jlib:iq_to_xml(ResIQ)),
{false, Attrs, StateData};
+ %{iq, ID, Type, ?NS_VCARD, SubEl} ->
+ % TODO: don't pass packets until roster loaded
+ %{true, Attrs, StateData};
_ ->
{true, Attrs, StateData}
end;
@@ -605,37 +608,56 @@ remove_element(E, Set) ->
roster_change(IJID, ISubscription, StateData) ->
LIJID = jlib:jid_tolower(IJID),
+ IsFrom = (ISubscription == both) or (ISubscription == from),
+ IsTo = (ISubscription == both) or (ISubscription == to),
+ FSet = if
+ IsFrom ->
+ ?SETS:add_element(LIJID, StateData#state.pres_f);
+ true ->
+ remove_element(LIJID, StateData#state.pres_f)
+ end,
+ TSet = if
+ IsTo ->
+ ?SETS:add_element(LIJID, StateData#state.pres_t);
+ true ->
+ remove_element(LIJID, StateData#state.pres_t)
+ end,
case StateData#state.pres_last of
unknown ->
- StateData;
+ StateData#state{pres_f = FSet, pres_t = TSet};
P ->
?DEBUG("roster changed for ~p~n", [StateData#state.user]),
From = {StateData#state.user,
StateData#state.server,
StateData#state.resource},
- Cond1 = (not StateData#state.pres_invis)
- and ((ISubscription == both) or (ISubscription == from)),
- Cond2 = ((ISubscription == none) or (ISubscription == to))
- and (?SETS:is_element(From, StateData#state.pres_a) or
- ?SETS:is_element(From, StateData#state.pres_i)),
+ Cond1 = (not StateData#state.pres_invis) and IsFrom,
+ Cond2 = (not IsFrom)
+ and (?SETS:is_element(LIJID, StateData#state.pres_a) or
+ ?SETS:is_element(LIJID, StateData#state.pres_i)),
if
Cond1 ->
?DEBUG("C1: ~p~n", [LIJID]),
ejabberd_router:route(From, IJID, P),
A = ?SETS:add_element(LIJID,
StateData#state.pres_a),
- StateData#state{pres_a = A};
+ StateData#state{pres_a = A,
+ pres_f = FSet,
+ pres_t = TSet};
Cond2 ->
?DEBUG("C2: ~p~n", [LIJID]),
- ejabberd_router:route(From, IJID, P),
+ ejabberd_router:route(From, IJID,
+ {xmlelement, "presence",
+ [{"type", "unavailable"}], []}),
I = remove_element(LIJID,
StateData#state.pres_i),
A = remove_element(LIJID,
StateData#state.pres_a),
StateData#state{pres_i = I,
- pres_a = A};
+ pres_a = A,
+ pres_f = FSet,
+ pres_t = TSet};
true ->
- StateData
+ StateData#state{pres_f = FSet, pres_t = TSet}
end
end.
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl
index 87c11139..a597a624 100644
--- a/src/ejabberd_s2s.erl
+++ b/src/ejabberd_s2s.erl
@@ -13,7 +13,8 @@
-export([start/0, init/0,
have_connection/1,
get_key/1,
- try_register/1]).
+ try_register/1,
+ dirty_get_connections/0]).
-include_lib("mnemosyne/include/mnemosyne.hrl").
-include("ejabberd.hrl").
@@ -193,3 +194,8 @@ do_route(From, To, Packet) ->
send_element(Pid, El) ->
Pid ! {send_element, El}.
+
+
+dirty_get_connections() ->
+ mnesia:dirty_all_keys(s2s).
+
diff --git a/src/mod_disco.erl b/src/mod_disco.erl
index 4c05791c..9284e141 100644
--- a/src/mod_disco.erl
+++ b/src/mod_disco.erl
@@ -53,8 +53,8 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
[{"code", "405"}],
[{xmlcdata, "Not Allowed"}]}]};
get ->
- case xml:get_tag_attr_s("node", SubEl) of
- "" ->
+ case string:tokens(xml:get_tag_attr_s("node", SubEl), "/") of
+ [] ->
Domains =
lists:map(fun domain_to_xml/1,
ejabberd_router:dirty_get_all_routes()),
@@ -70,18 +70,33 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{xmlelement, "item",
[{"jid", jlib:jid_to_string(To)},
{"name", translate:translate(Lang, "All Users")},
- {"node", "all users"}], []}]
- }]};
- "online users" ->
+ {"node", "all users"}], []},
+ {xmlelement, "item",
+ [{"jid", jlib:jid_to_string(To)},
+ {"name", translate:translate(
+ Lang, "Outgoing S2S connections")},
+ {"node", "outgoing s2s"}], []}
+ ]}]};
+ ["online users"] ->
{iq, ID, result, XMLNS,
[{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
get_online_users()
}]};
- "all users" ->
+ ["all users"] ->
{iq, ID, result, XMLNS,
[{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
get_all_users()
}]};
+ ["outgoing s2s"] ->
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
+ get_outgoing_s2s(Lang)
+ }]};
+ ["outgoing s2s", Host] ->
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
+ get_outgoing_s2s(Lang, Host)
+ }]};
_ ->
{iq, ID, error, XMLNS,
[SubEl, {xmlelement, "error",
@@ -98,8 +113,8 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
[{"code", "405"}],
[{xmlcdata, "Not Allowed"}]}]};
get ->
- case xml:get_tag_attr_s("node", SubEl) of
- "" ->
+ case string:tokens(xml:get_tag_attr_s("node", SubEl), "/") of
+ [] ->
Features = lists:map(fun feature_to_xml/1,
ets:tab2list(disco_features)),
{iq, ID, result, XMLNS, [{xmlelement,
@@ -111,8 +126,9 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{"name", "ejabberd"}], []}] ++
Features
}]};
- "online users" -> ?EMPTY_INFO_RESULT;
- "all users" -> ?EMPTY_INFO_RESULT;
+ ["online users"] -> ?EMPTY_INFO_RESULT;
+ ["all users"] -> ?EMPTY_INFO_RESULT;
+ ["outgoing s2s" | _] -> ?EMPTY_INFO_RESULT;
_ ->
{iq, ID, error, XMLNS,
[SubEl, {xmlelement, "error",
@@ -153,6 +169,44 @@ get_all_users() ->
end, lists:sort(Users))
end.
+get_outgoing_s2s(Lang) ->
+ case catch ejabberd_s2s:dirty_get_connections() of
+ {'EXIT', Reason} ->
+ [];
+ Connections ->
+ lists:map(
+ fun({F, T}) ->
+ {xmlelement, "item",
+ [{"jid", ?MYNAME},
+ {"node", "outgoing s2s/" ++ T},
+ {"name",
+ lists:flatten(
+ io_lib:format(
+ translate:translate(Lang, "To ~s"), [T]))}],
+ []}
+ end, lists:keysort(2, Connections))
+ end.
+
+get_outgoing_s2s(Lang, To) ->
+ case catch ejabberd_s2s:dirty_get_connections() of
+ {'EXIT', Reason} ->
+ [];
+ Connections ->
+ lists:map(
+ fun({F, T}) ->
+ {xmlelement, "item",
+ [{"jid", ?MYNAME},
+ {"node", "outgoing s2s/" ++ To ++ "/" ++ F},
+ {"name",
+ lists:flatten(
+ io_lib:format(
+ translate:translate(Lang, "From ~s"), [F]))}],
+ []}
+ end, lists:keysort(1, lists:filter(fun(E) ->
+ element(2, E) == To
+ end, Connections)))
+ end.
+
process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = To,
diff --git a/src/mod_roster.erl b/src/mod_roster.erl
index 281a7094..5de590f4 100644
--- a/src/mod_roster.erl
+++ b/src/mod_roster.erl
@@ -239,6 +239,11 @@ process_item_els(Item, []) ->
push_item(User, From, Item) ->
+ ejabberd_sm ! {route, {"", "", ""}, {User, "", ""},
+ {xmlelement, "broadcast", [],
+ [{item,
+ Item#roster.jid,
+ Item#roster.subscription}]}},
lists:foreach(fun(Resource) ->
push_item(User, Resource, From, Item)
end, ejabberd_sm:get_user_resources(User)).
diff --git a/src/msgs/ru.msg b/src/msgs/ru.msg
index 27b837ca..429a6cb7 100644
--- a/src/msgs/ru.msg
+++ b/src/msgs/ru.msg
@@ -3,6 +3,9 @@
% mod_disco.erl
{"Online Users", "Подключённые пользователи"}.
{"All Users", "Все пользователи"}.
+{"Outgoing S2S connections", "Исходящие S2S-соединения"}.
+{"To ~s", "К ~s"}.
+{"From ~s", "От ~s"}.
% mod_vcard.erl