mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Patch core for MH (thanks to Alexey Shchepin and Geoff Cant)
This commit is contained in:
parent
9336356efd
commit
cdb379a22c
20
src/acl.erl
20
src/acl.erl
@ -32,10 +32,12 @@
|
|||||||
add/3,
|
add/3,
|
||||||
add_list/3,
|
add_list/3,
|
||||||
match_rule/3,
|
match_rule/3,
|
||||||
|
for_host/1,
|
||||||
% for debugging only
|
% for debugging only
|
||||||
match_acl/3]).
|
match_acl/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
-include_lib("stdlib/include/ms_transform.hrl").
|
||||||
|
|
||||||
%% @type aclspec() = all | JID_Exact | JID_Regexp | JID_Glob | Shared_Group
|
%% @type aclspec() = all | JID_Exact | JID_Regexp | JID_Glob | Shared_Group
|
||||||
%% JID_Exact = {user, U} | {user, U, S} | {server, S} | {resource, R}
|
%% JID_Exact = {user, U} | {user, U, S} | {server, S} | {resource, R}
|
||||||
@ -234,7 +236,7 @@ match_acl(ACLName, JID, Host) ->
|
|||||||
User = exmpp_jid:prep_node_as_list(JID),
|
User = exmpp_jid:prep_node_as_list(JID),
|
||||||
Server = exmpp_jid:prep_domain_as_list(JID),
|
Server = exmpp_jid:prep_domain_as_list(JID),
|
||||||
Resource = exmpp_jid:prep_resource_as_list(JID),
|
Resource = exmpp_jid:prep_resource_as_list(JID),
|
||||||
lists:any(fun(#acl{aclspec = Spec}) ->
|
lists:any(fun(#acl{aclname=Name, aclspec = Spec}) ->
|
||||||
case Spec of
|
case Spec of
|
||||||
all ->
|
all ->
|
||||||
true;
|
true;
|
||||||
@ -243,17 +245,21 @@ match_acl(ACLName, JID, Host) ->
|
|||||||
andalso
|
andalso
|
||||||
((Host == Server) orelse
|
((Host == Server) orelse
|
||||||
((Host == global) andalso
|
((Host == global) andalso
|
||||||
lists:member(Server, ?MYHOSTS)));
|
?IS_MY_HOST(Server)));
|
||||||
{user, U, S} ->
|
{user, U, S} ->
|
||||||
(U == User) andalso (S == Server);
|
(U == User) andalso (S == Server);
|
||||||
{server, S} ->
|
{server, S} ->
|
||||||
S == Server;
|
S == Server;
|
||||||
{resource, R} ->
|
{resource, R} ->
|
||||||
R == Resource;
|
R == Resource;
|
||||||
|
{user_regexp, UR} when is_tuple(Name),
|
||||||
|
element(2, Name) =:= global ->
|
||||||
|
?IS_MY_HOST(Server)
|
||||||
|
andalso is_regexp_match(User, UR);
|
||||||
{user_regexp, UR} ->
|
{user_regexp, UR} ->
|
||||||
((Host == Server) orelse
|
((Host == Server) orelse
|
||||||
((Host == global) andalso
|
((Host == global) andalso
|
||||||
lists:member(Server, ?MYHOSTS)))
|
?IS_MY_HOST(Server)))
|
||||||
andalso is_regexp_match(User, UR);
|
andalso is_regexp_match(User, UR);
|
||||||
{shared_group, G} ->
|
{shared_group, G} ->
|
||||||
mod_shared_roster:is_user_in_group({User, Server}, G, Host);
|
mod_shared_roster:is_user_in_group({User, Server}, G, Host);
|
||||||
@ -272,7 +278,7 @@ match_acl(ACLName, JID, Host) ->
|
|||||||
{user_glob, UR} ->
|
{user_glob, UR} ->
|
||||||
((Host == Server) orelse
|
((Host == Server) orelse
|
||||||
((Host == global) andalso
|
((Host == global) andalso
|
||||||
lists:member(Server, ?MYHOSTS)))
|
?IS_MY_HOST(Server)))
|
||||||
andalso
|
andalso
|
||||||
is_glob_match(User, UR);
|
is_glob_match(User, UR);
|
||||||
{user_glob, UR, S} ->
|
{user_glob, UR, S} ->
|
||||||
@ -325,3 +331,9 @@ is_glob_match(String, Glob) ->
|
|||||||
is_regexp_match(String, xmerl_regexp:sh_to_awk(Glob)).
|
is_regexp_match(String, xmerl_regexp:sh_to_awk(Glob)).
|
||||||
|
|
||||||
|
|
||||||
|
for_host(Host) ->
|
||||||
|
mnesia:select(acl,
|
||||||
|
ets:fun2ms(fun (#acl{aclname = {_ACLName, H}})
|
||||||
|
when H =:= Host ->
|
||||||
|
object()
|
||||||
|
end)).
|
||||||
|
@ -28,8 +28,14 @@
|
|||||||
-author('alexey@process-one.net').
|
-author('alexey@process-one.net').
|
||||||
|
|
||||||
-export([start/0, stop/0,
|
-export([start/0, stop/0,
|
||||||
get_pid_file/0,
|
get_so_path/0,
|
||||||
get_so_path/0, get_bin_path/0]).
|
get_bin_path/0,
|
||||||
|
get_pid_file/0,
|
||||||
|
is_my_host/1,
|
||||||
|
normalize_host/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include("ejabberd.hrl").
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
%%ejabberd_cover:start(),
|
%%ejabberd_cover:start(),
|
||||||
@ -65,6 +71,33 @@ get_bin_path() ->
|
|||||||
Path
|
Path
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
is_my_host([$* | _]) ->
|
||||||
|
false;
|
||||||
|
is_my_host(Host) ->
|
||||||
|
case ejabberd_config:get_local_option({Host, host}) of
|
||||||
|
undefined ->
|
||||||
|
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
|
||||||
|
case ejabberd_config:get_local_option({WCHost, host}) of
|
||||||
|
undefined ->
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
true
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
true
|
||||||
|
end.
|
||||||
|
|
||||||
|
normalize_host(global) ->
|
||||||
|
global;
|
||||||
|
normalize_host(Host) ->
|
||||||
|
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
|
||||||
|
case ejabberd_config:get_local_option({WCHost, host}) of
|
||||||
|
undefined ->
|
||||||
|
Host;
|
||||||
|
_ ->
|
||||||
|
WCHost
|
||||||
|
end.
|
||||||
|
|
||||||
%% @spec () -> false | string()
|
%% @spec () -> false | string()
|
||||||
get_pid_file() ->
|
get_pid_file() ->
|
||||||
case os:getenv("EJABBERD_PID_PATH") of
|
case os:getenv("EJABBERD_PID_PATH") of
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
%% If the ejabberd application description isn't loaded, returns atom: undefined
|
%% If the ejabberd application description isn't loaded, returns atom: undefined
|
||||||
-define(VERSION, element(2, application:get_key(ejabberd,vsn))).
|
-define(VERSION, element(2, application:get_key(ejabberd,vsn))).
|
||||||
|
|
||||||
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)).
|
-define(IS_MY_HOST(Host), ejabberd:is_my_host(Host)).
|
||||||
|
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)). %% Deprecated
|
||||||
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
|
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
|
||||||
-define(MYLANG, ejabberd_config:get_global_option(language)).
|
-define(MYLANG, ejabberd_config:get_global_option(language)).
|
||||||
|
|
||||||
@ -35,6 +36,8 @@
|
|||||||
|
|
||||||
-define(S2STIMEOUT, 600000).
|
-define(S2STIMEOUT, 600000).
|
||||||
|
|
||||||
|
-define(PRIVACY_SUPPORT, true).
|
||||||
|
|
||||||
%%-define(DBGFSM, true).
|
%%-define(DBGFSM, true).
|
||||||
|
|
||||||
%% ---------------------------------
|
%% ---------------------------------
|
||||||
@ -58,4 +61,3 @@
|
|||||||
|
|
||||||
-define(CRITICAL_MSG(Format, Args),
|
-define(CRITICAL_MSG(Format, Args),
|
||||||
ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
|
ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
|
||||||
|
|
||||||
|
@ -278,8 +278,8 @@ send_service_message_all_mucs(Subject, AnnouncementText) ->
|
|||||||
Message = io_lib:format("~s~n~s", [Subject, AnnouncementText]),
|
Message = io_lib:format("~s~n~s", [Subject, AnnouncementText]),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(ServerHost) ->
|
fun(ServerHost) ->
|
||||||
MUCHost = gen_mod:get_module_opt_host(
|
MUCHost = gen_mod:expand_host_name(
|
||||||
ServerHost, mod_muc, "conference.@HOST@"),
|
ServerHost, mod_muc, "conference"),
|
||||||
MUCHostB = list_to_binary(MUCHost),
|
MUCHostB = list_to_binary(MUCHost),
|
||||||
mod_muc:broadcast_service_message(MUCHostB, Message)
|
mod_muc:broadcast_service_message(MUCHostB, Message)
|
||||||
end,
|
end,
|
||||||
|
@ -119,6 +119,15 @@ db_init() ->
|
|||||||
|
|
||||||
%% Start all the modules in all the hosts
|
%% Start all the modules in all the hosts
|
||||||
start_modules() ->
|
start_modules() ->
|
||||||
|
case ejabberd_config:get_local_option({static_modules, global}) of
|
||||||
|
undefined ->
|
||||||
|
ok;
|
||||||
|
StaticModules ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({Module, Args}) ->
|
||||||
|
gen_mod:start_module(global, Module, Args)
|
||||||
|
end, StaticModules)
|
||||||
|
end,
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
case ejabberd_config:get_local_option({modules, Host}) of
|
case ejabberd_config:get_local_option({modules, Host}) of
|
||||||
|
@ -52,6 +52,15 @@
|
|||||||
plain_password_required/1
|
plain_password_required/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
-export([start/1
|
||||||
|
,start_module/2
|
||||||
|
,stop_module/2
|
||||||
|
,start_modules/2
|
||||||
|
,start_method/2
|
||||||
|
,stop_method/2
|
||||||
|
,start_methods/2
|
||||||
|
]).
|
||||||
|
|
||||||
-export([auth_modules/1]).
|
-export([auth_modules/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
@ -67,13 +76,26 @@
|
|||||||
%% @spec () -> term()
|
%% @spec () -> term()
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
lists:foreach(
|
?DEBUG("About to start auth modules. Hosts: ~p", ?MYHOSTS),
|
||||||
fun(Host) ->
|
lists:foreach(fun start/1, ?MYHOSTS).
|
||||||
lists:foreach(
|
|
||||||
fun(M) ->
|
start(Host) ->
|
||||||
M:start(Host)
|
start_modules(Host, auth_modules(Host)).
|
||||||
end, auth_modules(Host))
|
|
||||||
end, ?MYHOSTS).
|
start_modules(Host, Modules) when is_list(Modules) ->
|
||||||
|
lists:foreach(fun (M) -> start_module(Host, M) end, Modules).
|
||||||
|
start_module(Host, Module) when is_atom(Module) ->
|
||||||
|
Module:start(Host).
|
||||||
|
stop_module(Host, Module) when is_atom(Module) ->
|
||||||
|
Module:stop(Host).
|
||||||
|
|
||||||
|
start_methods(Host, Methods) when is_list(Methods) ->
|
||||||
|
lists:foreach(fun (M) -> start_method(Host, M) end, Methods).
|
||||||
|
start_method(Host, Method) when is_atom(Method) ->
|
||||||
|
start_module(Host, module_name(Method)).
|
||||||
|
stop_method(Host, Method) when is_atom(Method) ->
|
||||||
|
stop_module(Host, module_name(Method)).
|
||||||
|
|
||||||
|
|
||||||
%% @spec (Server) -> bool()
|
%% @spec (Server) -> bool()
|
||||||
%% Server = string()
|
%% Server = string()
|
||||||
@ -186,7 +208,7 @@ try_register(User, Server, Password)
|
|||||||
true ->
|
true ->
|
||||||
{atomic, exists};
|
{atomic, exists};
|
||||||
false ->
|
false ->
|
||||||
case lists:member(exmpp_stringprep:nameprep(Server), ?MYHOSTS) of
|
case ?IS_MY_HOST(exmpp_stringprep:nameprep(Server)) of
|
||||||
true ->
|
true ->
|
||||||
Res = lists:foldl(
|
Res = lists:foldl(
|
||||||
fun (_M, {atomic, ok} = Res) ->
|
fun (_M, {atomic, ok} = Res) ->
|
||||||
@ -443,10 +465,13 @@ auth_modules() ->
|
|||||||
|
|
||||||
auth_modules(Server) when is_list(Server) ->
|
auth_modules(Server) when is_list(Server) ->
|
||||||
LServer = exmpp_stringprep:nameprep(Server),
|
LServer = exmpp_stringprep:nameprep(Server),
|
||||||
Method = ejabberd_config:get_local_option({auth_method, LServer}),
|
Method = ejabberd_config:get_local_option({auth_method, ejabberd:normalize_host(LServer)}),
|
||||||
Methods = if
|
Methods = if
|
||||||
Method == undefined -> [];
|
Method == undefined -> [];
|
||||||
is_list(Method) -> Method;
|
is_list(Method) -> Method;
|
||||||
is_atom(Method) -> [Method]
|
is_atom(Method) -> [Method]
|
||||||
end,
|
end,
|
||||||
[list_to_atom("ejabberd_auth_" ++ atom_to_list(M)) || M <- Methods].
|
[module_name(M) || M <- Methods].
|
||||||
|
|
||||||
|
module_name(Method) when is_atom(Method) ->
|
||||||
|
list_to_atom("ejabberd_auth_" ++ atom_to_list(Method)).
|
||||||
|
@ -72,7 +72,6 @@
|
|||||||
base,
|
base,
|
||||||
uids,
|
uids,
|
||||||
ufilter,
|
ufilter,
|
||||||
sfilter,
|
|
||||||
lfilter, %% Local filter (performed by ejabberd, not LDAP)
|
lfilter, %% Local filter (performed by ejabberd, not LDAP)
|
||||||
dn_filter,
|
dn_filter,
|
||||||
dn_filter_attrs
|
dn_filter_attrs
|
||||||
@ -99,21 +98,41 @@ handle_info(_Info, State) ->
|
|||||||
%% Host = string()
|
%% Host = string()
|
||||||
|
|
||||||
start(Host) ->
|
start(Host) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
?DEBUG("Starting ~p for ~p.", [?MODULE, Host]),
|
||||||
ChildSpec = {
|
case ejabberd_config:get_host_option(Host, ldap_servers) of
|
||||||
Proc, {?MODULE, start_link, [Host]},
|
undefined -> check_bad_config(Host);
|
||||||
transient, 1000, worker, [?MODULE]
|
{host, _Host} -> ok;
|
||||||
},
|
_ ->
|
||||||
supervisor:start_child(ejabberd_sup, ChildSpec).
|
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
||||||
|
ChildSpec = {
|
||||||
|
Proc, {?MODULE, start_link, [Host]},
|
||||||
|
transient, 1000, worker, [?MODULE]
|
||||||
|
},
|
||||||
|
supervisor:start_child(ejabberd_sup, ChildSpec)
|
||||||
|
end.
|
||||||
|
|
||||||
|
check_bad_config(Host) ->
|
||||||
|
case ejabberd_config:get_local_option({ldap_servers, Host}) of
|
||||||
|
undefined ->
|
||||||
|
?ERROR_MSG("Can't start ~p for host ~p: missing ldap_servers configuration",
|
||||||
|
[?MODULE, Host]),
|
||||||
|
{error, bad_config};
|
||||||
|
_ -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
%% @spec (Host) -> term()
|
%% @spec (Host) -> term()
|
||||||
%% Host = string()
|
%% Host = string()
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
case ejabberd_config:get_host_option(Host, ldap_servers) of
|
||||||
gen_server:call(Proc, stop),
|
undefined -> ok;
|
||||||
supervisor:terminate_child(ejabberd_sup, Proc),
|
{host, _Host} -> ok;
|
||||||
supervisor:delete_child(ejabberd_sup, Proc).
|
_ ->
|
||||||
|
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
||||||
|
gen_server:call(Proc, stop),
|
||||||
|
supervisor:terminate_child(ejabberd_sup, Proc),
|
||||||
|
supervisor:delete_child(ejabberd_sup, Proc)
|
||||||
|
end.
|
||||||
|
|
||||||
%% @spec (Host) -> term()
|
%% @spec (Host) -> term()
|
||||||
%% Host = string()
|
%% Host = string()
|
||||||
@ -190,7 +209,7 @@ check_password(User, Server, Password, _Digest, _DigestGen) ->
|
|||||||
|
|
||||||
set_password(User, Server, Password) ->
|
set_password(User, Server, Password) ->
|
||||||
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
||||||
case find_user_dn(User, State) of
|
case find_user_dn(User, Server, State) of
|
||||||
false ->
|
false ->
|
||||||
{error, user_not_found};
|
{error, user_not_found};
|
||||||
DN ->
|
DN ->
|
||||||
@ -285,8 +304,8 @@ remove_user(_User, _Server, _Password) ->
|
|||||||
%% Password = string()
|
%% Password = string()
|
||||||
|
|
||||||
check_password_ldap(User, Server, Password) ->
|
check_password_ldap(User, Server, Password) ->
|
||||||
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
{ok, State} = get_state(Server),
|
||||||
case find_user_dn(User, State) of
|
case find_user_dn(User, Server, State) of
|
||||||
false ->
|
false ->
|
||||||
false;
|
false;
|
||||||
DN ->
|
DN ->
|
||||||
@ -294,7 +313,21 @@ check_password_ldap(User, Server, Password) ->
|
|||||||
ok -> true;
|
ok -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% We need an ?MODULE server state to use for queries. This will
|
||||||
|
%% either be Server if this is a statically configured host or the
|
||||||
|
%% Server for a different host if this is a dynamically configured
|
||||||
|
%% vhost.
|
||||||
|
%% The {ldap_vhost, Server} -> Host. ejabberd config option specifies
|
||||||
|
%% which actual ?MODULE server to use for a particular Host. The value
|
||||||
|
%% of the option if it is defined or Server by default.
|
||||||
|
get_state(Server) ->
|
||||||
|
Host = case ejabberd_config:get_local_option({ldap_servers, Server}) of
|
||||||
|
{host, H} -> H;
|
||||||
|
_ -> Server
|
||||||
|
end,
|
||||||
|
eldap_utils:get_state(Host, ?MODULE).
|
||||||
|
|
||||||
%% @spec (Server) -> [{LUser, LServer}]
|
%% @spec (Server) -> [{LUser, LServer}]
|
||||||
%% Server = string()
|
%% Server = string()
|
||||||
@ -303,11 +336,11 @@ check_password_ldap(User, Server, Password) ->
|
|||||||
|
|
||||||
get_vh_registered_users_ldap(Server) ->
|
get_vh_registered_users_ldap(Server) ->
|
||||||
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
||||||
UIDs = State#state.uids,
|
UIDs = eldap_utils:uids_domain_subst(Server, State#state.uids),
|
||||||
Eldap_ID = State#state.eldap_id,
|
Eldap_ID = State#state.eldap_id,
|
||||||
Server = State#state.host,
|
SearchFilter = build_sfilter(State, UIDs),
|
||||||
ResAttrs = result_attrs(State),
|
ResAttrs = result_attrs(State),
|
||||||
case eldap_filter:parse(State#state.sfilter) of
|
case eldap_filter:parse(SearchFilter) of
|
||||||
{ok, EldapFilter} ->
|
{ok, EldapFilter} ->
|
||||||
case eldap_pool:search(Eldap_ID, [{base, State#state.base},
|
case eldap_pool:search(Eldap_ID, [{base, State#state.base},
|
||||||
{filter, EldapFilter},
|
{filter, EldapFilter},
|
||||||
@ -317,7 +350,7 @@ get_vh_registered_users_ldap(Server) ->
|
|||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun(#eldap_entry{attributes = Attrs,
|
fun(#eldap_entry{attributes = Attrs,
|
||||||
object_name = DN}) ->
|
object_name = DN}) ->
|
||||||
case is_valid_dn(DN, Attrs, State) of
|
case is_valid_dn(DN, Server, Attrs, State) of
|
||||||
false -> [];
|
false -> [];
|
||||||
_ ->
|
_ ->
|
||||||
case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
|
case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
|
||||||
@ -349,7 +382,7 @@ get_vh_registered_users_ldap(Server) ->
|
|||||||
|
|
||||||
is_user_exists_ldap(User, Server) ->
|
is_user_exists_ldap(User, Server) ->
|
||||||
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
|
||||||
case find_user_dn(User, State) of
|
case find_user_dn(User, Server, State) of
|
||||||
false -> false;
|
false -> false;
|
||||||
_DN -> true
|
_DN -> true
|
||||||
end.
|
end.
|
||||||
@ -363,16 +396,17 @@ handle_call(stop, _From, State) ->
|
|||||||
handle_call(_Request, _From, State) ->
|
handle_call(_Request, _From, State) ->
|
||||||
{reply, bad_request, State}.
|
{reply, bad_request, State}.
|
||||||
|
|
||||||
find_user_dn(User, State) ->
|
find_user_dn(User, Server, State) ->
|
||||||
ResAttrs = result_attrs(State),
|
ResAttrs = result_attrs(State),
|
||||||
case eldap_filter:parse(State#state.ufilter, [{"%u", User}]) of
|
UserFilter = build_ufilter(State, Server),
|
||||||
|
case eldap_filter:parse(UserFilter, [{"%u", User}]) of
|
||||||
{ok, Filter} ->
|
{ok, Filter} ->
|
||||||
case eldap_pool:search(State#state.eldap_id, [{base, State#state.base},
|
case eldap_pool:search(State#state.eldap_id, [{base, State#state.base},
|
||||||
{filter, Filter},
|
{filter, Filter},
|
||||||
{attributes, ResAttrs}]) of
|
{attributes, ResAttrs}]) of
|
||||||
#eldap_search_result{entries = [#eldap_entry{attributes = Attrs,
|
#eldap_search_result{entries = [#eldap_entry{attributes = Attrs,
|
||||||
object_name = DN} | _]} ->
|
object_name = DN} | _]} ->
|
||||||
dn_filter(DN, Attrs, State);
|
dn_filter(DN, Server, Attrs, State);
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end;
|
end;
|
||||||
@ -381,20 +415,20 @@ find_user_dn(User, State) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
%% apply the dn filter and the local filter:
|
%% apply the dn filter and the local filter:
|
||||||
dn_filter(DN, Attrs, State) ->
|
dn_filter(DN, Server, Attrs, State) ->
|
||||||
%% Check if user is denied access by attribute value (local check)
|
%% Check if user is denied access by attribute value (local check)
|
||||||
case check_local_filter(Attrs, State) of
|
case check_local_filter(Attrs, State) of
|
||||||
false -> false;
|
false -> false;
|
||||||
true -> is_valid_dn(DN, Attrs, State)
|
true -> is_valid_dn(DN, Server, Attrs, State)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Check that the DN is valid, based on the dn filter
|
%% Check that the DN is valid, based on the dn filter
|
||||||
is_valid_dn(DN, _, #state{dn_filter = undefined}) ->
|
is_valid_dn(DN, _, _, #state{dn_filter = undefined}) ->
|
||||||
DN;
|
DN;
|
||||||
|
|
||||||
is_valid_dn(DN, Attrs, State) ->
|
is_valid_dn(DN, Server, Attrs, State) ->
|
||||||
DNAttrs = State#state.dn_filter_attrs,
|
DNAttrs = State#state.dn_filter_attrs,
|
||||||
UIDs = State#state.uids,
|
UIDs = eldap_utils:uids_domain_subst(Server, State#state.uids),
|
||||||
Values = [{"%s", eldap_utils:get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs],
|
Values = [{"%s", eldap_utils:get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs],
|
||||||
SubstValues = case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
|
SubstValues = case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
|
||||||
"" -> Values;
|
"" -> Values;
|
||||||
@ -449,6 +483,22 @@ result_attrs(#state{uids = UIDs, dn_filter_attrs = DNFilterAttrs}) ->
|
|||||||
[UID | Acc]
|
[UID | Acc]
|
||||||
end, DNFilterAttrs, UIDs).
|
end, DNFilterAttrs, UIDs).
|
||||||
|
|
||||||
|
build_ufilter(State, VHost) ->
|
||||||
|
UIDs = eldap_utils:uids_domain_subst(VHost, State#state.uids),
|
||||||
|
SubFilter = lists:flatten(eldap_utils:generate_subfilter(UIDs)),
|
||||||
|
case State#state.ufilter of
|
||||||
|
"" -> SubFilter;
|
||||||
|
F -> "(&" ++ SubFilter ++ F ++ ")"
|
||||||
|
end.
|
||||||
|
|
||||||
|
build_sfilter(State, FormattedUIDs) ->
|
||||||
|
SubFilter = lists:flatten(eldap_utils:generate_subfilter(FormattedUIDs)),
|
||||||
|
UserFilter = case State#state.ufilter of
|
||||||
|
"" -> SubFilter;
|
||||||
|
F -> "(&" ++ SubFilter ++ F ++ ")"
|
||||||
|
end,
|
||||||
|
eldap_filter:do_sub(UserFilter, [{"%u", "*"}]).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Auxiliary functions
|
%%% Auxiliary functions
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -480,15 +530,12 @@ parse_options(Host) ->
|
|||||||
end,
|
end,
|
||||||
UIDs = case ejabberd_config:get_local_option({ldap_uids, Host}) of
|
UIDs = case ejabberd_config:get_local_option({ldap_uids, Host}) of
|
||||||
undefined -> [{"uid", "%u"}];
|
undefined -> [{"uid", "%u"}];
|
||||||
UI -> eldap_utils:uids_domain_subst(Host, UI)
|
UI -> UI
|
||||||
end,
|
end,
|
||||||
SubFilter = lists:flatten(eldap_utils:generate_subfilter(UIDs)),
|
|
||||||
UserFilter = case ejabberd_config:get_local_option({ldap_filter, Host}) of
|
UserFilter = case ejabberd_config:get_local_option({ldap_filter, Host}) of
|
||||||
undefined -> SubFilter;
|
undefined -> "";
|
||||||
"" -> SubFilter;
|
F -> F
|
||||||
F -> "(&" ++ SubFilter ++ F ++ ")"
|
|
||||||
end,
|
end,
|
||||||
SearchFilter = eldap_filter:do_sub(UserFilter, [{"%u", "*"}]),
|
|
||||||
LDAPBase = ejabberd_config:get_local_option({ldap_base, Host}),
|
LDAPBase = ejabberd_config:get_local_option({ldap_base, Host}),
|
||||||
{DNFilter, DNFilterAttrs} =
|
{DNFilter, DNFilterAttrs} =
|
||||||
case ejabberd_config:get_local_option({ldap_dn_filter, Host}) of
|
case ejabberd_config:get_local_option({ldap_dn_filter, Host}) of
|
||||||
@ -513,7 +560,6 @@ parse_options(Host) ->
|
|||||||
base = LDAPBase,
|
base = LDAPBase,
|
||||||
uids = UIDs,
|
uids = UIDs,
|
||||||
ufilter = UserFilter,
|
ufilter = UserFilter,
|
||||||
sfilter = SearchFilter,
|
|
||||||
lfilter = LocalFilter,
|
lfilter = LocalFilter,
|
||||||
dn_filter = DNFilter,
|
dn_filter = DNFilter,
|
||||||
dn_filter_attrs = DNFilterAttrs
|
dn_filter_attrs = DNFilterAttrs
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
%% External exports
|
%% External exports
|
||||||
-export([start/1,
|
-export([start/1,
|
||||||
|
stop/1,
|
||||||
set_password/3,
|
set_password/3,
|
||||||
check_password/3,
|
check_password/3,
|
||||||
check_password/5,
|
check_password/5,
|
||||||
@ -55,8 +56,14 @@
|
|||||||
%% @spec (Host) -> ok
|
%% @spec (Host) -> ok
|
||||||
%% Host = string()
|
%% Host = string()
|
||||||
|
|
||||||
start(_Host) ->
|
start(Host) ->
|
||||||
ok.
|
case ejabberd_odbc:running(Host) of
|
||||||
|
true -> ok;
|
||||||
|
false -> ejabberd_rdbms:start_odbc(Host)
|
||||||
|
end.
|
||||||
|
|
||||||
|
stop(Host) ->
|
||||||
|
ejabberd_rdbms:stop_odbc(Host).
|
||||||
|
|
||||||
%% @spec () -> bool()
|
%% @spec () -> bool()
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ wait_for_stream({xmlstreamstart, #xmlel{ns = NS} = Opening}, StateData) ->
|
|||||||
ServerB = exmpp_stringprep:nameprep(
|
ServerB = exmpp_stringprep:nameprep(
|
||||||
exmpp_stream:get_receiving_entity(Opening)),
|
exmpp_stream:get_receiving_entity(Opening)),
|
||||||
Server = binary_to_list(ServerB),
|
Server = binary_to_list(ServerB),
|
||||||
case lists:member(Server, ?MYHOSTS) of
|
case ?IS_MY_HOST(Server) of
|
||||||
true ->
|
true ->
|
||||||
Lang = exmpp_stream:get_lang(Opening),
|
Lang = exmpp_stream:get_lang(Opening),
|
||||||
change_shaper(StateData,
|
change_shaper(StateData,
|
||||||
|
@ -46,6 +46,8 @@ config() ->
|
|||||||
check_database_modules() ->
|
check_database_modules() ->
|
||||||
[check_database_module(M)||M<-get_db_used()].
|
[check_database_module(M)||M<-get_db_used()].
|
||||||
|
|
||||||
|
check_database_module(host) ->
|
||||||
|
ok;
|
||||||
check_database_module(odbc) ->
|
check_database_module(odbc) ->
|
||||||
check_modules(odbc, [odbc, odbc_app, odbc_sup, ejabberd_odbc, ejabberd_odbc_sup, odbc_queries]);
|
check_modules(odbc, [odbc, odbc_app, odbc_sup, ejabberd_odbc, ejabberd_odbc_sup, odbc_queries]);
|
||||||
check_database_module(mysql) ->
|
check_database_module(mysql) ->
|
||||||
|
@ -27,17 +27,32 @@
|
|||||||
-module(ejabberd_config).
|
-module(ejabberd_config).
|
||||||
-author('alexey@process-one.net').
|
-author('alexey@process-one.net').
|
||||||
|
|
||||||
-export([start/0, load_file/1,
|
-export([start/0, load_file/1, get_host_option/2,
|
||||||
add_global_option/2, add_local_option/2,
|
add_global_option/2, add_local_option/2,
|
||||||
|
mne_add_local_option/2, mne_del_local_option/1,
|
||||||
del_global_option/1, del_local_option/1,
|
del_global_option/1, del_local_option/1,
|
||||||
get_global_option/1, get_local_option/1]).
|
get_global_option/1, get_local_option/1]).
|
||||||
|
|
||||||
|
-export([for_host/1
|
||||||
|
,configure_host/2
|
||||||
|
,delete_host/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-export([search/1]).
|
||||||
|
|
||||||
-export([get_vh_by_auth_method/1]).
|
-export([get_vh_by_auth_method/1]).
|
||||||
-export([is_file_readable/1]).
|
-export([is_file_readable/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("ejabberd_config.hrl").
|
-include("ejabberd_config.hrl").
|
||||||
-include_lib("kernel/include/file.hrl").
|
-include_lib("kernel/include/file.hrl").
|
||||||
|
-include_lib("stdlib/include/ms_transform.hrl").
|
||||||
|
|
||||||
|
-record(state, {opts = [],
|
||||||
|
hosts = [],
|
||||||
|
override_local = false,
|
||||||
|
override_global = false,
|
||||||
|
override_acls = false}).
|
||||||
|
|
||||||
%% @type macro() = {macro_key(), macro_value()}
|
%% @type macro() = {macro_key(), macro_value()}
|
||||||
|
|
||||||
@ -153,6 +168,14 @@ search_hosts(Term, State) ->
|
|||||||
|
|
||||||
add_hosts_to_option(Hosts, State) ->
|
add_hosts_to_option(Hosts, State) ->
|
||||||
PrepHosts = normalize_hosts(Hosts),
|
PrepHosts = normalize_hosts(Hosts),
|
||||||
|
mnesia:transaction(
|
||||||
|
fun() ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(H) ->
|
||||||
|
mnesia:write(#local_config{key = {H, host},
|
||||||
|
value = []})
|
||||||
|
end, PrepHosts)
|
||||||
|
end),
|
||||||
add_option(hosts, PrepHosts, State#state{hosts = PrepHosts}).
|
add_option(hosts, PrepHosts, State#state{hosts = PrepHosts}).
|
||||||
|
|
||||||
normalize_hosts(Hosts) ->
|
normalize_hosts(Hosts) ->
|
||||||
@ -379,6 +402,8 @@ process_term(Term, State) ->
|
|||||||
{host_config, Host, Terms} ->
|
{host_config, Host, Terms} ->
|
||||||
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
|
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
|
||||||
State, Terms);
|
State, Terms);
|
||||||
|
{clusterid, ClusterID} ->
|
||||||
|
add_option(clusterid, ClusterID, State);
|
||||||
{listen, Listeners} ->
|
{listen, Listeners} ->
|
||||||
Listeners2 =
|
Listeners2 =
|
||||||
lists:map(
|
lists:map(
|
||||||
@ -443,8 +468,7 @@ process_term(Term, State) ->
|
|||||||
{max_fsm_queue, N} ->
|
{max_fsm_queue, N} ->
|
||||||
add_option(max_fsm_queue, N, State);
|
add_option(max_fsm_queue, N, State);
|
||||||
{_Opt, _Val} ->
|
{_Opt, _Val} ->
|
||||||
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
|
process_host_term(Term, global, State)
|
||||||
State, State#state.hosts)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_host_term(Term, Host, State) ->
|
process_host_term(Term, Host, State) ->
|
||||||
@ -569,10 +593,11 @@ add_global_option(Opt, Val) ->
|
|||||||
end).
|
end).
|
||||||
|
|
||||||
add_local_option(Opt, Val) ->
|
add_local_option(Opt, Val) ->
|
||||||
mnesia:transaction(fun() ->
|
mnesia:transaction(fun mne_add_local_option/2, [Opt, Val]).
|
||||||
mnesia:write(#local_config{key = Opt,
|
|
||||||
value = Val})
|
mne_add_local_option(Opt, Val) ->
|
||||||
end).
|
mnesia:write(#local_config{key = Opt,
|
||||||
|
value = Val}).
|
||||||
|
|
||||||
del_global_option(Opt) ->
|
del_global_option(Opt) ->
|
||||||
mnesia:transaction(fun() ->
|
mnesia:transaction(fun() ->
|
||||||
@ -585,6 +610,13 @@ del_local_option(Opt) ->
|
|||||||
end).
|
end).
|
||||||
|
|
||||||
|
|
||||||
|
get_global_option({Opt1, Host} = Opt) when is_list(Host) ->
|
||||||
|
case ets:lookup(config, Opt) of
|
||||||
|
[#config{value = Val}] ->
|
||||||
|
Val;
|
||||||
|
_ ->
|
||||||
|
get_global_option({Opt1, global})
|
||||||
|
end;
|
||||||
get_global_option(Opt) ->
|
get_global_option(Opt) ->
|
||||||
case ets:lookup(config, Opt) of
|
case ets:lookup(config, Opt) of
|
||||||
[#config{value = Val}] ->
|
[#config{value = Val}] ->
|
||||||
@ -593,6 +625,13 @@ get_global_option(Opt) ->
|
|||||||
undefined
|
undefined
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
get_local_option({Opt1, Host} = Opt) when is_list(Host) ->
|
||||||
|
case ets:lookup(local_config, Opt) of
|
||||||
|
[#local_config{value = Val}] ->
|
||||||
|
Val;
|
||||||
|
_ ->
|
||||||
|
get_local_option({Opt1, global})
|
||||||
|
end;
|
||||||
get_local_option(Opt) ->
|
get_local_option(Opt) ->
|
||||||
case ets:lookup(local_config, Opt) of
|
case ets:lookup(local_config, Opt) of
|
||||||
[#local_config{value = Val}] ->
|
[#local_config{value = Val}] ->
|
||||||
@ -601,6 +640,17 @@ get_local_option(Opt) ->
|
|||||||
undefined
|
undefined
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
get_host_option(Host, Option) ->
|
||||||
|
case ets:lookup(local_config, {Option, Host}) of
|
||||||
|
[#local_config{value=V}] -> V;
|
||||||
|
_ -> undefined
|
||||||
|
end.
|
||||||
|
|
||||||
|
mne_del_local_option({_OptName, Host} = Opt) when is_list(Host) ->
|
||||||
|
mnesia:delete({local_config, Opt});
|
||||||
|
mne_del_local_option({Host, host} = Opt) when is_list(Host) ->
|
||||||
|
mnesia:delete({local_config, Opt}).
|
||||||
|
|
||||||
%% Return the list of hosts handled by a given module
|
%% Return the list of hosts handled by a given module
|
||||||
get_vh_by_auth_method(AuthMethod) ->
|
get_vh_by_auth_method(AuthMethod) ->
|
||||||
mnesia:dirty_select(local_config,
|
mnesia:dirty_select(local_config,
|
||||||
@ -619,3 +669,54 @@ is_file_readable(Path) ->
|
|||||||
{error, _Reason} ->
|
{error, _Reason} ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
search(Pattern) ->
|
||||||
|
{atomic, Res} = mnesia:transaction(fun mnesia:select/2, [local_config, Pattern]),
|
||||||
|
Res.
|
||||||
|
|
||||||
|
for_host(Host) ->
|
||||||
|
mnesia:read({local_config, {Host, host}})
|
||||||
|
++ mnesia:select(local_config,
|
||||||
|
ets:fun2ms(fun (#local_config{key={_, H}})
|
||||||
|
when H =:= Host ->
|
||||||
|
object()
|
||||||
|
end))
|
||||||
|
++ acl:for_host(Host).
|
||||||
|
|
||||||
|
delete_host(Host) ->
|
||||||
|
mnesia_delete_objects(for_host(Host)),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
configure_host(Host, Config) ->
|
||||||
|
HostExistenceTerm = {{Host, host}, []},
|
||||||
|
Records = host_terms_to_records(Host, [HostExistenceTerm | Config]),
|
||||||
|
mnesia_write_objects(Records),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
host_terms_to_records(Host, Terms) ->
|
||||||
|
lists:foldl(fun (Term, Acc) ->
|
||||||
|
host_term_to_record(Term, Host, Acc)
|
||||||
|
end, [], Terms).
|
||||||
|
|
||||||
|
host_term_to_record({acl, ACLName, ACLData}, Host, Acc) ->
|
||||||
|
[acl:to_record(Host, ACLName, ACLData) | Acc];
|
||||||
|
host_term_to_record({access, RuleName, Rules}, Host, Acc) ->
|
||||||
|
[#config{key={access, RuleName, Host}, value=Rules} | Acc];
|
||||||
|
host_term_to_record({shaper, Name, Data}, Host, Acc) ->
|
||||||
|
[#config{key={shaper, Name, Host}, value=Data} | Acc];
|
||||||
|
host_term_to_record({host, _}, _Host, Acc) -> Acc;
|
||||||
|
host_term_to_record({hosts, _}, _Host, Acc) -> Acc;
|
||||||
|
host_term_to_record({{Host, host}, []}, Host, Acc) ->
|
||||||
|
[#local_config{key={Host, host}, value=[]} | Acc];
|
||||||
|
host_term_to_record({Opt, Val}, Host, Acc) when is_atom(Opt) ->
|
||||||
|
[#local_config{key={Opt, Host}, value=Val} | Acc].
|
||||||
|
|
||||||
|
|
||||||
|
mnesia_delete_objects(List) when is_list(List) ->
|
||||||
|
true = lists:all(fun (I) ->
|
||||||
|
ok =:= mnesia:delete_object(I)
|
||||||
|
end, List).
|
||||||
|
mnesia_write_objects(List) when is_list(List) ->
|
||||||
|
true = lists:all(fun (I) ->
|
||||||
|
ok =:= mnesia:write(I)
|
||||||
|
end, List).
|
||||||
|
@ -21,8 +21,3 @@
|
|||||||
|
|
||||||
-record(config, {key, value}).
|
-record(config, {key, value}).
|
||||||
-record(local_config, {key, value}).
|
-record(local_config, {key, value}).
|
||||||
-record(state, {opts = [],
|
|
||||||
hosts = [],
|
|
||||||
override_local = false,
|
|
||||||
override_global = false,
|
|
||||||
override_acls = false}).
|
|
||||||
|
@ -119,14 +119,27 @@ delete_dist(Hook, Host, Node, Module, Function, Seq) ->
|
|||||||
%% @doc Run the calls of this hook in order, don't care about function results.
|
%% @doc Run the calls of this hook in order, don't care about function results.
|
||||||
%% If a call returns stop, no more calls are performed.
|
%% If a call returns stop, no more calls are performed.
|
||||||
run(Hook, Args) ->
|
run(Hook, Args) ->
|
||||||
run(Hook, global, Args).
|
runx(Hook, global, Args).
|
||||||
|
|
||||||
run(Hook, Host, Args) when is_binary(Host) orelse is_atom(Host) ->
|
run(Hook, Host, Args) when is_binary(Host) ->
|
||||||
case ets:lookup(hooks, {Hook, Host}) of
|
case runx(Hook, Host, Args) of
|
||||||
|
stop -> stop;
|
||||||
|
_ -> runx(Hook, global, Args)
|
||||||
|
end;
|
||||||
|
run(Hook, Host, Args) when Host == global ->
|
||||||
|
runx(Hook, Host, Args).
|
||||||
|
|
||||||
|
runx(Hook, Host, Args) when is_binary(Host) orelse is_atom(Host) ->
|
||||||
|
case ets:lookup(hooks, {Hook, ejabberd:normalize_host(Host)}) of
|
||||||
[{_, Ls}] ->
|
[{_, Ls}] ->
|
||||||
run1(Ls, Hook, Args);
|
run1(Ls, Hook, Args);
|
||||||
[] ->
|
[] ->
|
||||||
ok
|
case ets:lookup(hooks, {Hook, global}) of
|
||||||
|
[{_, Ls}] ->
|
||||||
|
run1(Ls, Hook, Args);
|
||||||
|
[] ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @spec (Hook::atom(), Val, Args) -> Val | stopped | NewVal
|
%% @spec (Hook::atom(), Val, Args) -> Val | stopped | NewVal
|
||||||
@ -136,16 +149,29 @@ run(Hook, Host, Args) when is_binary(Host) orelse is_atom(Host) ->
|
|||||||
%% If a call returns 'stop', no more calls are performed and 'stopped' is returned.
|
%% If a call returns 'stop', no more calls are performed and 'stopped' is returned.
|
||||||
%% If a call returns {stopped, NewVal}, no more calls are performed and NewVal is returned.
|
%% If a call returns {stopped, NewVal}, no more calls are performed and NewVal is returned.
|
||||||
run_fold(Hook, Val, Args) ->
|
run_fold(Hook, Val, Args) ->
|
||||||
run_fold(Hook, global, Val, Args).
|
run_foldx(Hook, global, Val, Args).
|
||||||
|
|
||||||
%% @spec (Hook::atom(), Host, Val, Args) -> Val | stopped | NewVal
|
%% @spec (Hook::atom(), Host, Val, Args) -> Val | stopped | NewVal
|
||||||
%% Host = global | binary()
|
%% Host = global | binary()
|
||||||
run_fold(Hook, Host, Val, Args) when is_binary(Host) orelse is_atom(Host) ->
|
run_fold(Hook, Host, Val, Args) when is_binary(Host) ->
|
||||||
case ets:lookup(hooks, {Hook, Host}) of
|
case run_foldx(Hook, Host, Val, Args) of
|
||||||
|
stopped -> stopped;
|
||||||
|
Val2 -> run_foldx(Hook, global, Val2, Args)
|
||||||
|
end;
|
||||||
|
run_fold(Hook, Host, Val, Args) when Host == global ->
|
||||||
|
run_foldx(Hook, Host, Val, Args).
|
||||||
|
|
||||||
|
run_foldx(Hook, Host, Val, Args) ->
|
||||||
|
case ets:lookup(hooks, {Hook, ejabberd:normalize_host(Host)}) of
|
||||||
[{_, Ls}] ->
|
[{_, Ls}] ->
|
||||||
run_fold1(Ls, Hook, Val, Args);
|
run_fold1(Ls, Hook, Val, Args);
|
||||||
[] ->
|
[] ->
|
||||||
Val
|
case ets:lookup(hooks, {Hook, global}) of
|
||||||
|
[{_, Ls}] ->
|
||||||
|
run_fold1(Ls, Hook, Val, Args);
|
||||||
|
[] ->
|
||||||
|
Val
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -173,7 +199,8 @@ init([]) ->
|
|||||||
%% {stop, Reason, State} (terminate/2 is called)
|
%% {stop, Reason, State} (terminate/2 is called)
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) ->
|
handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) ->
|
||||||
Reply = case ets:lookup(hooks, {Hook, Host}) of
|
NHost = ejabberd:normalize_host(Host),
|
||||||
|
Reply = case ets:lookup(hooks, {Hook, NHost}) of
|
||||||
[{_, Ls}] ->
|
[{_, Ls}] ->
|
||||||
El = {Seq, Module, Function},
|
El = {Seq, Module, Function},
|
||||||
case lists:member(El, Ls) of
|
case lists:member(El, Ls) of
|
||||||
@ -181,12 +208,12 @@ handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) ->
|
|||||||
ok;
|
ok;
|
||||||
false ->
|
false ->
|
||||||
NewLs = lists:merge(Ls, [El]),
|
NewLs = lists:merge(Ls, [El]),
|
||||||
ets:insert(hooks, {{Hook, Host}, NewLs}),
|
ets:insert(hooks, {{Hook, NHost}, NewLs}),
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
[] ->
|
[] ->
|
||||||
NewLs = [{Seq, Module, Function}],
|
NewLs = [{Seq, Module, Function}],
|
||||||
ets:insert(hooks, {{Hook, Host}, NewLs}),
|
ets:insert(hooks, {{Hook, NHost}, NewLs}),
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{reply, Reply, State};
|
{reply, Reply, State};
|
||||||
@ -209,10 +236,11 @@ handle_call({add, Hook, Host, Node, Module, Function, Seq}, _From, State) ->
|
|||||||
end,
|
end,
|
||||||
{reply, Reply, State};
|
{reply, Reply, State};
|
||||||
handle_call({delete, Hook, Host, Module, Function, Seq}, _From, State) ->
|
handle_call({delete, Hook, Host, Module, Function, Seq}, _From, State) ->
|
||||||
Reply = case ets:lookup(hooks, {Hook, Host}) of
|
NHost = ejabberd:normalize_host(Host),
|
||||||
|
Reply = case ets:lookup(hooks, {Hook, NHost}) of
|
||||||
[{_, Ls}] ->
|
[{_, Ls}] ->
|
||||||
NewLs = lists:delete({Seq, Module, Function}, Ls),
|
NewLs = lists:delete({Seq, Module, Function}, Ls),
|
||||||
ets:insert(hooks, {{Hook, Host}, NewLs}),
|
ets:insert(hooks, {{Hook, NHost}, NewLs}),
|
||||||
ok;
|
ok;
|
||||||
[] ->
|
[] ->
|
||||||
ok
|
ok
|
||||||
|
@ -82,7 +82,7 @@ process_iq(From, To, Packet) ->
|
|||||||
case exmpp_iq:xmlel_to_iq(Packet) of
|
case exmpp_iq:xmlel_to_iq(Packet) of
|
||||||
#iq{kind = request, ns = XMLNS} = IQ_Rec ->
|
#iq{kind = request, ns = XMLNS} = IQ_Rec ->
|
||||||
Host = exmpp_jid:prep_domain(To),
|
Host = exmpp_jid:prep_domain(To),
|
||||||
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
|
case ets:lookup(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}) of
|
||||||
[{_, Module, Function}] ->
|
[{_, Module, Function}] ->
|
||||||
ResIQ = Module:Function(From, To, IQ_Rec),
|
ResIQ = Module:Function(From, To, IQ_Rec),
|
||||||
if
|
if
|
||||||
@ -96,8 +96,15 @@ process_iq(From, To, Packet) ->
|
|||||||
gen_iq_handler:handle(Host, Module, Function, Opts,
|
gen_iq_handler:handle(Host, Module, Function, Opts,
|
||||||
From, To, IQ_Rec);
|
From, To, IQ_Rec);
|
||||||
[] ->
|
[] ->
|
||||||
Err = exmpp_iq:error(Packet, 'feature-not-implemented'),
|
case ets:lookup(?IQTABLE, {XMLNS, global}) of
|
||||||
ejabberd_router:route(To, From, Err)
|
[{_, Module, Function, Opts}] ->
|
||||||
|
gen_iq_handler:handle(
|
||||||
|
global, Module, Function, Opts,
|
||||||
|
From, To, IQ_Rec);
|
||||||
|
[] ->
|
||||||
|
Err = exmpp_iq:error(Packet, 'feature-not-implemented'),
|
||||||
|
ejabberd_router:route(To, From, Err)
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
#iq{kind = response} = IQReply ->
|
#iq{kind = response} = IQReply ->
|
||||||
%%IQReply = jlib:iq_query_or_response_info(IQ_Rec),
|
%%IQReply = jlib:iq_query_or_response_info(IQ_Rec),
|
||||||
@ -193,10 +200,10 @@ bounce_resource_packet(From, To, Packet) ->
|
|||||||
init([]) ->
|
init([]) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
ejabberd_router:register_route(Host, {apply, ?MODULE, route}),
|
ejabberd_router:register_route(Host, {apply, ?MODULE, route})
|
||||||
ejabberd_hooks:add(local_send_to_resource_hook, list_to_binary(Host),
|
|
||||||
?MODULE, bounce_resource_packet, 100)
|
|
||||||
end, ?MYHOSTS),
|
end, ?MYHOSTS),
|
||||||
|
ejabberd_hooks:add(local_send_to_resource_hook, global,
|
||||||
|
?MODULE, bounce_resource_packet, 100),
|
||||||
catch ets:new(?IQTABLE, [named_table, public]),
|
catch ets:new(?IQTABLE, [named_table, public]),
|
||||||
mnesia:delete_table(iq_response),
|
mnesia:delete_table(iq_response),
|
||||||
catch ets:new(iq_response, [named_table, public,
|
catch ets:new(iq_response, [named_table, public,
|
||||||
@ -253,21 +260,21 @@ handle_info({route, From, To, Packet}, State) ->
|
|||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
||||||
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
|
ets:insert(?IQTABLE, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function}),
|
||||||
catch mod_disco:register_feature(Host, XMLNS),
|
catch mod_disco:register_feature(Host, XMLNS),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
||||||
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function, Opts}),
|
ets:insert(?IQTABLE, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function, Opts}),
|
||||||
catch mod_disco:register_feature(Host, XMLNS),
|
catch mod_disco:register_feature(Host, XMLNS),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
||||||
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
|
case ets:lookup(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}) of
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ets:delete(?IQTABLE, {XMLNS, Host}),
|
ets:delete(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}),
|
||||||
catch mod_disco:unregister_feature(Host, XMLNS),
|
catch mod_disco:unregister_feature(Host, XMLNS),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(refresh_iq_handlers, State) ->
|
handle_info(refresh_iq_handlers, State) ->
|
||||||
|
@ -27,8 +27,15 @@
|
|||||||
-module(ejabberd_rdbms).
|
-module(ejabberd_rdbms).
|
||||||
-author('alexey@process-one.net').
|
-author('alexey@process-one.net').
|
||||||
|
|
||||||
-export([start/0]).
|
-export([start/0
|
||||||
|
,start_odbc/1
|
||||||
|
,stop_odbc/1
|
||||||
|
,running/1
|
||||||
|
]).
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
-include("ejabberd_config.hrl").
|
||||||
|
-include_lib("stdlib/include/ms_transform.hrl").
|
||||||
|
-define(SUPERVISOR, ejabberd_sup).
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
%% Check if ejabberd has been compiled with ODBC
|
%% Check if ejabberd has been compiled with ODBC
|
||||||
@ -52,22 +59,39 @@ start_hosts() ->
|
|||||||
|
|
||||||
%% Start the ODBC module on the given host
|
%% Start the ODBC module on the given host
|
||||||
start_odbc(Host) ->
|
start_odbc(Host) ->
|
||||||
Supervisor_name = gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
SupervisorName = sup_name(Host),
|
||||||
ChildSpec =
|
ChildSpec =
|
||||||
{Supervisor_name,
|
{SupervisorName,
|
||||||
{ejabberd_odbc_sup, start_link, [Host]},
|
{ejabberd_odbc_sup, start_link, [Host]},
|
||||||
transient,
|
transient,
|
||||||
infinity,
|
infinity,
|
||||||
supervisor,
|
supervisor,
|
||||||
[ejabberd_odbc_sup]},
|
[ejabberd_odbc_sup]},
|
||||||
case supervisor:start_child(ejabberd_sup, ChildSpec) of
|
case supervisor:start_child(?SUPERVISOR, ChildSpec) of
|
||||||
{ok, _PID} ->
|
{ok, _PID} ->
|
||||||
ok;
|
ok;
|
||||||
_Error ->
|
_Error ->
|
||||||
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", [Supervisor_name, _Error]),
|
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", [SupervisorName, _Error]),
|
||||||
start_odbc(Host)
|
start_odbc(Host)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
stop_odbc(Host) ->
|
||||||
|
SupervisorName = sup_name(Host),
|
||||||
|
case running(Host) of
|
||||||
|
false -> ok;
|
||||||
|
true ->
|
||||||
|
case [H || H <- dependent_hosts(Host), ejabberd_hosts:running(H)] of
|
||||||
|
[] ->
|
||||||
|
?INFO_MSG("About to terminate ~p", [SupervisorName]),
|
||||||
|
ok = supervisor:terminate_child(?SUPERVISOR, SupervisorName),
|
||||||
|
ok = supervisor:delete_child(?SUPERVISOR, SupervisorName);
|
||||||
|
RunningHosts ->
|
||||||
|
?WARNING_MSG("Not stopping ODBC for ~p because the virtual hosts ~p are still using it.",
|
||||||
|
[Host, RunningHosts]),
|
||||||
|
{error, still_in_use}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
%% Returns true if we have configured odbc_server for the given host
|
%% Returns true if we have configured odbc_server for the given host
|
||||||
needs_odbc(Host) ->
|
needs_odbc(Host) ->
|
||||||
try
|
try
|
||||||
@ -75,9 +99,32 @@ needs_odbc(Host) ->
|
|||||||
case ejabberd_config:get_local_option({odbc_server, LHost}) of
|
case ejabberd_config:get_local_option({odbc_server, LHost}) of
|
||||||
undefined ->
|
undefined ->
|
||||||
false;
|
false;
|
||||||
_ -> true
|
{host, _} ->
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
true
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
running(Host) ->
|
||||||
|
Supervisors = supervisor:which_children(?SUPERVISOR),
|
||||||
|
SupervisorName = gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
||||||
|
case lists:keysearch(SupervisorName, 1, Supervisors) of
|
||||||
|
false -> false;
|
||||||
|
{value, Cspec} when is_tuple(Cspec) -> true
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
dependent_hosts(Host) ->
|
||||||
|
MS = ets:fun2ms(fun (#local_config{key={odbc_server, DHost},
|
||||||
|
value={host, H}})
|
||||||
|
when H =:= Host ->
|
||||||
|
DHost
|
||||||
|
end),
|
||||||
|
ejabberd_config:search(MS).
|
||||||
|
|
||||||
|
sup_name(Host) ->
|
||||||
|
gen_mod:get_module_proc(Host, ejabberd_odbc_sup).
|
||||||
|
@ -36,9 +36,11 @@
|
|||||||
register_route/2,
|
register_route/2,
|
||||||
register_routes/1,
|
register_routes/1,
|
||||||
unregister_route/1,
|
unregister_route/1,
|
||||||
|
force_unregister_route/1,
|
||||||
unregister_routes/1,
|
unregister_routes/1,
|
||||||
dirty_get_all_routes/0,
|
dirty_get_all_routes/0,
|
||||||
dirty_get_all_domains/0,
|
dirty_get_all_domains/0,
|
||||||
|
read_route/1,
|
||||||
make_id/0
|
make_id/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@ -98,56 +100,24 @@ route_error(From, To, ErrPacket, OrigPacket) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
register_route(Domain) ->
|
register_route({global, Prefix}) ->
|
||||||
|
ejabberd_global_router:register_route(Prefix);
|
||||||
|
register_route(Domain) when is_list(Domain) ->
|
||||||
register_route(Domain, undefined).
|
register_route(Domain, undefined).
|
||||||
|
|
||||||
register_route(Domain, LocalHint) ->
|
register_route(Domain, LocalHint) ->
|
||||||
try
|
try
|
||||||
LDomain = exmpp_stringprep:nameprep(Domain),
|
LDomain = exmpp_stringprep:nameprep(Domain),
|
||||||
LDomainB = list_to_binary(LDomain),
|
LDomainB = list_to_binary(LDomain),
|
||||||
Pid = self(),
|
Pid = self(),
|
||||||
case get_component_number(LDomain) of
|
case get_component_number(LDomain) of
|
||||||
undefined ->
|
undefined ->
|
||||||
F = fun() ->
|
mnesia:transaction(fun register_simple_route/3, [LDomainB, Pid, LocalHint]);
|
||||||
mnesia:write(#route{domain = LDomainB,
|
N ->
|
||||||
pid = Pid,
|
mnesia:transaction(fun register_balanced_route/3, [LDomainB, Pid, N])
|
||||||
local_hint = LocalHint})
|
end
|
||||||
end,
|
|
||||||
mnesia:transaction(F);
|
|
||||||
N ->
|
|
||||||
F = fun() ->
|
|
||||||
case mnesia:wread({route, LDomainB}) of
|
|
||||||
[] ->
|
|
||||||
mnesia:write(
|
|
||||||
#route{domain = LDomainB,
|
|
||||||
pid = Pid,
|
|
||||||
local_hint = 1}),
|
|
||||||
lists:foreach(
|
|
||||||
fun(I) ->
|
|
||||||
mnesia:write(
|
|
||||||
#route{domain = LDomainB,
|
|
||||||
pid = undefined,
|
|
||||||
local_hint = I})
|
|
||||||
end, lists:seq(2, N));
|
|
||||||
Rs ->
|
|
||||||
lists:any(
|
|
||||||
fun(#route{pid = undefined,
|
|
||||||
local_hint = I} = R) ->
|
|
||||||
mnesia:write(
|
|
||||||
#route{domain = LDomainB,
|
|
||||||
pid = Pid,
|
|
||||||
local_hint = I}),
|
|
||||||
mnesia:delete_object(R),
|
|
||||||
true;
|
|
||||||
(_) ->
|
|
||||||
false
|
|
||||||
end, Rs)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F)
|
|
||||||
end
|
|
||||||
catch
|
catch
|
||||||
_ ->
|
_ ->
|
||||||
erlang:error({invalid_domain, Domain})
|
erlang:error({invalid_domain, Domain})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -156,53 +126,112 @@ register_routes(Domains) ->
|
|||||||
register_route(Domain)
|
register_route(Domain)
|
||||||
end, Domains).
|
end, Domains).
|
||||||
|
|
||||||
unregister_route(Domain) ->
|
register_simple_route(LDomain, Pid, LocalHint) ->
|
||||||
|
mnesia:write(#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
local_hint = LocalHint}).
|
||||||
|
|
||||||
|
register_balanced_route(LDomain, Pid, N) ->
|
||||||
|
case mnesia:read({route, LDomain}) of
|
||||||
|
[] ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
local_hint = 1}),
|
||||||
|
lists:foreach(
|
||||||
|
fun(I) ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = undefined,
|
||||||
|
local_hint = I})
|
||||||
|
end, lists:seq(2, N));
|
||||||
|
Rs ->
|
||||||
|
lists:any(
|
||||||
|
fun(#route{pid = undefined,
|
||||||
|
local_hint = I} = R) ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
local_hint = I}),
|
||||||
|
mnesia:delete_object(R),
|
||||||
|
true;
|
||||||
|
(_) ->
|
||||||
|
false
|
||||||
|
end, Rs)
|
||||||
|
end.
|
||||||
|
|
||||||
|
unregister_route({global, Prefix}) ->
|
||||||
|
ejabberd_global_router:unregister_route(Prefix);
|
||||||
|
unregister_route(Domain) when is_list(Domain) ->
|
||||||
try
|
try
|
||||||
LDomain = exmpp_stringprep:nameprep(Domain),
|
LDomain = exmpp_stringprep:nameprep(Domain),
|
||||||
LDomainB = list_to_binary(LDomain),
|
LDomainB = list_to_binary(LDomain),
|
||||||
Pid = self(),
|
Pid = self(),
|
||||||
case get_component_number(LDomain) of
|
case get_component_number(LDomain) of
|
||||||
undefined ->
|
undefined ->
|
||||||
F = fun() ->
|
mnesia:transaction(fun delete_simple_route/2, [LDomainB, Pid]);
|
||||||
case mnesia:match_object(
|
|
||||||
#route{domain = LDomainB,
|
|
||||||
pid = Pid,
|
|
||||||
_ = '_'}) of
|
|
||||||
[R] ->
|
|
||||||
mnesia:delete_object(R);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F);
|
|
||||||
_ ->
|
_ ->
|
||||||
F = fun() ->
|
mnesia:transaction(fun delete_balanced_route/2, [LDomainB, Pid])
|
||||||
case mnesia:match_object(#route{domain=LDomainB,
|
|
||||||
pid = Pid,
|
|
||||||
_ = '_'}) of
|
|
||||||
[R] ->
|
|
||||||
I = R#route.local_hint,
|
|
||||||
mnesia:write(
|
|
||||||
#route{domain = LDomainB,
|
|
||||||
pid = undefined,
|
|
||||||
local_hint = I}),
|
|
||||||
mnesia:delete_object(R);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F)
|
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
_ ->
|
_ ->
|
||||||
erlang:error({invalid_domain, Domain})
|
erlang:error({invalid_domain, Domain})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
delete_simple_route(LDomain, Pid) ->
|
||||||
|
case mnesia:match_object(#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
_ = '_'}) of
|
||||||
|
[R] ->
|
||||||
|
mnesia:delete_object(R);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
delete_balanced_route(LDomain, Pid) ->
|
||||||
|
case mnesia:match_object(#route{domain=LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
_ = '_'}) of
|
||||||
|
[R] ->
|
||||||
|
I = R#route.local_hint,
|
||||||
|
ok = mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = undefined,
|
||||||
|
local_hint = I}),
|
||||||
|
mnesia:delete_object(R);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
force_unregister_route(Domain) ->
|
||||||
|
case jlib:nameprep(Domain) of
|
||||||
|
error ->
|
||||||
|
erlang:error({invalid_domain, Domain});
|
||||||
|
LDomain ->
|
||||||
|
F = fun() ->
|
||||||
|
case mnesia:match_object(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
_ = '_'}) of
|
||||||
|
Rs when is_list(Rs) ->
|
||||||
|
lists:foreach(fun(R) ->
|
||||||
|
mnesia:delete_object(R)
|
||||||
|
end, Rs);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F)
|
||||||
|
end.
|
||||||
|
|
||||||
unregister_routes(Domains) ->
|
unregister_routes(Domains) ->
|
||||||
lists:foreach(fun(Domain) ->
|
lists:foreach(fun(Domain) ->
|
||||||
unregister_route(Domain)
|
unregister_route(Domain)
|
||||||
end, Domains).
|
end, Domains).
|
||||||
|
|
||||||
|
read_route(Domain) ->
|
||||||
|
[{D,P,H}
|
||||||
|
|| #route{domain=D, pid=P, local_hint=H} <- mnesia:dirty_read({route, Domain})].
|
||||||
|
|
||||||
dirty_get_all_routes() ->
|
dirty_get_all_routes() ->
|
||||||
lists:usort(
|
lists:usort(
|
||||||
@ -376,10 +405,16 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
|||||||
case ejabberd_hooks:run_fold(filter_packet,
|
case ejabberd_hooks:run_fold(filter_packet,
|
||||||
{OrigFrom, OrigTo, OrigPacket}, []) of
|
{OrigFrom, OrigTo, OrigPacket}, []) of
|
||||||
{From, To, Packet} ->
|
{From, To, Packet} ->
|
||||||
LDomain = exmpp_jid:prep_domain(To),
|
LDstDomain = exmpp_jid:prep_domain_as_list(To),
|
||||||
case mnesia:dirty_read(route, LDomain) of
|
Destination = ejabberd:normalize_host(LDstDomain),
|
||||||
|
case mnesia:dirty_read(route, list_to_binary(Destination)) of
|
||||||
[] ->
|
[] ->
|
||||||
ejabberd_s2s:route(From, To, Packet);
|
case ejabberd_global_router:find_route(Destination) of
|
||||||
|
no_route ->
|
||||||
|
ejabberd_s2s:route(From, To, Packet);
|
||||||
|
Route ->
|
||||||
|
ejabberd_global_router:route(Route, From, To, Packet)
|
||||||
|
end;
|
||||||
[R] ->
|
[R] ->
|
||||||
Pid = R#route.pid,
|
Pid = R#route.pid,
|
||||||
if
|
if
|
||||||
@ -396,7 +431,6 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
|||||||
drop
|
drop
|
||||||
end;
|
end;
|
||||||
Rs ->
|
Rs ->
|
||||||
LDstDomain = exmpp_jid:prep_domain_as_list(To),
|
|
||||||
Value = case ejabberd_config:get_local_option(
|
Value = case ejabberd_config:get_local_option(
|
||||||
{domain_balancing, LDstDomain}) of
|
{domain_balancing, LDstDomain}) of
|
||||||
undefined -> now();
|
undefined -> now();
|
||||||
|
@ -353,6 +353,12 @@ init([]) ->
|
|||||||
mnesia:add_table_index(session, us),
|
mnesia:add_table_index(session, us),
|
||||||
mnesia:add_table_copy(session, node(), ram_copies),
|
mnesia:add_table_copy(session, node(), ram_copies),
|
||||||
ets:new(sm_iqtable, [named_table]),
|
ets:new(sm_iqtable, [named_table]),
|
||||||
|
ejabberd_hooks:add(roster_in_subscription, global,
|
||||||
|
ejabberd_sm, check_in_subscription, 20),
|
||||||
|
ejabberd_hooks:add(offline_message_hook, global,
|
||||||
|
ejabberd_sm, bounce_offline_message, 100),
|
||||||
|
ejabberd_hooks:add(remove_user, global,
|
||||||
|
ejabberd_sm, disconnect_removed_user, 100),
|
||||||
ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100),
|
ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
@ -417,19 +423,19 @@ handle_info({route, From, To, Packet}, State) ->
|
|||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
||||||
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function}),
|
ets:insert(sm_iqtable, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
||||||
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function, Opts}),
|
ets:insert(sm_iqtable, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function, Opts}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
||||||
case ets:lookup(sm_iqtable, {XMLNS, Host}) of
|
case ets:lookup(sm_iqtable, {XMLNS, ejabberd:normalize_host(Host)}) of
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ets:delete(sm_iqtable, {XMLNS, Host}),
|
ets:delete(sm_iqtable, {XMLNS, ejabberd:normalize_host(Host)}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) ->
|
handle_info(_Info, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
@ -763,7 +769,7 @@ process_iq(From, To, Packet) ->
|
|||||||
case exmpp_iq:xmlel_to_iq(Packet) of
|
case exmpp_iq:xmlel_to_iq(Packet) of
|
||||||
#iq{kind = request, ns = XMLNS} = IQ_Rec ->
|
#iq{kind = request, ns = XMLNS} = IQ_Rec ->
|
||||||
LServer = exmpp_jid:prep_domain(To),
|
LServer = exmpp_jid:prep_domain(To),
|
||||||
case ets:lookup(sm_iqtable, {XMLNS, LServer}) of
|
case ets:lookup(sm_iqtable, {XMLNS, ejabberd:normalize_host(LServer)}) of
|
||||||
[{_, Module, Function}] ->
|
[{_, Module, Function}] ->
|
||||||
ResIQ = Module:Function(From, To, IQ_Rec),
|
ResIQ = Module:Function(From, To, IQ_Rec),
|
||||||
if
|
if
|
||||||
@ -774,11 +780,17 @@ process_iq(From, To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:handle(LServer,
|
gen_iq_handler:handle(LServer,
|
||||||
Module, Function, Opts, From, To, IQ_Rec);
|
Module, Function, Opts, From, To, IQ_Rec);
|
||||||
[] ->
|
[] ->
|
||||||
Err = exmpp_iq:error(Packet, 'service-unavailable'),
|
case ets:lookup(sm_iqtable, {XMLNS, global}) of
|
||||||
ejabberd_router:route(To, From, Err)
|
[{_, Module, Function, Opts}] ->
|
||||||
|
gen_iq_handler:handle(global, Module, Function, Opts,
|
||||||
|
From, To, IQ_Rec);
|
||||||
|
[] ->
|
||||||
|
Err = exmpp_iq:error(Packet, 'service-unavailable'),
|
||||||
|
ejabberd_router:route(To, From, Err)
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
#iq{kind = response} ->
|
#iq{kind = response} ->
|
||||||
ok;
|
ok;
|
||||||
|
@ -42,13 +42,13 @@ init([]) ->
|
|||||||
brutal_kill,
|
brutal_kill,
|
||||||
worker,
|
worker,
|
||||||
[ejabberd_hooks]},
|
[ejabberd_hooks]},
|
||||||
SystemMonitor =
|
GlobalRouter =
|
||||||
{ejabberd_system_monitor,
|
{ejabberd_global_router,
|
||||||
{ejabberd_system_monitor, start_link, []},
|
{ejabberd_global_router, start_link, []},
|
||||||
permanent,
|
permanent,
|
||||||
brutal_kill,
|
brutal_kill,
|
||||||
worker,
|
worker,
|
||||||
[ejabberd_system_monitor]},
|
[ejabberd_global_router]},
|
||||||
Router =
|
Router =
|
||||||
{ejabberd_router,
|
{ejabberd_router,
|
||||||
{ejabberd_router, start_link, []},
|
{ejabberd_router, start_link, []},
|
||||||
@ -137,6 +137,13 @@ init([]) ->
|
|||||||
infinity,
|
infinity,
|
||||||
supervisor,
|
supervisor,
|
||||||
[ejabberd_tmp_sup]},
|
[ejabberd_tmp_sup]},
|
||||||
|
Hosts =
|
||||||
|
{ejabberd_hosts,
|
||||||
|
{ejabberd_hosts, start_link, []},
|
||||||
|
permanent,
|
||||||
|
brutal_kill,
|
||||||
|
worker,
|
||||||
|
[ejabberd_hosts]},
|
||||||
HTTPSupervisor =
|
HTTPSupervisor =
|
||||||
{ejabberd_http_sup,
|
{ejabberd_http_sup,
|
||||||
{ejabberd_tmp_sup, start_link,
|
{ejabberd_tmp_sup, start_link,
|
||||||
@ -186,8 +193,8 @@ init([]) ->
|
|||||||
[ejabberd_cluster]},
|
[ejabberd_cluster]},
|
||||||
{ok, {{one_for_one, 10, 1},
|
{ok, {{one_for_one, 10, 1},
|
||||||
[Hooks,
|
[Hooks,
|
||||||
|
GlobalRouter,
|
||||||
Cluster,
|
Cluster,
|
||||||
SystemMonitor,
|
|
||||||
Router,
|
Router,
|
||||||
Router_multicast,
|
Router_multicast,
|
||||||
SM,
|
SM,
|
||||||
@ -199,6 +206,7 @@ init([]) ->
|
|||||||
S2SInSupervisor,
|
S2SInSupervisor,
|
||||||
S2SOutSupervisor,
|
S2SOutSupervisor,
|
||||||
ServiceSupervisor,
|
ServiceSupervisor,
|
||||||
|
Hosts,
|
||||||
HTTPSupervisor,
|
HTTPSupervisor,
|
||||||
HTTPPollSupervisor,
|
HTTPPollSupervisor,
|
||||||
IQSupervisor,
|
IQSupervisor,
|
||||||
|
@ -57,8 +57,9 @@ if [ "$ERLANG_NODE_ARG" != "" ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# check the proper system user is used
|
# check the proper system user is used
|
||||||
ID=`id -g`
|
if [ `uname -s` = "SunOS" ]; then IDCMD=/usr/xpg4/bin/id; else IDCMD=id; fi
|
||||||
GIDS=`id -G`
|
ID=`$IDCMD -g`
|
||||||
|
EJID=`$IDCMD -g $INSTALLUSER`
|
||||||
EJID=`id -g $INSTALLUSER`
|
EJID=`id -g $INSTALLUSER`
|
||||||
EXEC_CMD="false"
|
EXEC_CMD="false"
|
||||||
for GID in $GIDS; do
|
for GID in $GIDS; do
|
||||||
@ -77,10 +78,13 @@ fi
|
|||||||
NAME=-name
|
NAME=-name
|
||||||
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname
|
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname
|
||||||
|
|
||||||
if [ "$FIREWALL_WINDOW" = "" ] ; then
|
KERNEL_OPTS=""
|
||||||
KERNEL_OPTS=""
|
if [ "$FIREWALL_WINDOW" != "" ] ; then
|
||||||
else
|
KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
|
||||||
KERNEL_OPTS="-kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
|
fi
|
||||||
|
|
||||||
|
if [ "$DIST_INTERFACE" != "" ] ; then
|
||||||
|
KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${DIST_INTERFACE}\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
|
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
|
||||||
@ -146,7 +150,7 @@ start ()
|
|||||||
$KERNEL_OPTS \
|
$KERNEL_OPTS \
|
||||||
-s ejabberd \
|
-s ejabberd \
|
||||||
-sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \
|
-sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \
|
||||||
$ERLANG_OPTS $ARGS \"$@\" $ERL_ARGS"
|
$ERLANG_OPTS -- $ARGS \"$@\" $ERL_ARGS"
|
||||||
}
|
}
|
||||||
|
|
||||||
# attach to server
|
# attach to server
|
||||||
@ -177,7 +181,7 @@ debug ()
|
|||||||
$NAME debug-${TTY}-${ERLANG_NODE} \
|
$NAME debug-${TTY}-${ERLANG_NODE} \
|
||||||
-remsh $ERLANG_NODE \
|
-remsh $ERLANG_NODE \
|
||||||
$KERNEL_OPTS \
|
$KERNEL_OPTS \
|
||||||
$ERLANG_OPTS $ARGS \"$@\" $ERL_ARGS"
|
$ERLANG_OPTS -- $ARGS \"$@\" $ERL_ARGS"
|
||||||
}
|
}
|
||||||
|
|
||||||
# start interactive server
|
# start interactive server
|
||||||
@ -209,7 +213,7 @@ live ()
|
|||||||
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
|
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
|
||||||
$KERNEL_OPTS \
|
$KERNEL_OPTS \
|
||||||
-s ejabberd \
|
-s ejabberd \
|
||||||
$ERLANG_OPTS $ARGS \"$@\" $ERL_ARGS"
|
$ERLANG_OPTS -- $ARGS \"$@\" $ERL_ARGS"
|
||||||
}
|
}
|
||||||
|
|
||||||
etop()
|
etop()
|
||||||
|
@ -261,7 +261,7 @@ export_private_storage(ServerS, Output) ->
|
|||||||
LXMLNS = ejabberd_odbc:escape(atom_to_list(XMLNS)),
|
LXMLNS = ejabberd_odbc:escape(atom_to_list(XMLNS)),
|
||||||
SData = ejabberd_odbc:escape(
|
SData = ejabberd_odbc:escape(
|
||||||
exmpp_xml:document_to_list(Data)),
|
exmpp_xml:document_to_list(Data)),
|
||||||
odbc_queries:set_private_data_sql(Username, LXMLNS, SData);
|
odbc_queries:set_private_data_sql(LServer, Username, LXMLNS, SData);
|
||||||
(_Host, _R) ->
|
(_Host, _R) ->
|
||||||
[]
|
[]
|
||||||
end).
|
end).
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
loaded_modules_with_opts/1,
|
loaded_modules_with_opts/1,
|
||||||
get_hosts/2,
|
get_hosts/2,
|
||||||
get_module_proc/2,
|
get_module_proc/2,
|
||||||
|
expand_host_name/3,
|
||||||
is_loaded/2]).
|
is_loaded/2]).
|
||||||
|
|
||||||
-export([behaviour_info/1]).
|
-export([behaviour_info/1]).
|
||||||
@ -192,6 +193,9 @@ loaded_modules_with_opts(Host) ->
|
|||||||
[],
|
[],
|
||||||
[{{'$1', '$2'}}]}]).
|
[{{'$1', '$2'}}]}]).
|
||||||
|
|
||||||
|
set_module_opts_mnesia(global, _Module, _Opts) ->
|
||||||
|
%% Modules on the global host are usually static, so we shouldn't manipulate them.
|
||||||
|
ok;
|
||||||
set_module_opts_mnesia(Host, Module, Opts) ->
|
set_module_opts_mnesia(Host, Module, Opts) ->
|
||||||
Modules = case ejabberd_config:get_local_option({modules, Host}) of
|
Modules = case ejabberd_config:get_local_option({modules, Host}) of
|
||||||
undefined ->
|
undefined ->
|
||||||
@ -203,6 +207,9 @@ set_module_opts_mnesia(Host, Module, Opts) ->
|
|||||||
Modules2 = [{Module, Opts} | Modules1],
|
Modules2 = [{Module, Opts} | Modules1],
|
||||||
ejabberd_config:add_local_option({modules, Host}, Modules2).
|
ejabberd_config:add_local_option({modules, Host}, Modules2).
|
||||||
|
|
||||||
|
del_module_mnesia(global, _Module) ->
|
||||||
|
%% Modules on the global host are usually static, so we shouldn't manipulate them.
|
||||||
|
ok;
|
||||||
del_module_mnesia(Host, Module) ->
|
del_module_mnesia(Host, Module) ->
|
||||||
Modules = case ejabberd_config:get_local_option({modules, Host}) of
|
Modules = case ejabberd_config:get_local_option({modules, Host}) of
|
||||||
undefined ->
|
undefined ->
|
||||||
@ -226,6 +233,8 @@ get_hosts(Opts, Prefix) ->
|
|||||||
Hosts
|
Hosts
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
get_module_proc(global, Base) ->
|
||||||
|
list_to_atom(atom_to_list(Base) ++ "__global");
|
||||||
get_module_proc(Host, {frontend, Base}) ->
|
get_module_proc(Host, {frontend, Base}) ->
|
||||||
get_module_proc("frontend_" ++ Host, Base);
|
get_module_proc("frontend_" ++ Host, Base);
|
||||||
get_module_proc(Host, Base) ->
|
get_module_proc(Host, Base) ->
|
||||||
@ -234,3 +243,11 @@ get_module_proc(Host, Base) ->
|
|||||||
is_loaded(Host, Module) ->
|
is_loaded(Host, Module) ->
|
||||||
ets:member(ejabberd_modules, {Module, Host}).
|
ets:member(ejabberd_modules, {Module, Host}).
|
||||||
|
|
||||||
|
expand_host_name(Host, Opts, DefaultPrefix) ->
|
||||||
|
case Host of
|
||||||
|
global ->
|
||||||
|
{global, gen_mod:get_opt(prefix, Opts, DefaultPrefix)};
|
||||||
|
_ ->
|
||||||
|
gen_mod:get_opt_host(Host, Opts, DefaultPrefix ++ ".@HOST@")
|
||||||
|
end.
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
%% External exports
|
%% External exports
|
||||||
-export([start/1, start_link/2,
|
-export([start/1, start_link/2,
|
||||||
|
running/1,
|
||||||
sql_query/2,
|
sql_query/2,
|
||||||
sql_query_t/1,
|
sql_query_t/1,
|
||||||
sql_transaction/2,
|
sql_transaction/2,
|
||||||
@ -106,6 +107,14 @@ sql_query_on_all_connections(Host, Query) ->
|
|||||||
erlang:now()}, ?TRANSACTION_TIMEOUT) end,
|
erlang:now()}, ?TRANSACTION_TIMEOUT) end,
|
||||||
lists:map(F, ejabberd_odbc_sup:get_pids(Host)).
|
lists:map(F, ejabberd_odbc_sup:get_pids(Host)).
|
||||||
|
|
||||||
|
%% Predicate returning true if there is an odbc process running for
|
||||||
|
%% host Host, false otherwise.
|
||||||
|
running(Host) ->
|
||||||
|
case catch ejabberd_odbc_sup:get_random_pid(Host) of
|
||||||
|
P when is_pid(P) -> true;
|
||||||
|
{'EXIT', {noproc, _}} -> false
|
||||||
|
end.
|
||||||
|
|
||||||
%% SQL transaction based on a list of queries
|
%% SQL transaction based on a list of queries
|
||||||
%% This function automatically
|
%% This function automatically
|
||||||
sql_transaction(Host, Queries) when is_list(Queries) ->
|
sql_transaction(Host, Queries) when is_list(Queries) ->
|
||||||
@ -497,7 +506,11 @@ pgsql_to_odbc({ok, PGSQLResult}) ->
|
|||||||
|
|
||||||
pgsql_item_to_odbc({"SELECT", Rows, Recs}) ->
|
pgsql_item_to_odbc({"SELECT", Rows, Recs}) ->
|
||||||
{selected,
|
{selected,
|
||||||
[element(1, Row) || Row <- Rows],
|
[case Row of
|
||||||
|
{desc, _, Col, _, _, _, _, _} -> Col; % Recent pgsql driver API change.
|
||||||
|
_ -> element(1, Row)
|
||||||
|
end
|
||||||
|
|| Row <- Rows],
|
||||||
[list_to_tuple(Rec) || Rec <- Recs]};
|
[list_to_tuple(Rec) || Rec <- Recs]};
|
||||||
pgsql_item_to_odbc("INSERT " ++ OIDN) ->
|
pgsql_item_to_odbc("INSERT " ++ OIDN) ->
|
||||||
[_OID, N] = string:tokens(OIDN, " "),
|
[_OID, N] = string:tokens(OIDN, " "),
|
||||||
@ -555,6 +568,7 @@ log(Level, Format, Args) ->
|
|||||||
?ERROR_MSG(Format, Args)
|
?ERROR_MSG(Format, Args)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% TODO: update this function to handle the case clase {host, VhostName}
|
||||||
db_opts(Host) ->
|
db_opts(Host) ->
|
||||||
case ejabberd_config:get_local_option({odbc_server, Host}) of
|
case ejabberd_config:get_local_option({odbc_server, Host}) of
|
||||||
%% Default pgsql port
|
%% Default pgsql port
|
||||||
|
@ -100,11 +100,16 @@ init([Host]) ->
|
|||||||
end, lists:seq(1, PoolSize))}}.
|
end, lists:seq(1, PoolSize))}}.
|
||||||
|
|
||||||
get_pids(Host) ->
|
get_pids(Host) ->
|
||||||
Rs = mnesia:dirty_read(sql_pool, Host),
|
case ejabberd_config:get_local_option({odbc_server, Host}) of
|
||||||
[R#sql_pool.pid || R <- Rs].
|
{host, Host1} ->
|
||||||
|
get_pids(Host1);
|
||||||
|
_ ->
|
||||||
|
Rs = mnesia:dirty_read(sql_pool, Host),
|
||||||
|
[R#sql_pool.pid || R <- Rs]
|
||||||
|
end.
|
||||||
|
|
||||||
get_random_pid(Host) ->
|
get_random_pid(Host) ->
|
||||||
Pids = get_pids(Host),
|
Pids = get_pids(ejabberd:normalize_host(Host)),
|
||||||
lists:nth(erlang:phash(now(), length(Pids)), Pids).
|
lists:nth(erlang:phash(now(), length(Pids)), Pids).
|
||||||
|
|
||||||
add_pid(Host, Pid) ->
|
add_pid(Host, Pid) ->
|
||||||
|
@ -20,21 +20,35 @@
|
|||||||
-- Needs MySQL (at least 4.0.x) with innodb back-end
|
-- Needs MySQL (at least 4.0.x) with innodb back-end
|
||||||
SET table_type=InnoDB;
|
SET table_type=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE hosts (
|
||||||
|
clusterid integer NOT NULL,
|
||||||
|
host varchar(250) NOT NULL PRIMARY KEY,
|
||||||
|
config text NOT NULL
|
||||||
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
|
INSERT INTO hosts (clusterid, host, config)
|
||||||
|
VALUES (1, 'localhost', '');
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
username varchar(250) PRIMARY KEY,
|
host varchar(250) NOT NULL,
|
||||||
|
username varchar(250) NOT NULL,
|
||||||
password text NOT NULL,
|
password text NOT NULL,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE last (
|
CREATE TABLE last (
|
||||||
username varchar(250) PRIMARY KEY,
|
host varchar(250) NOT NULL,
|
||||||
|
username varchar(250) NOT NULL,
|
||||||
seconds text NOT NULL,
|
seconds text NOT NULL,
|
||||||
state text NOT NULl
|
state text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE rosterusers (
|
CREATE TABLE rosterusers (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
jid varchar(250) NOT NULL,
|
jid varchar(250) NOT NULL,
|
||||||
nick text NOT NULL,
|
nick text NOT NULL,
|
||||||
@ -44,42 +58,44 @@ CREATE TABLE rosterusers (
|
|||||||
server character(1) NOT NULL,
|
server character(1) NOT NULL,
|
||||||
subscribe text NOT NULL,
|
subscribe text NOT NULL,
|
||||||
type text,
|
type text,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host(75), username(75), jid(75))
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers(username(75), jid(75));
|
|
||||||
CREATE INDEX i_rosteru_username ON rosterusers(username);
|
CREATE INDEX i_rosteru_username ON rosterusers(username);
|
||||||
CREATE INDEX i_rosteru_jid ON rosterusers(jid);
|
CREATE INDEX i_rosteru_jid ON rosterusers(jid);
|
||||||
|
|
||||||
CREATE TABLE rostergroups (
|
CREATE TABLE rostergroups (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
jid varchar(250) NOT NULL,
|
jid varchar(250) NOT NULL,
|
||||||
grp text NOT NULL
|
grp text NOT NULL,
|
||||||
|
PRIMARY KEY (host(75), username(75), jid(75))
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups(username(75), jid(75));
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE spool (
|
CREATE TABLE spool (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
xml text NOT NULL,
|
xml text NOT NULL,
|
||||||
seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host, username, seq)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE INDEX i_despool USING BTREE ON spool(username);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE vcard (
|
CREATE TABLE vcard (
|
||||||
username varchar(250) PRIMARY KEY,
|
host varchar(250) NOT NULL,
|
||||||
|
username varchar(250) NOT NULL,
|
||||||
vcard text NOT NULL,
|
vcard text NOT NULL,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE vcard_search (
|
CREATE TABLE vcard_search (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
lusername varchar(250) PRIMARY KEY,
|
lusername varchar(250) NOT NULL,
|
||||||
fn text NOT NULL,
|
fn text NOT NULL,
|
||||||
lfn varchar(250) NOT NULL,
|
lfn varchar(250) NOT NULL,
|
||||||
family text NOT NULL,
|
family text NOT NULL,
|
||||||
@ -101,7 +117,8 @@ CREATE TABLE vcard_search (
|
|||||||
orgname text NOT NULL,
|
orgname text NOT NULL,
|
||||||
lorgname varchar(250) NOT NULL,
|
lorgname varchar(250) NOT NULL,
|
||||||
orgunit text NOT NULL,
|
orgunit text NOT NULL,
|
||||||
lorgunit varchar(250) NOT NULL
|
lorgunit varchar(250) NOT NULL,
|
||||||
|
PRIMARY KEY (host, lusername)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
||||||
@ -117,20 +134,21 @@ CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
|
|||||||
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
||||||
|
|
||||||
CREATE TABLE privacy_default_list (
|
CREATE TABLE privacy_default_list (
|
||||||
username varchar(250) PRIMARY KEY,
|
host varchar(250) NOT NULL,
|
||||||
name varchar(250) NOT NULL
|
username varchar(250),
|
||||||
|
name varchar(250) NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE TABLE privacy_list (
|
CREATE TABLE privacy_list (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
name varchar(250) NOT NULL,
|
name varchar(250) NOT NULL,
|
||||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host, username, name)
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE INDEX i_privacy_list_username USING BTREE ON privacy_list(username);
|
|
||||||
CREATE UNIQUE INDEX i_privacy_list_username_name USING BTREE ON privacy_list (username(75), name(75));
|
|
||||||
|
|
||||||
CREATE TABLE privacy_list_data (
|
CREATE TABLE privacy_list_data (
|
||||||
id bigint,
|
id bigint,
|
||||||
t character(1) NOT NULL,
|
t character(1) NOT NULL,
|
||||||
@ -145,14 +163,15 @@ CREATE TABLE privacy_list_data (
|
|||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE TABLE private_storage (
|
CREATE TABLE private_storage (
|
||||||
|
host varchar(250) NOT NULL,
|
||||||
username varchar(250) NOT NULL,
|
username varchar(250) NOT NULL,
|
||||||
namespace varchar(250) NOT NULL,
|
namespace varchar(250) NOT NULL,
|
||||||
data text NOT NULL,
|
data text NOT NULL,
|
||||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (host(75), username(75), namespace(75))
|
||||||
) CHARACTER SET utf8;
|
) CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE INDEX i_private_storage_username USING BTREE ON private_storage(username);
|
CREATE INDEX i_private_storage_username USING BTREE ON private_storage(username);
|
||||||
CREATE UNIQUE INDEX i_private_storage_username_namespace USING BTREE ON private_storage(username(75), namespace(75));
|
|
||||||
|
|
||||||
-- Not tested in mysql
|
-- Not tested in mysql
|
||||||
CREATE TABLE roster_version (
|
CREATE TABLE roster_version (
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
list_users/2,
|
list_users/2,
|
||||||
users_number/1,
|
users_number/1,
|
||||||
users_number/2,
|
users_number/2,
|
||||||
add_spool_sql/2,
|
add_spool_sql/3,
|
||||||
add_spool/2,
|
add_spool/2,
|
||||||
get_and_del_spool_msg_t/2,
|
get_and_del_spool_msg_t/2,
|
||||||
del_spool_msg/2,
|
del_spool_msg/2,
|
||||||
@ -52,27 +52,27 @@
|
|||||||
get_roster_by_jid/3,
|
get_roster_by_jid/3,
|
||||||
get_rostergroup_by_jid/3,
|
get_rostergroup_by_jid/3,
|
||||||
del_roster/3,
|
del_roster/3,
|
||||||
del_roster_sql/2,
|
del_roster_sql/3,
|
||||||
update_roster/5,
|
update_roster/5,
|
||||||
update_roster_sql/4,
|
update_roster_sql/5,
|
||||||
roster_subscribe/4,
|
roster_subscribe/4,
|
||||||
get_subscription/3,
|
get_subscription/3,
|
||||||
set_private_data/4,
|
set_private_data/4,
|
||||||
set_private_data_sql/3,
|
set_private_data_sql/4,
|
||||||
get_private_data/3,
|
get_private_data/3,
|
||||||
del_user_private_storage/2,
|
del_user_private_storage/2,
|
||||||
get_default_privacy_list/2,
|
get_default_privacy_list/2,
|
||||||
get_default_privacy_list_t/1,
|
get_default_privacy_list_t/2,
|
||||||
get_privacy_list_names/2,
|
get_privacy_list_names/2,
|
||||||
get_privacy_list_names_t/1,
|
get_privacy_list_names_t/2,
|
||||||
get_privacy_list_id/3,
|
get_privacy_list_id/3,
|
||||||
get_privacy_list_id_t/2,
|
get_privacy_list_id_t/3,
|
||||||
get_privacy_list_data/3,
|
get_privacy_list_data/3,
|
||||||
get_privacy_list_data_by_id/2,
|
get_privacy_list_data_by_id/2,
|
||||||
set_default_privacy_list/2,
|
set_default_privacy_list/3,
|
||||||
unset_default_privacy_list/2,
|
unset_default_privacy_list/2,
|
||||||
remove_privacy_list/2,
|
remove_privacy_list/3,
|
||||||
add_privacy_list/2,
|
add_privacy_list/3,
|
||||||
set_privacy_list/2,
|
set_privacy_list/2,
|
||||||
del_privacy_lists/3,
|
del_privacy_lists/3,
|
||||||
set_vcard/26,
|
set_vcard/26,
|
||||||
@ -122,65 +122,75 @@ sql_transaction(LServer, F) ->
|
|||||||
ejabberd_odbc:sql_transaction(LServer, F).
|
ejabberd_odbc:sql_transaction(LServer, F).
|
||||||
|
|
||||||
get_last(LServer, Username) ->
|
get_last(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select seconds, state from last "
|
["select seconds, state from last "
|
||||||
"where username='", Username, "'"]).
|
"where username='", Username, "' and host='", Host, "'"]).
|
||||||
|
|
||||||
set_last_t(LServer, Username, Seconds, State) ->
|
set_last_t(LServer, Username, Seconds, State) ->
|
||||||
|
Host = escape(LServer),
|
||||||
%% MREMOND: I think this should be turn into a non transactional behaviour
|
%% MREMOND: I think this should be turn into a non transactional behaviour
|
||||||
ejabberd_odbc:sql_transaction(
|
ejabberd_odbc:sql_transaction(
|
||||||
LServer,
|
LServer,
|
||||||
fun() ->
|
fun() ->
|
||||||
update_t("last", ["username", "seconds", "state"],
|
update_t("last", ["username", "host", "seconds", "state"],
|
||||||
[Username, Seconds, State],
|
[Username, Host, Seconds, State],
|
||||||
["username='", Username, "'"])
|
["username='", Username, "' and host='", Host, "'"])
|
||||||
end).
|
end).
|
||||||
|
|
||||||
del_last(LServer, Username) ->
|
del_last(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from last where username='", Username, "'"]).
|
["delete from last where username='", Username, "' and host='", Host, "'"]).
|
||||||
|
|
||||||
get_password(LServer, Username) ->
|
get_password(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select password from users "
|
["select password from users "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", Host, "';"]).
|
||||||
|
|
||||||
set_password_t(LServer, Username, Pass) ->
|
set_password_t(LServer, Username, Pass) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_transaction(
|
ejabberd_odbc:sql_transaction(
|
||||||
LServer,
|
LServer,
|
||||||
fun() ->
|
fun() ->
|
||||||
update_t("users", ["username", "password"],
|
update_t("users", ["username", "host", "password"],
|
||||||
[Username, Pass],
|
[Username, Host, Pass],
|
||||||
["username='", Username ,"'"])
|
["username='", Username ,"' and host='", Host, "'"])
|
||||||
end).
|
end).
|
||||||
|
|
||||||
add_user(LServer, Username, Pass) ->
|
add_user(LServer, Username, Pass) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["insert into users(username, password) "
|
["insert into users(username, host, password) "
|
||||||
"values ('", Username, "', '", Pass, "');"]).
|
"values ('", Username, "', '", Host, "', '", Pass, "');"]).
|
||||||
|
|
||||||
del_user(LServer, Username) ->
|
del_user(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from users where username='", Username ,"';"]).
|
["delete from users where username='", Username ,"' and host='", Host, "';"]).
|
||||||
|
|
||||||
del_user_return_password(_LServer, Username, Pass) ->
|
del_user_return_password(LServer, Username, Pass) ->
|
||||||
P = ejabberd_odbc:sql_query_t(
|
Host = escape(LServer),
|
||||||
["select password from users where username='",
|
ejabberd_odbc:sql_query_t(
|
||||||
Username, "';"]),
|
["select password from users where username='",
|
||||||
|
Username, "' and host='", Host, "';"]),
|
||||||
ejabberd_odbc:sql_query_t(["delete from users "
|
ejabberd_odbc:sql_query_t(["delete from users "
|
||||||
"where username='", Username,
|
"where username='", Username,
|
||||||
|
"' and host='", Host,
|
||||||
"' and password='", Pass, "';"]),
|
"' and password='", Pass, "';"]),
|
||||||
P.
|
Pass. % REVIEWME
|
||||||
|
|
||||||
list_users(LServer) ->
|
list_users(LServer) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
"select username from users").
|
["select username from users where host='", Host, "'"]).
|
||||||
|
|
||||||
list_users(LServer, [{from, Start}, {to, End}]) when is_integer(Start) and
|
list_users(LServer, [{from, Start}, {to, End}]) when is_integer(Start) and
|
||||||
is_integer(End) ->
|
is_integer(End) ->
|
||||||
@ -211,6 +221,7 @@ list_users(LServer, [{prefix, Prefix},
|
|||||||
"limit ~w offset ~w ", [Prefix, Limit, Offset])).
|
"limit ~w offset ~w ", [Prefix, Limit, Offset])).
|
||||||
|
|
||||||
users_number(LServer) ->
|
users_number(LServer) ->
|
||||||
|
Host = escape(LServer),
|
||||||
case element(1, ejabberd_config:get_local_option({odbc_server, LServer})) of
|
case element(1, ejabberd_config:get_local_option({odbc_server, LServer})) of
|
||||||
mysql ->
|
mysql ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
@ -224,13 +235,13 @@ users_number(LServer) ->
|
|||||||
"select reltuples from pg_class where oid = 'users'::regclass::oid");
|
"select reltuples from pg_class where oid = 'users'::regclass::oid");
|
||||||
_ ->
|
_ ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
"select count(*) from users")
|
["select count(*) from users where host='", Host, "'"])
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
"select count(*) from users")
|
["select count(*) from users where host='", Host, "'"])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
users_number(LServer, [{prefix, Prefix}]) when is_list(Prefix) ->
|
users_number(LServer, [{prefix, Prefix}]) when is_list(Prefix) ->
|
||||||
@ -243,10 +254,10 @@ users_number(LServer, [{prefix, Prefix}]) when is_list(Prefix) ->
|
|||||||
users_number(LServer, []) ->
|
users_number(LServer, []) ->
|
||||||
users_number(LServer).
|
users_number(LServer).
|
||||||
|
|
||||||
|
add_spool_sql(LServer, Username, XML) ->
|
||||||
add_spool_sql(Username, XML) ->
|
Host = escape(LServer),
|
||||||
["insert into spool(username, xml) "
|
["insert into spool(username, host, xml) "
|
||||||
"values ('", Username, "', '",
|
"values ('", Username, "', '", Host, "', '",
|
||||||
XML,
|
XML,
|
||||||
"');"].
|
"');"].
|
||||||
|
|
||||||
@ -255,158 +266,177 @@ add_spool(LServer, Queries) ->
|
|||||||
LServer, Queries).
|
LServer, Queries).
|
||||||
|
|
||||||
get_and_del_spool_msg_t(LServer, Username) ->
|
get_and_del_spool_msg_t(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
Result = ejabberd_odbc:sql_query_t(
|
Result = ejabberd_odbc:sql_query_t(
|
||||||
["select username, xml from spool where username='", Username, "'"
|
["select username, xml from spool where username='", Username, "'"
|
||||||
|
" and host='", Host, "'"
|
||||||
" order by seq;"]),
|
" order by seq;"]),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from spool where username='", Username, "';"]),
|
["delete from spool where username='", Username, "' and host='", Host, "';"]),
|
||||||
Result
|
Result
|
||||||
end,
|
end,
|
||||||
ejabberd_odbc:sql_transaction(LServer,F).
|
ejabberd_odbc:sql_transaction(LServer,F).
|
||||||
|
|
||||||
del_spool_msg(LServer, Username) ->
|
del_spool_msg(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from spool where username='", Username, "';"]).
|
["delete from spool where username='", Username, "' and host='", Host, "';"]).
|
||||||
|
|
||||||
get_roster(LServer, Username) ->
|
get_roster(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select username, jid, nick, subscription, ask, "
|
["select username, jid, nick, subscription, ask, "
|
||||||
"askmessage, server, subscribe, type from rosterusers "
|
"askmessage, server, subscribe, type from rosterusers "
|
||||||
"where username='", Username, "'"]).
|
"where username='", Username, "' and host='", Host, "'"]).
|
||||||
|
|
||||||
get_roster_jid_groups(LServer, Username) ->
|
get_roster_jid_groups(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select jid, grp from rostergroups "
|
["select jid, grp from rostergroups "
|
||||||
"where username='", Username, "'"]).
|
"where username='", Username, "' and host='", Host, "'"]).
|
||||||
|
|
||||||
get_roster_groups(_LServer, Username, SJID) ->
|
get_roster_groups(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["select grp from rostergroups "
|
["select grp from rostergroups "
|
||||||
"where username='", Username, "' "
|
"where username='", Username, "' and host='", Host, "' "
|
||||||
"and jid='", SJID, "';"]).
|
"and jid='", SJID, "';"]).
|
||||||
|
|
||||||
del_user_roster_t(LServer, Username) ->
|
del_user_roster_t(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_transaction(
|
ejabberd_odbc:sql_transaction(
|
||||||
LServer,
|
LServer,
|
||||||
fun() ->
|
fun() ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from rosterusers "
|
["delete from rosterusers "
|
||||||
" where username='", Username, "';"]),
|
" where username='", Username, "' and host='", Host, "';"]),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from rostergroups "
|
["delete from rostergroups "
|
||||||
" where username='", Username, "';"])
|
" where username='", Username, "' and host='", Host, "';"])
|
||||||
end).
|
end).
|
||||||
|
|
||||||
get_roster_by_jid(_LServer, Username, SJID) ->
|
get_roster_by_jid(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["select username, jid, nick, subscription, "
|
["select username, jid, nick, subscription, "
|
||||||
"ask, askmessage, server, subscribe, type from rosterusers "
|
"ask, askmessage, server, subscribe, type from rosterusers "
|
||||||
"where username='", Username, "' "
|
"where username='", Username, "' and host='", Host, "' "
|
||||||
"and jid='", SJID, "';"]).
|
"and jid='", SJID, "';"]).
|
||||||
|
|
||||||
get_rostergroup_by_jid(LServer, Username, SJID) ->
|
get_rostergroup_by_jid(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select grp from rostergroups "
|
["select grp from rostergroups "
|
||||||
"where username='", Username, "' "
|
"where username='", Username, "' and host='", Host, "' "
|
||||||
"and jid='", SJID, "'"]).
|
"and jid='", SJID, "'"]).
|
||||||
|
|
||||||
del_roster(_LServer, Username, SJID) ->
|
del_roster(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from rosterusers "
|
["delete from rosterusers "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"]),
|
" and jid='", SJID, "';"]),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from rostergroups "
|
["delete from rostergroups "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"]).
|
" and jid='", SJID, "';"]).
|
||||||
|
|
||||||
del_roster_sql(Username, SJID) ->
|
del_roster_sql(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
[["delete from rosterusers "
|
[["delete from rosterusers "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"],
|
" and jid='", SJID, "';"],
|
||||||
["delete from rostergroups "
|
["delete from rostergroups "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"]].
|
" and jid='", SJID, "';"]].
|
||||||
|
|
||||||
update_roster(_LServer, Username, SJID, ItemVals, ItemGroups) ->
|
update_roster(LServer, Username, SJID, ItemVals, ItemGroups) ->
|
||||||
|
Host = escape(LServer),
|
||||||
update_t("rosterusers",
|
update_t("rosterusers",
|
||||||
["username", "jid", "nick", "subscription", "ask",
|
["host", "username", "jid", "nick", "subscription", "ask",
|
||||||
"askmessage", "server", "subscribe", "type"],
|
"askmessage", "server", "subscribe", "type"],
|
||||||
ItemVals,
|
[Host | ItemVals],
|
||||||
["username='", Username, "' and jid='", SJID, "'"]),
|
["username='", Username, "' and host='", Host, "' and jid='", SJID, "'"]),
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from rostergroups "
|
["delete from rostergroups "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"]),
|
" and jid='", SJID, "';"]),
|
||||||
lists:foreach(fun(ItemGroup) ->
|
lists:foreach(fun(ItemGroup) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["insert into rostergroups("
|
["insert into rostergroups("
|
||||||
" username, jid, grp) "
|
" host, username, jid, grp) "
|
||||||
" values ('", string:join(ItemGroup, "', '"), "');"])
|
" values ('", Host, "', '", string:join(ItemGroup, "', '"), "');"])
|
||||||
end,
|
end,
|
||||||
ItemGroups).
|
ItemGroups).
|
||||||
|
|
||||||
update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
|
update_roster_sql(LServer, Username, SJID, ItemVals, ItemGroups) ->
|
||||||
|
Host = escape(LServer),
|
||||||
[["delete from rosterusers "
|
[["delete from rosterusers "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"],
|
" and jid='", SJID, "';"],
|
||||||
["insert into rosterusers("
|
["insert into rosterusers("
|
||||||
" username, jid, nick, "
|
" host, username, jid, nick, "
|
||||||
" subscription, ask, askmessage, "
|
" subscription, ask, askmessage, "
|
||||||
" server, subscribe, type) "
|
" server, subscribe, type) "
|
||||||
" values ('", string:join(ItemVals, "', '"), "');"],
|
" values ('", Host, "', '", string:join(ItemVals, "', '"), "');"],
|
||||||
["delete from rostergroups "
|
["delete from rostergroups "
|
||||||
" where username='", Username, "' "
|
" where username='", Username, "' and host='", Host, "' "
|
||||||
" and jid='", SJID, "';"]] ++
|
" and jid='", SJID, "';"]] ++
|
||||||
[["insert into rostergroups("
|
[["insert into rostergroups("
|
||||||
" username, jid, grp) "
|
" host, username, jid, grp) "
|
||||||
" values ('", string:join(ItemGroup, "', '"), "');"] ||
|
" values ('", Host, "', '", string:join(ItemGroup, "', '"), "');"] ||
|
||||||
ItemGroup <- ItemGroups].
|
ItemGroup <- ItemGroups].
|
||||||
|
|
||||||
roster_subscribe(_LServer, Username, SJID, ItemVals) ->
|
roster_subscribe(LServer, Username, SJID, ItemVals) ->
|
||||||
|
Host = escape(LServer),
|
||||||
update_t("rosterusers",
|
update_t("rosterusers",
|
||||||
["username", "jid", "nick", "subscription", "ask",
|
["host", "username", "jid", "nick", "subscription", "ask",
|
||||||
"askmessage", "server", "subscribe", "type"],
|
"askmessage", "server", "subscribe", "type"],
|
||||||
ItemVals,
|
[Host | ItemVals],
|
||||||
["username='", Username, "' and jid='", SJID, "'"]).
|
["username='", Username, "' and host='", Host, "' and jid='", SJID, "'"]).
|
||||||
|
|
||||||
get_subscription(LServer, Username, SJID) ->
|
get_subscription(LServer, Username, SJID) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select subscription from rosterusers "
|
["select subscription from rosterusers "
|
||||||
"where username='", Username, "' "
|
"where username='", Username, "' and host='", Host, "' "
|
||||||
"and jid='", SJID, "'"]).
|
"and jid='", SJID, "'"]).
|
||||||
|
|
||||||
set_private_data(_LServer, Username, LXMLNS, SData) ->
|
set_private_data(LServer, Username, LXMLNS, SData) ->
|
||||||
|
Host = escape(LServer),
|
||||||
update_t("private_storage",
|
update_t("private_storage",
|
||||||
["username", "namespace", "data"],
|
["host", "username", "namespace", "data"],
|
||||||
[Username, LXMLNS, SData],
|
[Host, Username, LXMLNS, SData],
|
||||||
["username='", Username, "' and namespace='", LXMLNS, "'"]).
|
["username='", Username, "' and host='", Host, "' and namespace='", LXMLNS, "'"]).
|
||||||
|
|
||||||
set_private_data_sql(Username, LXMLNS, SData) ->
|
set_private_data_sql(LServer, Username, LXMLNS, SData) ->
|
||||||
|
Host = escape(LServer),
|
||||||
[["delete from private_storage "
|
[["delete from private_storage "
|
||||||
"where username='", Username, "' and "
|
"where username='", Username, "' and host='", Host, "' and "
|
||||||
"namespace='", LXMLNS, "';"],
|
"namespace='", LXMLNS, "';"],
|
||||||
["insert into private_storage(username, namespace, data) "
|
["insert into private_storage(host, username, namespace, data) "
|
||||||
"values ('", Username, "', '", LXMLNS, "', "
|
"values ('", Host, "', '", Username, "', '", LXMLNS, "', "
|
||||||
"'", SData, "');"]].
|
"'", SData, "');"]].
|
||||||
|
|
||||||
get_private_data(LServer, Username, LXMLNS) ->
|
get_private_data(LServer, Username, LXMLNS) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select data from private_storage "
|
["select data from private_storage "
|
||||||
"where username='", Username, "' and "
|
"where username='", Username, "' and host='", Host, "' and "
|
||||||
"namespace='", LXMLNS, "';"]).
|
"namespace='", LXMLNS, "';"]).
|
||||||
|
|
||||||
del_user_private_storage(LServer, Username) ->
|
del_user_private_storage(LServer, Username) ->
|
||||||
|
Host = escape(LServer),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from private_storage where username='", Username, "';"]).
|
["delete from private_storage where username='", Username, "' and host='", Host, "';"]).
|
||||||
|
|
||||||
set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
|
set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
|
||||||
SLBDay, SLCTRY, SLEMail, SLFN, SLFamily, SLGiven, SLLocality,
|
SLBDay, SLCTRY, SLEMail, SLFN, SLFamily, SLGiven, SLLocality,
|
||||||
@ -415,16 +445,16 @@ set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
|
|||||||
ejabberd_odbc:sql_transaction(
|
ejabberd_odbc:sql_transaction(
|
||||||
LServer,
|
LServer,
|
||||||
fun() ->
|
fun() ->
|
||||||
update_t("vcard", ["username", "vcard"],
|
update_t("vcard", ["host", "username", "vcard"],
|
||||||
[LUsername, SVCARD],
|
[LServer, LUsername, SVCARD],
|
||||||
["username='", LUsername, "'"]),
|
["username='", LUsername, "' and host='", LServer, "'"]),
|
||||||
update_t("vcard_search",
|
update_t("vcard_search",
|
||||||
["username", "lusername", "fn", "lfn", "family",
|
["host", "username", "lusername", "fn", "lfn", "family",
|
||||||
"lfamily", "given", "lgiven", "middle", "lmiddle",
|
"lfamily", "given", "lgiven", "middle", "lmiddle",
|
||||||
"nickname", "lnickname", "bday", "lbday", "ctry",
|
"nickname", "lnickname", "bday", "lbday", "ctry",
|
||||||
"lctry", "locality", "llocality", "email", "lemail",
|
"lctry", "locality", "llocality", "email", "lemail",
|
||||||
"orgname", "lorgname", "orgunit", "lorgunit"],
|
"orgname", "lorgname", "orgunit", "lorgunit"],
|
||||||
[Username, LUsername, SFN, SLFN, SFamily, SLFamily,
|
[LServer, Username, LUsername, SFN, SLFN, SFamily, SLFamily,
|
||||||
SGiven, SLGiven, SMiddle, SLMiddle, SNickname,
|
SGiven, SLGiven, SMiddle, SLMiddle, SNickname,
|
||||||
SLNickname, SBDay, SLBDay, SCTRY, SLCTRY,
|
SLNickname, SBDay, SLBDay, SCTRY, SLCTRY,
|
||||||
SLocality, SLLocality, SEMail, SLEMail, SOrgName,
|
SLocality, SLLocality, SEMail, SLEMail, SOrgName,
|
||||||
@ -436,7 +466,7 @@ get_vcard(LServer, Username) ->
|
|||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select vcard from vcard "
|
["select vcard from vcard "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
del_vcard(LServer, Username) ->
|
del_vcard(LServer, Username) ->
|
||||||
ejabberd_odbc:sql_transaction(
|
ejabberd_odbc:sql_transaction(
|
||||||
@ -457,34 +487,34 @@ get_default_privacy_list(LServer, Username) ->
|
|||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select name from privacy_default_list "
|
["select name from privacy_default_list "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_default_privacy_list_t(Username) ->
|
get_default_privacy_list_t(LServer, Username) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["select name from privacy_default_list "
|
["select name from privacy_default_list "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_privacy_list_names(LServer, Username) ->
|
get_privacy_list_names(LServer, Username) ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select name from privacy_list "
|
["select name from privacy_list "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_privacy_list_names_t(Username) ->
|
get_privacy_list_names_t(LServer, Username) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["select name from privacy_list "
|
["select name from privacy_list "
|
||||||
"where username='", Username, "';"]).
|
"where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_privacy_list_id(LServer, Username, SName) ->
|
get_privacy_list_id(LServer, Username, SName) ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["select id from privacy_list "
|
["select id from privacy_list "
|
||||||
"where username='", Username, "' and name='", SName, "';"]).
|
"where username='", Username, "' and name='", SName, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_privacy_list_id_t(Username, SName) ->
|
get_privacy_list_id_t(LServer, Username, SName) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["select id from privacy_list "
|
["select id from privacy_list "
|
||||||
"where username='", Username, "' and name='", SName, "';"]).
|
"where username='", Username, "' and name='", SName, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
get_privacy_list_data(LServer, Username, SName) ->
|
get_privacy_list_data(LServer, Username, SName) ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
@ -493,7 +523,7 @@ get_privacy_list_data(LServer, Username, SName) ->
|
|||||||
"match_message, match_presence_in, match_presence_out "
|
"match_message, match_presence_in, match_presence_out "
|
||||||
"from privacy_list_data "
|
"from privacy_list_data "
|
||||||
"where id = (select id from privacy_list where "
|
"where id = (select id from privacy_list where "
|
||||||
" username='", Username, "' and name='", SName, "') "
|
" username='", Username, "' and name='", SName, "' and host='", LServer, "') "
|
||||||
"order by ord;"]).
|
"order by ord;"]).
|
||||||
|
|
||||||
get_privacy_list_data_by_id(LServer, ID) ->
|
get_privacy_list_data_by_id(LServer, ID) ->
|
||||||
@ -504,25 +534,26 @@ get_privacy_list_data_by_id(LServer, ID) ->
|
|||||||
"from privacy_list_data "
|
"from privacy_list_data "
|
||||||
"where id='", ID, "' order by ord;"]).
|
"where id='", ID, "' order by ord;"]).
|
||||||
|
|
||||||
set_default_privacy_list(Username, SName) ->
|
set_default_privacy_list(LServer, Username, SName) ->
|
||||||
update_t("privacy_default_list", ["username", "name"],
|
update_t("privacy_default_list", ["host", "username", "name"],
|
||||||
[Username, SName], ["username='", Username, "'"]).
|
[LServer, Username, SName],
|
||||||
|
["host='", LServer, "' and username='", Username, "'"]).
|
||||||
|
|
||||||
unset_default_privacy_list(LServer, Username) ->
|
unset_default_privacy_list(LServer, Username) ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from privacy_default_list "
|
["delete from privacy_default_list "
|
||||||
" where username='", Username, "';"]).
|
" where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
remove_privacy_list(Username, SName) ->
|
remove_privacy_list(LServer, Username, SName) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["delete from privacy_list "
|
["delete from privacy_list "
|
||||||
"where username='", Username, "' and name='", SName, "';"]).
|
"where username='", Username, "' and name='", SName, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
add_privacy_list(Username, SName) ->
|
add_privacy_list(LServer, Username, SName) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
["insert into privacy_list(username, name) "
|
["insert into privacy_list(host, username, name) "
|
||||||
"values ('", Username, "', '", SName, "');"]).
|
"values ('", LServer, "', '", Username, "', '", SName, "');"]).
|
||||||
|
|
||||||
set_privacy_list(ID, RItems) ->
|
set_privacy_list(ID, RItems) ->
|
||||||
ejabberd_odbc:sql_query_t(
|
ejabberd_odbc:sql_query_t(
|
||||||
@ -542,13 +573,13 @@ set_privacy_list(ID, RItems) ->
|
|||||||
del_privacy_lists(LServer, Server, Username) ->
|
del_privacy_lists(LServer, Server, Username) ->
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from privacy_list where username='", Username, "';"]),
|
["delete from privacy_list where username='", Username, "' and host='", LServer, "';"]),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from privacy_list_data where value='", Username++"@"++Server, "';"]),
|
["delete from privacy_list_data where value='", Username++"@"++Server, "';"]),
|
||||||
ejabberd_odbc:sql_query(
|
ejabberd_odbc:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
["delete from privacy_default_list where username='", Username, "';"]).
|
["delete from privacy_default_list where username='", Username, "' and host='", LServer, "';"]).
|
||||||
|
|
||||||
%% Characters to escape
|
%% Characters to escape
|
||||||
escape($\0) -> "\\0";
|
escape($\0) -> "\\0";
|
||||||
|
@ -18,21 +18,24 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
username text PRIMARY KEY,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
"password" text NOT NULL,
|
"password" text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE last (
|
CREATE TABLE last (
|
||||||
username text PRIMARY KEY,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
seconds text NOT NULL,
|
seconds text NOT NULL,
|
||||||
state text NOT NULL
|
state text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE rosterusers (
|
CREATE TABLE rosterusers (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
jid text NOT NULL,
|
jid text NOT NULL,
|
||||||
nick text NOT NULL,
|
nick text NOT NULL,
|
||||||
subscription character(1) NOT NULL,
|
subscription character(1) NOT NULL,
|
||||||
@ -41,42 +44,50 @@ CREATE TABLE rosterusers (
|
|||||||
server character(1) NOT NULL,
|
server character(1) NOT NULL,
|
||||||
subscribe text,
|
subscribe text,
|
||||||
"type" text,
|
"type" text,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
PRIMARY KEY (host, username, jid)
|
||||||
|
=======
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
>>>>>>> 30
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers USING btree (username, jid);
|
|
||||||
CREATE INDEX i_rosteru_username ON rosterusers USING btree (username);
|
|
||||||
CREATE INDEX i_rosteru_jid ON rosterusers USING btree (jid);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE rostergroups (
|
CREATE TABLE rostergroups (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
jid text NOT NULL,
|
jid text NOT NULL,
|
||||||
grp text NOT NULL
|
grp text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username, jid)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE spool (
|
CREATE TABLE spool (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
xml text NOT NULL,
|
xml text NOT NULL,
|
||||||
seq SERIAL,
|
seq SERIAL,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
PRIMARY KEY (host, username, seq)
|
||||||
|
=======
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
>>>>>>> 30
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX i_despool ON spool USING btree (username);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE vcard (
|
CREATE TABLE vcard (
|
||||||
|
<<<<<<< HEAD
|
||||||
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
|
vcard text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
|
=======
|
||||||
username text PRIMARY KEY,
|
username text PRIMARY KEY,
|
||||||
vcard text NOT NULL,
|
vcard text NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
>>>>>>> 30
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE vcard_search (
|
CREATE TABLE vcard_search (
|
||||||
|
host text NOT NULL,
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
lusername text PRIMARY KEY,
|
lusername text NOT NULL,
|
||||||
fn text NOT NULL,
|
fn text NOT NULL,
|
||||||
lfn text NOT NULL,
|
lfn text NOT NULL,
|
||||||
family text NOT NULL,
|
family text NOT NULL,
|
||||||
@ -98,9 +109,11 @@ CREATE TABLE vcard_search (
|
|||||||
orgname text NOT NULL,
|
orgname text NOT NULL,
|
||||||
lorgname text NOT NULL,
|
lorgname text NOT NULL,
|
||||||
orgunit text NOT NULL,
|
orgunit text NOT NULL,
|
||||||
lorgunit text NOT NULL
|
lorgunit text NOT NULL,
|
||||||
|
PRIMARY KEY (host, lusername)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX i_vcard_search_lusername ON vcard_search(lusername);
|
||||||
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
||||||
CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
|
CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
|
||||||
CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
|
CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
|
||||||
@ -114,20 +127,24 @@ CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
|
|||||||
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
||||||
|
|
||||||
CREATE TABLE privacy_default_list (
|
CREATE TABLE privacy_default_list (
|
||||||
username text PRIMARY KEY,
|
username text NOT NULL,
|
||||||
name text NOT NULL
|
host text NOT NULL,
|
||||||
|
name text NOT NULL,
|
||||||
|
PRIMARY KEY (host, username)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE privacy_list (
|
CREATE TABLE privacy_list (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
name text NOT NULL,
|
name text NOT NULL,
|
||||||
id SERIAL UNIQUE,
|
id SERIAL UNIQUE,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
PRIMARY KEY (host, username, name)
|
||||||
|
=======
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
>>>>>>> 30
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX i_privacy_list_username ON privacy_list USING btree (username);
|
|
||||||
CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list USING btree (username, name);
|
|
||||||
|
|
||||||
CREATE TABLE privacy_list_data (
|
CREATE TABLE privacy_list_data (
|
||||||
id bigint REFERENCES privacy_list(id) ON DELETE CASCADE,
|
id bigint REFERENCES privacy_list(id) ON DELETE CASCADE,
|
||||||
t character(1) NOT NULL,
|
t character(1) NOT NULL,
|
||||||
@ -138,18 +155,28 @@ CREATE TABLE privacy_list_data (
|
|||||||
match_iq boolean NOT NULL,
|
match_iq boolean NOT NULL,
|
||||||
match_message boolean NOT NULL,
|
match_message boolean NOT NULL,
|
||||||
match_presence_in boolean NOT NULL,
|
match_presence_in boolean NOT NULL,
|
||||||
match_presence_out boolean NOT NULL
|
match_presence_out boolean NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE private_storage (
|
CREATE TABLE private_storage (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
namespace text NOT NULL,
|
namespace text NOT NULL,
|
||||||
data text NOT NULL,
|
data text NOT NULL,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
PRIMARY KEY (host, username, namespace)
|
||||||
|
=======
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
>>>>>>> 30
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX i_private_storage_username ON private_storage USING btree (username);
|
CREATE TABLE hosts (
|
||||||
CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage USING btree (username, namespace);
|
clusterid integer NOT NULL,
|
||||||
|
host text NOT NULL,
|
||||||
|
config text NOT NULL,
|
||||||
|
PRIMARY KEY (host)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE roster_version (
|
CREATE TABLE roster_version (
|
||||||
|
@ -33,7 +33,12 @@
|
|||||||
|
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
register(random_generator, spawn(randoms, init, [])).
|
case erlang:whereis(random_generator) of
|
||||||
|
Pid when is_pid(Pid) ->
|
||||||
|
true;
|
||||||
|
undefined ->
|
||||||
|
register(random_generator, spawn(randoms, init, []))
|
||||||
|
end.
|
||||||
|
|
||||||
init() ->
|
init() ->
|
||||||
{A1, A2, A3} = now(),
|
{A1, A2, A3} = now(),
|
||||||
|
@ -165,7 +165,7 @@ process(["doc", LocalFile], _Request) ->
|
|||||||
|
|
||||||
process(["server", SHost | RPath] = Path, #request{auth = Auth, lang = Lang, host = HostHTTP, method = Method} = Request) ->
|
process(["server", SHost | RPath] = Path, #request{auth = Auth, lang = Lang, host = HostHTTP, method = Method} = Request) ->
|
||||||
Host = exmpp_stringprep:nameprep(SHost),
|
Host = exmpp_stringprep:nameprep(SHost),
|
||||||
case lists:member(Host, ?MYHOSTS) of
|
case ?IS_MY_HOST(Host) of
|
||||||
true ->
|
true ->
|
||||||
case get_auth_admin(Auth, HostHTTP, Path, Method) of
|
case get_auth_admin(Auth, HostHTTP, Path, Method) of
|
||||||
{ok, {User, Server}} ->
|
{ok, {User, Server}} ->
|
||||||
|
Loading…
Reference in New Issue
Block a user