diff options
Diffstat (limited to 'src/mod_roster_mnesia.erl')
-rw-r--r-- | src/mod_roster_mnesia.erl | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/mod_roster_mnesia.erl b/src/mod_roster_mnesia.erl index c67d7d5e4..41da9a6b4 100644 --- a/src/mod_roster_mnesia.erl +++ b/src/mod_roster_mnesia.erl @@ -31,11 +31,13 @@ get_roster/2, get_roster_item/3, roster_subscribe/4, remove_user/2, update_roster/4, del_roster/3, transaction/2, read_subscription_and_groups/3, import/3, create_roster/1, + process_rosteritems/5, use_cache/2]). -export([need_transform/1, transform/1]). -include("mod_roster.hrl"). -include("logger.hrl"). +-include("xmpp.hrl"). %%%=================================================================== %%% API @@ -155,5 +157,141 @@ transform(#roster_version{us = {U, S}, version = Ver} = R) -> 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 %%%=================================================================== |