25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Improve ODBC import

This commit is contained in:
Christophe Romain 2016-11-22 14:48:01 +01:00
parent 577eeb642f
commit fbfbb96872
43 changed files with 718 additions and 539 deletions

View File

@ -36,8 +36,8 @@
check_password/6, check_password_with_authmodule/4, check_password/6, check_password_with_authmodule/4,
check_password_with_authmodule/6, try_register/3, check_password_with_authmodule/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1, dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, export/1, import/1, get_vh_registered_users/2, export/1, import_info/0,
get_vh_registered_users_number/1, import/3, get_vh_registered_users_number/1, import/5, import_start/2,
get_vh_registered_users_number/2, get_password/2, get_vh_registered_users_number/2, get_password/2,
get_password_s/2, get_password_with_authmodule/2, get_password_s/2, get_password_with_authmodule/2,
is_user_exists/2, is_user_exists_in_other_modules/3, is_user_exists/2, is_user_exists_in_other_modules/3,
@ -438,15 +438,20 @@ auth_modules(Server) ->
export(Server) -> export(Server) ->
ejabberd_auth_mnesia:export(Server). ejabberd_auth_mnesia:export(Server).
import(Server) -> import_info() ->
ejabberd_auth_mnesia:import(Server). [{<<"users">>, 3}].
import(Server, mnesia, Passwd) -> import_start(_LServer, mnesia) ->
ejabberd_auth_mnesia:import(Server, mnesia, Passwd); ejabberd_auth_mnesia:init_db();
import(Server, riak, Passwd) -> import_start(_LServer, _) ->
ejabberd_auth_riak:import(Server, riak, Passwd); ok.
import(_, _, _) ->
pass. import(Server, {sql, _}, mnesia, <<"users">>, Fields) ->
ejabberd_auth_mnesia:import(Server, Fields);
import(Server, {sql, _}, riak, <<"users">>, Fields) ->
ejabberd_auth_riak:import(Server, Fields);
import(_LServer, {sql, _}, sql, <<"users">>, _) ->
ok.
opt_type(auth_method) -> opt_type(auth_method) ->
fun (V) when is_list(V) -> fun (V) when is_list(V) ->

View File

@ -40,8 +40,8 @@
get_vh_registered_users_number/1, get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2, get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2, get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0, export/1, import/1, remove_user/3, store_type/0, export/1, import/2,
import/3, plain_password_required/0, opt_type/1]). plain_password_required/0, opt_type/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -493,16 +493,9 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(LServer, [LUser, Password, _TimeStamp]) ->
[{<<"select username, password from users;">>, mnesia:dirty_write(
fun([LUser, Password]) -> #passwd{us = {LUser, LServer}, password = Password}).
#passwd{us = {LUser, LServer}, password = Password}
end}].
import(_LServer, mnesia, #passwd{} = P) ->
mnesia:dirty_write(P);
import(_, _, _) ->
pass.
opt_type(auth_password_format) -> fun (V) -> V end; opt_type(auth_password_format) -> fun (V) -> V end;
opt_type(_) -> [auth_password_format]. opt_type(_) -> [auth_password_format].

View File

@ -27,6 +27,8 @@
-compile([{parse_transform, ejabberd_sql_pt}]). -compile([{parse_transform, ejabberd_sql_pt}]).
-behaviour(ejabberd_config).
-author('alexey@process-one.net'). -author('alexey@process-one.net').
-behaviour(ejabberd_auth). -behaviour(ejabberd_auth).
@ -39,8 +41,8 @@
get_vh_registered_users_number/1, get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2, get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2, get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0, export/1, import/3, remove_user/3, store_type/0, export/1, import/2,
plain_password_required/0]). plain_password_required/0, opt_type/1]).
-export([passwd_schema/0]). -export([passwd_schema/0]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -301,7 +303,9 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer, riak, #passwd{} = Passwd) -> import(LServer, [LUser, Password, _TimeStamp]) ->
ejabberd_riak:put(Passwd, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}]); Passwd = #passwd{us = {LUser, LServer}, password = Password},
import(_, _, _) -> ejabberd_riak:put(Passwd, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}]).
pass.
opt_type(auth_password_format) -> fun (V) -> V end;
opt_type(_) -> [auth_password_format].

View File

@ -30,12 +30,12 @@
-include("logger.hrl"). -include("logger.hrl").
-include("ejabberd_sql_pt.hrl"). -include("ejabberd_sql_pt.hrl").
-export([export/2, export/3, import_file/2, import/2, -export([export/2, export/3, import/3, import/4, delete/1, import_info/1]).
import/3, delete/1]).
-define(MAX_RECORDS_PER_TRANSACTION, 100). -define(MAX_RECORDS_PER_TRANSACTION, 100).
-record(dump, {fd, cont = start}). -record(sql_dump, {fd, type}).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% API %%% API
@ -50,13 +50,14 @@
modules() -> modules() ->
[ejabberd_auth, [ejabberd_auth,
mod_announce, mod_announce,
mod_caps,
mod_irc, mod_irc,
mod_last, mod_last,
mod_muc, mod_muc,
mod_offline, mod_offline,
mod_privacy, mod_privacy,
mod_private, mod_private,
%% mod_pubsub, mod_pubsub,
mod_roster, mod_roster,
mod_shared_roster, mod_shared_roster,
mod_vcard, mod_vcard,
@ -100,49 +101,44 @@ delete(Server, Module) ->
delete(LServer, Table, ConvertFun) delete(LServer, Table, ConvertFun)
end, Module:export(Server)). end, Module:export(Server)).
import_file(Server, FileName) when is_binary(FileName) -> import(Server, Dir, ToType) ->
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 = jid:nameprep(Server),
Mods = [{Mod, gen_mod:db_type(LServer, Mod)}
|| Mod <- modules(), gen_mod:is_loaded(LServer, Mod)],
AuthMods = case lists:member(ejabberd_auth_mnesia,
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) ->
import(Server, Output, [{fast, true}]).
import(Server, Output, Opts) ->
LServer = jid:nameprep(iolist_to_binary(Server)),
Modules = modules(),
IO = prepare_output(Output, disk_log),
lists:foreach( lists:foreach(
fun(Module) -> fun(Mod) ->
import(LServer, IO, Opts, Module) ?INFO_MSG("importing ~p...", [Mod]),
end, Modules), import(Mod, Server, Dir, ToType)
close_output(Output, IO). end, modules()).
import(Server, Output, Opts, Module) -> import(Mod, Server, Dir, ToType) ->
LServer = jid:nameprep(iolist_to_binary(Server)), LServer = jid:nameprep(iolist_to_binary(Server)),
IO = prepare_output(Output, disk_log), try Mod:import_start(LServer, ToType)
catch error:undef -> ok end,
lists:foreach( lists:foreach(
fun({SelectQuery, ConvertFun}) -> fun({File, Tab, _Mod, FieldsNumber}) ->
import(LServer, SelectQuery, IO, ConvertFun, Opts) FileName = filename:join([Dir, File]),
end, Module:import(Server)), case open_sql_dump(FileName) of
close_output(Output, IO). {ok, #sql_dump{type = FromType} = Dump} ->
import_rows(LServer, {sql, FromType}, ToType,
Tab, Mod, Dump, FieldsNumber),
close_sql_dump(Dump);
{error, enoent} ->
ok;
eof ->
?INFO_MSG("It seems like SQL dump ~s is empty", [FileName]);
Err ->
?ERROR_MSG("Failed to open SQL dump ~s: ~s",
[FileName, format_error(Err)])
end
end, import_info(Mod)),
try Mod:import_stop(LServer, ToType)
catch error:undef -> ok end.
import_info(Mod) ->
Info = Mod:import_info(),
lists:map(
fun({Tab, FieldsNum}) ->
FileName = <<Tab/binary, ".txt">>,
{FileName, Tab, Mod, FieldsNum}
end, Info).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% Internal functions %%% Internal functions
@ -200,79 +196,6 @@ delete(LServer, Table, ConvertFun) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
import(LServer, SelectQuery, IO, ConvertFun, Opts) ->
F = case proplists:get_bool(fast, Opts) of
true ->
fun() ->
case ejabberd_sql:sql_query_t(SelectQuery) of
{selected, _, Rows} ->
lists:foldl(fun process_sql_row/2,
{IO, ConvertFun, undefined}, Rows);
Err ->
erlang:error(Err)
end
end;
false ->
fun() ->
ejabberd_sql:sql_query_t(
[iolist_to_binary(
[<<"declare c cursor for ">>, SelectQuery])]),
fetch(IO, ConvertFun, undefined)
end
end,
ejabberd_sql:sql_transaction(LServer, F).
fetch(IO, ConvertFun, PrevRow) ->
case ejabberd_sql:sql_query_t([<<"fetch c;">>]) of
{selected, _, [Row]} ->
process_sql_row(Row, {IO, ConvertFun, PrevRow}),
fetch(IO, ConvertFun, Row);
{selected, _, []} ->
ok;
Err ->
erlang:error(Err)
end.
process_sql_row(Row, {IO, ConvertFun, PrevRow}) when Row == PrevRow ->
%% Avoid calling ConvertFun with the same input
{IO, ConvertFun, Row};
process_sql_row(Row, {IO, ConvertFun, _PrevRow}) ->
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,
{IO, ConvertFun, Row}.
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) ->
prepare_output(FileName, normal). prepare_output(FileName, normal).
@ -285,25 +208,11 @@ prepare_output(FileName, normal) when is_list(FileName) ->
Err -> Err ->
exit(Err) exit(Err)
end; end;
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) -> prepare_output(Output, _Type) ->
Output. Output.
close_output(FileName, Fd) when FileName /= Fd -> close_output(FileName, Fd) when FileName /= Fd ->
case Fd of file:close(Fd),
#dump{} ->
disk_log:close(Fd#dump.fd);
_ ->
file:close(Fd)
end,
ok; ok;
close_output(_, _) -> close_output(_, _) ->
ok. ok.
@ -321,6 +230,129 @@ flatten1([H|T], Acc) ->
flatten1([], Acc) -> flatten1([], Acc) ->
Acc. Acc.
import_rows(LServer, FromType, ToType, Tab, Mod, Dump, FieldsNumber) ->
case read_row_from_sql_dump(Dump, FieldsNumber) of
{ok, Fields} ->
case catch Mod:import(LServer, FromType, ToType, Tab, Fields) of
ok ->
ok;
Err ->
?ERROR_MSG("Failed to import fields ~p for tab ~p: ~p",
[Fields, Tab, Err])
end,
import_rows(LServer, FromType, ToType,
Tab, Mod, Dump, FieldsNumber);
eof ->
ok;
Err ->
?ERROR_MSG("Failed to read row from SQL dump: ~s",
[format_error(Err)])
end.
open_sql_dump(FileName) ->
case file:open(FileName, [raw, read, binary, read_ahead]) of
{ok, Fd} ->
case file:read(Fd, 11) of
{ok, <<"PGCOPY\n", 16#ff, "\r\n", 0>>} ->
case skip_pgcopy_header(Fd) of
ok ->
{ok, #sql_dump{fd = Fd, type = pgsql}};
Err ->
Err
end;
{ok, _} ->
file:position(Fd, 0),
{ok, #sql_dump{fd = Fd, type = mysql}};
Err ->
Err
end;
Err ->
Err
end.
close_sql_dump(#sql_dump{fd = Fd}) ->
file:close(Fd).
read_row_from_sql_dump(#sql_dump{fd = Fd, type = pgsql}, _) ->
case file:read(Fd, 2) of
{ok, <<(-1):16/signed>>} ->
eof;
{ok, <<FieldsNum:16>>} ->
read_fields(Fd, FieldsNum, []);
{ok, _} ->
{error, eof};
eof ->
{error, eof};
{error, _} = Err ->
Err
end;
read_row_from_sql_dump(#sql_dump{fd = Fd, type = mysql}, FieldsNum) ->
read_lines(Fd, FieldsNum, <<"">>, []).
skip_pgcopy_header(Fd) ->
try
{ok, <<_:4/binary, ExtSize:32>>} = file:read(Fd, 8),
{ok, <<_:ExtSize/binary>>} = file:read(Fd, ExtSize),
ok
catch error:{badmatch, {error, _} = Err} ->
Err;
error:{badmatch, _} ->
{error, eof}
end.
read_fields(_Fd, 0, Acc) ->
{ok, lists:reverse(Acc)};
read_fields(Fd, N, Acc) ->
case file:read(Fd, 4) of
{ok, <<(-1):32/signed>>} ->
read_fields(Fd, N-1, [null|Acc]);
{ok, <<ValSize:32>>} ->
case file:read(Fd, ValSize) of
{ok, <<Val:ValSize/binary>>} ->
read_fields(Fd, N-1, [Val|Acc]);
{ok, _} ->
{error, eof};
Err ->
Err
end;
{ok, _} ->
{error, eof};
eof ->
{error, eof};
{error, _} = Err ->
Err
end.
read_lines(_Fd, 0, <<"">>, Acc) ->
{ok, lists:reverse(Acc)};
read_lines(Fd, N, Buf, Acc) ->
case file:read_line(Fd) of
{ok, Data} when size(Data) >= 2 ->
Size = size(Data) - 2,
case Data of
<<Val:Size/binary, 0, $\n>> ->
NewBuf = <<Buf/binary, Val/binary>>,
read_lines(Fd, N-1, <<"">>, [NewBuf|Acc]);
_ ->
NewBuf = <<Buf/binary, Data/binary>>,
read_lines(Fd, N, NewBuf, Acc)
end;
{ok, Data} ->
NewBuf = <<Buf/binary, Data/binary>>,
read_lines(Fd, N, NewBuf, Acc);
eof when Buf == <<"">>, Acc == [] ->
eof;
eof ->
{error, eof};
{error, _} = Err ->
Err
end.
format_error({error, eof}) ->
"unexpected end of file";
format_error({error, Posix}) ->
file:format_error(Posix).
format_queries(SQLs) -> format_queries(SQLs) ->
lists:map( lists:map(
fun(#sql_query{} = SQL) -> fun(#sql_query{} = SQL) ->

View File

@ -31,8 +31,8 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, init/0, stop/1, export/1, import/1, -export([start/2, init/0, stop/1, export/1, import_info/0,
import/3, announce/3, send_motd/1, disco_identity/5, import_start/2, import/5, announce/3, send_motd/1, disco_identity/5,
disco_features/5, disco_items/5, depends/2, disco_features/5, disco_items/5, depends/2,
send_announcement_to_all/3, announce_commands/4, send_announcement_to_all/3, announce_commands/4,
announce_items/4, mod_opt_type/1]). announce_items/4, mod_opt_type/1]).
@ -43,7 +43,7 @@
-include("mod_announce.hrl"). -include("mod_announce.hrl").
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #motd{} | #motd_users{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback set_motd_users(binary(), [{binary(), binary(), binary()}]) -> {atomic, any()}. -callback set_motd_users(binary(), [{binary(), binary(), binary()}]) -> {atomic, any()}.
-callback set_motd(binary(), xmlel()) -> {atomic, any()}. -callback set_motd(binary(), xmlel()) -> {atomic, any()}.
-callback delete_motd(binary()) -> {atomic, any()}. -callback delete_motd(binary()) -> {atomic, any()}.
@ -832,15 +832,17 @@ export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import_info() ->
Mod = gen_mod:db_mod(LServer, ?MODULE), [{<<"motd">>, 3}].
Mod:import(LServer).
import(LServer, DBType, LA) -> import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, LA). Mod:init(LServer, []).
mod_opt_type(access) -> import(LServer, {sql, _}, DBType, Tab, List) ->
fun acl:access_rules_validator/1; Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, List).
mod_opt_type(access) -> fun acl:access_rules_validator/1;
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(_) -> [access, db_type]. mod_opt_type(_) -> [access, db_type].

View File

@ -11,7 +11,7 @@
%% API %% API
-export([init/2, set_motd_users/2, set_motd/2, delete_motd/1, -export([init/2, set_motd_users/2, set_motd/2, delete_motd/1,
get_motd/1, is_motd_user/2, set_motd_user/2, import/2]). get_motd/1, is_motd_user/2, set_motd_user/2, import/3]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_announce.hrl"). -include("mod_announce.hrl").
@ -81,10 +81,11 @@ set_motd_user(LUser, LServer) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #motd{} = Motd) -> import(LServer, <<"motd">>, [<<>>, XML, _TimeStamp]) ->
mnesia:dirty_write(Motd); El = fxml_stream:parse_element(XML),
import(_LServer, #motd_users{} = Users) -> mnesia:dirty_write(#motd{server = LServer, packet = El});
mnesia:dirty_write(Users). import(LServer, <<"motd">>, [LUser, <<>>, _TimeStamp]) ->
mnesia:dirty_write(#motd_users{us = {LUser, LServer}}).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -11,7 +11,7 @@
%% API %% API
-export([init/2, set_motd_users/2, set_motd/2, delete_motd/1, -export([init/2, set_motd_users/2, set_motd/2, delete_motd/1,
get_motd/1, is_motd_user/2, set_motd_user/2, import/2]). get_motd/1, is_motd_user/2, set_motd_user/2, import/3]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_announce.hrl"). -include("mod_announce.hrl").
@ -71,11 +71,13 @@ set_motd_user(LUser, LServer) ->
#motd_users{us = {LUser, LServer}}, motd_users_schema(), #motd_users{us = {LUser, LServer}}, motd_users_schema(),
[{'2i', [{<<"server">>, LServer}]}])}. [{'2i', [{<<"server">>, LServer}]}])}.
import(_LServer, #motd{} = Motd) -> import(LServer, <<"motd">>, [<<>>, XML, _TimeStamp]) ->
ejabberd_riak:put(Motd, motd_schema()); El = fxml_stream:parse_element(XML),
import(_LServer, #motd_users{us = {_, S}} = Users) -> ejabberd_riak:put(#motd{server = LServer, packet = El}, motd_schema());
import(LServer, <<"motd">>, [LUser, <<>>, _TimeStamp]) ->
Users = #motd_users{us = {LUser, LServer}},
ejabberd_riak:put(Users, motd_users_schema(), ejabberd_riak:put(Users, motd_users_schema(),
[{'2i', [{<<"server">>, S}]}]). [{'2i', [{<<"server">>, LServer}]}]).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -13,8 +13,8 @@
%% API %% API
-export([init/2, set_motd_users/2, set_motd/2, delete_motd/1, -export([init/2, set_motd_users/2, set_motd/2, delete_motd/1,
get_motd/1, is_motd_user/2, set_motd_user/2, import/1, get_motd/1, is_motd_user/2, set_motd_user/2, import/3,
import/2, export/1]). export/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_announce.hrl"). -include("mod_announce.hrl").
@ -108,19 +108,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select xml from motd where username='';">>, ok.
fun([XML]) ->
El = fxml_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(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -55,20 +55,16 @@
-include("logger.hrl"). -include("logger.hrl").
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_caps.hrl").
-define(PROCNAME, ejabberd_mod_caps). -define(PROCNAME, ejabberd_mod_caps).
-define(BAD_HASH_LIFETIME, 600). -define(BAD_HASH_LIFETIME, 600).
-record(caps_features,
{
node_pair = {<<"">>, <<"">>} :: {binary(), binary()},
features = [] :: [binary()] | pos_integer()
}).
-record(state, {host = <<"">> :: binary()}). -record(state, {host = <<"">> :: binary()}).
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), {binary(), binary()}, [binary() | pos_integer()]) -> ok.
-callback caps_read(binary(), {binary(), binary()}) -> -callback caps_read(binary(), {binary(), binary()}) ->
{ok, non_neg_integer() | [binary()]} | error. {ok, non_neg_integer() | [binary()]} | error.
-callback caps_write(binary(), {binary(), binary()}, -callback caps_write(binary(), {binary(), binary()},
@ -525,9 +521,6 @@ is_valid_node(Node) ->
false false
end. end.
caps_features_schema() ->
{record_info(fields, caps_features), #caps_features{}}.
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
@ -559,24 +552,8 @@ import_next(_LServer, _DBType, '$end_of_table') ->
ok; ok;
import_next(LServer, DBType, NodePair) -> import_next(LServer, DBType, NodePair) ->
Features = [F || {_, F} <- ets:lookup(caps_features_tmp, NodePair)], Features = [F || {_, F} <- ets:lookup(caps_features_tmp, NodePair)],
case Features of Mod = gen_mod:db_mod(DBType, ?MODULE),
[I] when is_integer(I), DBType == mnesia -> Mod:import(LServer, NodePair, Features),
mnesia:dirty_write(
#caps_features{node_pair = NodePair, features = I});
[I] when is_integer(I), DBType == riak ->
ejabberd_riak:put(
#caps_features{node_pair = NodePair, features = I},
caps_features_schema());
_ when DBType == mnesia ->
mnesia:dirty_write(
#caps_features{node_pair = NodePair, features = Features});
_ when DBType == riak ->
ejabberd_riak:put(
#caps_features{node_pair = NodePair, features = Features},
caps_features_schema());
_ when DBType == sql ->
ok
end,
import_next(LServer, DBType, ets:next(caps_features_tmp, NodePair)). import_next(LServer, DBType, ets:next(caps_features_tmp, NodePair)).
mod_opt_type(cache_life_time) -> mod_opt_type(cache_life_time) ->

View File

@ -10,7 +10,7 @@
-behaviour(mod_caps). -behaviour(mod_caps).
%% API %% API
-export([init/2, caps_read/2, caps_write/3]). -export([init/2, caps_read/2, caps_write/3, import/3]).
-include("mod_caps.hrl"). -include("mod_caps.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -46,6 +46,13 @@ caps_write(_LServer, Node, Features) ->
mnesia:dirty_write(#caps_features{node_pair = Node, mnesia:dirty_write(#caps_features{node_pair = Node,
features = Features}). features = Features}).
import(_LServer, NodePair, [I]) when is_integer(I) ->
mnesia:dirty_write(
#caps_features{node_pair = NodePair, features = I});
import(_LServer, NodePair, Features) ->
mnesia:dirty_write(
#caps_features{node_pair = NodePair, features = Features}).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================

View File

@ -10,7 +10,7 @@
-behaviour(mod_caps). -behaviour(mod_caps).
%% API %% API
-export([init/2, caps_read/2, caps_write/3]). -export([init/2, caps_read/2, caps_write/3, import/3]).
-include("mod_caps.hrl"). -include("mod_caps.hrl").
@ -31,6 +31,15 @@ caps_write(_LServer, Node, Features) ->
features = Features}, features = Features},
caps_features_schema()). caps_features_schema()).
import(_LServer, NodePair, [I]) when is_integer(I) ->
ejabberd_riak:put(
#caps_features{node_pair = NodePair, features = I},
caps_features_schema());
import(_LServer, NodePair, Features) ->
ejabberd_riak:put(
#caps_features{node_pair = NodePair, features = Features},
caps_features_schema()).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================

View File

@ -12,7 +12,7 @@
-compile([{parse_transform, ejabberd_sql_pt}]). -compile([{parse_transform, ejabberd_sql_pt}]).
%% API %% API
-export([init/2, caps_read/2, caps_write/3, export/1]). -export([init/2, caps_read/2, caps_write/3, export/1, import/3]).
-include("mod_caps.hrl"). -include("mod_caps.hrl").
-include("ejabberd_sql_pt.hrl"). -include("ejabberd_sql_pt.hrl").
@ -53,6 +53,9 @@ export(_Server) ->
[] []
end}]. end}].
import(_, _, _) ->
ok.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================

View File

@ -34,8 +34,8 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, stop/1, process_local_iq/1, export/1, -export([start/2, stop/1, process_local_iq/1, export/1,
process_sm_iq/1, on_presence_update/4, import/1, process_sm_iq/1, on_presence_update/4, import_info/0,
import/3, store_last_info/4, get_last_info/2, import/5, store_last_info/4, get_last_info/2,
remove_user/2, transform_options/1, mod_opt_type/1, remove_user/2, transform_options/1, mod_opt_type/1,
opt_type/1, register_user/2, depends/2]). opt_type/1, register_user/2, depends/2]).
@ -207,18 +207,28 @@ remove_user(User, Server) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:remove_user(LUser, LServer). Mod:remove_user(LUser, LServer).
import_info() ->
[{<<"last">>, 3}].
import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []).
import(LServer, {sql, _}, DBType, <<"last">>, [LUser, TimeStamp, State]) ->
TS = case TimeStamp of
<<"">> -> 0;
_ -> jlib:binary_to_integer(TimeStamp)
end,
LA = #last_activity{us = {LUser, LServer},
timestamp = TS,
status = State},
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, LA).
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, LA) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, LA).
transform_options(Opts) -> transform_options(Opts) ->
lists:foldl(fun transform_options/2, [], Opts). lists:foldl(fun transform_options/2, [], Opts).

View File

@ -13,7 +13,7 @@
%% API %% API
-export([init/2, get_last/2, store_last_info/4, remove_user/2, -export([init/2, get_last/2, store_last_info/4, remove_user/2,
import/1, import/2, export/1]). import/2, export/1]).
-include("mod_last.hrl"). -include("mod_last.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -43,9 +43,6 @@ store_last_info(LUser, LServer, TimeStamp, Status) ->
remove_user(LUser, LServer) -> remove_user(LUser, LServer) ->
sql_queries:del_last(LServer, LUser). sql_queries:del_last(LServer, LUser).
import(_LServer, _LA) ->
pass.
export(_Server) -> export(_Server) ->
[{last_activity, [{last_activity,
fun(Host, #last_activity{us = {LUser, LServer}, fun(Host, #last_activity{us = {LUser, LServer},
@ -58,15 +55,5 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_LServer, _LA) ->
[{<<"select username, seconds, state from last">>, pass.
fun([LUser, TimeStamp, State]) ->
#last_activity{us = {LUser, LServer},
timestamp = binary_to_integer(
TimeStamp),
status = State}
end}].
%%%===================================================================
%%% Internal functions
%%%===================================================================

View File

@ -51,8 +51,9 @@
process_mucsub/1, process_mucsub/1,
broadcast_service_message/2, broadcast_service_message/2,
export/1, export/1,
import/1, import_info/0,
import/3, import/5,
import_start/2,
opts_to_binary/1, opts_to_binary/1,
can_use_nick/4]). can_use_nick/4]).
@ -79,7 +80,7 @@
-type muc_room_opts() :: [{atom(), any()}]. -type muc_room_opts() :: [{atom(), any()}].
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #muc_room{} | #muc_registered{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback store_room(binary(), binary(), binary(), list()) -> {atomic, any()}. -callback store_room(binary(), binary(), binary(), list()) -> {atomic, any()}.
-callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error. -callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error.
-callback forget_room(binary(), binary(), binary()) -> {atomic, any()}. -callback forget_room(binary(), binary(), binary()) -> {atomic, any()}.
@ -904,13 +905,16 @@ export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import_info() ->
Mod = gen_mod:db_mod(LServer, ?MODULE), [{<<"muc_room">>, 4}, {<<"muc_registered">>, 4}].
Mod:import(LServer).
import(LServer, DBType, Data) -> import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Data). Mod:init(LServer, []).
import(LServer, {sql, _}, DBType, Tab, L) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, L).
mod_opt_type(access) -> mod_opt_type(access) ->
fun acl:access_rules_validator/1; fun acl:access_rules_validator/1;

View File

@ -9,11 +9,15 @@
-module(mod_muc_mnesia). -module(mod_muc_mnesia).
-behaviour(mod_muc). -behaviour(mod_muc).
-behaviour(mod_muc_room).
%% API %% API
-export([init/2, import/2, store_room/4, restore_room/3, forget_room/3, -export([init/2, import/3, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]). can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
-include("jlib.hrl").
-include("mod_muc.hrl"). -include("mod_muc.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -113,10 +117,33 @@ set_nick(_LServer, Host, From, Nick) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #muc_room{} = R) -> set_affiliation(_ServerHost, _Room, _Host, _JID, _Affiliation, _Reason) ->
mnesia:dirty_write(R); {error, not_implemented}.
import(_LServer, #muc_registered{} = R) ->
mnesia:dirty_write(R). set_affiliations(_ServerHost, _Room, _Host, _Affiliations) ->
{error, not_implemented}.
get_affiliation(_ServerHost, _Room, _Host, _LUser, _LServer) ->
{error, not_implemented}.
get_affiliations(_ServerHost, _Room, _Host) ->
{error, not_implemented}.
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
import(_LServer, <<"muc_room">>,
[Name, RoomHost, SOpts, _TimeStamp]) ->
Opts = mod_muc:opts_to_binary(ejabberd_sql:decode_term(SOpts)),
mnesia:dirty_write(
#muc_room{name_host = {Name, RoomHost},
opts = Opts});
import(_LServer, <<"muc_registered">>,
[J, RoomHost, Nick, _TimeStamp]) ->
#jid{user = U, server = S} = jid:from_string(J),
mnesia:dirty_write(
#muc_registered{us_host = {{U, S}, RoomHost},
nick = Nick}).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -9,11 +9,15 @@
-module(mod_muc_riak). -module(mod_muc_riak).
-behaviour(mod_muc). -behaviour(mod_muc).
-behaviour(mod_muc_room).
%% API %% API
-export([init/2, import/2, store_room/4, restore_room/3, forget_room/3, -export([init/2, import/3, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]). can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
-include("jlib.hrl").
-include("mod_muc.hrl"). -include("mod_muc.hrl").
%%%=================================================================== %%%===================================================================
@ -101,11 +105,33 @@ set_nick(LServer, Host, From, Nick) ->
end end
end}. end}.
import(_LServer, #muc_room{} = R) -> set_affiliation(_ServerHost, _Room, _Host, _JID, _Affiliation, _Reason) ->
ejabberd_riak:put(R, muc_room_schema()); {error, not_implemented}.
import(_LServer, #muc_registered{us_host = {_, Host}, nick = Nick} = R) ->
set_affiliations(_ServerHost, _Room, _Host, _Affiliations) ->
{error, not_implemented}.
get_affiliation(_ServerHost, _Room, _Host, _LUser, _LServer) ->
{error, not_implemented}.
get_affiliations(_ServerHost, _Room, _Host) ->
{error, not_implemented}.
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
import(_LServer, <<"muc_room">>,
[Name, RoomHost, SOpts, _TimeStamp]) ->
Opts = mod_muc:opts_to_binary(ejabberd_sql:decode_term(SOpts)),
ejabberd_riak:put(
#muc_room{name_host = {Name, RoomHost}, opts = Opts},
muc_room_schema());
import(_LServer, <<"muc_registered">>,
[J, RoomHost, Nick, _TimeStamp]) ->
#jid{user = U, server = S} = jid:from_string(J),
R = #muc_registered{us_host = {{U, S}, RoomHost}, nick = Nick},
ejabberd_riak:put(R, muc_registered_schema(), ejabberd_riak:put(R, muc_registered_schema(),
[{'2i', [{<<"nick_host">>, {Nick, Host}}]}]). [{'2i', [{<<"nick_host">>, {Nick, RoomHost}}]}]).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -11,11 +11,14 @@
-compile([{parse_transform, ejabberd_sql_pt}]). -compile([{parse_transform, ejabberd_sql_pt}]).
-behaviour(mod_muc). -behaviour(mod_muc).
-behaviour(mod_muc_room).
%% API %% API
-export([init/2, store_room/4, restore_room/3, forget_room/3, -export([init/2, store_room/4, restore_room/3, forget_room/3,
can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4, can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4,
import/1, import/2, export/1]). import/3, export/1]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
-include("jid.hrl"). -include("jid.hrl").
-include("mod_muc.hrl"). -include("mod_muc.hrl").
@ -127,6 +130,21 @@ set_nick(LServer, Host, From, Nick) ->
end, end,
ejabberd_sql:sql_transaction(LServer, F). ejabberd_sql:sql_transaction(LServer, F).
set_affiliation(_ServerHost, _Room, _Host, _JID, _Affiliation, _Reason) ->
{error, not_implemented}.
set_affiliations(_ServerHost, _Room, _Host, _Affiliations) ->
{error, not_implemented}.
get_affiliation(_ServerHost, _Room, _Host, _LUser, _LServer) ->
{error, not_implemented}.
get_affiliations(_ServerHost, _Room, _Host) ->
{error, not_implemented}.
search_affiliation(_ServerHost, _Room, _Host, _Affiliation) ->
{error, not_implemented}.
export(_Server) -> export(_Server) ->
[{muc_room, [{muc_room,
fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) -> fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) ->
@ -158,21 +176,8 @@ export(_Server) ->
end end
end}]. end}].
import(_LServer) -> import(_, _, _) ->
[{<<"select name, host, opts from muc_room;">>, ok.
fun([Name, RoomHost, SOpts]) ->
Opts = mod_muc:opts_to_binary(ejabberd_sql: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} = jid:from_string(J),
#muc_registered{us_host = {{U, S}, RoomHost},
nick = Nick}
end}].
import(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -53,8 +53,9 @@
remove_expired_messages/1, remove_expired_messages/1,
remove_old_messages/2, remove_old_messages/2,
remove_user/2, remove_user/2,
import/1, import_info/0,
import/3, import_start/2,
import/5,
export/1, export/1,
get_queue_length/2, get_queue_length/2,
count_offline_messages/2, count_offline_messages/2,
@ -90,7 +91,7 @@
-type us() :: {binary(), binary()}. -type us() :: {binary(), binary()}.
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #offline_msg{}) -> ok | pass. -callback import(#offline_msg{}) -> ok.
-callback store_messages(binary(), us(), [#offline_msg{}], -callback store_messages(binary(), us(), [#offline_msg{}],
non_neg_integer(), non_neg_integer()) -> non_neg_integer(), non_neg_integer()) ->
{atomic, any()}. {atomic, any()}.
@ -851,13 +852,35 @@ export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import_info() ->
Mod = gen_mod:db_mod(LServer, ?MODULE), [{<<"spool">>, 4}].
Mod:import(LServer).
import(LServer, DBType, Data) -> import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Data). Mod:import(LServer, []).
import(LServer, {sql, _}, DBType, <<"spool">>,
[LUser, XML, _Seq, _TimeStamp]) ->
El = fxml_stream:parse_element(XML),
From = #jid{} = jid:from_string(
fxml:get_attr_s(<<"from">>, El#xmlel.attrs)),
To = #jid{} = jid:from_string(
fxml:get_attr_s(<<"to">>, El#xmlel.attrs)),
Stamp = fxml:get_path_s(El, [{elem, <<"delay">>},
{attr, <<"stamp">>}]),
TS = case jlib:datetime_string_to_timestamp(Stamp) of
{MegaSecs, Secs, _} ->
{MegaSecs, Secs, 0};
undefined ->
p1_time_compat:timestamp()
end,
US = {LUser, LServer},
Expire = find_x_expire(TS, El#xmlel.children),
Msg = #offline_msg{us = US, packet = El,
from = From, to = To,
timestamp = TS, expire = Expire},
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(Msg).
mod_opt_type(access_max_user_messages) -> mod_opt_type(access_max_user_messages) ->
fun acl:shaper_rules_validator/1; fun acl:shaper_rules_validator/1;

View File

@ -13,7 +13,7 @@
-export([init/2, store_messages/5, pop_messages/2, remove_expired_messages/1, -export([init/2, store_messages/5, pop_messages/2, remove_expired_messages/1,
remove_old_messages/2, remove_user/2, read_message_headers/2, remove_old_messages/2, remove_user/2, read_message_headers/2,
read_message/3, remove_message/3, read_all_messages/2, read_message/3, remove_message/3, read_all_messages/2,
remove_all_messages/2, count_messages/2, import/2]). remove_all_messages/2, count_messages/2, import/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_offline.hrl"). -include("mod_offline.hrl").
@ -164,7 +164,7 @@ count_messages(LUser, LServer) ->
_ -> 0 _ -> 0
end. end.
import(_LServer, #offline_msg{} = Msg) -> import(#offline_msg{} = Msg) ->
mnesia:dirty_write(Msg). mnesia:dirty_write(Msg).
%%%=================================================================== %%%===================================================================

View File

@ -15,8 +15,7 @@
-export([init/2, store_messages/5, pop_messages/2, remove_expired_messages/1, -export([init/2, store_messages/5, pop_messages/2, remove_expired_messages/1,
remove_old_messages/2, remove_user/2, read_message_headers/2, remove_old_messages/2, remove_user/2, read_message_headers/2,
read_message/3, remove_message/3, read_all_messages/2, read_message/3, remove_message/3, read_all_messages/2,
remove_all_messages/2, count_messages/2, import/1, import/2, remove_all_messages/2, count_messages/2, import/1, export/1]).
export/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_offline.hrl"). -include("mod_offline.hrl").
@ -193,29 +192,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_) ->
[{<<"select username, xml from spool;">>, ok.
fun([LUser, XML]) ->
El = #xmlel{} = fxml_stream:parse_element(XML),
#message{} = Pkt = xmpp:decode(El, ?NS_CLIENT, [ignore_els]),
From = Pkt#message.from,
To = case Pkt#message.to of
undefined -> jid:make(LUser, LServer);
JID -> JID
end,
TS = case xmpp:get_subtag(Pkt, #delay{}) of
#delay{stamp = Stamp} -> Stamp;
false -> p1_time_compat:timestamp()
end,
Expire = mod_offline:find_x_expire(TS, Pkt),
#offline_msg{us = {LUser, LServer},
from = From, to = To,
packet = El,
timestamp = TS, expire = Expire}
end}].
import(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -31,11 +31,11 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, stop/1, process_iq/1, export/1, import/1, -export([start/2, stop/1, process_iq/1, export/1, import_info/0,
process_iq_set/3, process_iq_get/3, get_user_list/3, process_iq_set/3, process_iq_get/3, get_user_list/3,
check_packet/6, remove_user/2, encode_list_item/1, check_packet/6, remove_user/2, encode_list_item/1,
is_list_needdb/1, updated_list/3, is_list_needdb/1, updated_list/3,
item_to_xml/1, get_user_lists/2, import/3, item_to_xml/1, get_user_lists/2, import/5,
set_privacy_list/1, mod_opt_type/1, depends/2]). set_privacy_list/1, mod_opt_type/1, depends/2]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -46,7 +46,7 @@
-include("mod_privacy.hrl"). -include("mod_privacy.hrl").
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #privacy{}) -> ok | pass. -callback import(#privacy{}) -> ok.
-callback process_lists_get(binary(), binary()) -> {none | binary(), [binary()]} | error. -callback process_lists_get(binary(), binary()) -> {none | binary(), [binary()]} | error.
-callback process_list_get(binary(), binary(), binary()) -> [listitem()] | error | not_found. -callback process_list_get(binary(), binary(), binary()) -> [listitem()] | error | not_found.
-callback process_default_set(binary(), binary(), binary() | none) -> {atomic, any()}. -callback process_default_set(binary(), binary(), binary() | none) -> {atomic, any()}.
@ -544,18 +544,108 @@ updated_list(_, #userlist{name = OldName} = Old,
true -> Old true -> Old
end. end.
numeric_to_binary(<<0, 0, _/binary>>) ->
<<"0">>;
numeric_to_binary(<<0, _, _:6/binary, T/binary>>) ->
Res = lists:foldl(
fun(X, Sum) ->
Sum*10000 + X
end, 0, [X || <<X:16>> <= T]),
jlib:integer_to_binary(Res).
bool_to_binary(<<0>>) -> <<"0">>;
bool_to_binary(<<1>>) -> <<"1">>.
prepare_list_data(mysql, [ID|Row]) ->
[jlib:binary_to_integer(ID)|Row];
prepare_list_data(pgsql, [<<ID:64>>,
SType, SValue, SAction, SOrder, SMatchAll,
SMatchIQ, SMatchMessage, SMatchPresenceIn,
SMatchPresenceOut]) ->
[ID, SType, SValue, SAction,
numeric_to_binary(SOrder),
bool_to_binary(SMatchAll),
bool_to_binary(SMatchIQ),
bool_to_binary(SMatchMessage),
bool_to_binary(SMatchPresenceIn),
bool_to_binary(SMatchPresenceOut)].
prepare_id(mysql, ID) ->
jlib:binary_to_integer(ID);
prepare_id(pgsql, <<ID:32>>) ->
ID.
import_info() ->
[{<<"privacy_default_list">>, 2},
{<<"privacy_list_data">>, 10},
{<<"privacy_list">>, 4}].
import_start(LServer, DBType) ->
ets:new(privacy_default_list_tmp, [private, named_table]),
ets:new(privacy_list_data_tmp, [private, named_table, bag]),
ets:new(privacy_list_tmp, [private, named_table, bag,
{keypos, #privacy.us}]),
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []).
import(LServer, {sql, _}, _DBType, <<"privacy_default_list">>, [LUser, Name]) ->
US = {LUser, LServer},
ets:insert(privacy_default_list_tmp, {US, Name}),
ok;
import(LServer, {sql, SQLType}, _DBType, <<"privacy_list_data">>, Row1) ->
[ID|Row] = prepare_list_data(SQLType, Row1),
case mod_privacy_sql:raw_to_item(Row) of
[Item] ->
IS = {ID, LServer},
ets:insert(privacy_list_data_tmp, {IS, Item}),
ok;
[] ->
ok
end;
import(LServer, {sql, SQLType}, _DBType, <<"privacy_list">>,
[LUser, Name, ID, _TimeStamp]) ->
US = {LUser, LServer},
IS = {prepare_id(SQLType, ID), LServer},
Default = case ets:lookup(privacy_default_list_tmp, US) of
[{_, Name}] -> Name;
_ -> none
end,
case [Item || {_, Item} <- ets:lookup(privacy_list_data_tmp, IS)] of
[_|_] = Items ->
Privacy = #privacy{us = {LUser, LServer},
default = Default,
lists = [{Name, Items}]},
ets:insert(privacy_list_tmp, Privacy),
ets:delete(privacy_list_data_tmp, IS),
ok;
_ ->
ok
end.
import_stop(_LServer, DBType) ->
import_next(DBType, ets:first(privacy_list_tmp)),
ets:delete(privacy_default_list_tmp),
ets:delete(privacy_list_data_tmp),
ets:delete(privacy_list_tmp),
ok.
import_next(_DBType, '$end_of_table') ->
ok;
import_next(DBType, US) ->
[P|_] = Ps = ets:lookup(privacy_list_tmp, US),
Lists = lists:flatmap(
fun(#privacy{lists = Lists}) ->
Lists
end, Ps),
Privacy = P#privacy{lists = Lists},
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(Privacy),
import_next(DBType, ets:next(privacy_list_tmp, US)).
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, Data) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Data).
depends(_Host, _Opts) -> depends(_Host, _Opts) ->
[]. [].

View File

@ -17,7 +17,7 @@
process_default_set/3, process_active_set/3, process_default_set/3, process_active_set/3,
remove_privacy_list/3, set_privacy_list/1, remove_privacy_list/3, set_privacy_list/1,
set_privacy_list/4, get_user_list/2, get_user_lists/2, set_privacy_list/4, get_user_list/2, get_user_lists/2,
remove_user/2, import/1, import/2, export/1]). remove_user/2, import/1, export/1]).
-export([item_to_raw/1, raw_to_item/1, -export([item_to_raw/1, raw_to_item/1,
sql_add_privacy_list/2, sql_add_privacy_list/2,
@ -249,37 +249,8 @@ get_id() ->
put(id, ID + 1), put(id, ID + 1),
ID + 1. ID + 1.
import(LServer) -> import(_) ->
[{<<"select username from privacy_list;">>, ok.
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(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -31,9 +31,9 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, stop/1, process_sm_iq/1, import/3, -export([start/2, stop/1, process_sm_iq/1, import_info/0,
remove_user/2, get_data/2, get_data/3, export/1, import/1, remove_user/2, get_data/2, get_data/3, export/1,
mod_opt_type/1, set_data/3, depends/2]). import/5, import_start/2, mod_opt_type/1, set_data/3, depends/2]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -42,7 +42,7 @@
-include("mod_private.hrl"). -include("mod_private.hrl").
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #private_storage{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback set_data(binary(), binary(), [{binary(), xmlel()}]) -> {atomic, any()}. -callback set_data(binary(), binary(), [{binary(), xmlel()}]) -> {atomic, any()}.
-callback get_data(binary(), binary(), binary()) -> {ok, xmlel()} | error. -callback get_data(binary(), binary(), binary()) -> {ok, xmlel()} | error.
-callback get_all_data(binary(), binary()) -> [xmlel()]. -callback get_all_data(binary(), binary()) -> [xmlel()].
@ -124,17 +124,20 @@ remove_user(User, Server) ->
Mod = gen_mod:db_mod(Server, ?MODULE), Mod = gen_mod:db_mod(Server, ?MODULE),
Mod:remove_user(LUser, LServer). Mod:remove_user(LUser, LServer).
import_info() ->
[{<<"private_storage">>, 4}].
import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []).
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import(LServer, {sql, _}, DBType, Tab, L) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, PD) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, PD). Mod:import(LServer, Tab, L).
depends(_Host, _Opts) -> depends(_Host, _Opts) ->
[]. [].

View File

@ -11,7 +11,7 @@
%% API %% API
-export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2, -export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2,
import/2]). import/3]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_private.hrl"). -include("mod_private.hrl").
@ -72,7 +72,10 @@ remove_user(LUser, LServer) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #private_storage{} = PS) -> import(LServer, <<"private_storage">>,
[LUser, XMLNS, XML, _TimeStamp]) ->
El = #xmlel{} = fxml_stream:parse_element(XML),
PS = #private_storage{usns = {LUser, LServer, XMLNS}, xml = El},
mnesia:dirty_write(PS). mnesia:dirty_write(PS).
%%%=================================================================== %%%===================================================================

View File

@ -12,7 +12,7 @@
%% API %% API
-export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2, -export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2,
import/2]). import/3]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_private.hrl"). -include("mod_private.hrl").
@ -56,7 +56,10 @@ remove_user(LUser, LServer) ->
{atomic, ejabberd_riak:delete_by_index(private_storage, {atomic, ejabberd_riak:delete_by_index(private_storage,
<<"us">>, {LUser, LServer})}. <<"us">>, {LUser, LServer})}.
import(_LServer, #private_storage{usns = {LUser, LServer, _}} = PS) -> import(LServer, <<"private_storage">>,
[LUser, XMLNS, XML, _TimeStamp]) ->
El = #xmlel{} = fxml_stream:parse_element(XML),
PS = #private_storage{usns = {LUser, LServer, XMLNS}, xml = El},
ejabberd_riak:put(PS, private_storage_schema(), ejabberd_riak:put(PS, private_storage_schema(),
[{'2i', [{<<"us">>, {LUser, LServer}}]}]). [{'2i', [{<<"us">>, {LUser, LServer}}]}]).

View File

@ -12,7 +12,7 @@
%% API %% API
-export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2, -export([init/2, set_data/3, get_data/3, get_all_data/2, remove_user/2,
import/1, import/2, export/1]). import/3, export/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_private.hrl"). -include("mod_private.hrl").
@ -77,16 +77,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select username, namespace, data from private_storage;">>, ok.
fun([LUser, XMLNS, XML]) ->
El = #xmlel{} = fxml_stream:parse_element(XML),
#private_storage{usns = {LUser, LServer, XMLNS},
xml = El}
end}].
import(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -42,8 +42,9 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, stop/1, process_iq/1, export/1, -export([start/2, stop/1, process_iq/1, export/1,
import/1, process_local_iq/1, get_user_roster/2, import_info/0, process_local_iq/1, get_user_roster/2,
import/3, get_subscription_lists/3, get_roster/2, import/5, get_subscription_lists/3, get_roster/2,
import_start/2, import_stop/2,
get_in_pending_subscriptions/3, in_subscription/6, get_in_pending_subscriptions/3, in_subscription/6,
out_subscription/4, set_items/3, remove_user/2, out_subscription/4, set_items/3, remove_user/2,
get_jid_info/4, encode_item/1, webadmin_page/3, get_jid_info/4, encode_item/1, webadmin_page/3,
@ -65,7 +66,7 @@
-export_type([subscription/0]). -export_type([subscription/0]).
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #roster{} | #roster_version{}) -> ok | pass. -callback import(binary(), binary(), #roster{} | [binary()]) -> ok.
-callback read_roster_version(binary(), binary()) -> binary() | error. -callback read_roster_version(binary(), binary()) -> binary() | error.
-callback write_roster_version(binary(), binary(), boolean(), binary()) -> any(). -callback write_roster_version(binary(), binary(), boolean(), binary()) -> any().
-callback get_roster(binary(), binary()) -> [#roster{}]. -callback get_roster(binary(), binary()) -> [#roster{}].
@ -1022,13 +1023,34 @@ export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import_info() ->
Mod = gen_mod:db_mod(LServer, ?MODULE), [{<<"roster_version">>, 2},
Mod:import(LServer). {<<"rostergroups">>, 3},
{<<"rosterusers">>, 10}].
import(LServer, DBType, R) -> import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, R). ets:new(rostergroups_tmp, [private, named_table, bag]),
Mod:init(LServer, []),
ok.
import_stop(_LServer, _DBType) ->
ets:delete(rostergroups_tmp),
ok.
import(LServer, {sql, _}, _DBType, <<"rostergroups">>, [LUser, SJID, Group]) ->
LJID = jid:tolower(jid:from_string(SJID)),
ets:insert(rostergroups_tmp, {{LUser, LServer, LJID}, Group}),
ok;
import(LServer, {sql, _}, DBType, <<"rosterusers">>, Row) ->
I = mod_roster_sql:raw_to_record(LServer, lists:sublist(Row, 9)),
Groups = [G || {_, G} <- ets:lookup(rostergroups_tmp, I#roster.usj)],
RosterItem = I#roster{groups = Groups},
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, <<"rosterusers">>, RosterItem);
import(LServer, {sql, _}, DBType, <<"roster_version">>, [LUser, Ver]) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, <<"roster_version">>, [LUser, Ver]).
mod_opt_type(access) -> mod_opt_type(access) ->
fun acl:access_rules_validator/1; fun acl:access_rules_validator/1;

View File

@ -15,7 +15,7 @@
get_roster/2, get_roster_by_jid/3, get_only_items/2, get_roster/2, get_roster_by_jid/3, get_only_items/2,
roster_subscribe/4, get_roster_by_jid_with_groups/3, roster_subscribe/4, get_roster_by_jid_with_groups/3,
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/2]). read_subscription_and_groups/3, import/3, create_roster/1]).
-include("mod_roster.hrl"). -include("mod_roster.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -51,7 +51,7 @@ write_roster_version(LUser, LServer, InTransaction, Ver) ->
end. end.
get_roster(LUser, LServer) -> get_roster(LUser, LServer) ->
mnesia:dirty_index_read(roster, {LUser, LServer}, #roster.us). {ok, mnesia:dirty_index_read(roster, {LUser, LServer}, #roster.us)}.
get_roster_by_jid(LUser, LServer, LJID) -> get_roster_by_jid(LUser, LServer, LJID) ->
case mnesia:read({roster, {LUser, LServer, LJID}}) of case mnesia:read({roster, {LUser, LServer, LJID}}) of
@ -103,9 +103,13 @@ read_subscription_and_groups(LUser, LServer, LJID) ->
transaction(_LServer, F) -> transaction(_LServer, F) ->
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #roster{} = R) -> create_roster(RItem) ->
mnesia:dirty_write(RItem).
import(_LServer, <<"rosterusers">>, #roster{} = R) ->
mnesia:dirty_write(R); mnesia:dirty_write(R);
import(_LServer, #roster_version{} = RV) -> import(LServer, <<"roster_version">>, [LUser, Ver]) ->
RV = #roster_version{us = {LUser, LServer}, version = Ver},
mnesia:dirty_write(RV). mnesia:dirty_write(RV).
%%%=================================================================== %%%===================================================================

View File

@ -13,10 +13,10 @@
%% API %% API
-export([init/2, read_roster_version/2, write_roster_version/4, -export([init/2, read_roster_version/2, write_roster_version/4,
get_roster/2, get_roster_by_jid/3, get_roster/2, get_roster_by_jid/3, create_roster/1,
roster_subscribe/4, get_roster_by_jid_with_groups/3, roster_subscribe/4, get_roster_by_jid_with_groups/3,
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, get_only_items/2, import/2]). read_subscription_and_groups/3, get_only_items/2, import/3]).
-include("mod_roster.hrl"). -include("mod_roster.hrl").
@ -41,8 +41,8 @@ write_roster_version(LUser, LServer, _InTransaction, Ver) ->
get_roster(LUser, LServer) -> get_roster(LUser, LServer) ->
case ejabberd_riak:get_by_index(roster, roster_schema(), case ejabberd_riak:get_by_index(roster, roster_schema(),
<<"us">>, {LUser, LServer}) of <<"us">>, {LUser, LServer}) of
{ok, Items} -> Items; {ok, Items} -> {ok, Items};
_Err -> [] _Err -> error
end. end.
get_roster_by_jid(LUser, LServer, LJID) -> get_roster_by_jid(LUser, LServer, LJID) ->
@ -96,10 +96,17 @@ read_subscription_and_groups(LUser, LServer, LJID) ->
error error
end. end.
import(_LServer, #roster{us = {LUser, LServer}} = R) -> create_roster(#roster{us = {LUser, LServer}} = RItem) ->
ejabberd_riak:put(R, roster_schema(), ejabberd_riak:put(
RItem, roster_schema(),
[{'2i', [{<<"us">>, {LUser, LServer}}]}]).
import(_LServer, <<"rosterusers">>, RosterItem) ->
{LUser, LServer} = RosterItem#roster.us,
ejabberd_riak:put(RosterItem, roster_schema(),
[{'2i', [{<<"us">>, {LUser, LServer}}]}]); [{'2i', [{<<"us">>, {LUser, LServer}}]}]);
import(_LServer, #roster_version{} = RV) -> import(LServer, <<"roster_version">>, [LUser, Ver]) ->
RV = #roster_version{us = {LUser, LServer}, version = Ver},
ejabberd_riak:put(RV, roster_version_schema()). ejabberd_riak:put(RV, roster_version_schema()).
%%%=================================================================== %%%===================================================================

View File

@ -18,7 +18,7 @@
roster_subscribe/4, get_roster_by_jid_with_groups/3, roster_subscribe/4, get_roster_by_jid_with_groups/3,
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, get_only_items/2, read_subscription_and_groups/3, get_only_items/2,
import/1, import/2, export/1]). import/3, export/1]).
-include("mod_roster.hrl"). -include("mod_roster.hrl").
-include("ejabberd_sql_pt.hrl"). -include("ejabberd_sql_pt.hrl").
@ -185,27 +185,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select username, jid, nick, subscription, " ok.
"ask, askmessage, server, subscribe, type from rosterusers;">>,
fun([LUser, JID|_] = Row) ->
Item = raw_to_record(LServer, Row),
Username = ejabberd_sql:escape(LUser),
SJID = ejabberd_sql:escape(JID),
{selected, _, Rows} =
ejabberd_sql: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(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -30,9 +30,9 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, stop/1, export/1, -export([start/2, stop/1, export/1,
import/1, webadmin_menu/3, webadmin_page/3, import_info/0, webadmin_menu/3, webadmin_page/3,
get_user_roster/2, get_subscription_lists/3, get_user_roster/2, get_subscription_lists/3,
get_jid_info/4, import/3, process_item/2, get_jid_info/4, import/5, process_item/2, import_start/2,
in_subscription/6, out_subscription/4, user_available/1, in_subscription/6, out_subscription/4, user_available/1,
unset_presence/4, register_user/2, remove_user/2, unset_presence/4, register_user/2, remove_user/2,
list_groups/1, create_group/2, create_group/3, list_groups/1, create_group/2, create_group/3,
@ -56,7 +56,7 @@
-type group_options() :: [{atom(), any()}]. -type group_options() :: [{atom(), any()}].
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #sr_user{} | #sr_group{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback list_groups(binary()) -> [binary()]. -callback list_groups(binary()) -> [binary()].
-callback groups_with_opts(binary()) -> [{binary(), group_options()}]. -callback groups_with_opts(binary()) -> [{binary(), group_options()}].
-callback create_group(binary(), binary(), group_options()) -> {atomic, any()}. -callback create_group(binary(), binary(), group_options()) -> {atomic, any()}.
@ -1072,13 +1072,16 @@ export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) -> import_info() ->
Mod = gen_mod:db_mod(LServer, ?MODULE), [{<<"sr_group">>, 3}, {<<"sr_user">>, 3}].
Mod:import(LServer).
import(LServer, DBType, Data) -> import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE), Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Data). Mod:init(LServer, []).
import(LServer, {sql, _}, DBType, Tab, L) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, L).
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(_) -> [db_type]. mod_opt_type(_) -> [db_type].

View File

@ -15,11 +15,12 @@
delete_group/2, get_group_opts/2, set_group_opts/3, delete_group/2, get_group_opts/2, set_group_opts/3,
get_user_groups/2, get_group_explicit_users/2, get_user_groups/2, get_group_explicit_users/2,
get_user_displayed_groups/3, is_user_in_group/3, get_user_displayed_groups/3, is_user_in_group/3,
add_user_to_group/3, remove_user_from_group/3, import/2]). add_user_to_group/3, remove_user_from_group/3, import/3]).
-include("mod_roster.hrl"). -include("mod_roster.hrl").
-include("mod_shared_roster.hrl"). -include("mod_shared_roster.hrl").
-include("logger.hrl"). -include("logger.hrl").
-include("xmpp.hrl").
%%%=================================================================== %%%===================================================================
%%% API %%% API
@ -118,10 +119,14 @@ remove_user_from_group(Host, US, Group) ->
F = fun () -> mnesia:delete_object(R) end, F = fun () -> mnesia:delete_object(R) end,
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #sr_group{} = G) -> import(LServer, <<"sr_group">>, [Group, SOpts, _TimeStamp]) ->
G = #sr_group{group_host = {Group, LServer},
opts = ejabberd_sql:decode_term(SOpts)},
mnesia:dirty_write(G); mnesia:dirty_write(G);
import(_LServer, #sr_user{} = U) -> import(LServer, <<"sr_user">>, [SJID, Group, _TimeStamp]) ->
mnesia:dirty_write(U). #jid{luser = U, lserver = S} = jid:from_string(SJID),
User = #sr_user{us = {U, S}, group_host = {Group, LServer}},
mnesia:dirty_write(User).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -15,10 +15,11 @@
delete_group/2, get_group_opts/2, set_group_opts/3, delete_group/2, get_group_opts/2, set_group_opts/3,
get_user_groups/2, get_group_explicit_users/2, get_user_groups/2, get_group_explicit_users/2,
get_user_displayed_groups/3, is_user_in_group/3, get_user_displayed_groups/3, is_user_in_group/3,
add_user_to_group/3, remove_user_from_group/3, import/2]). add_user_to_group/3, remove_user_from_group/3, import/3]).
-include("mod_roster.hrl"). -include("mod_roster.hrl").
-include("mod_shared_roster.hrl"). -include("mod_shared_roster.hrl").
-include("xmpp.hrl").
%%%=================================================================== %%%===================================================================
%%% API %%% API
@ -120,13 +121,17 @@ add_user_to_group(Host, US, Group) ->
remove_user_from_group(Host, US, Group) -> remove_user_from_group(Host, US, Group) ->
{atomic, ejabberd_riak:delete(sr_group, {US, {Group, Host}})}. {atomic, ejabberd_riak:delete(sr_group, {US, {Group, Host}})}.
import(_LServer, #sr_group{group_host = {_, Host}} = G) -> import(LServer, <<"sr_group">>, [Group, SOpts, _TimeStamp]) ->
ejabberd_riak:put(G, sr_group_schema(), [{'2i', [{<<"host">>, Host}]}]); G = #sr_group{group_host = {Group, LServer},
import(_LServer, #sr_user{us = US, group_host = {Group, Host}} = User) -> opts = ejabberd_sql:decode_term(SOpts)},
ejabberd_riak:put(G, sr_group_schema(), [{'2i', [{<<"host">>, LServer}]}]);
import(LServer, <<"sr_user">>, [SJID, Group|_]) ->
#jid{luser = U, lserver = S} = jid:from_string(SJID),
User = #sr_user{us = {U, S}, group_host = {Group, LServer}},
ejabberd_riak:put(User, sr_user_schema(), ejabberd_riak:put(User, sr_user_schema(),
[{i, {US, {Group, Host}}}, [{i, {{U, S}, {Group, LServer}}},
{'2i', [{<<"us">>, US}, {'2i', [{<<"us">>, {U, S}},
{<<"group_host">>, {Group, Host}}]}]). {<<"group_host">>, {Group, LServer}}]}]).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -17,8 +17,8 @@
delete_group/2, get_group_opts/2, set_group_opts/3, delete_group/2, get_group_opts/2, set_group_opts/3,
get_user_groups/2, get_group_explicit_users/2, get_user_groups/2, get_group_explicit_users/2,
get_user_displayed_groups/3, is_user_in_group/3, get_user_displayed_groups/3, is_user_in_group/3,
add_user_to_group/3, remove_user_from_group/3, import/1, add_user_to_group/3, remove_user_from_group/3, import/3,
import/2, export/1]). export/1]).
-include("jid.hrl"). -include("jid.hrl").
-include("mod_roster.hrl"). -include("mod_roster.hrl").
@ -177,20 +177,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select name, opts from sr_group;">>, ok.
fun([Group, SOpts]) ->
#sr_group{group_host = {Group, LServer},
opts = ejabberd_sql:decode_term(SOpts)}
end},
{<<"select jid, grp from sr_user;">>,
fun([SJID, Group]) ->
#jid{luser = U, lserver = S} = jid:from_string(SJID),
#sr_user{us = {U, S}, group_host = {Group, LServer}}
end}].
import(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -34,8 +34,8 @@
-export([start/2, init/3, stop/1, get_sm_features/5, -export([start/2, init/3, stop/1, get_sm_features/5,
process_local_iq/1, process_sm_iq/1, string2lower/1, process_local_iq/1, process_sm_iq/1, string2lower/1,
remove_user/2, export/1, import/1, import/3, depends/2, remove_user/2, export/1, import_info/0, import/5, import_start/2,
process_search/1, process_vcard/1, get_vcard/2, depends/2, process_search/1, process_vcard/1, get_vcard/2,
disco_items/5, disco_features/5, disco_identity/5, disco_items/5, disco_features/5, disco_identity/5,
decode_iq_subel/1, mod_opt_type/1, set_vcard/3, make_vcard_search/4]). decode_iq_subel/1, mod_opt_type/1, set_vcard/3, make_vcard_search/4]).
@ -50,7 +50,7 @@
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback stop(binary()) -> any(). -callback stop(binary()) -> any().
-callback import(binary(), #vcard{} | #vcard_search{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback get_vcard(binary(), binary()) -> [xmlel()] | error. -callback get_vcard(binary(), binary()) -> [xmlel()] | error.
-callback set_vcard(binary(), binary(), -callback set_vcard(binary(), binary(),
xmlel(), #vcard_search{}) -> {atomic, any()}. xmlel(), #vcard_search{}) -> {atomic, any()}.
@ -59,6 +59,7 @@
-callback search(binary(), [{binary(), [binary()]}], boolean(), -callback search(binary(), [{binary(), [binary()]}], boolean(),
infinity | pos_integer()) -> [{binary(), binary()}]. infinity | pos_integer()) -> [{binary(), binary()}].
-callback remove_user(binary(), binary()) -> {atomic, any()}. -callback remove_user(binary(), binary()) -> {atomic, any()}.
-callback is_search_supported(binary()) -> boolean().
start(Host, Opts) -> start(Host, Opts) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE), Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
@ -105,6 +106,15 @@ init(Host, ServerHost, Search) ->
false -> loop(Host, ServerHost); false -> loop(Host, ServerHost);
_ -> _ ->
ejabberd_router:register_route(Host, ServerHost), ejabberd_router:register_route(Host, ServerHost),
Mod = gen_mod:db_mod(ServerHost, ?MODULE),
case Mod:is_search_supported(ServerHost) of
false ->
?WARNING_MSG("vcard search functionality is "
"not implemented for ~s backend",
[gen_mod:db_type(ServerHost, ?MODULE)]);
true ->
ejabberd_router:register_route(Host, ServerHost)
end,
loop(Host, ServerHost) loop(Host, ServerHost)
end. end.
@ -438,18 +448,21 @@ remove_user(User, Server) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:remove_user(LUser, LServer). Mod:remove_user(LUser, LServer).
import_info() ->
[{<<"vcard">>, 3}, {<<"vcard_search">>, 24}].
import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []).
import(LServer, {sql, _}, DBType, Tab, L) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, L).
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, VCard) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, VCard).
depends(_Host, _Opts) -> depends(_Host, _Opts) ->
[]. [].

View File

@ -11,8 +11,9 @@
-behaviour(mod_vcard). -behaviour(mod_vcard).
%% API %% API
-export([init/2, stop/1, import/2, get_vcard/2, set_vcard/4, search/4, -export([init/2, stop/1, import/3, get_vcard/2, set_vcard/4, search/4,
search_fields/1, search_reported/1, remove_user/2]). search_fields/1, search_reported/1, remove_user/2]).
-export([is_search_supported/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("xmpp.hrl"). -include("xmpp.hrl").
@ -47,6 +48,9 @@ init(_Host, _Opts) ->
stop(_Host) -> stop(_Host) ->
ok. ok.
is_search_supported(_ServerHost) ->
true.
get_vcard(LUser, LServer) -> get_vcard(LUser, LServer) ->
US = {LUser, LServer}, US = {LUser, LServer},
F = fun () -> mnesia:read({vcard, US}) end, F = fun () -> mnesia:read({vcard, US}) end,
@ -121,10 +125,29 @@ remove_user(LUser, LServer) ->
end, end,
mnesia:transaction(F). 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); mnesia:dirty_write(VCard);
import(_LServer, #vcard_search{} = S) -> import(LServer, <<"vcard_search">>,
mnesia:dirty_write(S). [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}).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -12,7 +12,8 @@
%% API %% API
-export([init/2, get_vcard/2, set_vcard/4, search/4, remove_user/2, -export([init/2, get_vcard/2, set_vcard/4, search/4, remove_user/2,
search_fields/1, search_reported/1, import/2, stop/1]). search_fields/1, search_reported/1, import/3, stop/1]).
-export([is_search_supported/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_vcard.hrl"). -include("mod_vcard.hrl").
@ -26,6 +27,9 @@ init(_Host, _Opts) ->
stop(_Host) -> stop(_Host) ->
ok. ok.
is_search_supported(_LServer) ->
false.
get_vcard(LUser, LServer) -> get_vcard(LUser, LServer) ->
case ejabberd_riak:get(vcard, vcard_schema(), {LUser, LServer}) of case ejabberd_riak:get(vcard, vcard_schema(), {LUser, LServer}) of
{ok, R} -> {ok, R} ->
@ -101,7 +105,9 @@ search_reported(_LServer) ->
remove_user(LUser, LServer) -> remove_user(LUser, LServer) ->
{atomic, ejabberd_riak:delete(vcard, {LUser, LServer})}. {atomic, ejabberd_riak:delete(vcard, {LUser, LServer})}.
import(_LServer, #vcard{us = {LUser, LServer}, vcard = El} = VCard) -> import(LServer, <<"vcard">>, [LUser, XML, _TimeStamp]) ->
El = fxml_stream:parse_element(XML),
VCard = #vcard{us = {LUser, LServer}, vcard = El},
#vcard_search{fn = FN, #vcard_search{fn = FN,
lfn = LFN, lfn = LFN,
family = Family, family = Family,
@ -150,7 +156,7 @@ import(_LServer, #vcard{us = {LUser, LServer}, vcard = El} = VCard) ->
{<<"lorgname">>, LOrgName}, {<<"lorgname">>, LOrgName},
{<<"orgunit">>, OrgUnit}, {<<"orgunit">>, OrgUnit},
{<<"lorgunit">>, LOrgUnit}]}]); {<<"lorgunit">>, LOrgUnit}]}]);
import(_LServer, #vcard_search{}) -> import(_LServer, <<"vcard_search">>, _) ->
ok. ok.
%%%=================================================================== %%%===================================================================

View File

@ -14,7 +14,8 @@
%% API %% API
-export([init/2, stop/1, get_vcard/2, set_vcard/4, search/4, remove_user/2, -export([init/2, stop/1, get_vcard/2, set_vcard/4, search/4, remove_user/2,
search_fields/1, search_reported/1, import/1, import/2, export/1]). search_fields/1, search_reported/1, import/3, export/1]).
-export([is_search_supported/1]).
-include("xmpp.hrl"). -include("xmpp.hrl").
-include("mod_vcard.hrl"). -include("mod_vcard.hrl").
@ -30,6 +31,9 @@ init(_Host, _Opts) ->
stop(_Host) -> stop(_Host) ->
ok. ok.
is_search_supported(_LServer) ->
true.
get_vcard(LUser, LServer) -> get_vcard(LUser, LServer) ->
case catch sql_queries:get_vcard(LServer, LUser) of case catch sql_queries:get_vcard(LServer, LUser) of
{selected, [{SVCARD}]} -> {selected, [{SVCARD}]} ->
@ -188,37 +192,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select username, vcard from vcard;">>, ok.
fun([LUser, SVCard]) ->
#xmlel{} = VCARD = fxml_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(_, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -13,14 +13,15 @@
-export([start/2, stop/1]). -export([start/2, stop/1]).
-export([update_presence/3, vcard_set/3, export/1, -export([update_presence/3, vcard_set/3, export/1,
import/1, import/3, mod_opt_type/1, depends/2]). import_info/0, import/5, import_start/2,
mod_opt_type/1, depends/2]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("logger.hrl"). -include("logger.hrl").
-include("xmpp.hrl"). -include("xmpp.hrl").
-callback init(binary(), gen_mod:opts()) -> any(). -callback init(binary(), gen_mod:opts()) -> any().
-callback import(binary(), #vcard_xupdate{}) -> ok | pass. -callback import(binary(), binary(), [binary()]) -> ok.
-callback add_xupdate(binary(), binary(), binary()) -> {atomic, any()}. -callback add_xupdate(binary(), binary(), binary()) -> {atomic, any()}.
-callback get_xupdate(binary(), binary()) -> binary() | undefined. -callback get_xupdate(binary(), binary()) -> binary() | undefined.
-callback remove_xupdate(binary(), binary()) -> {atomic, any()}. -callback remove_xupdate(binary(), binary()) -> {atomic, any()}.
@ -94,17 +95,20 @@ presence_with_xupdate(Presence, User, Host) ->
Presence1 = xmpp:remove_subtag(Presence, #vcard_xupdate{}), Presence1 = xmpp:remove_subtag(Presence, #vcard_xupdate{}),
xmpp:set_subtag(Presence1, #vcard_xupdate{hash = Hash}). xmpp:set_subtag(Presence1, #vcard_xupdate{hash = Hash}).
import_info() ->
[{<<"vcard_xupdate">>, 3}].
import_start(LServer, DBType) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:init(LServer, []).
import(LServer, {sql, _}, DBType, Tab, [LUser, Hash, TimeStamp]) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, [LUser, Hash, TimeStamp]).
export(LServer) -> export(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:export(LServer). Mod:export(LServer).
import(LServer) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:import(LServer).
import(LServer, DBType, LA) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, LA).
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(_) -> [db_type]. mod_opt_type(_) -> [db_type].

View File

@ -10,7 +10,7 @@
-behaviour(mod_vcard_xupdate). -behaviour(mod_vcard_xupdate).
%% API %% API
-export([init/2, import/2, add_xupdate/3, get_xupdate/2, remove_xupdate/2]). -export([init/2, import/3, add_xupdate/3, get_xupdate/2, remove_xupdate/2]).
-include("mod_vcard_xupdate.hrl"). -include("mod_vcard_xupdate.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -45,8 +45,9 @@ remove_xupdate(LUser, LServer) ->
end, end,
mnesia:transaction(F). mnesia:transaction(F).
import(_LServer, #vcard_xupdate{} = R) -> import(LServer, <<"vcard_xupdate">>, [LUser, Hash, _TimeStamp]) ->
mnesia:dirty_write(R). mnesia:dirty_write(
#vcard_xupdate{us = {LUser, LServer}, hash = Hash}).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -11,7 +11,7 @@
-behaviour(mod_vcard_xupdate). -behaviour(mod_vcard_xupdate).
%% API %% API
-export([init/2, import/2, add_xupdate/3, get_xupdate/2, remove_xupdate/2]). -export([init/2, import/3, add_xupdate/3, get_xupdate/2, remove_xupdate/2]).
-include("mod_vcard_xupdate.hrl"). -include("mod_vcard_xupdate.hrl").
@ -36,8 +36,10 @@ get_xupdate(LUser, LServer) ->
remove_xupdate(LUser, LServer) -> remove_xupdate(LUser, LServer) ->
{atomic, ejabberd_riak:delete(vcard_xupdate, {LUser, LServer})}. {atomic, ejabberd_riak:delete(vcard_xupdate, {LUser, LServer})}.
import(_LServer, #vcard_xupdate{} = R) -> import(LServer, <<"vcard_xupdate">>, [LUser, Hash, _TimeStamp]) ->
ejabberd_riak:put(R, vcard_xupdate_schema()). ejabberd_riak:put(
#vcard_xupdate{us = {LUser, LServer}, hash = Hash},
vcard_xupdate_schema()).
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions

View File

@ -13,8 +13,8 @@
-behaviour(mod_vcard_xupdate). -behaviour(mod_vcard_xupdate).
%% API %% API
-export([init/2, import/2, add_xupdate/3, get_xupdate/2, remove_xupdate/2, -export([init/2, import/3, add_xupdate/3, get_xupdate/2, remove_xupdate/2,
import/1, export/1]). export/1]).
-include("mod_vcard_xupdate.hrl"). -include("mod_vcard_xupdate.hrl").
-include("ejabberd_sql_pt.hrl"). -include("ejabberd_sql_pt.hrl").
@ -62,14 +62,8 @@ export(_Server) ->
[] []
end}]. end}].
import(LServer) -> import(_, _, _) ->
[{<<"select username, hash from vcard_xupdate;">>, ok.
fun([LUser, Hash]) ->
#vcard_xupdate{us = {LUser, LServer}, hash = Hash}
end}].
import(_LServer, _) ->
pass.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions