Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_vcard.erl')
-rw-r--r--src/mod_vcard.erl319
1 files changed, 250 insertions, 69 deletions
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
index b796375f5..6381ec55c 100644
--- a/src/mod_vcard.erl
+++ b/src/mod_vcard.erl
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : mod_vcard.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : Vcard management in Mnesia
+%%% Purpose : Vcard management
%%% Created : 2 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
@@ -61,25 +61,32 @@
-define(PROCNAME, ejabberd_mod_vcard).
start(Host, Opts) ->
- mnesia:create_table(vcard, [{disc_only_copies, [node()]},
- {attributes, record_info(fields, vcard)}]),
- mnesia:create_table(vcard_search,
- [{disc_copies, [node()]},
- {attributes, record_info(fields, vcard_search)}]),
- update_tables(),
- mnesia:add_table_index(vcard_search, luser),
- mnesia:add_table_index(vcard_search, lfn),
- mnesia:add_table_index(vcard_search, lfamily),
- mnesia:add_table_index(vcard_search, lgiven),
- mnesia:add_table_index(vcard_search, lmiddle),
- mnesia:add_table_index(vcard_search, lnickname),
- mnesia:add_table_index(vcard_search, lbday),
- mnesia:add_table_index(vcard_search, lctry),
- mnesia:add_table_index(vcard_search, llocality),
- mnesia:add_table_index(vcard_search, lemail),
- mnesia:add_table_index(vcard_search, lorgname),
- mnesia:add_table_index(vcard_search, lorgunit),
-
+ case gen_mod:db_type(Opts) of
+ mnesia ->
+ mnesia:create_table(vcard,
+ [{disc_only_copies, [node()]},
+ {attributes,
+ record_info(fields, vcard)}]),
+ mnesia:create_table(vcard_search,
+ [{disc_copies, [node()]},
+ {attributes,
+ record_info(fields, vcard_search)}]),
+ update_tables(),
+ mnesia:add_table_index(vcard_search, luser),
+ mnesia:add_table_index(vcard_search, lfn),
+ mnesia:add_table_index(vcard_search, lfamily),
+ mnesia:add_table_index(vcard_search, lgiven),
+ mnesia:add_table_index(vcard_search, lmiddle),
+ mnesia:add_table_index(vcard_search, lnickname),
+ mnesia:add_table_index(vcard_search, lbday),
+ mnesia:add_table_index(vcard_search, lctry),
+ mnesia:add_table_index(vcard_search, llocality),
+ mnesia:add_table_index(vcard_search, lemail),
+ mnesia:add_table_index(vcard_search, lorgname),
+ mnesia:add_table_index(vcard_search, lorgunit);
+ _ ->
+ ok
+ end,
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
@@ -183,19 +190,45 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
end;
get ->
#jid{luser = LUser, lserver = LServer} = To,
- US = {LUser, LServer},
- F = fun() ->
- mnesia:read({vcard, US})
- end,
- Els = case mnesia:transaction(F) of
- {atomic, Rs} ->
- lists:map(fun(R) ->
- R#vcard.vcard
- end, Rs);
- {aborted, _Reason} ->
- []
- end,
- IQ#iq{type = result, sub_el = Els}
+ case get_vcard(LUser, LServer) of
+ error ->
+ IQ#iq{type = error,
+ sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
+ Els ->
+ IQ#iq{type = result, sub_el = Els}
+ end
+ end.
+
+get_vcard(LUser, LServer) ->
+ get_vcard(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)).
+
+get_vcard(LUser, LServer, mnesia) ->
+ US = {LUser, LServer},
+ F = fun() ->
+ mnesia:read({vcard, US})
+ end,
+ case mnesia:transaction(F) of
+ {atomic, Rs} ->
+ lists:map(fun(R) ->
+ R#vcard.vcard
+ end, Rs);
+ {aborted, _Reason} ->
+ error
+ end;
+get_vcard(LUser, LServer, odbc) ->
+ Username = ejabberd_odbc:escape(LUser),
+ case catch odbc_queries:get_vcard(LServer, Username) of
+ {selected, ["vcard"], [{SVCARD}]} ->
+ case xml_stream:parse_element(SVCARD) of
+ {error, _Reason} ->
+ error;
+ VCARD ->
+ [VCARD]
+ end;
+ {selected, ["vcard"], []} ->
+ [];
+ _ ->
+ error
end.
set_vcard(User, LServer, VCARD) ->
@@ -231,8 +264,6 @@ set_vcard(User, LServer, VCARD) ->
LOrgName = string2lower(OrgName),
LOrgUnit = string2lower(OrgUnit),
- US = {LUser, LServer},
-
if
(LUser == error) or
(LFN == error) or
@@ -248,26 +279,66 @@ set_vcard(User, LServer, VCARD) ->
(LOrgUnit == error) ->
{error, badarg};
true ->
- F = fun() ->
- mnesia:write(#vcard{us = US, vcard = VCARD}),
- mnesia:write(
- #vcard_search{us = US,
- user = {User, LServer},
- luser = LUser,
- fn = FN, lfn = LFN,
- family = Family, lfamily = LFamily,
- given = Given, lgiven = LGiven,
- middle = Middle, lmiddle = LMiddle,
- nickname = Nickname, lnickname = LNickname,
- bday = BDay, lbday = LBDay,
- ctry = CTRY, lctry = LCTRY,
- locality = Locality, llocality = LLocality,
- email = EMail, lemail = LEMail,
- orgname = OrgName, lorgname = LOrgName,
- orgunit = OrgUnit, lorgunit = LOrgUnit
- })
- end,
- mnesia:transaction(F),
+ case gen_mod:db_type(LServer, ?MODULE) of
+ mnesia ->
+ US = {LUser, LServer},
+ F = fun() ->
+ mnesia:write(#vcard{us = US, vcard = VCARD}),
+ mnesia:write(
+ #vcard_search{us = US,
+ user = {User, LServer},
+ luser = LUser,
+ fn = FN, lfn = LFN,
+ family = Family, lfamily = LFamily,
+ given = Given, lgiven = LGiven,
+ middle = Middle, lmiddle = LMiddle,
+ nickname = Nickname, lnickname = LNickname,
+ bday = BDay, lbday = LBDay,
+ ctry = CTRY, lctry = LCTRY,
+ locality = Locality, llocality = LLocality,
+ email = EMail, lemail = LEMail,
+ orgname = OrgName, lorgname = LOrgName,
+ orgunit = OrgUnit, lorgunit = LOrgUnit
+ })
+ end,
+ mnesia:transaction(F);
+ odbc ->
+ Username = ejabberd_odbc:escape(User),
+ LUsername = ejabberd_odbc:escape(LUser),
+ SVCARD = ejabberd_odbc:escape(
+ xml:element_to_binary(VCARD)),
+
+ SFN = ejabberd_odbc:escape(FN),
+ SLFN = ejabberd_odbc:escape(LFN),
+ SFamily = ejabberd_odbc:escape(Family),
+ SLFamily = ejabberd_odbc:escape(LFamily),
+ SGiven = ejabberd_odbc:escape(Given),
+ SLGiven = ejabberd_odbc:escape(LGiven),
+ SMiddle = ejabberd_odbc:escape(Middle),
+ SLMiddle = ejabberd_odbc:escape(LMiddle),
+ SNickname = ejabberd_odbc:escape(Nickname),
+ SLNickname = ejabberd_odbc:escape(LNickname),
+ SBDay = ejabberd_odbc:escape(BDay),
+ SLBDay = ejabberd_odbc:escape(LBDay),
+ SCTRY = ejabberd_odbc:escape(CTRY),
+ SLCTRY = ejabberd_odbc:escape(LCTRY),
+ SLocality = ejabberd_odbc:escape(Locality),
+ SLLocality = ejabberd_odbc:escape(LLocality),
+ SEMail = ejabberd_odbc:escape(EMail),
+ SLEMail = ejabberd_odbc:escape(LEMail),
+ SOrgName = ejabberd_odbc:escape(OrgName),
+ SLOrgName = ejabberd_odbc:escape(LOrgName),
+ SOrgUnit = ejabberd_odbc:escape(OrgUnit),
+ SLOrgUnit = ejabberd_odbc:escape(LOrgUnit),
+
+ odbc_queries:set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail,
+ SFN, SFamily, SGiven, SLBDay, SLCTRY,
+ SLEMail, SLFN, SLFamily, SLGiven,
+ SLLocality, SLMiddle, SLNickname,
+ SLOrgName, SLOrgUnit, SLocality,
+ SMiddle, SNickname, SOrgName,
+ SOrgUnit, SVCARD, Username)
+ end,
ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD])
end.
@@ -481,14 +552,34 @@ search_result(Lang, JID, ServerHost, Data) ->
?TLFIELD("text-single", "Email", "email"),
?TLFIELD("text-single", "Organization Name", "orgname"),
?TLFIELD("text-single", "Organization Unit", "orgunit")
- ]}] ++ lists:map(fun record_to_item/1, search(ServerHost, Data)).
+ ]}] ++ lists:map(fun(R) -> record_to_item(ServerHost, R) end,
+ search(ServerHost, Data)).
-define(FIELD(Var, Val),
{xmlelement, "field", [{"var", Var}],
[{xmlelement, "value", [],
[{xmlcdata, Val}]}]}).
-record_to_item(R) ->
+record_to_item(LServer, {Username, FN, Family, Given, Middle,
+ Nickname, BDay, CTRY, Locality,
+ EMail, OrgName, OrgUnit}) ->
+ {xmlelement, "item", [],
+ [
+ ?FIELD("jid", Username ++ "@" ++ LServer),
+ ?FIELD("fn", FN),
+ ?FIELD("last", Family),
+ ?FIELD("first", Given),
+ ?FIELD("middle", Middle),
+ ?FIELD("nick", Nickname),
+ ?FIELD("bday", BDay),
+ ?FIELD("ctry", CTRY),
+ ?FIELD("locality", Locality),
+ ?FIELD("email", EMail),
+ ?FIELD("orgname", OrgName),
+ ?FIELD("orgunit", OrgUnit)
+ ]
+ };
+record_to_item(_LServer, #vcard_search{} = R) ->
{User, Server} = R#vcard_search.user,
{xmlelement, "item", [],
[
@@ -509,9 +600,13 @@ record_to_item(R) ->
search(LServer, Data) ->
- MatchSpec = make_matchspec(LServer, Data),
+ DBType = gen_mod:db_type(LServer, ?MODULE),
+ MatchSpec = make_matchspec(LServer, Data, DBType),
AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE,
allow_return_all, false),
+ search(LServer, MatchSpec, AllowReturnAll, DBType).
+
+search(LServer, MatchSpec, AllowReturnAll, mnesia) ->
if
(MatchSpec == #vcard_search{_ = '_'}) and (not AllowReturnAll) ->
[];
@@ -535,17 +630,58 @@ search(LServer, Data) ->
lists:sublist(Rs, ?JUD_MATCHES)
end
end
+ end;
+search(LServer, MatchSpec, AllowReturnAll, odbc) ->
+ if
+ (MatchSpec == "") and (not AllowReturnAll) ->
+ [];
+ true ->
+ Limit = case gen_mod:get_module_opt(LServer, ?MODULE,
+ matches, ?JUD_MATCHES) of
+ infinity ->
+ "";
+ Val when is_integer(Val) and (Val > 0) ->
+ [" LIMIT ", integer_to_list(Val)];
+ Val ->
+ ?ERROR_MSG("Illegal option value ~p. "
+ "Default value ~p substituted.",
+ [{matches, Val}, ?JUD_MATCHES]),
+ [" LIMIT ", integer_to_list(?JUD_MATCHES)]
+ end,
+ case catch ejabberd_odbc:sql_query(
+ LServer,
+ ["select username, fn, family, given, middle, "
+ " nickname, bday, ctry, locality, "
+ " email, orgname, orgunit from vcard_search ",
+ MatchSpec, Limit, ";"]) of
+ {selected, ["username", "fn", "family", "given", "middle",
+ "nickname", "bday", "ctry", "locality",
+ "email", "orgname", "orgunit"],
+ Rs} when is_list(Rs) ->
+ Rs;
+ Error ->
+ ?ERROR_MSG("~p", [Error]),
+ []
+ end
end.
-
-make_matchspec(LServer, Data) ->
+make_matchspec(LServer, Data, mnesia) ->
GlobMatch = #vcard_search{_ = '_'},
- Match = filter_fields(Data, GlobMatch, LServer),
- Match.
+ Match = filter_fields(Data, GlobMatch, LServer, mnesia),
+ Match;
+make_matchspec(LServer, Data, odbc) ->
+ filter_fields(Data, "", LServer, odbc).
-filter_fields([], Match, _LServer) ->
+filter_fields([], Match, _LServer, mnesia) ->
Match;
-filter_fields([{SVar, [Val]} | Ds], Match, LServer)
+filter_fields([], Match, _LServer, odbc) ->
+ case Match of
+ "" ->
+ "";
+ _ ->
+ [" where ", Match]
+ end;
+filter_fields([{SVar, [Val]} | Ds], Match, LServer, mnesia)
when is_list(Val) and (Val /= "") ->
LVal = string2lower(Val),
NewMatch = case SVar of
@@ -571,9 +707,46 @@ filter_fields([{SVar, [Val]} | Ds], Match, LServer)
"orgunit" -> Match#vcard_search{lorgunit = make_val(LVal)};
_ -> Match
end,
- filter_fields(Ds, NewMatch, LServer);
-filter_fields([_ | Ds], Match, LServer) ->
- filter_fields(Ds, Match, LServer).
+ filter_fields(Ds, NewMatch, LServer, mnesia);
+filter_fields([{SVar, [Val]} | Ds], Match, LServer, odbc)
+ when is_list(Val) and (Val /= "") ->
+ LVal = string2lower(Val),
+ NewMatch = case SVar of
+ "user" -> make_val(Match, "lusername", LVal);
+ "fn" -> make_val(Match, "lfn", LVal);
+ "last" -> make_val(Match, "lfamily", LVal);
+ "first" -> make_val(Match, "lgiven", LVal);
+ "middle" -> make_val(Match, "lmiddle", LVal);
+ "nick" -> make_val(Match, "lnickname", LVal);
+ "bday" -> make_val(Match, "lbday", LVal);
+ "ctry" -> make_val(Match, "lctry", LVal);
+ "locality" -> make_val(Match, "llocality", LVal);
+ "email" -> make_val(Match, "lemail", LVal);
+ "orgname" -> make_val(Match, "lorgname", LVal);
+ "orgunit" -> make_val(Match, "lorgunit", LVal);
+ _ -> Match
+ end,
+ filter_fields(Ds, NewMatch, LServer, odbc);
+filter_fields([_ | Ds], Match, LServer, DBType) ->
+ filter_fields(Ds, Match, LServer, DBType).
+
+make_val(Match, Field, Val) ->
+ Condition =
+ case lists:suffix("*", Val) of
+ true ->
+ Val1 = lists:sublist(Val, length(Val) - 1),
+ SVal = ejabberd_odbc:escape_like(Val1) ++ "%",
+ [Field, " LIKE '", SVal, "'"];
+ _ ->
+ SVal = ejabberd_odbc:escape(Val),
+ [Field, " = '", SVal, "'"]
+ end,
+ case Match of
+ "" ->
+ Condition;
+ _ ->
+ [Match, " and ", Condition]
+ end.
make_val(Val) ->
case lists:suffix("*", Val) of
@@ -679,13 +852,21 @@ reindex_vcards() ->
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
+ remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)).
+
+remove_user(LUser, LServer, mnesia) ->
US = {LUser, LServer},
F = fun() ->
mnesia:delete({vcard, US}),
mnesia:delete({vcard_search, US})
end,
- mnesia:transaction(F).
-
+ mnesia:transaction(F);
+remove_user(LUser, LServer, odbc) ->
+ Username = ejabberd_odbc:escape(LUser),
+ ejabberd_odbc:sql_transaction(
+ LServer,
+ [["delete from vcard where username='", Username, "';"],
+ ["delete from vcard_search where lusername='", Username, "';"]]).
update_tables() ->
update_vcard_table(),