25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-26 16:26:24 +01:00

o Document the type of the argument(s) and the returned type of every

functions.
o  Add guardians expression to exported functions to ensure at an early
stage that we were given the right arguments.
o  Fix table conversion to exmpp; many fields were left as string(),
preventing matching from working correctly.
o  In user_roster_item_parse_query/4, fix a bug where the same variable
was used for two distinct purpose.
o  In user_roster_item_parse_query/4, fix a bad usage of
exmpp_jid:jid_to_list/1.

PR:		EJABP-1

SVN Revision: 1867
This commit is contained in:
Jean-Sébastien Pédron 2009-02-06 13:43:40 +00:00
parent 25bd2bc7fe
commit bf82bac328
2 changed files with 284 additions and 44 deletions

View File

@ -5,6 +5,15 @@
* src/jlib.erl: Document the short JID type. * src/jlib.erl: Document the short JID type.
* src/mod_roster.erl: Document the type of the argument(s) and the
returned type of every functions. Add guardians expression to exported
functions to ensure at an early stage that we were given the right
arguments. Fix table conversion to exmpp; many fields were left as
string(), preventing matching from working correctly.
(user_roster_item_parse_query/4): Fix a bug where the same variable
was used for two distinct purpose. Fix a bad usage of
exmpp_jid:jid_to_list/1.
2009-02-05 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2009-02-05 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/ejabberd_auth.erl, src/ejabberd_auth_anonymous.erl, * src/ejabberd_auth.erl, src/ejabberd_auth_anonymous.erl,

View File

@ -51,8 +51,25 @@
-include("web/ejabberd_http.hrl"). -include("web/ejabberd_http.hrl").
-include("web/ejabberd_web_admin.hrl"). -include("web/ejabberd_web_admin.hrl").
%% @type rosteritem() = {roster, USJ, US, Contact_JID, Name, Subscription, Ask, Groups, Askmessage, Xs}
%% USJ = {LUser, LServer, Prepd_Contact_JID}
%% LUser = binary()
%% LServer = binary()
%% Prepd_Contact_JID = jlib:shortjid()
%% US = {LUser, LServer}
%% Contact_JID = jlib:shortjid()
%% Name = binary()
%% Subscription = none | to | from | both
%% Ask = none | out | in | both
%% Groups = [binary()]
%% Askmessage = binary()
%% Xs = [exmpp_xml:xmlel()]
start(Host, Opts) -> %% @spec (Host, Opts) -> term()
%% Host = string()
%% Opts = list()
start(Host, Opts) when is_list(Host) ->
HostB = list_to_binary(Host), HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(roster,[{disc_copies, [node()]}, mnesia:create_table(roster,[{disc_copies, [node()]},
@ -82,7 +99,10 @@ start(Host, Opts) ->
gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_ROSTER, gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_ROSTER,
?MODULE, process_iq, IQDisc). ?MODULE, process_iq, IQDisc).
stop(Host) -> %% @spec (Host) -> term()
%% Host = string()
stop(Host) when is_list(Host) ->
HostB = list_to_binary(Host), HostB = list_to_binary(Host),
ejabberd_hooks:delete(roster_get, HostB, ejabberd_hooks:delete(roster_get, HostB,
?MODULE, get_user_roster, 50), ?MODULE, get_user_roster, 50),
@ -107,8 +127,14 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, HostB, gen_iq_handler:remove_iq_handler(ejabberd_sm, HostB,
?NS_ROSTER). ?NS_ROSTER).
%% @spec (From, To, IQ_Rec) -> IQ_Result
%% From = exmpp_jid:jid()
%% To = exmpp_jid:jid()
%% IQ_Rec = exmpp_iq:iq()
%% IQ_Result = exmpp_iq:iq()
process_iq(From, To, IQ_Rec) -> process_iq(From, To, IQ_Rec)
when ?IS_JID(From), ?IS_JID(To), ?IS_IQ_RECORD(IQ_Rec) ->
LServer = exmpp_jid:ldomain_as_list(From), LServer = exmpp_jid:ldomain_as_list(From),
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
@ -117,12 +143,24 @@ process_iq(From, To, IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'item-not-found') exmpp_iq:error(IQ_Rec, 'item-not-found')
end. end.
process_local_iq(From, To, #iq{type = get} = IQ_Rec) -> %% @spec (From, To, IQ_Rec) -> IQ_Result
%% From = exmpp_jid:jid()
%% To = exmpp_jid:jid()
%% IQ_Rec = exmpp_iq:iq()
%% IQ_Result = exmpp_iq:iq()
process_local_iq(From, To, #iq{type = get} = IQ_Rec)
when ?IS_JID(From), ?IS_JID(To), ?IS_IQ_RECORD(IQ_Rec) ->
process_iq_get(From, To, IQ_Rec); process_iq_get(From, To, IQ_Rec);
process_local_iq(From, To, #iq{type = set} = IQ_Rec) -> process_local_iq(From, To, #iq{type = set} = IQ_Rec)
when ?IS_JID(From), ?IS_JID(To), ?IS_IQ_RECORD(IQ_Rec) ->
process_iq_set(From, To, IQ_Rec). process_iq_set(From, To, IQ_Rec).
%% @spec (From, To, IQ_Rec) -> IQ_Result
%% From = exmpp_jid:jid()
%% To = exmpp_jid:jid()
%% IQ_Rec = exmpp_iq:iq()
%% IQ_Result = exmpp_iq:iq()
process_iq_get(From, To, IQ_Rec) -> process_iq_get(From, To, IQ_Rec) ->
US = {exmpp_jid:lnode(From), exmpp_jid:ldomain(From)}, US = {exmpp_jid:lnode(From), exmpp_jid:ldomain(From)},
@ -136,7 +174,14 @@ process_iq_get(From, To, IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'internal-server-error') exmpp_iq:error(IQ_Rec, 'internal-server-error')
end. end.
get_user_roster(Acc, US) -> %% @spec (Acc, US) -> New_Acc
%% Acc = [rosteritem()]
%% US = {User, Server}
%% User = binary()
%% Server = binary()
%% New_Acc = [rosteritem()]
get_user_roster(Acc, {U, S} = US) when is_binary(U), is_binary(S) ->
case catch mnesia:dirty_index_read(roster, US, #roster.us) of case catch mnesia:dirty_index_read(roster, US, #roster.us) of
Items when is_list(Items) -> Items when is_list(Items) ->
lists:filter(fun(#roster{subscription = none, ask = in}) -> lists:filter(fun(#roster{subscription = none, ask = in}) ->
@ -148,6 +193,9 @@ get_user_roster(Acc, US) ->
Acc Acc
end. end.
%% @spec (Item) -> XML
%% Item = rosteritem()
%% XML = exmpp_xml:xmlel()
item_to_xml(Item) -> item_to_xml(Item) ->
{U, S, R} = Item#roster.jid, {U, S, R} = Item#roster.jid,
@ -178,6 +226,11 @@ item_to_xml(Item) ->
SubEls = SubEls1 ++ Item#roster.xs, SubEls = SubEls1 ++ Item#roster.xs,
#xmlel{ns = ?NS_ROSTER, name = 'item', attrs = Attrs4, children = SubEls}. #xmlel{ns = ?NS_ROSTER, name = 'item', attrs = Attrs4, children = SubEls}.
%% @spec (From, To, IQ_Rec) -> IQ_Result
%% From = exmpp_jid:jid()
%% To = exmpp_jid:jid()
%% IQ_Rec = exmpp_iq:iq()
%% IQ_Result = exmpp_iq:iq()
process_iq_set(From, To, #iq{payload = Request} = IQ_Rec) -> process_iq_set(From, To, #iq{payload = Request} = IQ_Rec) ->
case Request of case Request of
@ -188,12 +241,17 @@ process_iq_set(From, To, #iq{payload = Request} = IQ_Rec) ->
end, end,
exmpp_iq:result(IQ_Rec). exmpp_iq:result(IQ_Rec).
%% @spec (From, To, El) -> ok
%% From = exmpp_jid:jid()
%% To = exmpp_jid:jid()
%% El = exmpp_xml:xmlel()
process_item_set(From, To, #xmlel{} = El) -> process_item_set(From, To, #xmlel{} = El) ->
try try
JID1 = exmpp_jid:parse_jid(exmpp_xml:get_attribute_as_binary(El, 'jid', <<>>)), JID1 = exmpp_jid:parse_jid(exmpp_xml:get_attribute_as_binary(El, 'jid', <<>>)),
User = exmpp_jid:node(From), User = exmpp_jid:node(From),
LUser = exmpp_jid:lnode(From), LUser = exmpp_jid:lnode(From),
LServer = exmpp_jid:ldomain(From), LServer = exmpp_jid:ldomain(From),
JID = jlib:short_jid(JID1), JID = jlib:short_jid(JID1),
LJID = jlib:short_prepd_jid(JID1), LJID = jlib:short_prepd_jid(JID1),
F = fun() -> F = fun() ->
@ -268,6 +326,11 @@ process_item_set(From, To, #xmlel{} = El) ->
process_item_set(_From, _To, _) -> process_item_set(_From, _To, _) ->
ok. ok.
%% @spec (Item, Attrs) -> New_Item
%% Item = rosteritem()
%% Attrs = [exmpp_xml:xmlnsattribute()]
%% New_Item = rosteritem()
process_item_attrs(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) -> process_item_attrs(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
case Attr of case Attr of
'name' -> 'name' ->
@ -288,6 +351,10 @@ process_item_attrs(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
process_item_attrs(Item, []) -> process_item_attrs(Item, []) ->
Item. Item.
%% @spec (Item, Els) -> New_Item
%% Item = rosteritem()
%% Els = [exmpp_xml:xmlel()]
%% New_Item = rosteritem()
process_item_els(Item, [#xmlel{ns = NS, name = Name} = El | Els]) -> process_item_els(Item, [#xmlel{ns = NS, name = Name} = El | Els]) ->
case Name of case Name of
@ -308,8 +375,14 @@ process_item_els(Item, [_ | Els]) ->
process_item_els(Item, []) -> process_item_els(Item, []) ->
Item. Item.
%% @spec (User, Server, From, Item) -> term()
%% User = binary()
%% Server = binary()
%% From = exmpp_jid:jid()
%% Item = rosteritem()
push_item(User, Server, From, Item) when is_binary(User), is_binary(Server) -> push_item(User, Server, From, Item)
when is_binary(User), is_binary(Server), ?IS_JID(From) ->
ejabberd_sm:route(exmpp_jid:make_jid(), ejabberd_sm:route(exmpp_jid:make_jid(),
exmpp_jid:make_jid(User, Server), exmpp_jid:make_jid(User, Server),
#xmlel{name = 'broadcast', children = #xmlel{name = 'broadcast', children =
@ -320,9 +393,17 @@ push_item(User, Server, From, Item) when is_binary(User), is_binary(Server) ->
push_item(User, Server, Resource, From, Item) push_item(User, Server, Resource, From, Item)
end, ejabberd_sm:get_user_resources(User, Server)). end, ejabberd_sm:get_user_resources(User, Server)).
%% @spec (User, Server, Resource, From, Item) -> term()
%% User = binary()
%% Server = binary()
%% Resource = binary()
%% From = exmpp_jid:jid()
%% Item = rosteritem()
% TODO: don't push to those who didn't load roster % TODO: don't push to those who didn't load roster
push_item(User, Server, Resource, From, Item) when is_binary(User), push_item(User, Server, Resource, From, Item)
is_binary(Server) -> when is_binary(User), is_binary(Server), is_binary(Resource),
?IS_JID(From) ->
Request = #xmlel{ns = ?NS_ROSTER, name = 'query', Request = #xmlel{ns = ?NS_ROSTER, name = 'query',
children = [item_to_xml(Item)]}, children = [item_to_xml(Item)]},
ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request, ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request,
@ -332,8 +413,16 @@ push_item(User, Server, Resource, From, Item) when is_binary(User),
exmpp_jid:make_jid(User, Server, Resource), exmpp_jid:make_jid(User, Server, Resource),
ResIQ). ResIQ).
%% @spec (Ignored, User, Server) -> Subscription_Lists
%% Ignored = term()
%% User = binary()
%% Server = binary()
%% Subscription_Lists = {F, T}
%% F = [jlib:shortjid()]
%% T = [jlib:shortjid()]
get_subscription_lists(_, User, Server) get_subscription_lists(_, User, Server)
when is_binary(User), is_binary(Server) -> when is_binary(User), is_binary(Server) ->
try try
US = {User,Server}, US = {User,Server},
case mnesia:dirty_index_read(roster, US, #roster.us) of case mnesia:dirty_index_read(roster, US, #roster.us) of
@ -347,6 +436,13 @@ get_subscription_lists(_, User, Server)
{[], []} {[], []}
end. end.
%% @spec (Items, F, T) -> {New_F, New_T}
%% Items = [rosteritem()]
%% F = [jlib:shortjid()]
%% T = [jlib:shortjid()]
%% New_F = [jlib:shortjid()]
%% New_T = [jlib:shortjid()]
fill_subscription_lists([I | Is], F, T) -> fill_subscription_lists([I | Is], F, T) ->
J = element(3, I#roster.usj), J = element(3, I#roster.usj),
case I#roster.subscription of case I#roster.subscription of
@ -362,20 +458,44 @@ fill_subscription_lists([I | Is], F, T) ->
fill_subscription_lists([], F, T) -> fill_subscription_lists([], F, T) ->
{F, T}. {F, T}.
%% @hidden
ask_to_pending(subscribe) -> out; ask_to_pending(subscribe) -> out;
ask_to_pending(unsubscribe) -> none; ask_to_pending(unsubscribe) -> none;
ask_to_pending(Ask) -> Ask. ask_to_pending(Ask) -> Ask.
%% @spec (Ignored, User, Server, JID, Type, Reason) -> bool()
%% Ignored = term()
%% User = binary()
%% Server = binary()
%% JID = exmpp_jid:jid()
%% Type = subscribe | subscribed | unsubscribe | unsubscribed
%% Reason = binary() | undefined
in_subscription(_, User, Server, JID, Type, Reason)
in_subscription(_, User, Server, JID, Type, Reason) -> when is_binary(User), is_binary(Server), ?IS_JID(JID) ->
process_subscription(in, User, Server, JID, Type, Reason). process_subscription(in, User, Server, JID, Type, Reason).
out_subscription(User, Server, JID, Type) -> %% @spec (User, Server, JID, Type) -> bool()
%% User = binary()
%% Server = binary()
%% JID = exmpp_jid:jid()
%% Type = subscribe | subscribed | unsubscribe | unsubscribed
out_subscription(User, Server, JID, Type)
when is_binary(User), is_binary(Server), ?IS_JID(JID) ->
process_subscription(out, User, Server, JID, Type, <<>>). process_subscription(out, User, Server, JID, Type, <<>>).
%% @spec (Direction, User, Server, JID1, Type, Reason) -> bool()
%% Direction = in | out
%% User = binary()
%% Server = binary()
%% JID1 = exmpp_jid:jid()
%% Type = subscribe | subscribed | unsubscribe | unsubscribed
%% Reason = binary() | undefined
process_subscription(Direction, User, Server, JID1, Type, Reason) process_subscription(Direction, User, Server, JID1, Type, Reason)
when is_binary(User), is_binary(Server) -> when is_binary(User), is_binary(Server) ->
try try
US = {User, Server}, US = {User, Server},
LJID = jlib:short_prepd_jid(JID1), LJID = jlib:short_prepd_jid(JID1),
@ -558,9 +678,12 @@ in_auto_reply(from, out, unsubscribe) -> unsubscribed;
in_auto_reply(both, none, unsubscribe) -> unsubscribed; in_auto_reply(both, none, unsubscribe) -> unsubscribed;
in_auto_reply(_, _, _) -> none. in_auto_reply(_, _, _) -> none.
%% @spec (User, Server) -> term()
%% User = binary()
%% Server = binary()
remove_user(User, Server) remove_user(User, Server)
when is_binary(User), is_binary(Server) -> when is_binary(User), is_binary(Server) ->
try try
LUser = list_to_binary(exmpp_stringprep:nodeprep(User)), LUser = list_to_binary(exmpp_stringprep:nodeprep(User)),
LServer = list_to_binary(exmpp_stringprep:nameprep(Server)), LServer = list_to_binary(exmpp_stringprep:nameprep(Server)),
@ -579,7 +702,13 @@ remove_user(User, Server)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
set_items(User, Server, #xmlel{children = Els}) -> %% @spec (User, Server, El) -> term()
%% User = binary()
%% Server = binary()
%% El = exmpp_xml:xmlel()
set_items(User, Server, #xmlel{children = Els})
when is_binary(User), is_binary(Server) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
@ -594,6 +723,11 @@ set_items(User, Server, #xmlel{children = Els}) ->
ok ok
end. end.
%% @spec (LUser, LServer, El) -> term()
%% LUser = binary()
%% LServer = binary()
%% El = exmpp_xml:xmlel()
process_item_set_t(LUser, LServer, #xmlel{} = El) -> process_item_set_t(LUser, LServer, #xmlel{} = El) ->
try try
JID1 = exmpp_jid:parse_jid(exmpp_xml:get_attribute_as_list(El, 'jid', <<>>)), JID1 = exmpp_jid:parse_jid(exmpp_xml:get_attribute_as_list(El, 'jid', <<>>)),
@ -617,6 +751,11 @@ process_item_set_t(LUser, LServer, #xmlel{} = El) ->
process_item_set_t(_LUser, _LServer, _) -> process_item_set_t(_LUser, _LServer, _) ->
ok. ok.
%% @spec (Item, Attrs) -> New_Item
%% Item = rosteritem()
%% Attrs = [exmpp_xml:xmlnsattribute()]
%% New_Item = rosteritem()
process_item_attrs_ws(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) -> process_item_attrs_ws(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
case Attr of case Attr of
'name' -> 'name' ->
@ -649,8 +788,14 @@ process_item_attrs_ws(Item, [#xmlattr{name = Attr, value = Val} | Attrs]) ->
process_item_attrs_ws(Item, []) -> process_item_attrs_ws(Item, []) ->
Item. Item.
%% @spec (Ls, User, Server) -> New_Ls
%% Ls = [exmpp_xml:xmlel()]
%% User = binary()
%% Server = binary()
%% New_Ls = [exmpp_xml:xmlel()]
get_in_pending_subscriptions(Ls, User, Server) get_in_pending_subscriptions(Ls, User, Server)
when is_binary(User), is_binary(Server) -> when is_binary(User), is_binary(Server) ->
JID = exmpp_jid:make_jid(User, Server), JID = exmpp_jid:make_jid(User, Server),
US = {exmpp_jid:lnode(JID), exmpp_jid:ldomain(JID)}, US = {exmpp_jid:lnode(JID), exmpp_jid:ldomain(JID)},
case mnesia:dirty_index_read(roster, US, #roster.us) of case mnesia:dirty_index_read(roster, US, #roster.us) of
@ -681,7 +826,16 @@ get_in_pending_subscriptions(Ls, User, Server)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_jid_info(_, User, Server, JID) when is_binary(User), is_binary(Server) -> %% @spec (Ignored, User, Server, JID) -> {Subscription, Groups}
%% Ignored = term()
%% User = binary()
%% Server = binary()
%% JID = exmpp_jid:jid()
%% Subscription = none | to | from | both
%% Groups = [binary()]
get_jid_info(_, User, Server, JID)
when is_binary(User), is_binary(Server), ?IS_JID(JID) ->
try try
LJID = jlib:short_prepd_jid(JID), LJID = jlib:short_prepd_jid(JID),
case catch mnesia:dirty_read(roster, {User, Server, LJID}) of case catch mnesia:dirty_read(roster, {User, Server, LJID}) of
@ -710,6 +864,7 @@ get_jid_info(_, User, Server, JID) when is_binary(User), is_binary(Server) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% @hidden
update_table() -> update_table() ->
Fields = record_info(fields, roster), Fields = record_info(fields, roster),
@ -725,6 +880,7 @@ update_table() ->
mnesia:transform_table(roster, ignore, Fields) mnesia:transform_table(roster, ignore, Fields)
end. end.
%% @hidden
%% Convert roster table to support virtual host %% Convert roster table to support virtual host
convert_table1(Fields) -> convert_table1(Fields) ->
@ -769,6 +925,7 @@ convert_table1(Fields) ->
mnesia:transaction(F2), mnesia:transaction(F2),
mnesia:delete_table(mod_roster_tmp_table). mnesia:delete_table(mod_roster_tmp_table).
%% @hidden
%% Convert roster table: xattrs fields become %% Convert roster table: xattrs fields become
convert_table2(Fields) -> convert_table2(Fields) ->
@ -777,58 +934,83 @@ convert_table2(Fields) ->
mnesia:transform_table(roster, ignore, Fields), mnesia:transform_table(roster, ignore, Fields),
convert_to_exmpp(). convert_to_exmpp().
%% @hidden
convert_to_exmpp() -> convert_to_exmpp() ->
Fun = fun() -> Fun = fun() ->
case mnesia:first(roster) of case mnesia:first(roster) of
'$end_of_table' -> {_User, Server, _JID} when is_binary(Server) ->
none; none;
Key -> {_User, Server, _JID} when is_list(Server) ->
case mnesia:read({roster, Key}) of mnesia:foldl(fun convert_to_exmpp2/2,
[#roster{jid = {_, _, undefined}}] -> done, roster, write);
none; '$end_of_table' ->
[#roster{jid = {_, _, ""}}] -> none
mnesia:foldl(fun convert_to_exmpp2/2,
done, roster, write)
end
end end
end, end,
mnesia:transaction(Fun). mnesia:transaction(Fun).
%% @hidden
convert_to_exmpp2(#roster{ convert_to_exmpp2(#roster{
usj = {USJ_U, USJ_S, {USJ_JU, USJ_JS, USJ_JR}} = Key, usj = {USJ_U, USJ_S, {USJ_JU, USJ_JS, USJ_JR}} = Key,
us = {US_U, US_S}, us = {US_U, US_S},
jid = {JID_U, JID_S, JID_R}, jid = {JID_U, JID_S, JID_R},
xs = XS, askmessage = AM} = R, Acc) -> name = N, xs = XS, groups = G, askmessage = AM} = R, Acc) ->
% Remove old entry. % Remove old entry.
mnesia:delete({roster, Key}), mnesia:delete({roster, Key}),
% Convert "" to undefined in JIDs. % Convert "" to undefined in JIDs and string() to binary().
USJ_U1 = convert_jid_to_exmpp(USJ_U), USJ_U1 = convert_jid_to_exmpp(USJ_U),
USJ_S1 = convert_jid_to_exmpp(USJ_S),
USJ_JU1 = convert_jid_to_exmpp(USJ_JU), USJ_JU1 = convert_jid_to_exmpp(USJ_JU),
USJ_JS1 = convert_jid_to_exmpp(USJ_JS),
USJ_JR1 = convert_jid_to_exmpp(USJ_JR), USJ_JR1 = convert_jid_to_exmpp(USJ_JR),
US_U1 = convert_jid_to_exmpp(US_U), US_U1 = convert_jid_to_exmpp(US_U),
US_S1 = convert_jid_to_exmpp(US_S),
JID_U1 = convert_jid_to_exmpp(JID_U), JID_U1 = convert_jid_to_exmpp(JID_U),
JID_S1 = convert_jid_to_exmpp(JID_S),
JID_R1 = convert_jid_to_exmpp(JID_R), JID_R1 = convert_jid_to_exmpp(JID_R),
% Convert name.
N1 = convert_name_to_exmpp(N),
% Convert groups.
G1 = convert_groups_to_exmpp(G, []),
% Convert xs. % Convert xs.
XS1 = convert_xs_to_exmpp(XS), XS1 = convert_xs_to_exmpp(XS),
% Convert askmessage. % Convert askmessage.
AM1 = convert_askmessage_to_exmpp(AM), AM1 = convert_askmessage_to_exmpp(AM),
% Prepare the new record. % Prepare the new record.
New_R = R#roster{ New_R = R#roster{
usj = {USJ_U1, USJ_S, {USJ_JU1, USJ_JS, USJ_JR1}}, usj = {USJ_U1, USJ_S1, {USJ_JU1, USJ_JS1, USJ_JR1}},
us = {US_U1, US_S}, us = {US_U1, US_S1},
jid = {JID_U1, JID_S, JID_R1}, jid = {JID_U1, JID_S1, JID_R1},
xs = XS1, askmessage = AM1}, name = N1, groups = G1, xs = XS1, askmessage = AM1},
% Write the new record. % Write the new record.
mnesia:write(New_R), mnesia:write(New_R),
Acc. Acc.
convert_jid_to_exmpp("") -> undefined; %% @hidden
convert_jid_to_exmpp(V) -> V.
convert_jid_to_exmpp("") -> undefined;
convert_jid_to_exmpp(V) when is_list(V) -> list_to_binary(V).
%% @hidden
convert_name_to_exmpp(N) when is_list(N) -> list_to_binary(N).
%% @hidden
convert_groups_to_exmpp([G | Rest], New_G) ->
convert_groups_to_exmpp(Rest, [list_to_binary(G) | New_G]);
convert_groups_to_exmpp([], New_G) ->
lists:reverse(New_G).
%% @hidden
convert_xs_to_exmpp(Els) -> convert_xs_to_exmpp(Els) ->
convert_xs_to_exmpp(Els, []). convert_xs_to_exmpp(Els, []).
%% @hidden
convert_xs_to_exmpp([El | Rest], Result) -> convert_xs_to_exmpp([El | Rest], Result) ->
New_El = exmpp_xml:xmlelement_to_xmlel(El, New_El = exmpp_xml:xmlelement_to_xmlel(El,
[?NS_JABBER_CLIENT], [{?NS_XMPP, ?NS_XMPP_pfx}]), [?NS_JABBER_CLIENT], [{?NS_XMPP, ?NS_XMPP_pfx}]),
@ -836,21 +1018,37 @@ convert_xs_to_exmpp([El | Rest], Result) ->
convert_xs_to_exmpp([], Result) -> convert_xs_to_exmpp([], Result) ->
lists:reverse(Result). lists:reverse(Result).
%% @hidden
convert_askmessage_to_exmpp(AM) when is_binary(AM) -> convert_askmessage_to_exmpp(AM) when is_binary(AM) ->
AM; AM;
convert_askmessage_to_exmpp(AM) -> convert_askmessage_to_exmpp(AM) ->
list_to_binary(AM). list_to_binary(AM).
%% @spec (Acc, Host, Request) -> {stop, Result} | Acc
%% Acc = term()
%% Host = string()
%% Request = ejabberd_http:request()
%% Result = [ejabberd_web:html()]
webadmin_page(_, Host, webadmin_page(_, Host,
#request{us = _US, #request{us = _US,
path = ["user", U, "roster"], path = ["user", U, "roster"],
q = Query, q = Query,
lang = Lang} = _Request) -> lang = Lang} = _Request)
Res = user_roster(U, Host, Query, Lang), when is_list(Host), is_list(U) ->
Res = user_roster(list_to_binary(U), list_to_binary(Host), Query, Lang),
{stop, Res}; {stop, Res};
webadmin_page(Acc, _, _) -> Acc. webadmin_page(Acc, _, _) -> Acc.
%% @spec (User, Server, Query, Lang) -> Result
%% User = binary()
%% Server = binary()
%% Query = ejabberd_http:query()
%% Lang = string()
%% Result = [ejabberd_web:html()]
user_roster(User, Server, Query, Lang) -> user_roster(User, Server, Query, Lang) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
@ -933,6 +1131,10 @@ user_roster(User, Server, Query, Lang) ->
])] ])]
end. end.
%% @spec (JID) -> Result
%% JID = jlib:shortjid()
%% Result = ejabberd_web:html()
build_contact_jid_td({U, S, R}) -> build_contact_jid_td({U, S, R}) ->
%% Convert {U, S, R} into {jid, U, S, R, U, S, R}: %% Convert {U, S, R} into {jid, U, S, R, U, S, R}:
ContactJID = exmpp_jid:make_jid(U, S, R), ContactJID = exmpp_jid:make_jid(U, S, R),
@ -953,6 +1155,12 @@ build_contact_jid_td({U, S, R}) ->
?XAE('td', [?XMLATTR('class', <<"valign">>)], [?AC(JIDURI, exmpp_jid:jid_to_list(ContactJID))]) ?XAE('td', [?XMLATTR('class', <<"valign">>)], [?AC(JIDURI, exmpp_jid:jid_to_list(ContactJID))])
end. end.
%% @spec (User, Server, Items, Query) -> ok | nothing | error
%% User = binary()
%% Server = binary()
%% Items = [rosteritem()]
%% Query = ejabberd_http:query()
user_roster_parse_query(User, Server, Items, Query) -> user_roster_parse_query(User, Server, Items, Query) ->
case lists:keysearch("addjid", 1, Query) of case lists:keysearch("addjid", 1, Query) of
{value, _} -> {value, _} ->
@ -983,6 +1191,10 @@ user_roster_parse_query(User, Server, Items, Query) ->
end end
end. end.
%% @spec (User, Server, JID) -> term()
%% User = binary()
%% Server = binary()
%% JID = exmpp_jid:jid()
user_roster_subscribe_jid(User, Server, JID) -> user_roster_subscribe_jid(User, Server, JID) ->
out_subscription(User, Server, JID, subscribe), out_subscription(User, Server, JID, subscribe),
@ -990,10 +1202,16 @@ user_roster_subscribe_jid(User, Server, JID) ->
ejabberd_router:route( ejabberd_router:route(
UJID, JID, exmpp_presence:subscribe()). UJID, JID, exmpp_presence:subscribe()).
%% @spec (User, Server, Items, Query) -> term()
%% User = binary()
%% Server = binary()
%% Items = [rosteritem()]
%% Query = ejabberd_http:query()
user_roster_item_parse_query(User, Server, Items, Query) -> user_roster_item_parse_query(User, Server, Items, Query) ->
lists:foreach( lists:foreach(
fun(R) -> fun(Roster) ->
JID = R#roster.jid, JID = Roster#roster.jid,
case lists:keysearch( case lists:keysearch(
"validate" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of "validate" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of
{value, _} -> {value, _} ->
@ -1009,9 +1227,10 @@ user_roster_item_parse_query(User, Server, Items, Query) ->
case lists:keysearch( case lists:keysearch(
"remove" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of "remove" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of
{value, _} -> {value, _} ->
{U, S, R} = JID,
UJID = exmpp_jid:make_jid(User, Server), UJID = exmpp_jid:make_jid(User, Server),
Attrs1 = exmpp_xml:set_attribute_in_list([], Attrs1 = exmpp_xml:set_attribute_in_list([],
'jid', exmpp_jid:jid_to_list(JID)), 'jid', exmpp_jid:jid_to_list(U, S, R)),
Attrs2 = exmpp_xml:set_attribute_in_list(Attrs1, Attrs2 = exmpp_xml:set_attribute_in_list(Attrs1,
'subscription', "remove"), 'subscription', "remove"),
Item = #xmlel{ns = ?NS_ROSTER, name = 'item', Item = #xmlel{ns = ?NS_ROSTER, name = 'item',
@ -1032,9 +1251,21 @@ user_roster_item_parse_query(User, Server, Items, Query) ->
end, Items), end, Items),
nothing. nothing.
%% @spec ({User, Server}) -> string()
%% User = binary()
%% Server = binary()
us_to_list({User, Server}) -> us_to_list({User, Server}) ->
exmpp_jid:bare_jid_to_list(User, Server). exmpp_jid:bare_jid_to_list(User, Server).
%% @spec (Acc, User, Server, Lang) -> New_Acc
%% Acc = [ejabberd_web:html()]
%% User = string()
%% Server = string()
%% Lang = string()
%% New_Acc = [ejabberd_web:html()]
webadmin_user(Acc, _User, _Server, Lang) -> webadmin_user(Acc, _User, _Server, Lang) ->
% `Lang' is used by the `T' macro, called from the `ACT' macro.
Acc ++ [?XE("h3", [?ACT("roster/", "Roster")])]. Acc ++ [?XE("h3", [?ACT("roster/", "Roster")])].