+2005-07-13 Alexey Shchepin <alexey@sevcom.net>
+
+ * src/mod_register.erl: Bugfix
+
+ * src/mod_vcard.erl: Bugfix
+
+ * src/ejabberd_app.erl: Updated to allow different authentication
+ methods for different virtual hosts
+ * src/ejabberd_auth.erl: Likewise
+ * src/ejabberd_auth_external.erl: Likewise
+ * src/ejabberd_auth_internal.erl: Likewise
+ * src/ejabberd_auth_ldap.erl: Likewise
+ * src/ejabberd_auth_odbc.erl: Likewise
+ * src/cyrsasl.erl: Likewise
+ * src/cyrsasl_digest.erl: Likewise
+ * src/cyrsasl_plain.erl: Likewise
+ * src/ejabberd_c2s.erl: Likewise
+ * src/ejabberd_config.erl: Likewise
+ * src/extauth.erl: Likewise
+ * src/mod_last_odbc.erl: Likewise
+ * src/mod_offline_odbc.erl: Likewise
+ * src/mod_roster_odbc.erl: Likewise
+ * src/odbc/ejabberd_odbc.erl: Likewise
+ * src/odbc/ejabberd_odbc_sup.erl: Likewise
+
2005-07-03 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_app.erl: Bugfix
-vsn('$Revision$ ').
-export([start/0,
- register_mechanism/2,
- listmech/0,
+ register_mechanism/3,
+ listmech/1,
server_new/6,
server_start/3,
server_step/2]).
--record(sasl_mechanism, {mechanism, module}).
+-record(sasl_mechanism, {mechanism, module, require_plain_password}).
-record(sasl_state, {service, myname, realm,
get_password, check_password,
mech_mod, mech_state}).
cyrsasl_digest:start([]),
ok.
-register_mechanism(Mechanism, Module) ->
- ets:insert(sasl_mechanism, #sasl_mechanism{mechanism = Mechanism,
- module = Module}).
+register_mechanism(Mechanism, Module, RequirePlainPassword) ->
+ ets:insert(sasl_mechanism,
+ #sasl_mechanism{mechanism = Mechanism,
+ module = Module,
+ require_plain_password = RequirePlainPassword}).
% TODO: use callbacks
-include("ejabberd.hrl").
ok
end.
-listmech() ->
+listmech(Host) ->
+ RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
ets:select(sasl_mechanism,
- [{#sasl_mechanism{mechanism = '$1', _ = '_'}, [], ['$1']}]).
+ [{#sasl_mechanism{mechanism = '$1',
+ require_plain_password = '$2',
+ _ = '_'},
+ if
+ RequirePlainPassword ->
+ [{'==', '$2', false}];
+ true ->
+ []
+ end,
+ ['$1']}]).
server_new(Service, ServerFQDN, UserRealm, SecFlags,
-record(state, {step, nonce, username, authzid, get_password}).
start(_Opts) ->
- case ejabberd_auth:plain_password_required() of
- true ->
- ok;
- false ->
- cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE),
- ok
- end.
+ cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
stop() ->
ok.
-record(state, {check_password}).
start(_Opts) ->
- cyrsasl:register_mechanism("PLAIN", ?MODULE),
+ cyrsasl:register_mechanism("PLAIN", ?MODULE, false),
ok.
stop() ->
acl:start(),
gen_mod:start(),
ejabberd_config:start(),
+ Sup = ejabberd_sup:start_link(),
ejabberd_auth:start(),
cyrsasl:start(),
% Profiling
%eprof:start(),
%eprof:profile([self()]),
%fprof:trace(start, "/tmp/fprof"),
- Sup = ejabberd_sup:start_link(),
start(),
load_modules(),
Sup;
is_user_exists/2,
remove_user/2,
remove_user/3,
- plain_password_required/0
+ plain_password_required/1
]).
-include("ejabberd.hrl").
%%% API
%%%----------------------------------------------------------------------
start() ->
- (auth_module()):start().
+ lists:foreach(fun(Host) ->
+ (auth_module(Host)):start(Host)
+ end, ?MYHOSTS).
-plain_password_required() ->
- (auth_module()):plain_password_required().
+plain_password_required(Server) ->
+ (auth_module(Server)):plain_password_required().
check_password(User, Server, Password) ->
- (auth_module()):check_password(User, Server, Password).
+ (auth_module(Server)):check_password(User, Server, Password).
check_password(User, Server, Password, StreamID, Digest) ->
- (auth_module()):check_password(User, Server, Password, StreamID, Digest).
+ (auth_module(Server)):check_password(User, Server, Password, StreamID, Digest).
set_password(User, Server, Password) ->
- (auth_module()):set_password(User, Server, Password).
+ (auth_module(Server)):set_password(User, Server, Password).
try_register(User, Server, Password) ->
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
true ->
- (auth_module()):try_register(User, Server, Password);
+ (auth_module(Server)):try_register(User, Server, Password);
false ->
{error, not_allowed}
end.
dirty_get_registered_users() ->
- (auth_module()):dirty_get_registered_users().
+ (auth_module(?MYNAME)):dirty_get_registered_users().
get_vh_registered_users(Server) ->
- (auth_module()):get_vh_registered_users(Server).
+ (auth_module(Server)):get_vh_registered_users(Server).
get_password(User, Server) ->
- (auth_module()):get_password(User, Server).
+ (auth_module(Server)):get_password(User, Server).
get_password_s(User, Server) ->
- (auth_module()):get_password_s(User, Server).
+ (auth_module(Server)):get_password_s(User, Server).
is_user_exists(User, Server) ->
- (auth_module()):is_user_exists(User, Server).
+ (auth_module(Server)):is_user_exists(User, Server).
remove_user(User, Server) ->
- (auth_module()):remove_user(User, Server).
+ (auth_module(Server)):remove_user(User, Server).
remove_user(User, Server, Password) ->
- (auth_module()):remove_user(User, Server, Password).
+ (auth_module(Server)):remove_user(User, Server, Password).
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
-auth_module() ->
- case ejabberd_config:get_local_option(auth_method) of
+auth_module(Server) ->
+ LServer = jlib:nameprep(Server),
+ case ejabberd_config:get_local_option({auth_method, LServer}) of
external ->
ejabberd_auth_external;
ldap ->
-vsn('$Revision$ ').
%% External exports
--export([start/0,
+-export([start/1,
set_password/3,
check_password/3,
check_password/5,
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start() ->
- extauth:start(ejabberd_config:get_local_option(extauth_program)),
+start(Host) ->
+ extauth:start(
+ Host, ejabberd_config:get_local_option({extauth_program, Host})),
ok.
plain_password_required() ->
true.
-check_password(User, _Server, Password) ->
- extauth:check_password(User, Password).
+check_password(User, Server, Password) ->
+ extauth:check_password(User, Server, Password).
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
-set_password(User, _Server, Password) ->
- extauth:set_password(User, Password).
+set_password(User, Server, Password) ->
+ extauth:set_password(User, Server, Password).
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
get_password_s(_User, _Server) ->
"".
-is_user_exists(User, _Server) ->
- extauth:is_user_exists(User).
+is_user_exists(User, Server) ->
+ extauth:is_user_exists(User, Server).
remove_user(_User, _Server) ->
{error, not_allowed}.
-vsn('$Revision$ ').
%% External exports
--export([start/0,
+-export([start/1,
set_password/3,
check_password/3,
check_password/5,
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start() ->
+start(_Host) ->
mnesia:create_table(passwd, [{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
update_table(),
-vsn('$Revision$ ').
%% External exports
--export([start/0,
+-export([start/1,
set_password/3,
check_password/3,
check_password/5,
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start() ->
- LDAPServers = ejabberd_config:get_local_option(ldap_servers),
- RootDN = ejabberd_config:get_local_option(ldap_rootdn),
- Password = ejabberd_config:get_local_option(ldap_password),
- eldap:start_link("ejabberd", LDAPServers, 389, RootDN, Password),
- eldap:start_link("ejabberd_bind", LDAPServers, 389, RootDN, Password),
+start(Host) ->
+ LDAPServers = ejabberd_config:get_local_option({ldap_servers, Host}),
+ RootDN = ejabberd_config:get_local_option({ldap_rootdn, Host}),
+ Password = ejabberd_config:get_local_option({ldap_password, Host}),
+ eldap:start_link(gen_mod:get_module_proc(Host, ejabberd),
+ LDAPServers, 389, RootDN, Password),
+ eldap:start_link(gen_mod:get_module_proc(Host, ejabberd_bind),
+ LDAPServers, 389, RootDN, Password),
ok.
plain_password_required() ->
true.
-check_password(User, _Server, Password) ->
- case find_user_dn(User) of
+check_password(User, Server, Password) ->
+ case find_user_dn(User, Server) of
false ->
false;
DN ->
- case eldap:bind("ejabberd_bind", DN, Password) of
+ LServer = jlib:nameprep(Server),
+ case eldap:bind(gen_mod:get_module_proc(LServer, ejabberd_bind),
+ DN, Password) of
ok ->
true;
_ ->
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
- Attr = ejabberd_config:get_local_option(ldap_uidattr),
+ Attr = ejabberd_config:get_local_option({ldap_uidattr, LServer}),
Filter = eldap:present(Attr),
- Base = ejabberd_config:get_local_option(ldap_base),
- case eldap:search("ejabberd", [{base, Base},
- {filter, Filter},
- {attributes, [Attr]}]) of
+ Base = ejabberd_config:get_local_option({ldap_base, LServer}),
+ case eldap:search(gen_mod:get_module_proc(LServer, ejabberd),
+ [{base, Base},
+ {filter, Filter},
+ {attributes, [Attr]}]) of
#eldap_search_result{entries = Es} ->
lists:flatmap(
fun(E) ->
get_password_s(_User, _Server) ->
"".
-is_user_exists(User, _Server) ->
- case find_user_dn(User) of
+is_user_exists(User, Server) ->
+ case find_user_dn(User, Server) of
false ->
false;
_DN ->
%%% Internal functions
%%%----------------------------------------------------------------------
-find_user_dn(User) ->
- Attr = ejabberd_config:get_local_option(ldap_uidattr),
+find_user_dn(User, Server) ->
+ LServer = jlib:nameprep(Server),
+ Attr = ejabberd_config:get_local_option({ldap_uidattr, LServer}),
Filter = eldap:equalityMatch(Attr, User),
- Base = ejabberd_config:get_local_option(ldap_base),
- case eldap:search("ejabberd", [{base, Base},
- {filter, Filter},
- {attributes, []}]) of
+ Base = ejabberd_config:get_local_option({ldap_base, LServer}),
+ case eldap:search(gen_mod:get_module_proc(LServer, ejabberd),
+ [{base, Base},
+ {filter, Filter},
+ {attributes, []}]) of
#eldap_search_result{entries = [E | _]} ->
E#eldap_entry.object_name;
_ ->
-vsn('$Revision$ ').
%% External exports
--export([start/0,
+-export([start/1,
set_password/3,
check_password/3,
check_password/5,
plain_password_required/0
]).
+-include("ejabberd.hrl").
+
-record(passwd, {user, password}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start() ->
+start(Host) ->
+ ejabberd_odbc_sup:start_link(Host),
ok.
plain_password_required() ->
false.
-check_password(User, _Server, Password) ->
+check_password(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
{selected, ["password"], [{Password}]} ->
end
end.
-check_password(User, _Server, Password, StreamID, Digest) ->
+check_password(User, Server, Password, StreamID, Digest) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
{selected, ["password"], [{Passwd}]} ->
end
end.
-set_password(User, _Server, Password) ->
+set_password(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["begin;"
"delete from users where username='", Username ,"';"
"insert into users(username, password) "
end.
-try_register(User, _Server, Password) ->
+try_register(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "')"]) of
{updated, _} ->
end.
dirty_get_registered_users() ->
- case catch ejabberd_odbc:sql_query("select username from users") of
+ get_vh_registered_users(?MYNAME).
+
+get_vh_registered_users(Server) ->
+ case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
+ "select username from users") of
{selected, ["username"], Res} ->
[U || {U} <- Res];
_ ->
[]
end.
-get_vh_registered_users(Server) ->
- dirty_get_registered_users().
-
-get_password(User, _Server) ->
+get_password(User, Server) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
{selected, ["password"], [{Password}]} ->
end
end.
-get_password_s(User, _Server) ->
+get_password_s(User, Server) ->
case jlib:nodeprep(User) of
error ->
"";
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
{selected, ["password"], [{Password}]} ->
end
end.
-is_user_exists(User, _Server) ->
+is_user_exists(User, Server) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
{selected, ["password"], [{_Password}]} ->
LUser ->
Username = ejabberd_odbc:escape(LUser),
catch ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["delete from users where username='", Username ,"'"]),
ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User])
end.
Pass = ejabberd_odbc:escape(Password),
case catch
ejabberd_odbc:sql_query(
+ jlib:nameprep(Server),
["begin;"
"select password from users where username='", Username, "';"
"delete from users "
fun(S) ->
{xmlelement, "mechanism", [],
[{xmlcdata, S}]}
- end, cyrsasl:listmech()),
+ end, cyrsasl:listmech(Server)),
TLS = StateData#state.tls,
TLSEnabled = StateData#state.tls_enabled,
TLSRequired = StateData#state.tls_required,
{next_state, wait_for_auth, StateData};
{auth, _ID, get, {U, _, _, _}} ->
{xmlelement, Name, Attrs, _Els} = jlib:make_result_iq_reply(El),
- Res = case ejabberd_auth:plain_password_required() of
+ Res = case ejabberd_auth:plain_password_required(
+ StateData#state.server) of
false ->
{xmlelement, Name, Attrs,
[{xmlelement, "query", [{"xmlns", ?NS_AUTH}],
State;
{listen, Val} ->
add_option(listen, Val, State);
+ {outgoing_s2s_port, Port} ->
+ add_option(outgoing_s2s_port, Port, State);
{Opt, Val} ->
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
State, State#state.hosts)
-module(extauth).
-author('leifj@it.su.se').
--export([start/1, stop/0, init/1,
- check_password/2, set_password/2, is_user_exists/1 ]).
+-export([start/2, stop/1, init/2,
+ check_password/3, set_password/3, is_user_exists/2]).
-start(ExtPrg) ->
- spawn(?MODULE, init, [ExtPrg]).
+start(Host, ExtPrg) ->
+ spawn(?MODULE, init, [Host, ExtPrg]).
-init(ExtPrg) ->
- register(eauth,self()),
+init(Host, ExtPrg) ->
+ register(gen_mod:get_module_proc(Host, eauth), self()),
process_flag(trap_exit,true),
Port = open_port({spawn, ExtPrg}, [{packet,2}]),
loop(Port).
-stop() ->
- eauth ! stop.
+stop(Host) ->
+ gen_mod:get_module_proc(Host, eauth) ! stop.
-check_password(User,Password) ->
- call_port(["auth",User,Password]).
+check_password(User, Server, Password) ->
+ call_port(Server, ["auth", User, Server, Password]).
-is_user_exists(User) ->
- call_port(["isuser",User]).
+is_user_exists(User, Server) ->
+ call_port(Server, ["isuser", User, Server]).
-set_password(User,Password) ->
- call_port(["setpass",User,Password]).
+set_password(User, Server, Password) ->
+ call_port(Server, ["setpass", User, Server, Password]).
-call_port(Msg) ->
- eauth ! {call, self(), Msg},
+call_port(Server, Msg) ->
+ LServer = jlib:nameprep(Server),
+ gen_mod:get_module_proc(LServer, eauth) ! {call, self(), Msg},
receive
- {eauth,Result}->
+ {eauth,Result} ->
Result
end.
process_sm_iq/3,
on_presence_update/4,
store_last_info/4,
- remove_user/1]).
+ remove_user/2]).
-include("ejabberd.hrl").
-include("jlib.hrl").
(Subscription == both) or (Subscription == from) ->
case catch mod_privacy:get_user_list(User, Server) of
{'EXIT', _Reason} ->
- get_last(IQ, SubEl, User);
+ get_last(IQ, SubEl, User, Server);
List ->
case catch mod_privacy:check_packet(
- User, ?MYNAME, List, % TODO
+ User, Server, List,
{From, To,
{xmlelement, "presence", [], []}},
out) of
{'EXIT', _Reason} ->
- get_last(IQ, SubEl, User);
+ get_last(IQ, SubEl, User, Server);
allow ->
- get_last(IQ, SubEl, User);
+ get_last(IQ, SubEl, User, Server);
deny ->
IQ#iq{type = error,
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end
end.
-get_last(IQ, SubEl, LUser) ->
+get_last(IQ, SubEl, LUser, LServer) ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ LServer,
["select seconds, state from last "
"where username='", Username, "'"]) of
{'EXIT', _Reason} ->
store_last_info(User, Server, TimeStamp, Status) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(User),
Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status),
ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"delete from last where username='", Username, "';"
"insert into last(username, seconds, state) "
"commit"]).
-remove_user(User) ->
+remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
+ LServer,
["delete from last where username='", Username, "'"]).
-behaviour(gen_mod).
-export([start/2,
- init/0,
+ init/1,
stop/1,
store_packet/3,
- pop_offline_messages/2,
- remove_user/1]).
+ pop_offline_messages/3,
+ remove_user/2]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
start(Host, _Opts) ->
- % TODO: remove
- ejabberd_odbc:start(),
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
- register(?PROCNAME, spawn(?MODULE, init, [])).
+ register(gen_mod:get_module_proc(Host, ?PROCNAME),
+ spawn(?MODULE, init, [Host])).
-init() ->
- loop().
+init(Host) ->
+ loop(Host).
-loop() ->
+loop(Host) ->
receive
#offline_msg{} = Msg ->
Msgs = receive_all([Msg]),
"');"]
end, Msgs),
case catch ejabberd_odbc:sql_query(
+ Host,
["begin; ", Query, " commit"]) of
{'EXIT', Reason} ->
?ERROR_MSG("~p~n", [Reason]);
_ ->
ok
end,
- loop();
+ loop(Host);
_ ->
- loop()
+ loop(Host)
end.
receive_all(Msgs) ->
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50),
- exit(whereis(?PROCNAME), stop),
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
+ exit(whereis(Proc), stop),
ok.
store_packet(From, To, Packet) ->
TimeStamp = now(),
{xmlelement, _Name, _Attrs, Els} = Packet,
Expire = find_x_expire(TimeStamp, Els),
- ?PROCNAME ! #offline_msg{user = LUser,
- timestamp = TimeStamp,
- expire = Expire,
- from = From,
- to = To,
- packet = Packet},
+ gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) !
+ #offline_msg{user = LUser,
+ timestamp = TimeStamp,
+ expire = Expire,
+ from = From,
+ to = To,
+ packet = Packet},
stop;
_ ->
ok
end.
-pop_offline_messages(Ls, User) ->
+pop_offline_messages(Ls, User, Server) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
EUser = ejabberd_odbc:escape(LUser),
case ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"select * from spool where username='", EUser, "';"
"delete from spool where username='", EUser, "';"
end.
-remove_user(User) ->
+remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
+ LServer,
["delete from spool where username='", Username, "'"]).
send_welcome_message(JID) ->
- case ejabberd_config:get_local_option(welcome_message) of
+ Host = JID#jid.lserver,
+ case ejabberd_config:get_local_option({welcome_message, Host}) of
{"", ""} ->
ok;
{Subj, Body} ->
ejabberd_router:route(
- jlib:make_jid("", ?MYNAME, ""),
+ jlib:make_jid("", Host, ""),
JID,
{xmlelement, "message", [{"type", "normal"}],
[{xmlelement, "subject", [], [{xmlcdata, Subj}]},
end.
send_registration_notifications(UJID) ->
- case ejabberd_config:get_local_option(registration_watchers) of
+ Host = UJID#jid.lserver,
+ case ejabberd_config:get_local_option({registration_watchers, Host}) of
[] -> ok;
JIDs when is_list(JIDs) ->
Body = lists:flatten(
error -> ok;
JID ->
ejabberd_router:route(
- jlib:make_jid("", ?MYNAME, ""),
+ jlib:make_jid("", Host, ""),
JID,
{xmlelement, "message", [{"type", "chat"}],
[{xmlelement, "body", [],
-export([start/2, stop/1,
process_iq/3,
process_local_iq/3,
- get_subscription_lists/2,
- in_subscription/4,
- out_subscription/3,
- set_items/2,
- remove_user/1,
- get_jid_info/3]).
+ get_user_roster/2,
+ get_subscription_lists/3,
+ in_subscription/5,
+ out_subscription/4,
+ set_items/3,
+ remove_user/2,
+ get_jid_info/4]).
-include("ejabberd.hrl").
-include("jlib.hrl").
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
- ejabberd_hooks:add(roster_out_subscription, Host,
- ?MODULE, out_subscription, 50),
+ ejabberd_hooks:add(roster_get, Host,
+ ?MODULE, get_user_roster, 50),
ejabberd_hooks:add(roster_in_subscription, Host,
?MODULE, in_subscription, 50),
ejabberd_hooks:add(roster_out_subscription, Host,
?MODULE, process_iq, IQDisc).
stop(Host) ->
+ ejabberd_hooks:delete(roster_get, Host,
+ ?MODULE, get_user_roster, 50),
ejabberd_hooks:delete(roster_in_subscription, Host,
?MODULE, in_subscription, 50),
ejabberd_hooks:delete(roster_out_subscription, Host,
process_iq_get(From, _To, #iq{sub_el = SubEl} = IQ) ->
LUser = From#jid.luser,
+ LServer = From#jid.lserver,
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
end.
+get_user_roster(Acc, {LUser, LServer}) ->
+ Username = ejabberd_odbc:escape(LUser),
+ case catch ejabberd_odbc:sql_query(
+ LServer,
+ ["select username, jid, nick, subscription, ask, "
+ "server, subscribe, type from rosterusers "
+ "where username='", Username, "'"]) of
+ {selected, ["username", "jid", "nick", "subscription", "ask",
+ "server", "subscribe", "type"],
+ Items} when is_list(Items) ->
+ RItems = lists:flatmap(
+ fun(I) ->
+ case raw_to_record(I) of
+ error ->
+ [];
+ R ->
+ [R]
+ end
+ end, Items),
+ RItems ++ Acc;
+ _ ->
+ Acc
+ end.
+
+
item_to_xml(Item) ->
Attrs1 = [{"jid", jlib:jid_to_string(Item#roster.jid)}],
Attrs2 = case Item#roster.name of
process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
- #jid{user = User, luser = LUser} = From,
+ #jid{user = User, luser = LUser, lserver = LServer} = From,
case JID1 of
error ->
ok;
Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
case catch ejabberd_odbc:sql_query(
+ LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "' "
case Item1#roster.subscription of
remove ->
catch ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"delete from rosterusers "
" where username='", Username, "' "
_ ->
ItemVals = record_to_string(Item1),
catch ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
% TODO
"commit"])
-
- %mnesia:write(Item1)
end,
push_item(User, To, Item1),
case Item1#roster.subscription of
-endif.
-get_subscription_lists(_, User) ->
+get_subscription_lists(_, User, Server) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
+ LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
-in_subscription(_, User, JID, Type) ->
- process_subscription(in, User, JID, Type).
+in_subscription(_, User, Server, JID, Type) ->
+ process_subscription(in, User, Server, JID, Type).
-out_subscription(User, JID, Type) ->
- process_subscription(out, User, JID, Type).
+out_subscription(User, Server, JID, Type) ->
+ process_subscription(out, User, Server, JID, Type).
-process_subscription(Direction, User, JID1, Type) ->
+process_subscription(Direction, User, Server, JID1, Type) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
LJID = jlib:jid_tolower(JID1),
Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
Item = case catch ejabberd_odbc:sql_query(
+ LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "' "
ask = Pending},
ItemVals = record_to_string(NewItem),
catch ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"delete from rosterusers "
" where username='", Username, "' "
in_auto_reply(_, _, _) -> none.
-remove_user(User) ->
+remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
catch ejabberd_odbc:sql_query(
+ LServer,
["begin;"
"delete from rosterusers "
" where username='", Username, "';"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-set_items(User, SubEl) ->
+set_items(User, Server, SubEl) ->
{xmlelement, _Name, _Attrs, Els} = SubEl,
LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
F = fun() ->
- lists:foreach(fun(El) -> process_item_set_t(LUser, El) end, Els)
+ lists:foreach(fun(El) ->
+ process_item_set_t(LUser, LServer, El)
+ end, Els)
end,
mnesia:transaction(F).
-process_item_set_t(LUser, {xmlelement, _Name, Attrs, Els}) ->
+process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
case JID1 of
error ->
_ ->
mnesia:write(Item2)
end
+ % TODO
+ %case Item2#roster.subscription of
+ % remove ->
+ % catch ejabberd_odbc:sql_query(
+ % LServer,
+ % ["begin;"
+ % "delete from rosterusers "
+ % " where username='", Username, "' "
+ % " and jid='", SJID, "';"
+ % "delete from rostergroups "
+ % " where username='", Username, "' "
+ % " and jid='", SJID, "';"
+ % "commit"]);
+ % _ ->
+ % ItemVals = record_to_string(Item1),
+ % catch ejabberd_odbc:sql_query(
+ % LServer,
+ % ["begin;"
+ % "delete from rosterusers "
+ % " where username='", Username, "' "
+ % " and jid='", SJID, "';"
+ % "insert into rosterusers("
+ % " username, jid, nick, "
+ % " subscription, ask, "
+ % " server, subscribe, type) "
+ % " values ", ItemVals, ";"
+ % "delete from rostergroups "
+ % " where username='", Username, "' "
+ % " and jid='", SJID, "';"
+ % % TODO
+ % "commit"])
+ %end
end;
-process_item_set_t(_LUser, _) ->
+process_item_set_t(_LUser, _LServer, _) ->
ok.
process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_jid_info(_, User, JID) ->
+get_jid_info(_, User, Server, JID) ->
% TODO
% LUser = jlib:nodeprep(User),
% LJID = jlib:jid_tolower(JID),
% end
% end
% end.
-{none, []}.
+ {none, []}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc),
- catch mod_disco:register_sm_feature(?NS_VCARD),
+ catch mod_disco:register_sm_feature(Host, ?NS_VCARD),
Hosts = gen_mod:get_hosts(Opts, "vjud."),
Search = gen_mod:get_opt(search, Opts, true),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
-behaviour(gen_server).
%% External exports
--export([start/0, start_link/0,
- sql_query/1,
+-export([start/1, start_link/1,
+ sql_query/2,
escape/1]).
%% gen_server callbacks
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start() ->
- gen_server:start(ejabberd_odbc, [], []).
+start(Host) ->
+ gen_server:start(ejabberd_odbc, [Host], []).
-start_link() ->
- gen_server:start_link(ejabberd_odbc, [], []).
+start_link(Host) ->
+ gen_server:start_link(ejabberd_odbc, [Host], []).
-sql_query(Query) ->
- gen_server:call(ejabberd_odbc_sup:get_random_pid(),
+sql_query(Host, Query) ->
+ gen_server:call(ejabberd_odbc_sup:get_random_pid(Host),
{sql_query, Query}, 60000).
escape(S) ->
%% ignore |
%% {stop, Reason}
%%----------------------------------------------------------------------
-init([]) ->
- {ok, Ref} = odbc:connect(ejabberd_config:get_local_option(odbc_server),
+init([Host]) ->
+ {ok, Ref} = odbc:connect(ejabberd_config:get_local_option(
+ {odbc_server, Host}),
[{scrollable_cursors, off}]),
{ok, #state{odbc_ref = Ref}}.
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start_link/0,
+-export([start_link/1,
init/1,
- get_pids/0,
- get_random_pid/0
+ get_pids/1,
+ get_random_pid/1
]).
-include("ejabberd.hrl").
-start_link() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+start_link(Host) ->
+ supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)},
+ ?MODULE, [Host]).
-init(_) ->
+init([Host]) ->
% TODO
N = 10,
{ok, {{one_for_one, 10, 1},
lists:map(
fun(I) ->
{I,
- {ejabberd_odbc, start_link, []},
+ {ejabberd_odbc, start_link, [Host]},
transient,
brutal_kill,
worker,
[?MODULE]}
end, lists:seq(1, N))}}.
-get_pids() ->
+get_pids(Host) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
[Child ||
- {_Id, Child, _Type, _Modules} <- supervisor:which_children(?MODULE),
+ {_Id, Child, _Type, _Modules} <- supervisor:which_children(Proc),
Child /= undefined].
-get_random_pid() ->
- Pids = get_pids(),
+get_random_pid(Host) ->
+ Pids = get_pids(Host),
lists:nth(erlang:phash(now(), length(Pids)), Pids).