diff options
Diffstat (limited to 'src/mod_vcard_mnesia.erl')
-rw-r--r-- | src/mod_vcard_mnesia.erl | 237 |
1 files changed, 150 insertions, 87 deletions
diff --git a/src/mod_vcard_mnesia.erl b/src/mod_vcard_mnesia.erl index 781a135c8..d4394b677 100644 --- a/src/mod_vcard_mnesia.erl +++ b/src/mod_vcard_mnesia.erl @@ -1,56 +1,70 @@ %%%------------------------------------------------------------------- -%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net> -%%% @copyright (C) 2016, Evgeny Khramtsov -%%% @doc -%%% -%%% @end +%%% File : mod_vcard_mnesia.erl +%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net> %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> -%%%------------------------------------------------------------------- +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License along +%%% with this program; if not, write to the Free Software Foundation, Inc., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + -module(mod_vcard_mnesia). -behaviour(mod_vcard). %% API --export([init/2, import/2, get_vcard/2, set_vcard/4, search/4, remove_user/2]). +-export([init/2, stop/1, import/3, get_vcard/2, set_vcard/4, search/4, + search_fields/1, search_reported/1, remove_user/2]). +-export([is_search_supported/1]). +-export([need_transform/1, transform/1]). +-export([mod_opt_type/1, mod_options/1]). --include("ejabberd.hrl"). --include("jlib.hrl"). +-include("xmpp.hrl"). -include("mod_vcard.hrl"). -include("logger.hrl"). +-include("translate.hrl"). %%%=================================================================== %%% API %%%=================================================================== init(_Host, _Opts) -> - mnesia:create_table(vcard, + ejabberd_mnesia:create(?MODULE, vcard, [{disc_only_copies, [node()]}, {attributes, record_info(fields, vcard)}]), - mnesia:create_table(vcard_search, + ejabberd_mnesia:create(?MODULE, vcard_search, [{disc_copies, [node()]}, {attributes, - record_info(fields, vcard_search)}]), - update_tables(), - mnesia:add_table_index(vcard_search, luser), - mnesia:add_table_index(vcard_search, lfn), - mnesia:add_table_index(vcard_search, lfamily), - mnesia:add_table_index(vcard_search, lgiven), - mnesia:add_table_index(vcard_search, lmiddle), - mnesia:add_table_index(vcard_search, lnickname), - mnesia:add_table_index(vcard_search, lbday), - mnesia:add_table_index(vcard_search, lctry), - mnesia:add_table_index(vcard_search, llocality), - mnesia:add_table_index(vcard_search, lemail), - mnesia:add_table_index(vcard_search, lorgname), - mnesia:add_table_index(vcard_search, lorgunit). + record_info(fields, vcard_search)}, + {index, [ luser, lfn, lfamily, + lgiven, lmiddle, lnickname, + lbday, lctry, llocality, + lemail, lorgname, lorgunit + ]}]). + +stop(_Host) -> + ok. + +is_search_supported(_ServerHost) -> + true. get_vcard(LUser, LServer) -> US = {LUser, LServer}, - F = fun () -> mnesia:read({vcard, US}) end, - case mnesia:transaction(F) of - {atomic, Rs} -> - lists:map(fun (R) -> R#vcard.vcard end, Rs); - {aborted, _Reason} -> error - end. + Rs = mnesia:dirty_read(vcard, US), + {ok, lists:map(fun (R) -> R#vcard.vcard end, Rs)}. set_vcard(LUser, LServer, VCARD, VCardSearch) -> US = {LUser, LServer}, @@ -71,15 +85,44 @@ search(LServer, Data, AllowReturnAll, MaxMatch) -> {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), []; Rs -> + Fields = lists:map(fun record_to_item/1, Rs), case MaxMatch of infinity -> - Rs; + Fields; Val -> - lists:sublist(Rs, Val) + lists:sublist(Fields, Val) end end end. +search_fields(_LServer) -> + [{?T("User"), <<"user">>}, + {?T("Full Name"), <<"fn">>}, + {?T("Name"), <<"first">>}, + {?T("Middle Name"), <<"middle">>}, + {?T("Family Name"), <<"last">>}, + {?T("Nickname"), <<"nick">>}, + {?T("Birthday"), <<"bday">>}, + {?T("Country"), <<"ctry">>}, + {?T("City"), <<"locality">>}, + {?T("Email"), <<"email">>}, + {?T("Organization Name"), <<"orgname">>}, + {?T("Organization Unit"), <<"orgunit">>}]. + +search_reported(_LServer) -> + [{?T("Jabber ID"), <<"jid">>}, + {?T("Full Name"), <<"fn">>}, + {?T("Name"), <<"first">>}, + {?T("Middle Name"), <<"middle">>}, + {?T("Family Name"), <<"last">>}, + {?T("Nickname"), <<"nick">>}, + {?T("Birthday"), <<"bday">>}, + {?T("Country"), <<"ctry">>}, + {?T("City"), <<"locality">>}, + {?T("Email"), <<"email">>}, + {?T("Organization Name"), <<"orgname">>}, + {?T("Organization Unit"), <<"orgunit">>}]. + remove_user(LUser, LServer) -> US = {LUser, LServer}, F = fun () -> @@ -88,58 +131,60 @@ remove_user(LUser, LServer) -> end, mnesia:transaction(F). -import(_LServer, #vcard{} = VCard) -> +import(LServer, <<"vcard">>, [LUser, XML, _TimeStamp]) -> + #xmlel{} = El = fxml_stream:parse_element(XML), + VCard = #vcard{us = {LUser, LServer}, vcard = El}, mnesia:dirty_write(VCard); -import(_LServer, #vcard_search{} = S) -> - mnesia:dirty_write(S). +import(LServer, <<"vcard_search">>, + [User, LUser, FN, LFN, + Family, LFamily, Given, LGiven, + Middle, LMiddle, Nickname, LNickname, + BDay, LBDay, CTRY, LCTRY, Locality, LLocality, + EMail, LEMail, OrgName, LOrgName, OrgUnit, LOrgUnit]) -> + mnesia:dirty_write( + #vcard_search{us = {LUser, LServer}, + user = {User, LServer}, luser = LUser, + fn = FN, lfn = LFN, family = Family, + lfamily = LFamily, given = Given, + lgiven = LGiven, middle = Middle, + lmiddle = LMiddle, nickname = Nickname, + lnickname = LNickname, bday = BDay, + lbday = LBDay, ctry = CTRY, lctry = LCTRY, + locality = Locality, llocality = LLocality, + email = EMail, lemail = LEMail, + orgname = OrgName, lorgname = LOrgName, + orgunit = OrgUnit, lorgunit = LOrgUnit}). + +need_transform({vcard, {U, S}, _}) when is_list(U) orelse is_list(S) -> + ?INFO_MSG("Mnesia table 'vcard' will be converted to binary", []), + true; +need_transform(R) when element(1, R) == vcard_search -> + case element(2, R) of + {U, S} when is_list(U) orelse is_list(S) -> + ?INFO_MSG("Mnesia table 'vcard_search' will be converted to binary", []), + true; + _ -> + false + end; +need_transform(_) -> + false. + +transform(#vcard{us = {U, S}, vcard = El} = R) -> + R#vcard{us = {iolist_to_binary(U), iolist_to_binary(S)}, + vcard = fxml:to_xmlel(El)}; +transform(#vcard_search{} = VS) -> + [vcard_search | L] = tuple_to_list(VS), + NewL = lists:map( + fun({U, S}) -> + {iolist_to_binary(U), iolist_to_binary(S)}; + (Str) -> + iolist_to_binary(Str) + end, L), + list_to_tuple([vcard_search | NewL]). %%%=================================================================== %%% Internal functions %%%=================================================================== -update_tables() -> - update_vcard_table(), - update_vcard_search_table(). - -update_vcard_table() -> - Fields = record_info(fields, vcard), - case mnesia:table_info(vcard, attributes) of - Fields -> - ejabberd_config:convert_table_to_binary( - vcard, Fields, set, - fun(#vcard{us = {U, _}}) -> U end, - fun(#vcard{us = {U, S}, vcard = El} = R) -> - R#vcard{us = {iolist_to_binary(U), - iolist_to_binary(S)}, - vcard = fxml:to_xmlel(El)} - end); - _ -> - ?INFO_MSG("Recreating vcard table", []), - mnesia:transform_table(vcard, ignore, Fields) - end. - -update_vcard_search_table() -> - Fields = record_info(fields, vcard_search), - case mnesia:table_info(vcard_search, attributes) of - Fields -> - ejabberd_config:convert_table_to_binary( - vcard_search, Fields, set, - fun(#vcard_search{us = {U, _}}) -> U end, - fun(#vcard_search{} = VS) -> - [vcard_search | L] = tuple_to_list(VS), - NewL = lists:map( - fun({U, S}) -> - {iolist_to_binary(U), - iolist_to_binary(S)}; - (Str) -> - iolist_to_binary(Str) - end, L), - list_to_tuple([vcard_search | NewL]) - end); - _ -> - ?INFO_MSG("Recreating vcard_search table", []), - mnesia:transform_table(vcard_search, ignore, Fields) - end. - make_matchspec(LServer, Data) -> GlobMatch = #vcard_search{_ = '_'}, Match = filter_fields(Data, GlobMatch, LServer), @@ -152,11 +197,7 @@ filter_fields([{SVar, [Val]} | Ds], Match, LServer) LVal = mod_vcard:string2lower(Val), NewMatch = case SVar of <<"user">> -> - case gen_mod:get_module_opt(LServer, ?MODULE, - search_all_hosts, - fun(B) when is_boolean(B) -> - B - end, true) of + case mod_vcard_mnesia_opt:search_all_hosts(LServer) of true -> Match#vcard_search{luser = make_val(LVal)}; false -> Host = find_my_host(LServer), @@ -197,9 +238,9 @@ make_val(Val) -> find_my_host(LServer) -> Parts = str:tokens(LServer, <<".">>), - find_my_host(Parts, ?MYHOSTS). + find_my_host(Parts, ejabberd_option:hosts()). -find_my_host([], _Hosts) -> ?MYNAME; +find_my_host([], _Hosts) -> ejabberd_config:get_myname(); find_my_host([_ | Tail] = Parts, Hosts) -> Domain = parts_to_string(Parts), case lists:member(Domain, Hosts) of @@ -211,3 +252,25 @@ parts_to_string(Parts) -> str:strip(list_to_binary( lists:map(fun (S) -> <<S/binary, $.>> end, Parts)), right, $.). + +-spec record_to_item(#vcard_search{}) -> [{binary(), binary()}]. +record_to_item(R) -> + {User, Server} = R#vcard_search.user, + [{<<"jid">>, <<User/binary, "@", Server/binary>>}, + {<<"fn">>, (R#vcard_search.fn)}, + {<<"last">>, (R#vcard_search.family)}, + {<<"first">>, (R#vcard_search.given)}, + {<<"middle">>, (R#vcard_search.middle)}, + {<<"nick">>, (R#vcard_search.nickname)}, + {<<"bday">>, (R#vcard_search.bday)}, + {<<"ctry">>, (R#vcard_search.ctry)}, + {<<"locality">>, (R#vcard_search.locality)}, + {<<"email">>, (R#vcard_search.email)}, + {<<"orgname">>, (R#vcard_search.orgname)}, + {<<"orgunit">>, (R#vcard_search.orgunit)}]. + +mod_opt_type(search_all_hosts) -> + econf:bool(). + +mod_options(_) -> + [{search_all_hosts, true}]. |