mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-14 22:00:16 +02:00
Preliminary support for SQL in process_rosteritems, and move code (#2448)
This commit is contained in:
parent
122cb4b959
commit
e996579dd1
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
% Roster
|
% Roster
|
||||||
add_rosteritem/7, delete_rosteritem/4,
|
add_rosteritem/7, delete_rosteritem/4,
|
||||||
process_rosteritems/5, get_roster/2, push_roster/3,
|
get_roster/2, push_roster/3,
|
||||||
push_roster_all/1, push_alltoall/2,
|
push_roster_all/1, push_alltoall/2,
|
||||||
push_roster_item/5, build_roster_item/3,
|
push_roster_item/5, build_roster_item/3,
|
||||||
|
|
||||||
|
@ -506,7 +506,7 @@ get_commands_spec() ->
|
||||||
args_desc = ["User name", "Server name", "Contact user name", "Contact server name"],
|
args_desc = ["User name", "Server name", "Contact user name", "Contact server name"],
|
||||||
result = {res, rescode}},
|
result = {res, rescode}},
|
||||||
#ejabberd_commands{name = process_rosteritems, tags = [roster],
|
#ejabberd_commands{name = process_rosteritems, tags = [roster],
|
||||||
desc = "List/delete rosteritems that match filter (only Mnesia)",
|
desc = "List/delete rosteritems that match filter",
|
||||||
longdesc = "Explanation of each argument:\n"
|
longdesc = "Explanation of each argument:\n"
|
||||||
" - action: what to do with each rosteritem that "
|
" - action: what to do with each rosteritem that "
|
||||||
"matches all the filtering options\n"
|
"matches all the filtering options\n"
|
||||||
|
@ -515,6 +515,8 @@ get_commands_spec() ->
|
||||||
" - users: the JIDs of the local user\n"
|
" - users: the JIDs of the local user\n"
|
||||||
" - contacts: the JIDs of the contact in the roster\n"
|
" - contacts: the JIDs of the contact in the roster\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" *** Mnesia: \n"
|
||||||
|
"\n"
|
||||||
"Allowed values in the arguments:\n"
|
"Allowed values in the arguments:\n"
|
||||||
" ACTION = list | delete\n"
|
" ACTION = list | delete\n"
|
||||||
" SUBS = SUB[:SUB]* | any\n"
|
" SUBS = SUB[:SUB]* | any\n"
|
||||||
|
@ -532,8 +534,26 @@ get_commands_spec() ->
|
||||||
"'example.org' and that the contact JID is either a "
|
"'example.org' and that the contact JID is either a "
|
||||||
"bare server name (without user part) or that has a "
|
"bare server name (without user part) or that has a "
|
||||||
"user part and the server part contains the word 'icq'"
|
"user part and the server part contains the word 'icq'"
|
||||||
":\n list none:from:to any *@example.org *:*@*icq*",
|
":\n list none:from:to any *@example.org *:*@*icq*"
|
||||||
module = ?MODULE, function = process_rosteritems,
|
"\n\n"
|
||||||
|
" *** SQL:\n"
|
||||||
|
"\n"
|
||||||
|
"Allowed values in the arguments:\n"
|
||||||
|
" ACTION = list | delete\n"
|
||||||
|
" SUBS = any | none | from | to | both\n"
|
||||||
|
" ASKS = any | none | out | in\n"
|
||||||
|
" USERS = JID\n"
|
||||||
|
" CONTACTS = JID\n"
|
||||||
|
" JID = characters valid in a JID, and can use the "
|
||||||
|
"globs: _ and %\n"
|
||||||
|
"\n"
|
||||||
|
"This example will list roster items with subscription "
|
||||||
|
"'to' that have any ask property, of "
|
||||||
|
"local users which JID is in the virtual host "
|
||||||
|
"'example.org' and that the contact JID's "
|
||||||
|
"server part contains the word 'icq'"
|
||||||
|
":\n list to any %@example.org %@%icq%",
|
||||||
|
module = mod_roster, function = process_rosteritems,
|
||||||
args = [{action, string}, {subs, string},
|
args = [{action, string}, {subs, string},
|
||||||
{asks, string}, {users, string},
|
{asks, string}, {users, string},
|
||||||
{contacts, string}],
|
{contacts, string}],
|
||||||
|
@ -1535,132 +1555,6 @@ stats(Name, Host) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%-----------------------------
|
|
||||||
%% Purge roster items
|
|
||||||
%%-----------------------------
|
|
||||||
|
|
||||||
process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
|
|
||||||
Action = case ActionS of
|
|
||||||
"list" -> list;
|
|
||||||
"delete" -> delete
|
|
||||||
end,
|
|
||||||
|
|
||||||
Subs = lists:foldl(
|
|
||||||
fun(any, _) -> [none, from, to, both];
|
|
||||||
(Sub, Subs) -> [Sub | Subs]
|
|
||||||
end,
|
|
||||||
[],
|
|
||||||
[list_to_atom(S) || S <- string:tokens(SubsS, ":")]
|
|
||||||
),
|
|
||||||
|
|
||||||
Asks = lists:foldl(
|
|
||||||
fun(any, _) -> [none, out, in];
|
|
||||||
(Ask, Asks) -> [Ask | Asks]
|
|
||||||
end,
|
|
||||||
[],
|
|
||||||
[list_to_atom(S) || S <- string:tokens(AsksS, ":")]
|
|
||||||
),
|
|
||||||
|
|
||||||
Users = lists:foldl(
|
|
||||||
fun("any", _) -> ["*", "*@*"];
|
|
||||||
(U, Us) -> [U | Us]
|
|
||||||
end,
|
|
||||||
[],
|
|
||||||
[S || S <- string:tokens(UsersS, ":")]
|
|
||||||
),
|
|
||||||
|
|
||||||
Contacts = lists:foldl(
|
|
||||||
fun("any", _) -> ["*", "*@*"];
|
|
||||||
(U, Us) -> [U | Us]
|
|
||||||
end,
|
|
||||||
[],
|
|
||||||
[S || S <- string:tokens(ContactsS, ":")]
|
|
||||||
),
|
|
||||||
|
|
||||||
rosteritem_purge({Action, Subs, Asks, Users, Contacts}).
|
|
||||||
|
|
||||||
%% @spec ({Action::atom(), Subs::[atom()], Asks::[atom()], User::string(), Contact::string()}) -> {atomic, ok}
|
|
||||||
rosteritem_purge(Options) ->
|
|
||||||
Num_rosteritems = mnesia:table_info(roster, size),
|
|
||||||
io:format("There are ~p roster items in total.~n", [Num_rosteritems]),
|
|
||||||
Key = mnesia:dirty_first(roster),
|
|
||||||
rip(Key, Options, {0, Num_rosteritems, 0, 0}, []).
|
|
||||||
|
|
||||||
rip('$end_of_table', _Options, Counters, Res) ->
|
|
||||||
print_progress_line(Counters),
|
|
||||||
Res;
|
|
||||||
rip(Key, Options, {Pr, NT, NV, ND}, Res) ->
|
|
||||||
Key_next = mnesia:dirty_next(roster, Key),
|
|
||||||
{Action, _, _, _, _} = Options,
|
|
||||||
{ND2, Res2} = case decide_rip(Key, Options) of
|
|
||||||
true ->
|
|
||||||
Jids = apply_action(Action, Key),
|
|
||||||
{ND+1, [Jids | Res]};
|
|
||||||
false ->
|
|
||||||
{ND, Res}
|
|
||||||
end,
|
|
||||||
NV2 = NV+1,
|
|
||||||
Pr2 = print_progress_line({Pr, NT, NV2, ND2}),
|
|
||||||
rip(Key_next, Options, {Pr2, NT, NV2, ND2}, Res2).
|
|
||||||
|
|
||||||
apply_action(list, Key) ->
|
|
||||||
{User, Server, JID} = Key,
|
|
||||||
{RUser, RServer, _} = JID,
|
|
||||||
Jid1string = <<User/binary, "@", Server/binary>>,
|
|
||||||
Jid2string = <<RUser/binary, "@", RServer/binary>>,
|
|
||||||
io:format("Matches: ~s ~s~n", [Jid1string, Jid2string]),
|
|
||||||
{Jid1string, Jid2string};
|
|
||||||
apply_action(delete, Key) ->
|
|
||||||
R = apply_action(list, Key),
|
|
||||||
mnesia:dirty_delete(roster, Key),
|
|
||||||
R.
|
|
||||||
|
|
||||||
print_progress_line({_Pr, 0, _NV, _ND}) ->
|
|
||||||
ok;
|
|
||||||
print_progress_line({Pr, NT, NV, ND}) ->
|
|
||||||
Pr2 = trunc((NV/NT)*100),
|
|
||||||
case Pr == Pr2 of
|
|
||||||
true ->
|
|
||||||
ok;
|
|
||||||
false ->
|
|
||||||
io:format("Progress ~p% - visited ~p - deleted ~p~n", [Pr2, NV, ND])
|
|
||||||
end,
|
|
||||||
Pr2.
|
|
||||||
|
|
||||||
decide_rip(Key, {_Action, Subs, Asks, User, Contact}) ->
|
|
||||||
case catch mnesia:dirty_read(roster, Key) of
|
|
||||||
[RI] ->
|
|
||||||
lists:member(RI#roster.subscription, Subs)
|
|
||||||
andalso lists:member(RI#roster.ask, Asks)
|
|
||||||
andalso decide_rip_jid(RI#roster.us, User)
|
|
||||||
andalso decide_rip_jid(RI#roster.jid, Contact);
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% Returns true if the server of the JID is included in the servers
|
|
||||||
decide_rip_jid({UName, UServer, _UResource}, Match_list) ->
|
|
||||||
decide_rip_jid({UName, UServer}, Match_list);
|
|
||||||
decide_rip_jid({UName, UServer}, Match_list) ->
|
|
||||||
lists:any(
|
|
||||||
fun(Match_string) ->
|
|
||||||
MJID = jid:decode(list_to_binary(Match_string)),
|
|
||||||
MName = MJID#jid.luser,
|
|
||||||
MServer = MJID#jid.lserver,
|
|
||||||
Is_server = is_glob_match(UServer, MServer),
|
|
||||||
case MName of
|
|
||||||
<<>> when UName == <<>> ->
|
|
||||||
Is_server;
|
|
||||||
<<>> ->
|
|
||||||
false;
|
|
||||||
_ ->
|
|
||||||
Is_server
|
|
||||||
andalso is_glob_match(UName, MName)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
Match_list).
|
|
||||||
|
|
||||||
user_action(User, Server, Fun, OK) ->
|
user_action(User, Server, Fun, OK) ->
|
||||||
case ejabberd_auth:user_exists(User, Server) of
|
case ejabberd_auth:user_exists(User, Server) of
|
||||||
true ->
|
true ->
|
||||||
|
@ -1675,24 +1569,6 @@ user_action(User, Server, Fun, OK) ->
|
||||||
throw({not_found, "unknown_user"})
|
throw({not_found, "unknown_user"})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Copied from ejabberd-2.0.0/src/acl.erl
|
|
||||||
is_regexp_match(String, RegExp) ->
|
|
||||||
case ejabberd_regexp:run(String, RegExp) of
|
|
||||||
nomatch ->
|
|
||||||
false;
|
|
||||||
match ->
|
|
||||||
true;
|
|
||||||
{error, ErrDesc} ->
|
|
||||||
io:format(
|
|
||||||
"Wrong regexp ~p in ACL: ~p",
|
|
||||||
[RegExp, ErrDesc]),
|
|
||||||
false
|
|
||||||
end.
|
|
||||||
is_glob_match(String, <<"!", Glob/binary>>) ->
|
|
||||||
not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob));
|
|
||||||
is_glob_match(String, Glob) ->
|
|
||||||
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
|
|
||||||
|
|
||||||
num_prio(Priority) when is_integer(Priority) ->
|
num_prio(Priority) when is_integer(Priority) ->
|
||||||
Priority;
|
Priority;
|
||||||
num_prio(_) ->
|
num_prio(_) ->
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
webadmin_user/4, get_versioning_feature/2,
|
webadmin_user/4, get_versioning_feature/2,
|
||||||
roster_versioning_enabled/1, roster_version/2,
|
roster_versioning_enabled/1, roster_version/2,
|
||||||
mod_opt_type/1, mod_options/1, set_roster/1, del_roster/3,
|
mod_opt_type/1, mod_options/1, set_roster/1, del_roster/3,
|
||||||
|
process_rosteritems/5,
|
||||||
depends/2]).
|
depends/2]).
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
@ -892,6 +893,11 @@ is_subscribed(From, #jid{luser = LUser, lserver = LServer}) ->
|
||||||
(Sub /= none) orelse (Ask == subscribe)
|
(Sub /= none) orelse (Ask == subscribe)
|
||||||
orelse (Ask == out) orelse (Ask == both).
|
orelse (Ask == out) orelse (Ask == both).
|
||||||
|
|
||||||
|
process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
|
||||||
|
LServer = ejabberd_config:get_myname(),
|
||||||
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
|
Mod:process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
webadmin_page(_, Host,
|
webadmin_page(_, Host,
|
||||||
|
|
|
@ -31,11 +31,13 @@
|
||||||
get_roster/2, get_roster_item/3, roster_subscribe/4,
|
get_roster/2, get_roster_item/3, roster_subscribe/4,
|
||||||
remove_user/2, update_roster/4, del_roster/3, transaction/2,
|
remove_user/2, update_roster/4, del_roster/3, transaction/2,
|
||||||
read_subscription_and_groups/3, import/3, create_roster/1,
|
read_subscription_and_groups/3, import/3, create_roster/1,
|
||||||
|
process_rosteritems/5,
|
||||||
use_cache/2]).
|
use_cache/2]).
|
||||||
-export([need_transform/1, transform/1]).
|
-export([need_transform/1, transform/1]).
|
||||||
|
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% API
|
%%% API
|
||||||
|
@ -154,6 +156,142 @@ transform(#roster_version{us = {U, S}, version = Ver} = R) ->
|
||||||
R#roster_version{us = {iolist_to_binary(U), iolist_to_binary(S)},
|
R#roster_version{us = {iolist_to_binary(U), iolist_to_binary(S)},
|
||||||
version = iolist_to_binary(Ver)}.
|
version = iolist_to_binary(Ver)}.
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
|
||||||
|
process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
|
||||||
|
Action = case ActionS of
|
||||||
|
"list" -> list;
|
||||||
|
"delete" -> delete
|
||||||
|
end,
|
||||||
|
Subs = lists:foldl(
|
||||||
|
fun(any, _) -> [none, from, to, both];
|
||||||
|
(Sub, Subs) -> [Sub | Subs]
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
[list_to_atom(S) || S <- string:tokens(SubsS, ":")]
|
||||||
|
),
|
||||||
|
Asks = lists:foldl(
|
||||||
|
fun(any, _) -> [none, out, in];
|
||||||
|
(Ask, Asks) -> [Ask | Asks]
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
[list_to_atom(S) || S <- string:tokens(AsksS, ":")]
|
||||||
|
),
|
||||||
|
Users = lists:foldl(
|
||||||
|
fun("any", _) -> ["*", "*@*"];
|
||||||
|
(U, Us) -> [U | Us]
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
[S || S <- string:tokens(UsersS, ":")]
|
||||||
|
),
|
||||||
|
Contacts = lists:foldl(
|
||||||
|
fun("any", _) -> ["*", "*@*"];
|
||||||
|
(U, Us) -> [U | Us]
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
[S || S <- string:tokens(ContactsS, ":")]
|
||||||
|
),
|
||||||
|
rosteritem_purge({Action, Subs, Asks, Users, Contacts}).
|
||||||
|
|
||||||
|
%% @spec ({Action::atom(), Subs::[atom()], Asks::[atom()], User::string(), Contact::string()}) -> {atomic, ok}
|
||||||
|
rosteritem_purge(Options) ->
|
||||||
|
Num_rosteritems = mnesia:table_info(roster, size),
|
||||||
|
io:format("There are ~p roster items in total.~n", [Num_rosteritems]),
|
||||||
|
Key = mnesia:dirty_first(roster),
|
||||||
|
rip(Key, Options, {0, Num_rosteritems, 0, 0}, []).
|
||||||
|
|
||||||
|
rip('$end_of_table', _Options, Counters, Res) ->
|
||||||
|
print_progress_line(Counters),
|
||||||
|
Res;
|
||||||
|
rip(Key, Options, {Pr, NT, NV, ND}, Res) ->
|
||||||
|
Key_next = mnesia:dirty_next(roster, Key),
|
||||||
|
{Action, _, _, _, _} = Options,
|
||||||
|
{ND2, Res2} = case decide_rip(Key, Options) of
|
||||||
|
true ->
|
||||||
|
Jids = apply_action(Action, Key),
|
||||||
|
{ND+1, [Jids | Res]};
|
||||||
|
false ->
|
||||||
|
{ND, Res}
|
||||||
|
end,
|
||||||
|
NV2 = NV+1,
|
||||||
|
Pr2 = print_progress_line({Pr, NT, NV2, ND2}),
|
||||||
|
rip(Key_next, Options, {Pr2, NT, NV2, ND2}, Res2).
|
||||||
|
|
||||||
|
apply_action(list, Key) ->
|
||||||
|
{User, Server, JID} = Key,
|
||||||
|
{RUser, RServer, _} = JID,
|
||||||
|
Jid1string = <<User/binary, "@", Server/binary>>,
|
||||||
|
Jid2string = <<RUser/binary, "@", RServer/binary>>,
|
||||||
|
io:format("Matches: ~s ~s~n", [Jid1string, Jid2string]),
|
||||||
|
{Jid1string, Jid2string};
|
||||||
|
apply_action(delete, Key) ->
|
||||||
|
R = apply_action(list, Key),
|
||||||
|
mnesia:dirty_delete(roster, Key),
|
||||||
|
R.
|
||||||
|
|
||||||
|
print_progress_line({_Pr, 0, _NV, _ND}) ->
|
||||||
|
ok;
|
||||||
|
print_progress_line({Pr, NT, NV, ND}) ->
|
||||||
|
Pr2 = trunc((NV/NT)*100),
|
||||||
|
case Pr == Pr2 of
|
||||||
|
true ->
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
io:format("Progress ~p% - visited ~p - deleted ~p~n", [Pr2, NV, ND])
|
||||||
|
end,
|
||||||
|
Pr2.
|
||||||
|
|
||||||
|
decide_rip(Key, {_Action, Subs, Asks, User, Contact}) ->
|
||||||
|
case catch mnesia:dirty_read(roster, Key) of
|
||||||
|
[RI] ->
|
||||||
|
lists:member(RI#roster.subscription, Subs)
|
||||||
|
andalso lists:member(RI#roster.ask, Asks)
|
||||||
|
andalso decide_rip_jid(RI#roster.us, User)
|
||||||
|
andalso decide_rip_jid(RI#roster.jid, Contact);
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% Returns true if the server of the JID is included in the servers
|
||||||
|
decide_rip_jid({UName, UServer, _UResource}, Match_list) ->
|
||||||
|
decide_rip_jid({UName, UServer}, Match_list);
|
||||||
|
decide_rip_jid({UName, UServer}, Match_list) ->
|
||||||
|
lists:any(
|
||||||
|
fun(Match_string) ->
|
||||||
|
MJID = jid:decode(list_to_binary(Match_string)),
|
||||||
|
MName = MJID#jid.luser,
|
||||||
|
MServer = MJID#jid.lserver,
|
||||||
|
Is_server = is_glob_match(UServer, MServer),
|
||||||
|
case MName of
|
||||||
|
<<>> when UName == <<>> ->
|
||||||
|
Is_server;
|
||||||
|
<<>> ->
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
Is_server
|
||||||
|
andalso is_glob_match(UName, MName)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
Match_list).
|
||||||
|
|
||||||
|
%% Copied from ejabberd-2.0.0/src/acl.erl
|
||||||
|
is_regexp_match(String, RegExp) ->
|
||||||
|
case ejabberd_regexp:run(String, RegExp) of
|
||||||
|
nomatch ->
|
||||||
|
false;
|
||||||
|
match ->
|
||||||
|
true;
|
||||||
|
{error, ErrDesc} ->
|
||||||
|
io:format(
|
||||||
|
"Wrong regexp ~p in ACL: ~p",
|
||||||
|
[RegExp, ErrDesc]),
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
is_glob_match(String, <<"!", Glob/binary>>) ->
|
||||||
|
not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob));
|
||||||
|
is_glob_match(String, Glob) ->
|
||||||
|
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
|
@ -33,11 +33,13 @@
|
||||||
get_roster/2, get_roster_item/3, roster_subscribe/4,
|
get_roster/2, get_roster_item/3, roster_subscribe/4,
|
||||||
read_subscription_and_groups/3, remove_user/2,
|
read_subscription_and_groups/3, remove_user/2,
|
||||||
update_roster/4, del_roster/3, transaction/2,
|
update_roster/4, del_roster/3, transaction/2,
|
||||||
|
process_rosteritems/5,
|
||||||
import/3, export/1, raw_to_record/2]).
|
import/3, export/1, raw_to_record/2]).
|
||||||
|
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
-include("ejabberd_sql_pt.hrl").
|
-include("ejabberd_sql_pt.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
-include("jid.hrl").
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% API
|
%%% API
|
||||||
|
@ -375,3 +377,39 @@ format_row_error(User, Server, Why) ->
|
||||||
{ask, Ask} -> ["Malformed 'ask' field with value '", Ask, "'"]
|
{ask, Ask} -> ["Malformed 'ask' field with value '", Ask, "'"]
|
||||||
end,
|
end,
|
||||||
" detected for ", User, "@", Server, " in table 'rosterusers'"].
|
" detected for ", User, "@", Server, " in table 'rosterusers'"].
|
||||||
|
|
||||||
|
process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
|
||||||
|
process_rosteritems_sql(ActionS, list_to_atom(SubsS), list_to_atom(AsksS),
|
||||||
|
list_to_binary(UsersS), list_to_binary(ContactsS)).
|
||||||
|
|
||||||
|
process_rosteritems_sql(ActionS, Subscription, Ask, SLocalJID, SJID) ->
|
||||||
|
[LUser, LServer] = binary:split(SLocalJID, <<"@">>),
|
||||||
|
SSubscription = case Subscription of
|
||||||
|
any -> <<"_">>;
|
||||||
|
both -> <<"B">>;
|
||||||
|
to -> <<"T">>;
|
||||||
|
from -> <<"F">>;
|
||||||
|
none -> <<"N">>
|
||||||
|
end,
|
||||||
|
SAsk = case Ask of
|
||||||
|
any -> <<"_">>;
|
||||||
|
subscribe -> <<"S">>;
|
||||||
|
unsubscribe -> <<"U">>;
|
||||||
|
both -> <<"B">>;
|
||||||
|
out -> <<"O">>;
|
||||||
|
in -> <<"I">>;
|
||||||
|
none -> <<"N">>
|
||||||
|
end,
|
||||||
|
{selected, List} = ejabberd_sql:sql_query(
|
||||||
|
LServer,
|
||||||
|
?SQL("select @(username)s, @(jid)s from rosterusers "
|
||||||
|
"where username LIKE %(LUser)s"
|
||||||
|
" and %(LServer)H"
|
||||||
|
" and jid LIKE %(SJID)s"
|
||||||
|
" and subscription LIKE %(SSubscription)s"
|
||||||
|
" and ask LIKE %(SAsk)s")),
|
||||||
|
case ActionS of
|
||||||
|
"delete" -> [mod_roster:del_roster(User, LServer, jid:decode(Contact)) || {User, Contact} <- List];
|
||||||
|
"list" -> ok
|
||||||
|
end,
|
||||||
|
List.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user