diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index a82c343e4..7cc40ae1e 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -35,8 +35,8 @@ check_password/5, check_password_with_authmodule/3, check_password_with_authmodule/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, export/1, - get_vh_registered_users_number/1, + get_vh_registered_users/2, export/1, import/1, + get_vh_registered_users_number/1, import/3, get_vh_registered_users_number/2, get_password/2, get_password_s/2, get_password_with_authmodule/2, is_user_exists/2, is_user_exists_in_other_modules/3, @@ -437,3 +437,11 @@ auth_modules(Server) -> export(Server) -> ejabberd_auth_internal:export(Server). + +import(Server) -> + ejabberd_auth_internal:import(Server). + +import(Server, mnesia, Passwd) -> + ejabberd_auth_internal:import(Server, mnesia, Passwd); +import(_, _, _) -> + pass. diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index f66b09c88..5a6c1b10a 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -38,8 +38,8 @@ get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, export/1, - plain_password_required/0]). + remove_user/3, store_type/0, export/1, import/1, + import/3, plain_password_required/0]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -474,3 +474,14 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, password from users;">>, + fun([LUser, Password]) -> + #passwd{us = {LUser, LServer}, password = Password} + end}]. + +import(_LServer, mnesia, #passwd{} = P) -> + mnesia:dirty_write(P); +import(_, _, _) -> + pass. diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index b530f8f29..937805579 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -515,6 +515,9 @@ pgsql_to_odbc({ok, PGSQLResult}) -> pgsql_item_to_odbc({<<"SELECT", _/binary>>, Rows, Recs}) -> {selected, [element(1, Row) || Row <- Rows], Recs}; +pgsql_item_to_odbc({<<"FETCH", _/binary>>, Rows, + Recs}) -> + {selected, [element(1, Row) || Row <- Rows], Recs}; pgsql_item_to_odbc(<<"INSERT ", OIDN/binary>>) -> [_OID, N] = str:tokens(OIDN, <<" ">>), {updated, jlib:binary_to_integer(N)}; diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index b96503dbe..8777a7597 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -28,10 +28,14 @@ -author('alexey@process-one.net'). --export([export/2, export/3]). +-include("logger.hrl"). + +-export([export/2, export/3, import_file/2, import/2, import/3]). -define(MAX_RECORDS_PER_TRANSACTION, 100). +-record(dump, {fd, cont = start}). + %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- @@ -42,21 +46,24 @@ %%% - Output can be either odbc to export to the configured relational %%% database or "Filename" to export to text file. +modules() -> + [ejabberd_auth, + mod_announce, + mod_caps, + mod_irc, + mod_last, + mod_muc, + mod_offline, + mod_privacy, + mod_private, + mod_roster, + mod_shared_roster, + mod_vcard, + mod_vcard_xupdate]. + export(Server, Output) -> LServer = jlib:nameprep(iolist_to_binary(Server)), - Modules = [ejabberd_auth, - mod_announce, - mod_caps, - mod_irc, - mod_last, - mod_muc, - mod_offline, - mod_privacy, - mod_private, - mod_roster, - mod_shared_roster, - mod_vcard, - mod_vcard_xupdate], + Modules = modules(), IO = prepare_output(Output), lists:foreach( fun(Module) -> @@ -73,6 +80,47 @@ export(Server, Output, Module) -> end, Module:export(Server)), close_output(Output, IO). +import_file(Server, FileName) when is_binary(FileName) -> + import(Server, binary_to_list(FileName)); +import_file(Server, FileName) -> + case disk_log:open([{name, make_ref()}, + {file, FileName}, + {mode, read_only}]) of + {ok, Fd} -> + LServer = jlib:nameprep(Server), + Mods = [{Mod, gen_mod:db_type(LServer, Mod)} + || Mod <- modules(), gen_mod:is_loaded(LServer, Mod)], + AuthMods = case lists:member(ejabberd_auth_internal, + ejabberd_auth:auth_modules(LServer)) of + true -> + [{ejabberd_auth, mnesia}]; + false -> + [] + end, + import_dump(LServer, AuthMods ++ Mods, #dump{fd = Fd}); + Err -> + exit(Err) + end. + +import(Server, Output) -> + LServer = jlib:nameprep(iolist_to_binary(Server)), + Modules = modules(), + IO = prepare_output(Output, disk_log), + lists:foreach( + fun(Module) -> + import(LServer, IO, Module) + end, Modules), + close_output(Output, IO). + +import(Server, Output, Module) -> + LServer = jlib:nameprep(iolist_to_binary(Server)), + IO = prepare_output(Output, disk_log), + lists:foreach( + fun({SelectQuery, ConvertFun}) -> + import(LServer, SelectQuery, IO, ConvertFun) + end, Module:import(Server)), + close_output(Output, IO). + %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- @@ -109,18 +157,97 @@ output(_LServer, Table, Fd, SQLs) -> file:write(Fd, ["-- \n-- Mnesia table: ", atom_to_list(Table), "\n--\n", SQLs]). -prepare_output(FileName) when is_list(FileName); is_binary(FileName) -> +import(LServer, SelectQuery, IO, ConvertFun) -> + F = fun() -> + ejabberd_odbc:sql_query_t( + iolist_to_binary( + [<<"declare c cursor for ">>, SelectQuery])), + fetch(IO, ConvertFun) + end, + ejabberd_odbc:sql_transaction(LServer, F). + +fetch(IO, ConvertFun) -> + fetch(IO, ConvertFun, undefined). + +fetch(IO, ConvertFun, PrevRow) -> + case ejabberd_odbc:sql_query_t([<<"fetch c;">>]) of + {selected, _, [Row]} when Row == PrevRow -> + %% Avoid calling ConvertFun with the same input + fetch(IO, ConvertFun, Row); + {selected, _, [Row]} -> + case catch ConvertFun(Row) of + {'EXIT', _} = Err -> + ?ERROR_MSG("failed to convert ~p: ~p", + [Row, Err]); + Term -> + ok = disk_log:log(IO#dump.fd, Term) + end, + fetch(IO, ConvertFun, Row); + {selected, _, []} -> + ok; + Err -> + erlang:error(Err) + end. + +import_dump(LServer, Mods, #dump{fd = Fd, cont = Cont}) -> + case disk_log:chunk(Fd, Cont) of + {NewCont, Terms} -> + import_terms(LServer, Mods, Terms), + import_dump(LServer, Mods, #dump{fd = Fd, cont = NewCont}); + eof -> + ok; + Err -> + exit(Err) + end. + +import_terms(LServer, Mods, [Term|Terms]) -> + import_term(LServer, Mods, Term), + import_terms(LServer, Mods, Terms); +import_terms(_LServer, _Mods, []) -> + ok. + +import_term(LServer, [{Mod, DBType}|Mods], Term) -> + case catch Mod:import(LServer, DBType, Term) of + pass -> import_term(LServer, Mods, Term); + ok -> ok; + Err -> + ?ERROR_MSG("failed to import ~p for module ~p: ~p", + [Term, Mod, Err]) + end; +import_term(_LServer, [], _Term) -> + ok. + +prepare_output(FileName) -> + prepare_output(FileName, normal). + +prepare_output(FileName, Type) when is_binary(FileName) -> + prepare_output(binary_to_list(FileName), Type); +prepare_output(FileName, normal) when is_list(FileName) -> case file:open(FileName, [write, raw]) of {ok, Fd} -> Fd; Err -> exit(Err) end; -prepare_output(Output) -> +prepare_output(FileName, disk_log) when is_list(FileName) -> + case disk_log:open([{name, make_ref()}, + {repair, truncate}, + {file, FileName}]) of + {ok, Fd} -> + #dump{fd = Fd}; + Err -> + exit(Err) + end; +prepare_output(Output, _Type) -> Output. close_output(FileName, Fd) when FileName /= Fd -> - file:close(Fd), + case Fd of + #dump{} -> + disk_log:close(Fd#dump.fd); + _ -> + file:close(Fd) + end, ok; close_output(_, _) -> ok. diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 8d72b4bf7..b558897a0 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -35,7 +35,9 @@ -export([start/2, init/0, stop/1, - export/1, + export/1, + import/1, + import/3, announce/3, send_motd/1, disco_identity/5, @@ -1072,3 +1074,21 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select xml from motd where username='';">>, + fun([XML]) -> + El = xml_stream:parse_element(XML), + #motd{server = LServer, packet = El} + end}, + {<<"select username from motd where xml='';">>, + fun([LUser]) -> + #motd_users{us = {LUser, LServer}} + end}]. + +import(_LServer, mnesia, #motd{} = Motd) -> + mnesia:dirty_write(Motd); +import(_LServer, mnesia, #motd_users{} = Users) -> + mnesia:dirty_write(Users); +import(_, _, _) -> + pass. diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 9d9246fad..3aa57002f 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -33,8 +33,8 @@ -behaviour(gen_mod). %% API --export([start_link/2, start/2, stop/1, export/1, - closed_connection/3, get_connection_params/3]). +-export([start_link/2, start/2, stop/1, export/1, import/1, + import/3, closed_connection/3, get_connection_params/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, @@ -1288,3 +1288,17 @@ export(_Server) -> [] end end}]. + +import(_LServer) -> + [{<<"select jid, host, data from irc_custom;">>, + fun([SJID, IRCHost, SData]) -> + #jid{luser = U, lserver = S} = jlib:string_to_jid(SJID), + Data = ejabberd_odbc:decode_term(SData), + #irc_custom{us_host = {{U, S}, IRCHost}, + data = Data} + end}]. + +import(_LServer, mnesia, #irc_custom{} = R) -> + mnesia:dirty_write(R); +import(_, _, _) -> + pass. diff --git a/src/mod_last.erl b/src/mod_last.erl index 28fcda63a..3ea86b350 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -31,7 +31,7 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, export/1, - process_sm_iq/3, on_presence_update/4, + process_sm_iq/3, on_presence_update/4, import/1, import/3, store_last_info/4, get_last_info/2, remove_user/2]). -include("ejabberd.hrl"). @@ -305,3 +305,17 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, seconds, state from last">>, + fun([LUser, TimeStamp, State]) -> + #last_activity{us = {LUser, LServer}, + timestamp = jlib:binary_to_integer( + TimeStamp), + status = State} + end}]. + +import(_LServer, mnesia, #last_activity{} = LA) -> + mnesia:dirty_write(LA); +import(_, _, _) -> + pass. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 6b87f1579..cfed60a3c 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -44,6 +44,9 @@ shutdown_rooms/1, process_iq_disco_items/4, broadcast_service_message/2, + export/1, + import/1, + import/3, can_use_nick/4]). %% gen_server callbacks @@ -1141,3 +1144,64 @@ update_muc_registered_table(_Host) -> ?INFO_MSG("Recreating muc_registered table", []), mnesia:transform_table(muc_registered, ignore, Fields) end. + +export(_Server) -> + [{muc_room, + fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) -> + case str:suffix(Host, RoomHost) of + true -> + SName = ejabberd_odbc:escape(Name), + SRoomHost = ejabberd_odbc:escape(RoomHost), + SOpts = ejabberd_odbc:encode_term(Opts), + [[<<"delete from muc_room where name='">>, SName, + <<"' and host='">>, SRoomHost, <<"';">>], + [<<"insert into muc_room(name, host, opts) ", + "values (">>, + <<"'">>, SName, <<"', '">>, SRoomHost, + <<"', '">>, SOpts, <<"');">>]]; + false -> + [] + end + end}, + {muc_registered, + fun(Host, #muc_registered{us_host = {{U, S}, RoomHost}, + nick = Nick}) -> + case str:suffix(Host, RoomHost) of + true -> + SJID = ejabberd_odbc:escape( + jlib:jid_to_string( + jlib:make_jid(U, S, <<"">>))), + SNick = ejabberd_odbc:escape(Nick), + SRoomHost = ejabberd_odbc:escape(RoomHost), + [[<<"delete from muc_registered where jid='">>, + SJID, <<"' and host='">>, SRoomHost, <<"';">>], + [<<"insert into muc_registered(jid, host, " + "nick) values ('">>, + SJID, <<"', '">>, SRoomHost, <<"', '">>, SNick, + <<"');">>]]; + false -> + [] + end + end}]. + +import(_LServer) -> + [{<<"select name, host, opts from muc_room;">>, + fun([Name, RoomHost, SOpts]) -> + Opts = opts_to_binary(ejabberd_odbc:decode_term(SOpts)), + #muc_room{name_host = {Name, RoomHost}, + opts = Opts} + end}, + {<<"select jid, host, nick from muc_registered;">>, + fun([J, RoomHost, Nick]) -> + #jid{user = U, server = S} = + jlib:string_to_jid(J), + #muc_registered{us_host = {{U, S}, RoomHost}, + nick = Nick} + end}]. + +import(_LServer, mnesia, #muc_room{} = R) -> + mnesia:dirty_write(R); +import(_LServer, mnesia, #muc_registered{} = R) -> + mnesia:dirty_write(R); +import(_, _, _) -> + pass. diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 503317485..10ee7b409 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -42,6 +42,9 @@ remove_expired_messages/1, remove_old_messages/2, remove_user/2, + import/1, + import/3, + export/1, get_queue_length/2, get_offline_els/2, webadmin_page/3, @@ -873,3 +876,60 @@ count_offline_messages(LUser, LServer) -> _ -> 0 end. + +export(_Server) -> + [{offline_msg, + fun(Host, #offline_msg{us = {LUser, LServer}, + timestamp = TimeStamp, from = From, to = To, + packet = Packet}) + when LServer == Host -> + Username = ejabberd_odbc:escape(LUser), + #xmlel{name = Name, attrs = Attrs, children = Els} = + Packet, + Attrs2 = + jlib:replace_from_to_attrs(jlib:jid_to_string(From), + jlib:jid_to_string(To), + Attrs), + NewPacket = #xmlel{name = Name, attrs = Attrs2, + children = + Els ++ + [jlib:timestamp_to_xml( + calendar:now_to_universal_time(TimeStamp), + utc, + jlib:make_jid(<<"">>, + LServer, + <<"">>), + <<"Offline Storage">>), + jlib:timestamp_to_xml( + calendar:now_to_universal_time(TimeStamp))]}, + XML = + ejabberd_odbc:escape(xml:element_to_binary(NewPacket)), + [[<<"delete from spool where username='">>, Username, <<"';">>], + [<<"insert into spool(username, xml) values ('">>, + Username, <<"', '">>, XML, <<"');">>]]; + (_Host, _R) -> + [] + end}]. + +import(LServer) -> + [{<<"select username, xml from spool;">>, + fun([LUser, XML]) -> + El = #xmlel{} = xml_stream:parse_element(XML), + From = #jid{} = jlib:string_to_jid( + xml:get_attr_s(<<"from">>, El)), + To = #jid{} = jlib:string_to_jid( + xml:get_attr_s(<<"to">>, El)), + Stamp = xml:get_path_s(El, [{elem, <<"delay">>}, + {elem, <<"stamp">>}, + cdata]), + {_, _, _} = TS = jlib:datetime_string_to_timestamp(Stamp), + Expire = find_x_expire(TS, El#xmlel.children), + #offline_msg{us = {LUser, LServer}, + from = From, to = To, + timestamp = TS, expire = Expire} + end}]. + +import(_LServer, mnesia, #offline_msg{} = Msg) -> + mnesia:dirty_write(Msg); +import(_, _, _) -> + pass. diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index ab77a30d3..5edfccd28 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -30,11 +30,11 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_iq/3, export/1, +-export([start/2, stop/1, process_iq/3, export/1, import/1, process_iq_set/4, process_iq_get/5, get_user_list/3, check_packet/6, remove_user/2, item_to_raw/1, raw_to_item/1, is_list_needdb/1, updated_list/3, - item_to_xml/1, get_user_lists/2]). + item_to_xml/1, get_user_lists/2, import/3]). %% For mod_blocking -export([sql_add_privacy_list/2, @@ -965,6 +965,11 @@ sql_get_privacy_list_data(LUser, LServer, Name) -> odbc_queries:get_privacy_list_data(LServer, Username, SName). +sql_get_privacy_list_data_t(LUser, Name) -> + Username = ejabberd_odbc:escape(LUser), + SName = ejabberd_odbc:escape(Name), + odbc_queries:get_privacy_list_data_t(Username, SName). + sql_get_privacy_list_data_by_id(ID, LServer) -> odbc_queries:get_privacy_list_data_by_id(LServer, ID). @@ -1098,3 +1103,37 @@ get_id() -> ID = get(id), put(id, ID + 1), ID + 1. + +import(LServer) -> + [{<<"select username from privacy_list;">>, + fun([LUser]) -> + Default = case sql_get_default_privacy_list_t(LUser) of + {selected, [<<"name">>], []} -> + none; + {selected, [<<"name">>], [[DefName]]} -> + DefName; + _ -> + none + end, + {selected, [<<"name">>], Names} = + sql_get_privacy_list_names_t(LUser), + Lists = lists:flatmap( + fun([Name]) -> + case sql_get_privacy_list_data_t(LUser, Name) of + {selected, _, RItems} -> + [{Name, + lists:map(fun raw_to_item/1, + RItems)}]; + _ -> + [] + end + end, Names), + #privacy{default = Default, + us = {LUser, LServer}, + lists = Lists} + end}]. + +import(_LServer, mnesia, #privacy{} = P) -> + mnesia:dirty_write(P); +import(_, _, _) -> + pass. diff --git a/src/mod_private.erl b/src/mod_private.erl index 19e1e038e..ae7068480 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -30,8 +30,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_sm_iq/3, - remove_user/2, get_data/2, export/1]). +-export([start/2, stop/1, process_sm_iq/3, import/3, + remove_user/2, get_data/2, export/1, import/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -277,3 +277,16 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, namespace, data from private_storage;">>, + fun([LUser, XMLNS, XML]) -> + El = #xmlel{} = xml_stream:parse_element(XML), + #private_storage{usns = {LUser, LServer, XMLNS}, + xml = El} + end}]. + +import(_LServer, mnesia, #private_storage{} = PS) -> + mnesia:dirty_write(PS); +import(_, _, _) -> + pass. diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 1ab618a43..e04822915 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -39,8 +39,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_iq/3, export/1, - process_local_iq/3, get_user_roster/2, +-export([start/2, stop/1, process_iq/3, export/1, import/1, + process_local_iq/3, get_user_roster/2, import/3, get_subscription_lists/3, get_roster/2, get_in_pending_subscriptions/3, in_subscription/6, out_subscription/4, set_items/3, remove_user/2, @@ -1569,3 +1569,29 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, jid, nick, subscription, " + "ask, askmessage, server, subscribe, type from rosterusers;">>, + fun([LUser, JID|_] = Row) -> + Item = raw_to_record(LServer, Row), + Username = ejabberd_odbc:escape(LUser), + SJID = ejabberd_odbc:escape(JID), + {selected, _, Rows} = + ejabberd_odbc:sql_query_t( + [<<"select grp from rostergroups where username='">>, + Username, <<"' and jid='">>, SJID, <<"'">>]), + Groups = [Grp || [Grp] <- Rows], + Item#roster{groups = Groups} + end}, + {<<"select username, version from roster_version;">>, + fun([LUser, Ver]) -> + #roster_version{us = {LUser, LServer}, version = Ver} + end}]. + +import(_LServer, mnesia, #roster{} = R) -> + mnesia:dirty_write(R); +import(_LServer, mnesia, #roster_version{} = RV) -> + mnesia:dirty_write(RV); +import(_, _, _) -> + ok. diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 2501ef2b5..743b1dd62 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -30,9 +30,9 @@ -behaviour(gen_mod). --export([start/2, stop/1, item_to_xml/1, export/1, +-export([start/2, stop/1, item_to_xml/1, export/1, import/1, webadmin_menu/3, webadmin_page/3, get_user_roster/2, - get_subscription_lists/3, get_jid_info/4, + get_subscription_lists/3, get_jid_info/4, import/3, process_item/2, in_subscription/6, out_subscription/4, user_available/1, unset_presence/4, register_user/2, remove_user/2, list_groups/1, create_group/2, @@ -1334,3 +1334,22 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select name, opts from sr_group;">>, + fun([Group, SOpts]) -> + #sr_group{group_host = {Group, LServer}, + opts = ejabberd_odbc:decode_term(SOpts)} + end}, + {<<"select jid, grp from sr_user;">>, + fun([SJID, Group]) -> + #jid{luser = U, lserver = S} = jlib:string_to_jid(SJID), + #sr_user{us = {U, S}, group_host = {Group, LServer}} + end}]. + +import(_LServer, mnesia, #sr_group{} = G) -> + mnesia:dirty_write(G); +import(_LServer, mnesia, #sr_user{} = U) -> + mnesia:dirty_write(U); +import(_, _, _) -> + pass. diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index fa657df5d..08feb071a 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -32,7 +32,7 @@ -export([start/2, init/3, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, reindex_vcards/0, - remove_user/2, export/1]). + remove_user/2, export/1, import/1, import/3]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1006,3 +1006,39 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, vcard from vcard;">>, + fun([LUser, SVCard]) -> + #xmlel{} = VCARD = xml_stream:parse_element(SVCard), + #vcard{us = {LUser, LServer}, vcard = VCARD} + end}, + {<<"select username, lusername, fn, lfn, family, lfamily, " + "given, lgiven, middle, lmiddle, nickname, lnickname, " + "bday, lbday, ctry, lctry, locality, llocality, email, " + "lemail, orgname, lorgname, orgunit, lorgunit from vcard_search;">>, + fun([User, LUser, FN, LFN, + Family, LFamily, Given, LGiven, + Middle, LMiddle, Nickname, LNickname, + BDay, LBDay, CTRY, LCTRY, Locality, LLocality, + EMail, LEMail, OrgName, LOrgName, OrgUnit, LOrgUnit]) -> + #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} + end}]. + +import(_LServer, mnesia, #vcard{} = VCard) -> + mnesia:dirty_write(VCard); +import(_LServer, mnesia, #vcard_search{} = S) -> + mnesia:dirty_write(S); +import(_, _, _) -> + pass. diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 4c70315f7..b2ea34419 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -13,7 +13,7 @@ -export([start/2, stop/1]). %% hooks --export([update_presence/3, vcard_set/3, export/1]). +-export([update_presence/3, vcard_set/3, export/1, import/1, import/3]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -203,3 +203,14 @@ export(_Server) -> (_Host, _R) -> [] end}]. + +import(LServer) -> + [{<<"select username, hash from vcard_xupdate;">>, + fun([LUser, Hash]) -> + #vcard_xupdate{us = {LUser, LServer}, hash = Hash} + end}]. + +import(_LServer, mnesia, #vcard_xupdate{} = R) -> + mnesia:dirty_write(R); +import(_, _, _) -> + pass. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index e8fb47379..23b8e8da6 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -45,7 +45,7 @@ get_default_privacy_list_t/1, get_privacy_list_names/2, get_privacy_list_names_t/1, get_privacy_list_id/3, get_privacy_list_id_t/2, get_privacy_list_data/3, - get_privacy_list_data_by_id/2, + get_privacy_list_data_by_id/2, get_privacy_list_data_t/2, get_privacy_list_data_by_id_t/1, set_default_privacy_list/2, unset_default_privacy_list/2, @@ -519,6 +519,15 @@ get_privacy_list_data(LServer, Username, SName) -> Username, <<"' and name='">>, SName, <<"') order by ord;">>]). +get_privacy_list_data_t(Username, SName) -> + ejabberd_odbc:sql_query_t([<<"select t, value, action, ord, match_all, " + "match_iq, match_message, match_presence_in, " + "match_presence_out from privacy_list_data " + "where id = (select id from privacy_list " + "where username='">>, + Username, <<"' and name='">>, SName, + <<"') order by ord;">>]). + get_privacy_list_data_by_id(LServer, ID) -> ejabberd_odbc:sql_query(LServer, [<<"select t, value, action, ord, match_all, "