mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/web/ejabberd_http_poll.erl: Properly handle bad requests
* src/web/ejabberd_web_admin.erl: Ported features from J-EAI SVN Revision: 272
This commit is contained in:
parent
34de660c44
commit
b5e8850de9
@ -1,3 +1,9 @@
|
||||
2004-10-05 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/web/ejabberd_http_poll.erl: Properly handle bad requests
|
||||
|
||||
* src/web/ejabberd_web_admin.erl: Ported features from J-EAI
|
||||
|
||||
2004-09-30 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/web/ejabberd_http.erl: Fixed processing of POST body for
|
||||
|
@ -119,8 +119,10 @@ process_request(#request{path = [],
|
||||
end;
|
||||
_ ->
|
||||
{200, [?CT, {"Set-Cookie", "ID=-2:0; expires=-1"}], ""}
|
||||
end.
|
||||
|
||||
end;
|
||||
process_request(_Request) ->
|
||||
{400, [], {xmlelement, "h1", [],
|
||||
[{xmlcdata, "400 Bad Request"}]}}.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Callback functions from gen_fsm
|
||||
|
@ -5,6 +5,9 @@
|
||||
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
|
||||
%%% Id : $Id$
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Copyright (c) 2004 Alexey Shchepin
|
||||
%%% Copyright (c) 2004 Process One
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_web_admin).
|
||||
-author('alexey@sevcom.net').
|
||||
@ -101,6 +104,7 @@ make_xhtml(Els, Lang) ->
|
||||
[?LI([?ACT("/admin/acls/", "Access Control Lists")]),
|
||||
?LI([?ACT("/admin/access/", "Access Rules")]),
|
||||
?LI([?ACT("/admin/users/", "Users")]),
|
||||
?LI([?ACT("/admin/online-users/", "Online Users")]),
|
||||
?LI([?ACT("/admin/nodes/", "Nodes")]),
|
||||
?LI([?ACT("/admin/stats/", "Statistics")])
|
||||
])]),
|
||||
@ -115,7 +119,7 @@ make_xhtml(Els, Lang) ->
|
||||
[?XE("tbody",
|
||||
[?XE("tr",
|
||||
[?XCT("td",
|
||||
"ejabberd (c) 2002-2004 Alexey Shchepin")
|
||||
"ejabberd (c) 2002-2004 Alexey Shchepin, 2004 Process One")
|
||||
])])
|
||||
])])])])])])
|
||||
]}}.
|
||||
@ -494,6 +498,7 @@ process_admin(#request{user = User,
|
||||
?LI([?ACT("access/", "Access Rules"), ?C(" "),
|
||||
?ACT("access-raw/", "(raw)")]),
|
||||
?LI([?ACT("users/", "Users")]),
|
||||
?LI([?ACT("online-users/", "Online Users")]),
|
||||
?LI([?ACT("nodes/", "Nodes")]),
|
||||
?LI([?ACT("stats/", "Statistics")])
|
||||
])
|
||||
@ -753,14 +758,21 @@ process_admin(#request{user = User,
|
||||
path = ["users"],
|
||||
q = Query,
|
||||
lang = Lang} = Request) ->
|
||||
Res = list_users(),
|
||||
Res = list_users(Query, Lang),
|
||||
make_xhtml([?XCT("h1", "ejabberd users")] ++ Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
path = ["users", Diap],
|
||||
q = Query,
|
||||
lang = Lang} = Request) ->
|
||||
Res = list_users_in_diapason(Diap),
|
||||
Res = list_users_in_diapason(Diap, Lang),
|
||||
make_xhtml([?XCT("h1", "ejabberd users")] ++ Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
path = ["online-users"],
|
||||
q = Query,
|
||||
lang = Lang} = Request) ->
|
||||
Res = list_online_users(Lang),
|
||||
make_xhtml([?XCT("h1", "ejabberd users")] ++ Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
@ -777,11 +789,18 @@ process_admin(#request{user = User,
|
||||
Res = user_info(U, Query, Lang),
|
||||
make_xhtml(Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
path = ["user", U, "queue"],
|
||||
q = Query,
|
||||
lang = Lang} = Request) ->
|
||||
Res = user_queue(U, Query, Lang),
|
||||
make_xhtml(Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
path = ["user", U, "roster"],
|
||||
q = Query,
|
||||
lang = Lang} = Request) ->
|
||||
Res = user_roster(U, Query, Lang),
|
||||
Res = user_roster(U, Query, Lang, true),
|
||||
make_xhtml(Res, Lang);
|
||||
|
||||
process_admin(#request{user = User,
|
||||
@ -1036,44 +1055,123 @@ parse_access_rule(Text) ->
|
||||
|
||||
|
||||
|
||||
list_users() ->
|
||||
list_users(Query, Lang) ->
|
||||
Res = list_users_parse_query(Query),
|
||||
Users = ejabberd_auth:dirty_get_registered_users(),
|
||||
SUsers = lists:sort(Users),
|
||||
case length(SUsers) of
|
||||
N when N =< 100 ->
|
||||
lists:flatmap(
|
||||
fun(U) ->
|
||||
[?AC("../user/" ++ U ++ "/", U), ?BR]
|
||||
end, SUsers);
|
||||
N ->
|
||||
NParts = trunc(math:sqrt(N * 0.618)) + 1,
|
||||
M = trunc(N / NParts) + 1,
|
||||
lists:flatmap(
|
||||
fun(K) ->
|
||||
L = K + M - 1,
|
||||
Node = integer_to_list(K) ++ "-" ++ integer_to_list(L),
|
||||
Last = if L < N -> lists:nth(L, SUsers);
|
||||
true -> lists:last(SUsers)
|
||||
end,
|
||||
Name =
|
||||
lists:nth(K, SUsers) ++ [$\s, 226, 128, 148, $\s] ++
|
||||
Last,
|
||||
[?AC(Node ++ "/", Name), ?BR]
|
||||
end, lists:seq(1, N, M))
|
||||
FUsers =
|
||||
case length(SUsers) of
|
||||
N when N =< 100 ->
|
||||
[list_given_users(SUsers, Lang)];
|
||||
N ->
|
||||
NParts = trunc(math:sqrt(N * 0.618)) + 1,
|
||||
M = trunc(N / NParts) + 1,
|
||||
lists:flatmap(
|
||||
fun(K) ->
|
||||
L = K + M - 1,
|
||||
Node = integer_to_list(K) ++ "-" ++ integer_to_list(L),
|
||||
Last = if L < N -> lists:nth(L, SUsers);
|
||||
true -> lists:last(SUsers)
|
||||
end,
|
||||
Name =
|
||||
lists:nth(K, SUsers) ++ [$\s, 226, 128, 148, $\s] ++
|
||||
Last,
|
||||
[?AC(Node ++ "/", Name), ?BR]
|
||||
end, lists:seq(1, N, M))
|
||||
end,
|
||||
case Res of
|
||||
ok -> [?CT("submitted"), ?P];
|
||||
error -> [?CT("bad format"), ?P];
|
||||
nothing -> []
|
||||
end ++
|
||||
[?XAE("form", [{"method", "post"}],
|
||||
[?XE("table",
|
||||
[?XE("tr",
|
||||
[?XC("td", ?T("User") ++ ":"),
|
||||
?XE("td", [?INPUT("text", "newusername", "")])
|
||||
]),
|
||||
?XE("tr",
|
||||
[?XC("td", ?T("Password") ++ ":"),
|
||||
?XE("td", [?INPUT("password", "newuserpassword", "")])
|
||||
]),
|
||||
?XE("tr",
|
||||
[?X("td"),
|
||||
?XAE("td", [{"class", "alignright"}],
|
||||
[?INPUTT("submit", "addnewuser", "Add User")])
|
||||
])]),
|
||||
?P] ++
|
||||
FUsers)].
|
||||
|
||||
list_users_parse_query(Query) ->
|
||||
case lists:keysearch("addnewuser", 1, Query) of
|
||||
{value, _} ->
|
||||
{value, {_, User}} =
|
||||
lists:keysearch("newusername", 1, Query),
|
||||
{value, {_, Password}} =
|
||||
lists:keysearch("newuserpassword", 1, Query),
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
error;
|
||||
"" ->
|
||||
error;
|
||||
_ ->
|
||||
ejabberd_auth:try_register(User, Password),
|
||||
ok
|
||||
end;
|
||||
false ->
|
||||
nothing
|
||||
end.
|
||||
|
||||
list_users_in_diapason(Diap) ->
|
||||
list_users_in_diapason(Diap, Lang) ->
|
||||
Users = ejabberd_auth:dirty_get_registered_users(),
|
||||
SUsers = lists:sort(Users),
|
||||
{ok, [S1, S2]} = regexp:split(Diap, "-"),
|
||||
N1 = list_to_integer(S1),
|
||||
N2 = list_to_integer(S2),
|
||||
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
|
||||
lists:flatmap(
|
||||
fun(U) ->
|
||||
[?AC("../../user/" ++ U ++ "/", U), ?BR]
|
||||
end, Sub).
|
||||
[list_given_users(Sub, Lang)].
|
||||
|
||||
list_given_users(Users, Lang) ->
|
||||
?XE("table",
|
||||
[?XE("thead",
|
||||
[?XE("tr",
|
||||
[?XCT("td", "User"),
|
||||
?XCT("td", "Offline messages"),
|
||||
?XCT("td", "Last Activity")])]),
|
||||
?XE("tbody",
|
||||
lists:map(
|
||||
fun(User) ->
|
||||
QueueLen = length(mnesia:dirty_read({offline_msg, User})),
|
||||
FQueueLen = [?AC("../../user/" ++ User ++ "/queue/",
|
||||
integer_to_list(QueueLen))],
|
||||
FLast =
|
||||
case ejabberd_sm:get_user_resources(User) of
|
||||
[] ->
|
||||
case mnesia:dirty_read({last_activity, User}) of
|
||||
[] ->
|
||||
?T("Never");
|
||||
[E] ->
|
||||
Shift = element(3, E),
|
||||
TimeStamp = {Shift div 1000000,
|
||||
Shift rem 1000000,
|
||||
0},
|
||||
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
||||
calendar:now_to_local_time(TimeStamp),
|
||||
lists:flatten(
|
||||
io_lib:format(
|
||||
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||
[Year, Month, Day, Hour, Minute, Second]))
|
||||
end;
|
||||
_ ->
|
||||
?T("Online")
|
||||
end,
|
||||
?XE("tr",
|
||||
[?XE("td", [?AC("../../user/" ++ User ++ "/",
|
||||
User)]),
|
||||
?XE("td", FQueueLen),
|
||||
?XC("td", FLast)])
|
||||
end, Users)
|
||||
)]).
|
||||
|
||||
|
||||
get_stats(Lang) ->
|
||||
@ -1100,6 +1198,15 @@ get_stats(Lang) ->
|
||||
])].
|
||||
|
||||
|
||||
list_online_users(_Lang) ->
|
||||
Users = lists:map(fun({U, R}) -> U end,
|
||||
ejabberd_sm:dirty_get_sessions_list()),
|
||||
SUsers = lists:usort(Users),
|
||||
lists:flatmap(
|
||||
fun(U) ->
|
||||
[?AC("../user/" ++ U ++ "/", U), ?BR]
|
||||
end, SUsers).
|
||||
|
||||
user_info(User, Query, Lang) ->
|
||||
Res = user_parse_query(User, Query),
|
||||
Resources = ejabberd_sm:get_user_resources(User),
|
||||
@ -1116,6 +1223,9 @@ user_info(User, Query, Lang) ->
|
||||
Password = ejabberd_auth:get_password_s(User),
|
||||
FPassword = [?INPUT("text", "password", Password), ?C(" "),
|
||||
?INPUTT("submit", "chpassword", "Change Password")],
|
||||
QueueLen = length(mnesia:dirty_read({offline_msg, User})),
|
||||
FQueueLen = [?AC("queue/",
|
||||
integer_to_list(QueueLen))],
|
||||
[?XC("h1", "User: " ++ User)] ++
|
||||
case Res of
|
||||
ok -> [?CT("submitted"), ?P];
|
||||
@ -1124,13 +1234,18 @@ user_info(User, Query, Lang) ->
|
||||
end ++
|
||||
[?XAE("form", [{"method", "post"}],
|
||||
[?XCT("h3", "Connected Resources:")] ++ FResources ++
|
||||
[?XCT("h3", "Password:")] ++ FPassword)].
|
||||
[?XCT("h3", "Password:")] ++ FPassword ++
|
||||
[?XCT("h3", "Offline messages:")] ++ FQueueLen ++
|
||||
[?XE("h3", [?ACT("roster/", "Roster")])] ++
|
||||
[?BR, ?INPUTT("submit", "removeuser", "Remove User")])].
|
||||
|
||||
|
||||
user_parse_query(User, Query) ->
|
||||
case lists:keysearch("chpassword", 1, Query) of
|
||||
{value, _} ->
|
||||
case lists:keysearch("password", 1, Query) of
|
||||
{value, {_, undefined}} ->
|
||||
error;
|
||||
{value, {_, Password}} ->
|
||||
ejabberd_auth:set_password(User, Password),
|
||||
ok;
|
||||
@ -1138,10 +1253,90 @@ user_parse_query(User, Query) ->
|
||||
error
|
||||
end;
|
||||
_ ->
|
||||
case lists:keysearch("removeuser", 1, Query) of
|
||||
{value, _} ->
|
||||
ejabberd_auth:remove_user(User),
|
||||
ok;
|
||||
false ->
|
||||
nothing
|
||||
end
|
||||
end.
|
||||
|
||||
|
||||
user_queue(User, Query, Lang) ->
|
||||
Res = user_queue_parse_query(User, Query),
|
||||
Msgs = lists:keysort(3, mnesia:dirty_read({offline_msg, User})),
|
||||
FMsgs =
|
||||
lists:map(
|
||||
fun({offline_msg, _User, TimeStamp, _Expire, From, To,
|
||||
{xmlelement, Name, Attrs, Els}} = Msg) ->
|
||||
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
||||
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
||||
calendar:now_to_local_time(TimeStamp),
|
||||
Time = lists:flatten(
|
||||
io_lib:format(
|
||||
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||
[Year, Month, Day, Hour, Minute, Second])),
|
||||
SFrom = jlib:jid_to_string(From),
|
||||
STo = jlib:jid_to_string(To),
|
||||
Attrs2 = jlib:replace_from_to_attrs(SFrom, STo, Attrs),
|
||||
Packet = jlib:remove_attr(
|
||||
"jeai-id", {xmlelement, Name, Attrs2, Els}),
|
||||
FPacket = pretty_print(Packet),
|
||||
?XE("tr",
|
||||
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
||||
?XAC("td", [{"class", "valign"}], Time),
|
||||
?XAC("td", [{"class", "valign"}], SFrom),
|
||||
?XAC("td", [{"class", "valign"}], STo),
|
||||
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
||||
)
|
||||
end, Msgs),
|
||||
[?XC("h1", User ++ " offline messages queue")] ++
|
||||
case Res of
|
||||
ok -> [?CT("submitted"), ?P];
|
||||
error -> [?CT("bad format"), ?P];
|
||||
nothing -> []
|
||||
end ++
|
||||
[?XAE("form", [{"method", "post"}],
|
||||
[?XE("table",
|
||||
[?XE("thead",
|
||||
[?XE("tr",
|
||||
[?X("td"),
|
||||
?XCT("td", "Time"),
|
||||
?XCT("td", "From"),
|
||||
?XCT("td", "To"),
|
||||
?XCT("td", "Packet")
|
||||
])]),
|
||||
?XE("tbody", FMsgs)]),
|
||||
?BR,
|
||||
?INPUTT("submit", "delete", "Delete Selected")
|
||||
])].
|
||||
|
||||
user_queue_parse_query(User, Query) ->
|
||||
case lists:keysearch("delete", 1, Query) of
|
||||
{value, _} ->
|
||||
Msgs = lists:keysort(3, mnesia:dirty_read({offline_msg, User})),
|
||||
F = fun() ->
|
||||
lists:foreach(
|
||||
fun(Msg) ->
|
||||
ID = jlib:encode_base64(
|
||||
binary_to_list(term_to_binary(Msg))),
|
||||
case lists:member({"selected", ID}, Query) of
|
||||
true ->
|
||||
mnesia:delete_object(Msg);
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, Msgs)
|
||||
end,
|
||||
mnesia:transaction(F),
|
||||
ok;
|
||||
false ->
|
||||
nothing
|
||||
end.
|
||||
|
||||
|
||||
|
||||
-record(roster, {uj,
|
||||
user,
|
||||
jid,
|
||||
@ -1156,10 +1351,11 @@ ask_to_pending(subscribe) -> out;
|
||||
ask_to_pending(unsubscribe) -> none;
|
||||
ask_to_pending(Ask) -> Ask.
|
||||
|
||||
user_roster(User, Query, Lang) ->
|
||||
%Res = user_parse_query(User, Query),
|
||||
Res = nothing, % TODO
|
||||
|
||||
user_roster(User, Query, Lang, Admin) ->
|
||||
LUser = jlib:nameprep(User),
|
||||
Items1 = mnesia:dirty_index_read(roster, LUser, #roster.user),
|
||||
Res = user_roster_parse_query(User, Items1, Query, Admin),
|
||||
Items = mnesia:dirty_index_read(roster, LUser, #roster.user),
|
||||
SItems = lists:sort(Items),
|
||||
FItems =
|
||||
@ -1173,22 +1369,43 @@ user_roster(User, Query, Lang) ->
|
||||
[?XCT("td", "JID"),
|
||||
?XCT("td", "Name"),
|
||||
?XCT("td", "Subscription"),
|
||||
?XCT("td", "Pending")
|
||||
?XCT("td", "Pending"),
|
||||
?XCT("td", "Groups")
|
||||
])]),
|
||||
?XE("tbody",
|
||||
lists:map(
|
||||
fun(R) ->
|
||||
Groups =
|
||||
lists:flatmap(
|
||||
fun(Group) ->
|
||||
[?C(Group), ?BR]
|
||||
end, R#roster.groups),
|
||||
Pending = ask_to_pending(R#roster.ask),
|
||||
?XE("tr",
|
||||
[?XE("td", [?C(jlib:jid_to_string(
|
||||
R#roster.jid))]),
|
||||
?XE("td", [?C(R#roster.name)]),
|
||||
?XE("td",
|
||||
[?C(atom_to_list(
|
||||
R#roster.subscription))]),
|
||||
?XE("td",
|
||||
[?C(atom_to_list(
|
||||
ask_to_pending(
|
||||
R#roster.ask)))])])
|
||||
[?XAC("td", [{"class", "valign"}],
|
||||
jlib:jid_to_string(R#roster.jid)),
|
||||
?XAC("td", [{"class", "valign"}],
|
||||
R#roster.name),
|
||||
?XAC("td", [{"class", "valign"}],
|
||||
atom_to_list(R#roster.subscription)),
|
||||
?XAC("td", [{"class", "valign"}],
|
||||
atom_to_list(Pending)),
|
||||
?XAE("td", [{"class", "valign"}], Groups),
|
||||
if
|
||||
Pending == in ->
|
||||
?XAE("td", [{"class", "valign"}],
|
||||
[?INPUTT("submit",
|
||||
"validate" ++
|
||||
term_to_id(R#roster.jid),
|
||||
"Validate")]);
|
||||
true ->
|
||||
?X("td")
|
||||
end,
|
||||
?XAE("td", [{"class", "valign"}],
|
||||
[?INPUTT("submit",
|
||||
"remove" ++
|
||||
term_to_id(R#roster.jid),
|
||||
"Remove")])])
|
||||
end, SItems))])]
|
||||
end,
|
||||
[?XC("h1", "Roster of " ++ User)] ++
|
||||
@ -1198,7 +1415,129 @@ user_roster(User, Query, Lang) ->
|
||||
nothing -> []
|
||||
end ++
|
||||
[?XAE("form", [{"method", "post"}],
|
||||
FItems)].
|
||||
FItems ++
|
||||
[?P,
|
||||
?INPUT("text", "newjid", ""), ?C(" "),
|
||||
?INPUTT("submit", "addjid", "Add JID")
|
||||
])].
|
||||
|
||||
user_roster_parse_query(User, Items, Query, Admin) ->
|
||||
case lists:keysearch("addjid", 1, Query) of
|
||||
{value, _} ->
|
||||
case lists:keysearch("newjid", 1, Query) of
|
||||
{value, {_, undefined}} ->
|
||||
error;
|
||||
{value, {_, SJID}} ->
|
||||
case jlib:string_to_jid(SJID) of
|
||||
JID when is_record(JID, jid) ->
|
||||
user_roster_subscribe_jid(User, JID),
|
||||
ok;
|
||||
error ->
|
||||
error
|
||||
end;
|
||||
false ->
|
||||
error
|
||||
end;
|
||||
false ->
|
||||
case lists:keysearch("adduser", 1, Query) of
|
||||
{value, _} ->
|
||||
case lists:keysearch("newuser", 1, Query) of
|
||||
{value, {_, undefined}} ->
|
||||
error;
|
||||
{value, {_, U}} ->
|
||||
if
|
||||
Admin ->
|
||||
user_roster_subscribe_users(User, U);
|
||||
true ->
|
||||
case jlib:make_jid(U, ?MYNAME, "") of
|
||||
JID when is_record(JID, jid) ->
|
||||
user_roster_subscribe_jid(
|
||||
User, JID),
|
||||
ok;
|
||||
false ->
|
||||
error
|
||||
end
|
||||
end;
|
||||
false ->
|
||||
error
|
||||
end;
|
||||
false ->
|
||||
case catch user_roster_item_parse_query(
|
||||
User, Items, Query) of
|
||||
submitted ->
|
||||
ok;
|
||||
{'EXIT', _Reason} ->
|
||||
error;
|
||||
_ ->
|
||||
nothing
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
user_roster_subscribe_users(User1, User2) ->
|
||||
case jlib:make_jid(User1, ?MYNAME, "") of
|
||||
JID1 when is_record(JID1, jid) ->
|
||||
case jlib:make_jid(User2, ?MYNAME, "") of
|
||||
JID2 when is_record(JID2, jid) ->
|
||||
mod_roster:out_subscription(User1, JID2, subscribe),
|
||||
mod_roster:in_subscription(User2, JID1, subscribe),
|
||||
mod_roster:out_subscription(User2, JID1, subscribe),
|
||||
mod_roster:in_subscription(User1, JID2, subscribe),
|
||||
mod_roster:out_subscription(User1, JID2, subscribed),
|
||||
mod_roster:in_subscription(User2, JID1, subscribed),
|
||||
mod_roster:out_subscription(User2, JID1, subscribed),
|
||||
mod_roster:in_subscription(User1, JID2, subscribed),
|
||||
ok;
|
||||
false ->
|
||||
error
|
||||
end;
|
||||
false ->
|
||||
error
|
||||
end.
|
||||
|
||||
user_roster_subscribe_jid(User, JID) ->
|
||||
mod_roster:out_subscription(User, JID, subscribe),
|
||||
UJID = jlib:make_jid(User, ?MYNAME, ""),
|
||||
ejabberd_router:route(
|
||||
UJID, JID, {xmlelement, "presence", [{"type", "subscribe"}], []}).
|
||||
|
||||
user_roster_item_parse_query(User, Items, Query) ->
|
||||
lists:foreach(
|
||||
fun(R) ->
|
||||
JID = R#roster.jid,
|
||||
case lists:keysearch(
|
||||
"validate" ++ term_to_id(JID), 1, Query) of
|
||||
{value, _} ->
|
||||
JID1 = jlib:make_jid(JID),
|
||||
mod_roster:out_subscription(User, JID1, subscribed),
|
||||
UJID = jlib:make_jid(User, ?MYNAME, ""),
|
||||
ejabberd_router:route(
|
||||
UJID, JID1, {xmlelement, "presence",
|
||||
[{"type", "subscribed"}], []}),
|
||||
throw(submitted);
|
||||
false ->
|
||||
case lists:keysearch(
|
||||
"remove" ++ term_to_id(JID), 1, Query) of
|
||||
{value, _} ->
|
||||
UJID = jlib:make_jid(User, ?MYNAME, ""),
|
||||
mod_roster:process_iq(
|
||||
UJID, UJID,
|
||||
#iq{type = set,
|
||||
sub_el = {xmlelement, "query",
|
||||
[{"xmlns", ?NS_ROSTER}],
|
||||
[{xmlelement, "item",
|
||||
[{"jid", jlib:jid_to_string(JID)},
|
||||
{"subscription", "remove"}],
|
||||
[]}]}}),
|
||||
throw(submitted);
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
|
||||
end
|
||||
end, Items),
|
||||
nothing.
|
||||
|
||||
|
||||
|
||||
get_nodes(Lang) ->
|
||||
@ -1650,3 +1989,45 @@ node_ports_parse_query(Node, Ports, Query) ->
|
||||
|
||||
|
||||
|
||||
pretty_print(El) ->
|
||||
lists:flatten(pretty_print(El, "")).
|
||||
|
||||
pretty_print({xmlcdata, CData}, Prefix) ->
|
||||
[Prefix, CData, $\n];
|
||||
pretty_print({xmlelement, Name, Attrs, Els}, Prefix) ->
|
||||
[Prefix, $<, Name,
|
||||
case Attrs of
|
||||
[] ->
|
||||
[];
|
||||
[{Attr, Val} | RestAttrs] ->
|
||||
AttrPrefix = [Prefix,
|
||||
string:copies(" ", length(Name) + 2)],
|
||||
[$\s, Attr, $=, $', xml:crypt(Val), $' |
|
||||
lists:map(fun({Attr1, Val1}) ->
|
||||
[$\n, AttrPrefix,
|
||||
Attr1, $=, $', xml:crypt(Val1), $']
|
||||
end, RestAttrs)]
|
||||
end,
|
||||
if
|
||||
Els == [] ->
|
||||
"/>\n";
|
||||
true ->
|
||||
OnlyCData = lists:all(fun({xmlcdata, _}) -> true;
|
||||
({xmlelement, _, _, _}) -> false
|
||||
end, Els),
|
||||
if
|
||||
OnlyCData ->
|
||||
[$>,
|
||||
xml:get_cdata(Els),
|
||||
$<, $/, Name, $>, $\n
|
||||
];
|
||||
true ->
|
||||
[$>, $\n,
|
||||
lists:map(fun(E) ->
|
||||
pretty_print(E, [Prefix, " "])
|
||||
end, Els),
|
||||
Prefix, $<, $/, Name, $>, $\n
|
||||
]
|
||||
end
|
||||
end].
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user