mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-26 17:38:45 +01:00
Copy changes from Apollo's mod_xmlrpc to 2.2.x's mod_xmlrpc
Changes: * link_contacts new arguments: group1::string, group2::string * New method add_rosteritem_groups/5 * New method del_rosteritem_groups/5 * New method modify_rosteritem_groups/7 * get_roster change argument group::string -> groups::[string]
This commit is contained in:
parent
437d8c6b7c
commit
5cd3de9cd7
@ -73,6 +73,9 @@
|
|||||||
stop/1]).
|
stop/1]).
|
||||||
|
|
||||||
-export([add_rosteritem/6]).
|
-export([add_rosteritem/6]).
|
||||||
|
-export([add_rosteritem_groups/5,
|
||||||
|
del_rosteritem_groups/5,
|
||||||
|
modify_rosteritem_groups/7]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
@ -224,12 +227,12 @@ handler(_State, {call, add_rosteritem, [{struct, Struct}]}) ->
|
|||||||
|
|
||||||
%% link_contacts struct[{jid1, String}, {nick1, String}, {jid2, String}, {nick2, String}] Integer
|
%% link_contacts struct[{jid1, String}, {nick1, String}, {jid2, String}, {nick2, String}] Integer
|
||||||
handler(_State, {call, link_contacts, [{struct, Struct}]}) ->
|
handler(_State, {call, link_contacts, [{struct, Struct}]}) ->
|
||||||
[{jid1, JID1}, {jid2, JID2}, {nick1, Nick1}, {nick2, Nick2}] = lists:sort(Struct),
|
[{group1, G1}, {group2, G2}, {jid1, JID1}, {jid2, JID2}, {nick1, Nick1}, {nick2, Nick2}] = lists:sort(Struct),
|
||||||
{U1, S1, _} = jlib:jid_tolower(jlib:string_to_jid(JID1)),
|
{U1, S1, _} = jlib:jid_tolower(jlib:string_to_jid(JID1)),
|
||||||
{U2, S2, _} = jlib:jid_tolower(jlib:string_to_jid(JID2)),
|
{U2, S2, _} = jlib:jid_tolower(jlib:string_to_jid(JID2)),
|
||||||
case {ejabberd_auth:is_user_exists(U1, S1), ejabberd_auth:is_user_exists(U2, S2)} of
|
case {ejabberd_auth:is_user_exists(U1, S1), ejabberd_auth:is_user_exists(U2, S2)} of
|
||||||
{true, true} ->
|
{true, true} ->
|
||||||
case link_contacts(JID1, Nick1, JID2, Nick2) of
|
case link_contacts(JID1, Nick1, G1, JID2, Nick2, G2) of
|
||||||
{atomic, ok} ->
|
{atomic, ok} ->
|
||||||
{false, {response, [0]}};
|
{false, {response, [0]}};
|
||||||
_ ->
|
_ ->
|
||||||
@ -262,8 +265,64 @@ handler(_State, {call, unlink_contacts, [{struct, Struct}]}) ->
|
|||||||
{false, {response, [404]}}
|
{false, {response, [404]}}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
handler(_State, {call, add_rosteritem_groups, [{struct, Struct}]}) ->
|
||||||
|
[{jid, JID}, {newgroups, NewGroupsString}, {push, PushString}, {server, Server}, {user, User}] = lists:sort(Struct),
|
||||||
|
{U1, S1, _} = jlib:jid_tolower(jlib:string_to_jid(JID)),
|
||||||
|
NewGroups = string:tokens(NewGroupsString, ";"),
|
||||||
|
Push = list_to_atom(PushString),
|
||||||
|
case {ejabberd_auth:is_user_exists(U1, S1), ejabberd_auth:is_user_exists(User, Server)} of
|
||||||
|
{true, true} ->
|
||||||
|
case add_rosteritem_groups(User, Server, JID, NewGroups, Push) of
|
||||||
|
ok ->
|
||||||
|
{false, {response, [0]}};
|
||||||
|
Error ->
|
||||||
|
?INFO_MSG("Error found: ~n~p", [Error]),
|
||||||
|
{false, {response, [1]}}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{false, {response, [404]}}
|
||||||
|
end;
|
||||||
|
|
||||||
|
handler(_State, {call, del_rosteritem_groups, [{struct, Struct}]}) ->
|
||||||
|
[{jid, JID}, {newgroups, NewGroupsString}, {push, PushString}, {server, Server}, {user, User}] = lists:sort(Struct),
|
||||||
|
{U1, S1, _} = jlib:jid_tolower(jlib:string_to_jid(JID)),
|
||||||
|
NewGroups = string:tokens(NewGroupsString, ";"),
|
||||||
|
Push = list_to_atom(PushString),
|
||||||
|
case {ejabberd_auth:is_user_exists(U1, S1), ejabberd_auth:is_user_exists(User, Server)} of
|
||||||
|
{true, true} ->
|
||||||
|
case del_rosteritem_groups(User, Server, JID, NewGroups, Push) of
|
||||||
|
ok ->
|
||||||
|
{false, {response, [0]}};
|
||||||
|
Error ->
|
||||||
|
?INFO_MSG("Error found: ~n~p", [Error]),
|
||||||
|
{false, {response, [1]}}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{false, {response, [404]}}
|
||||||
|
end;
|
||||||
|
|
||||||
|
handler(_State, {call, modify_rosteritem_groups, [{struct, Struct}]}) ->
|
||||||
|
[{jid, JID}, {newgroups, NewGroupsString}, {nick, Nick}, {push, PushString},
|
||||||
|
{server, Server}, {subscription, SubsString}, {user, User}] = lists:sort(Struct),
|
||||||
|
Subs = list_to_atom(SubsString),
|
||||||
|
{U1, S1, _} = jlib:jid_tolower(jlib:string_to_jid(JID)),
|
||||||
|
NewGroups = string:tokens(NewGroupsString, ";"),
|
||||||
|
Push = list_to_atom(PushString),
|
||||||
|
case {ejabberd_auth:is_user_exists(U1, S1), ejabberd_auth:is_user_exists(User, Server)} of
|
||||||
|
{true, true} ->
|
||||||
|
case modify_rosteritem_groups(User, Server, JID, NewGroups, Push, Nick, Subs) of
|
||||||
|
ok ->
|
||||||
|
{false, {response, [0]}};
|
||||||
|
Error ->
|
||||||
|
?INFO_MSG("Error found: ~n~p", [Error]),
|
||||||
|
{false, {response, [1]}}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{false, {response, [404]}}
|
||||||
|
end;
|
||||||
|
|
||||||
%% get_roster struct[{user, String}, {server, String}]
|
%% get_roster struct[{user, String}, {server, String}]
|
||||||
%% array[struct[{jid, String}, {group, String}, {nick, String},
|
%% array[struct[{jid, String}, {groups, array[String]}, {nick, String},
|
||||||
%% {subscription, String}, {pending, String}]]
|
%% {subscription, String}, {pending, String}]]
|
||||||
handler(_State, {call, get_roster, [{struct, Struct}]}) ->
|
handler(_State, {call, get_roster, [{struct, Struct}]}) ->
|
||||||
[{server, S}, {user, U}] = lists:sort(Struct),
|
[{server, S}, {user, U}] = lists:sort(Struct),
|
||||||
@ -576,9 +635,9 @@ add_rosteritem(User, Server, JID, Nick, Group, Subscription, Push) ->
|
|||||||
{selected, ["username"],[]} ->
|
{selected, ["username"],[]} ->
|
||||||
ItemVals = record_to_string(Roster),
|
ItemVals = record_to_string(Roster),
|
||||||
ItemGroups = groups_to_string(Roster),
|
ItemGroups = groups_to_string(Roster),
|
||||||
ejabberd_odbc:sql_query_t(
|
odbc_queries:update_roster(Server, Username,
|
||||||
odbc_queries:update_roster_sql(
|
SJID, ItemVals,
|
||||||
Username, SJID, ItemVals, ItemGroups));
|
ItemGroups);
|
||||||
_ ->
|
_ ->
|
||||||
already_added
|
already_added
|
||||||
end
|
end
|
||||||
@ -588,7 +647,8 @@ add_rosteritem(User, Server, JID, Nick, Group, Subscription, Push) ->
|
|||||||
Error -> Error
|
Error -> Error
|
||||||
end;
|
end;
|
||||||
none ->
|
none ->
|
||||||
{error, no_roster}
|
%% Apollo change: force roster push anyway with success
|
||||||
|
{atomic, ok}
|
||||||
end,
|
end,
|
||||||
case {Result, Push} of
|
case {Result, Push} of
|
||||||
{{atomic, already_added}, _} -> ok; %% No need for roster push
|
{{atomic, already_added}, _} -> ok; %% No need for roster push
|
||||||
@ -619,11 +679,12 @@ del_rosteritem(User, Server, JID, Push) ->
|
|||||||
Error -> Error
|
Error -> Error
|
||||||
end;
|
end;
|
||||||
none ->
|
none ->
|
||||||
{error, no_roster}
|
%% Apollo change: force roster push anyway with success
|
||||||
|
{atomic, ok}
|
||||||
end,
|
end,
|
||||||
case {Result, Push} of
|
case {Result, Push} of
|
||||||
{{atomic, ok}, true} -> roster_push(User, Server, JID, "", "remove");
|
{{atomic, ok}, true} -> roster_push(User, Server, JID, "", "remove");
|
||||||
{{error, no_roster}, true} -> roster_push(User, Server, JID, "", "remove");
|
%{{error, no_roster}, true} -> roster_push(User, Server, JID, "", "remove");
|
||||||
{{atomic, ok}, false} -> ok;
|
{{atomic, ok}, false} -> ok;
|
||||||
_ -> error
|
_ -> error
|
||||||
end,
|
end,
|
||||||
@ -654,7 +715,126 @@ unlink_contacts(JID1, JID2, Push) ->
|
|||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
add_rosteritem_groups(User, Server, JID, NewGroups, Push) ->
|
||||||
|
GroupsFun =
|
||||||
|
fun(Groups) ->
|
||||||
|
lists:usort(NewGroups ++ Groups)
|
||||||
|
end,
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push).
|
||||||
|
|
||||||
|
del_rosteritem_groups(User, Server, JID, NewGroups, Push) ->
|
||||||
|
GroupsFun =
|
||||||
|
fun(Groups) ->
|
||||||
|
Groups -- NewGroups
|
||||||
|
end,
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push).
|
||||||
|
|
||||||
|
modify_rosteritem_groups(User, Server, JID2, NewGroups, Push, Nick, Subs) when NewGroups == [] ->
|
||||||
|
JID1 = jlib:jid_to_string(jlib:make_jid(User, Server, "")),
|
||||||
|
case unlink_contacts(JID1, JID2) of
|
||||||
|
{atomic, ok} ->
|
||||||
|
ok;
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
|
modify_rosteritem_groups(User, Server, JID, NewGroups, Push, Nick, Subs) ->
|
||||||
|
GroupsFun =
|
||||||
|
fun(_Groups) ->
|
||||||
|
NewGroups
|
||||||
|
end,
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push, NewGroups, Nick, Subs).
|
||||||
|
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push) ->
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push, [], "unknownnickname", "both").
|
||||||
|
|
||||||
|
change_rosteritem_group(User, Server, JID, GroupsFun, Push, NewGroups, Nick, Subs) ->
|
||||||
|
{RU, RS, _} = jlib:jid_tolower(jlib:string_to_jid(JID)),
|
||||||
|
LJID = {RU,RS,[]},
|
||||||
|
LUser = jlib:nodeprep(User),
|
||||||
|
LServer = jlib:nameprep(Server),
|
||||||
|
Result =
|
||||||
|
case roster_backend(LServer) of
|
||||||
|
mnesia ->
|
||||||
|
mnesia:transaction(
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read({roster, {LUser, LServer, LJID}}) of
|
||||||
|
[#roster{} = Roster] ->
|
||||||
|
NewGroups = GroupsFun(Roster#roster.groups),
|
||||||
|
NewRoster = Roster#roster{groups = NewGroups},
|
||||||
|
mnesia:write(NewRoster),
|
||||||
|
{ok, NewRoster#roster.name,
|
||||||
|
NewRoster#roster.subscription,
|
||||||
|
NewGroups};
|
||||||
|
_ ->
|
||||||
|
not_in_roster
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
odbc ->
|
||||||
|
ejabberd_odbc:sql_transaction(
|
||||||
|
LServer,
|
||||||
|
fun() ->
|
||||||
|
Username = ejabberd_odbc:escape(User),
|
||||||
|
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
|
||||||
|
case ejabberd_odbc:sql_query_t(
|
||||||
|
["select nick, subscription from rosterusers "
|
||||||
|
" where username='", Username, "' "
|
||||||
|
" and jid='", SJID, "';"]) of
|
||||||
|
{selected, ["nick", "subscription"],
|
||||||
|
[{Name, SSubscription}]} ->
|
||||||
|
Subscription =
|
||||||
|
case SSubscription of
|
||||||
|
"B" -> both;
|
||||||
|
"T" -> to;
|
||||||
|
"F" -> from;
|
||||||
|
_ -> none
|
||||||
|
end,
|
||||||
|
Groups =
|
||||||
|
case odbc_queries:get_roster_groups(
|
||||||
|
LServer, Username, SJID) of
|
||||||
|
{selected, ["grp"], JGrps}
|
||||||
|
when is_list(JGrps) ->
|
||||||
|
[JGrp || {JGrp} <- JGrps];
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
NewGroups = GroupsFun(Groups),
|
||||||
|
ejabberd_odbc:sql_query_t(
|
||||||
|
["delete from rostergroups "
|
||||||
|
" where username='", Username, "' "
|
||||||
|
" and jid='", SJID, "';"]),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Group) ->
|
||||||
|
ejabberd_odbc:sql_query_t(
|
||||||
|
["insert into rostergroups("
|
||||||
|
" username, jid, grp) "
|
||||||
|
" values ('", Username, "',"
|
||||||
|
"'", SJID, "',"
|
||||||
|
"'", ejabberd_odbc:escape(Group), "');"])
|
||||||
|
end,
|
||||||
|
NewGroups),
|
||||||
|
{ok, Name, Subscription, NewGroups};
|
||||||
|
_ ->
|
||||||
|
not_in_roster
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
none ->
|
||||||
|
%% Apollo change: force roster push anyway with success
|
||||||
|
{atomic, {ok, Nick, Subs, NewGroups}}
|
||||||
|
end,
|
||||||
|
case {Result, Push} of
|
||||||
|
{{atomic, {ok, Name, Subscription, NewGroups}}, true} ->
|
||||||
|
roster_push(User, Server, JID,
|
||||||
|
Name, atom_to_list(Subscription), NewGroups),
|
||||||
|
ok;
|
||||||
|
{{atomic, {ok, _Name, _Subscription, _NewGroups}}, false} -> ok;
|
||||||
|
{{atomic, not_in_roster}, _} -> not_in_roster;
|
||||||
|
Error -> {error, Error}
|
||||||
|
end.
|
||||||
|
|
||||||
roster_push(User, Server, JID, Nick, Subscription) ->
|
roster_push(User, Server, JID, Nick, Subscription) ->
|
||||||
|
roster_push(User, Server, JID, Nick, Subscription, []).
|
||||||
|
|
||||||
|
roster_push(User, Server, JID, Nick, Subscription, Groups) ->
|
||||||
LJID = jlib:make_jid(User, Server, ""),
|
LJID = jlib:make_jid(User, Server, ""),
|
||||||
TJID = jlib:string_to_jid(JID),
|
TJID = jlib:string_to_jid(JID),
|
||||||
{TU, TS, _} = jlib:jid_tolower(TJID),
|
{TU, TS, _} = jlib:jid_tolower(TJID),
|
||||||
@ -665,28 +845,37 @@ roster_push(User, Server, JID, Nick, Subscription) ->
|
|||||||
"both" -> "subscribed";
|
"both" -> "subscribed";
|
||||||
_ -> "subscribe"
|
_ -> "subscribe"
|
||||||
end}], []},
|
end}], []},
|
||||||
Item = case Nick of
|
ItemAttrs = case Nick of
|
||||||
"" -> [{"jid", JID}, {"subscription", Subscription}];
|
"" -> [{"jid", JID}, {"subscription", Subscription}];
|
||||||
_ -> [{"jid", JID}, {"name", Nick}, {"subscription", Subscription}]
|
_ -> [{"jid", JID}, {"name", Nick}, {"subscription", Subscription}]
|
||||||
end,
|
end,
|
||||||
Result = jlib:iq_to_xml(#iq{type = set, xmlns = ?NS_ROSTER, id = "push",
|
ItemGroups =
|
||||||
|
lists:map(fun(G) ->
|
||||||
|
{xmlelement, "group", [], [{xmlcdata, G}]}
|
||||||
|
end, Groups),
|
||||||
|
Result =
|
||||||
|
jlib:iq_to_xml(
|
||||||
|
#iq{type = set, xmlns = ?NS_ROSTER, id = "push",
|
||||||
sub_el = [{xmlelement, "query", [{"xmlns", ?NS_ROSTER}],
|
sub_el = [{xmlelement, "query", [{"xmlns", ?NS_ROSTER}],
|
||||||
[{xmlelement, "item", Item, []}]}]}),
|
[{xmlelement, "item", ItemAttrs, ItemGroups}]}]}),
|
||||||
ejabberd_router:route(TJID, LJID, Presence),
|
%% ejabberd_router:route(TJID, LJID, Presence),
|
||||||
ejabberd_router:route(LJID, LJID, Result),
|
%% ejabberd_router:route(LJID, LJID, Result),
|
||||||
lists:foreach(fun(Resource) ->
|
lists:foreach(
|
||||||
|
fun(Resource) ->
|
||||||
UJID = jlib:make_jid(User, Server, Resource),
|
UJID = jlib:make_jid(User, Server, Resource),
|
||||||
ejabberd_router:route(TJID, UJID, Presence),
|
ejabberd_router:route(TJID, UJID, Presence),
|
||||||
ejabberd_router:route(UJID, UJID, Result),
|
ejabberd_router:route(UJID, UJID, Result),
|
||||||
case Subscription of
|
case Subscription of
|
||||||
"remove" -> none;
|
"remove" -> none;
|
||||||
_ ->
|
_ ->
|
||||||
lists:foreach(fun(TR) ->
|
lists:foreach(
|
||||||
ejabberd_router:route(jlib:make_jid(TU, TS, TR), UJID,
|
fun(TR) ->
|
||||||
|
ejabberd_router:route(
|
||||||
|
jlib:make_jid(TU, TS, TR), UJID,
|
||||||
{xmlelement, "presence", [], []})
|
{xmlelement, "presence", [], []})
|
||||||
end, get_resources(TU, TS))
|
end, get_resources(TU, TS))
|
||||||
end
|
end
|
||||||
end, [R || R <- get_resources(User, Server), Subscription =/= "remove"]).
|
end, [R || R <- get_resources(User, Server)]).
|
||||||
|
|
||||||
roster_backend(Server) ->
|
roster_backend(Server) ->
|
||||||
Modules = gen_mod:loaded_modules(Server),
|
Modules = gen_mod:loaded_modules(Server),
|
||||||
@ -758,7 +947,7 @@ format_roster([#roster{jid=JID, name=Nick, groups=Group,
|
|||||||
subscription=Subs, ask=Ask}|Items], Structs) ->
|
subscription=Subs, ask=Ask}|Items], Structs) ->
|
||||||
{User,Server,_Resource} = JID,
|
{User,Server,_Resource} = JID,
|
||||||
Struct = {struct, [{jid,lists:flatten([User,"@",Server])},
|
Struct = {struct, [{jid,lists:flatten([User,"@",Server])},
|
||||||
{group, extract_group(Group)},
|
{groups, extract_groups(Group)},
|
||||||
{nick, Nick},
|
{nick, Nick},
|
||||||
{subscription, atom_to_list(Subs)},
|
{subscription, atom_to_list(Subs)},
|
||||||
{pending, atom_to_list(Ask)}
|
{pending, atom_to_list(Ask)}
|
||||||
@ -801,7 +990,12 @@ format_roster_with_presence([#roster{jid=JID, name=Nick, groups=Group,
|
|||||||
format_roster_with_presence(Items, [Struct|Structs]).
|
format_roster_with_presence(Items, [Struct|Structs]).
|
||||||
|
|
||||||
extract_group([]) -> [];
|
extract_group([]) -> [];
|
||||||
extract_group([Group|_Groups]) -> Group.
|
%extract_group([Group|_Groups]) -> Group.
|
||||||
|
extract_group(Groups) -> string:join(Groups, ";").
|
||||||
|
|
||||||
|
extract_groups([]) -> [];
|
||||||
|
%extract_groups([Group|_Groups]) -> Group.
|
||||||
|
extract_groups(Groups) -> {array, Groups}.
|
||||||
|
|
||||||
%% -----------------------------
|
%% -----------------------------
|
||||||
%% Internal session handling
|
%% Internal session handling
|
||||||
|
Loading…
Reference in New Issue
Block a user