25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-30 16:36:29 +01:00

Convert to exmpp.

SVN Revision: 1464
This commit is contained in:
Jean-Sébastien Pédron 2008-07-21 15:30:32 +00:00
parent 6e91399922
commit b33ac47228
3 changed files with 311 additions and 305 deletions

View File

@ -4,7 +4,8 @@
the new format to a built-in list of modules known to support them. the new format to a built-in list of modules known to support them.
Other modules will still receive arguments in the old format. Other modules will still receive arguments in the old format.
* src/mod_roster.erl, src/gen_iq_handler.erl: Convert to exmpp. * src/mod_roster.erl, src/mod_vcard.erl, src/gen_iq_handler.erl:
Convert to exmpp.
2008-07-17 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-07-17 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>

View File

@ -59,7 +59,8 @@
% XXX OLD FORMAT: modules not in the following list will receive % XXX OLD FORMAT: modules not in the following list will receive
% old format strudctures. % old format strudctures.
-define(CONVERTED_MODULES, [ -define(CONVERTED_MODULES, [
mod_roster mod_roster,
mod_vcard
]). ]).
%%==================================================================== %%====================================================================

View File

@ -36,8 +36,9 @@
reindex_vcards/0, reindex_vcards/0,
remove_user/2]). remove_user/2]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl").
-define(JUD_MATCHES, 30). -define(JUD_MATCHES, 30).
@ -83,9 +84,11 @@ start(Host, Opts) ->
ejabberd_hooks:add(remove_user, Host, ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD, % XXX OLD FORMAT: NS as string.
gen_iq_handler:add_iq_handler(ejabberd_local, Host, atom_to_list(?NS_VCARD),
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, % XXX OLD FORMAT: NS as string.
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, atom_to_list(?NS_VCARD),
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"), MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"),
@ -123,8 +126,12 @@ loop(Host, ServerHost) ->
stop(Host) -> stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), % XXX OLD FORMAT: NS as string.
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
atom_to_list(?NS_VCARD)),
% XXX OLD FORMAT: NS as string.
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
atom_to_list(?NS_VCARD)),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop, Proc ! stop,
@ -138,51 +145,53 @@ get_sm_features(Acc, _From, _To, Node, _Lang) ->
[] -> [] ->
case Acc of case Acc of
{result, Features} -> {result, Features} ->
{result, [?NS_VCARD | Features]}; % XXX OLD FORMAT: NS as string.
{result, [atom_to_list(?NS_VCARD) | Features]};
empty -> empty ->
{result, [?NS_VCARD]} % XXX OLD FORMAT: NS as string.
{result, [atom_to_list(?NS_VCARD)]}
end; end;
_ -> _ ->
Acc Acc
end. end.
process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> process_local_iq(_From, _To, IQ) ->
case Type of case exmpp_iq:get_type(IQ) of
set -> set ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; exmpp_iq:error(IQ, 'not-allowed');
get -> get ->
IQ#iq{type = result, Lang = case exmpp_stanza:get_lang(IQ) of
sub_el = [{xmlelement, "vCard", undefined -> "";
[{"xmlns", ?NS_VCARD}], L -> L
[{xmlelement, "FN", [], end,
[{xmlcdata, "ejabberd"}]}, Result = #xmlel{ns = ?NS_VCARD, name = 'vCard', children = [
{xmlelement, "URL", [], exmpp_xml:set_cdata(#xmlel{ns = ?NS_VCARD, name = 'FN'},
[{xmlcdata, ?EJABBERD_URI}]}, "ejabberd"),
{xmlelement, "DESC", [], exmpp_xml:set_cdata(#xmlel{ns = ?NS_VCARD, name = 'URL'},
[{xmlcdata, ?EJABBERD_URI),
translate:translate( exmpp_xml:set_cdata(#xmlel{ns = ?NS_VCARD, name = 'DESC'},
Lang, translate:translate(Lang, "Erlang Jabber Server") ++
"Erlang Jabber Server") ++ "\nCopyright (c) 2002-2008 ProcessOne"),
"\nCopyright (c) 2002-2008 ProcessOne"}]}, exmpp_xml:set_cdata(#xmlel{ns = ?NS_VCARD, name = 'BDAY'},
{xmlelement, "BDAY", [], "2002-11-16")
[{xmlcdata, "2002-11-16"}]} ]},
]}]} exmpp_iq:result(IQ, Result)
end. end.
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> process_sm_iq(From, To, IQ) ->
case Type of case exmpp_iq:get_type(IQ) of
set -> set ->
#jid{user = User, lserver = LServer} = From, #jid{node = User, ldomain = LServer} = From,
case lists:member(LServer, ?MYHOSTS) of case lists:member(LServer, ?MYHOSTS) of
true -> true ->
set_vcard(User, LServer, SubEl), set_vcard(User, LServer, exmpp_iq:get_request(IQ)),
IQ#iq{type = result, sub_el = []}; exmpp_iq:result(IQ);
false -> false ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} exmpp_iq:error(IQ, 'not-allowed')
end; end;
get -> get ->
#jid{luser = LUser, lserver = LServer} = To, #jid{lnode = LUser, ldomain = LServer} = To,
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
mnesia:read({vcard, US}) mnesia:read({vcard, US})
@ -190,27 +199,46 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
Els = case mnesia:transaction(F) of Els = case mnesia:transaction(F) of
{atomic, Rs} -> {atomic, Rs} ->
lists:map(fun(R) -> lists:map(fun(R) ->
R#vcard.vcard case R#vcard.vcard of
#xmlel{} = E ->
E;
#xmlelement{} = E ->
% XXX OLD FORMAT: Base contains old elements.
io:format("VCARD: Old element in base: ~p~n", [E]),
exmpp_xml:xmlelement_to_xmlel(E, [?NS_VCARD], [])
end
end, Rs); end, Rs);
{aborted, _Reason} -> {aborted, _Reason} ->
[] []
end, end,
IQ#iq{type = result, sub_el = Els} exmpp_iq:result(IQ, Els)
end. end.
set_vcard(User, LServer, VCARD) -> set_vcard(User, LServer, VCARD) ->
FN = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]), FN = exmpp_xml:get_path(VCARD,
Family = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"}, cdata]), [{element, 'FN'}, cdata_as_list]),
Given = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "GIVEN"}, cdata]), Family = exmpp_xml:get_path(VCARD,
Middle = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "MIDDLE"}, cdata]), [{element, 'N'}, {element, 'FAMILY'}, cdata_as_list]),
Nickname = xml:get_path_s(VCARD, [{elem, "NICKNAME"}, cdata]), Given = exmpp_xml:get_path(VCARD,
BDay = xml:get_path_s(VCARD, [{elem, "BDAY"}, cdata]), [{element, 'N'}, {element, 'GIVEN'}, cdata_as_list]),
CTRY = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "CTRY"}, cdata]), Middle = exmpp_xml:get_path(VCARD,
Locality = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "LOCALITY"},cdata]), [{element, 'N'}, {element, 'MIDDLE'}, cdata_as_list]),
EMail1 = xml:get_path_s(VCARD, [{elem, "EMAIL"}, {elem, "USERID"},cdata]), Nickname = exmpp_xml:get_path(VCARD,
EMail2 = xml:get_path_s(VCARD, [{elem, "EMAIL"}, cdata]), [{element, 'NICKNAME'}, cdata_as_list]),
OrgName = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]), BDay = exmpp_xml:get_path(VCARD,
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]), [{element, 'BDAY'}, cdata_as_list]),
CTRY = exmpp_xml:get_path(VCARD,
[{element, 'ADR'}, {element, 'CTRY'}, cdata_as_list]),
Locality = exmpp_xml:get_path(VCARD,
[{element, 'ADR'}, {element, 'LOCALITY'}, cdata_as_list]),
EMail1 = exmpp_xml:get_path(VCARD,
[{element, 'EMAIL'}, {element, 'USERID'}, cdata_as_list]),
EMail2 = exmpp_xml:get_path(VCARD,
[{element, 'EMAIL'}, cdata_as_list]),
OrgName = exmpp_xml:get_path(VCARD,
[{element, 'ORG'}, {element, 'ORGNAME'}, cdata_as_list]),
OrgUnit = exmpp_xml:get_path(VCARD,
[{element, 'ORG'}, {element, 'ORGUNIT'}, cdata_as_list]),
EMail = case EMail1 of EMail = case EMail1 of
"" -> "" ->
EMail2; EMail2;
@ -218,76 +246,70 @@ set_vcard(User, LServer, VCARD) ->
EMail1 EMail1
end, end,
LUser = jlib:nodeprep(User), try
LFN = stringprep:tolower(FN), LUser = exmpp_stringprep:nodeprep(User),
LFamily = stringprep:tolower(Family), LFN = exmpp_stringprep:to_lower(FN),
LGiven = stringprep:tolower(Given), LFamily = exmpp_stringprep:to_lower(Family),
LMiddle = stringprep:tolower(Middle), LGiven = exmpp_stringprep:to_lower(Given),
LNickname = stringprep:tolower(Nickname), LMiddle = exmpp_stringprep:to_lower(Middle),
LBDay = stringprep:tolower(BDay), LNickname = exmpp_stringprep:to_lower(Nickname),
LCTRY = stringprep:tolower(CTRY), LBDay = exmpp_stringprep:to_lower(BDay),
LLocality = stringprep:tolower(Locality), LCTRY = exmpp_stringprep:to_lower(CTRY),
LEMail = stringprep:tolower(EMail), LLocality = exmpp_stringprep:to_lower(Locality),
LOrgName = stringprep:tolower(OrgName), LEMail = exmpp_stringprep:to_lower(EMail),
LOrgUnit = stringprep:tolower(OrgUnit), LOrgName = exmpp_stringprep:to_lower(OrgName),
LOrgUnit = exmpp_stringprep:to_lower(OrgUnit),
US = {LUser, LServer}, US = {LUser, LServer},
if F = fun() ->
(LUser == error) or % XXX OLD FORMAT: We keep persistent data in the old format
(LFN == error) or % for now.
(LFamily == error) or VCARDOld = exmpp_xml:xmlel_to_xmlelement(VCARD, [?NS_VCARD], []),
(LGiven == error) or mnesia:write(#vcard{us = US, vcard = VCARDOld}),
(LMiddle == error) or mnesia:write(
(LNickname == error) or #vcard_search{us = US,
(LBDay == error) or user = {User, LServer},
(LCTRY == error) or luser = LUser,
(LLocality == error) or fn = FN, lfn = LFN,
(LEMail == error) or family = Family, lfamily = LFamily,
(LOrgName == error) or given = Given, lgiven = LGiven,
(LOrgUnit == error) -> middle = Middle, lmiddle = LMiddle,
{error, badarg}; nickname = Nickname, lnickname = LNickname,
true -> bday = BDay, lbday = LBDay,
F = fun() -> ctry = CTRY, lctry = LCTRY,
mnesia:write(#vcard{us = US, vcard = VCARD}), locality = Locality, llocality = LLocality,
mnesia:write( email = EMail, lemail = LEMail,
#vcard_search{us = US, orgname = OrgName, lorgname = LOrgName,
user = {User, LServer}, orgunit = OrgUnit, lorgunit = LOrgUnit
luser = LUser, })
fn = FN, lfn = LFN, end,
family = Family, lfamily = LFamily, mnesia:transaction(F)
given = Given, lgiven = LGiven, catch
middle = Middle, lmiddle = LMiddle, _ ->
nickname = Nickname, lnickname = LNickname, {error, badarg}
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)
end. end.
-define(TLFIELD(Type, Label, Var), -define(TLFIELD(Type, Label, Var),
{xmlelement, "field", [{"type", Type}, #xmlel{ns = ?NS_VCARD, name = 'field', attrs = [
{"label", translate:translate(Lang, Label)}, #xmlattr{name = 'type', value = Type},
{"var", Var}], []}). #xmlattr{name = 'label', value = translate:translate(Lang, Label)},
#xmlattr{name = 'var', value = Var}]}).
-define(FORM(JID), -define(FORM(JID),
[{xmlelement, "instructions", [], [#xmlel{ns = ?NS_SEARCH, name = 'instructions', children =
[{xmlcdata, translate:translate(Lang, "You need an x:data capable client to search")}]}, [#xmlcdata{cdata = list_to_binary(translate:translate(Lang, "You need an x:data capable client to search"))}]},
{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], #xmlel{ns = ?NS_DATA_FORMS, name = 'x', attrs =
[{xmlelement, "title", [], [#xmlattr{name = 'type', value = "form"}], children =
[{xmlcdata, translate:translate(Lang, "Search users in ") ++ [#xmlel{ns = ?NS_DATA_FORMS, name = 'title', children =
jlib:jid_to_string(JID)}]}, [#xmlcdata{cdata = list_to_binary(translate:translate(Lang, "Search users in ") ++ jlib:jid_to_string(JID))}]},
{xmlelement, "instructions", [], #xmlel{ns = ?NS_SEARCH, name = 'instructions', children =
[{xmlcdata, translate:translate(Lang, "Fill in the form to search " [#xmlcdata{cdata = list_to_binary(translate:translate(Lang,
"for any matching Jabber User " "Fill in the form to search "
"(Add * to the end of field to " "for any matching Jabber User "
"match substring)")}]}, "(Add * to the end of field to "
"match substring)"))}]},
?TLFIELD("text-single", "User", "user"), ?TLFIELD("text-single", "User", "user"),
?TLFIELD("text-single", "Full Name", "fn"), ?TLFIELD("text-single", "Full Name", "fn"),
?TLFIELD("text-single", "Name", "first"), ?TLFIELD("text-single", "Name", "first"),
@ -306,157 +328,139 @@ set_vcard(User, LServer, VCARD) ->
do_route(ServerHost, From, To, Packet) -> do_route(ServerHost, From, To, Packet) ->
#jid{user = User, resource = Resource} = To, #jid{node = User, resource = Resource} = To,
if if
(User /= "") or (Resource /= "") -> (User /= undefined) or (Resource /= undefined) ->
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), Err = exmpp_stanza:reply_with_error(Packet, 'service-unavailable'),
ejabberd_router ! {route, To, From, Err}; ejabberd_router ! {route, To, From, Err};
true -> true ->
IQ = jlib:iq_query_info(Packet), try
case IQ of Request = exmpp_iq:get_request(Packet),
#iq{type = Type, xmlns = ?NS_SEARCH, lang = Lang, sub_el = SubEl} -> Type = exmpp_iq:get_type(Packet),
case Type of Lang = exmpp_stanza:get_lang(Packet),
set -> case {Type, Request#xmlel.ns} of
XDataEl = find_xdata_el(SubEl), {set, ?NS_SEARCH} ->
case XDataEl of XDataEl = find_xdata_el(Request),
false -> case XDataEl of
Err = jlib:make_error_reply( false ->
Packet, ?ERR_BAD_REQUEST), Err = exmpp_iq:error(Packet, 'bad-request'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
_ -> _ ->
XData = jlib:parse_xdata_submit(XDataEl), XData = jlib:parse_xdata_submit(XDataEl),
case XData of case XData of
invalid -> invalid ->
Err = jlib:make_error_reply( Err = exmpp_iq:error(Packet,
Packet, 'bad-request'),
?ERR_BAD_REQUEST), ejabberd_router:route(To, From,
ejabberd_router:route(To, From, Err);
Err); _ ->
_ -> Result = #xmlel{
ResIQ = ns = ?NS_SEARCH,
IQ#iq{ name = 'query',
type = result, children = [
sub_el = #xmlel{
[{xmlelement, ns = ?NS_DATA_FORMS,
"query", name = 'x',
[{"xmlns", ?NS_SEARCH}], attrs = [#xmlattr{name = 'type',
[{xmlelement, "x", value = "result"}],
[{"xmlns", ?NS_XDATA}, children = search_result(Lang,
{"type", "result"}], To, ServerHost, XData)}]},
search_result(Lang, To, ServerHost, XData) ResIQ = exmpp_iq:result(Packet,
}]}]}, Result),
ejabberd_router:route( ejabberd_router:route(
To, From, jlib:iq_to_xml(ResIQ)) To, From, ResIQ)
end end
end; end;
get -> {get, ?NS_SEARCH} ->
ResIQ = IQ#iq{type = result, Result = #xmlel{ns = ?NS_SEARCH, name = 'query',
sub_el = [{xmlelement, children = ?FORM(To)},
"query", ResIQ = exmpp_iq:result(Packet, Result),
[{"xmlns", ?NS_SEARCH}], ejabberd_router:route(To,
?FORM(To) From,
}]}, ResIQ);
ejabberd_router:route(To, {set, ?NS_DISCO_INFO} ->
From, Err = exmpp_iq:error(Packet, 'not-allowed'),
jlib:iq_to_xml(ResIQ)) ejabberd_router:route(To, From, Err);
end; {get, ?NS_DISCO_INFO} ->
#iq{type = Type, xmlns = ?NS_DISCO_INFO, lang = Lang} -> Result = #xmlel{ns = ?NS_DISCO_INFO, name = 'query',
case Type of children = [
set -> #xmlel{ns = ?NS_DISCO_INFO, name = 'identity',
Err = jlib:make_error_reply( attrs = [
Packet, ?ERR_NOT_ALLOWED), #xmlattr{name = 'category',
ejabberd_router:route(To, From, Err); value = "directory"},
get -> #xmlattr{name = 'type',
ResIQ = value = "user"},
IQ#iq{type = result, #xmlattr{name = 'name',
sub_el = [{xmlelement, value = translate:translate(Lang,
"query", "vCard User Search")}]},
[{"xmlns", ?NS_DISCO_INFO}], #xmlel{ns = ?NS_DISCO_INFO, name = 'feature',
[{xmlelement, "identity", attrs = [
[{"category", "directory"}, #xmlattr{name = 'var',
{"type", "user"}, value = atom_to_list(?NS_SEARCH)}]},
{"name", #xmlel{ns = ?NS_DISCO_INFO, name = 'feature',
translate:translate(Lang, "vCard User Search")}], attrs = [
[]}, #xmlattr{name = 'var',
{xmlelement, "feature", value = atom_to_list(?NS_VCARD)}]}
[{"var", ?NS_SEARCH}], []}, ]},
{xmlelement, "feature", ResIQ = exmpp_iq:result(Packet, Result),
[{"var", ?NS_VCARD}], []} ejabberd_router:route(To,
] From,
}]}, ResIQ);
ejabberd_router:route(To, {set, ?NS_DISCO_ITEMS} ->
From, Err = exmpp_iq:error(Packet, 'not-allowed'),
jlib:iq_to_xml(ResIQ)) ejabberd_router:route(To, From, Err);
end; {get, ?NS_DISCO_ITEMS} ->
#iq{type = Type, xmlns = ?NS_DISCO_ITEMS} -> Result = #xmlel{ns = ?NS_DISCO_ITEMS, name = 'query'},
case Type of ResIQ = exmpp_iq:result(Packet, Result),
set -> ejabberd_router:route(To,
Err = jlib:make_error_reply( From,
Packet, ?ERR_NOT_ALLOWED), ResIQ);
ejabberd_router:route(To, From, Err); {get, ?NS_VCARD} ->
get -> Result = #xmlel{ns = ?NS_VCARD, name = 'vCard',
ResIQ = children = iq_get_vcard(Lang)},
IQ#iq{type = result, ResIQ = exmpp_iq:result(Packet, Result),
sub_el = [{xmlelement, ejabberd_router:route(To,
"query", From,
[{"xmlns", ?NS_DISCO_ITEMS}], ResIQ);
[]}]}, _ ->
ejabberd_router:route(To, Err = exmpp_iq:error(Packet, 'service-unavailable'),
From, ejabberd_router:route(To, From, Err)
jlib:iq_to_xml(ResIQ)) end
end; catch
#iq{type = get, xmlns = ?NS_VCARD, lang = Lang} ->
ResIQ =
IQ#iq{type = result,
sub_el = [{xmlelement,
"vCard",
[{"xmlns", ?NS_VCARD}],
iq_get_vcard(Lang)}]},
ejabberd_router:route(To,
From,
jlib:iq_to_xml(ResIQ));
_ -> _ ->
Err = jlib:make_error_reply(Packet, Err1 = exmpp_iq:error(Packet, 'service-unavailable'),
?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err1)
ejabberd_router:route(To, From, Err)
end end
end. end.
iq_get_vcard(Lang) -> iq_get_vcard(Lang) ->
[{xmlelement, "FN", [], [
[{xmlcdata, "ejabberd/mod_vcard"}]}, #xmlel{ns = ?NS_SEARCH, name = 'FN', children = [
{xmlelement, "URL", [], #xmlcdata{cdata = <<"ejabberd/mod_vcard">>}]},
[{xmlcdata, ?EJABBERD_URI}]}, #xmlel{ns = ?NS_SEARCH, name = 'URL', children = [
{xmlelement, "DESC", [], #xmlcdata{cdata = list_to_binary(?EJABBERD_URI)}]},
[{xmlcdata, translate:translate( #xmlel{ns = ?NS_SEARCH, name ='DESC', children = [
Lang, #xmlcdata{cdata = list_to_binary(
"ejabberd vCard module") ++ translate:translate(Lang, "ejabberd vCard module") ++
"\nCopyright (c) 2003-2008 ProcessOne"}]}]. "\nCopyright (c) 2003-2008 ProcessOne")}]}
].
find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) -> find_xdata_el(#xmlel{children = SubEls}) ->
find_xdata_el1(SubEls). find_xdata_el1(SubEls).
find_xdata_el1([]) -> find_xdata_el1([]) ->
false; false;
find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) -> find_xdata_el1([#xmlel{ns = ?NS_DATA_FORMS} = El | _Els]) ->
case xml:get_attr_s("xmlns", Attrs) of El;
?NS_XDATA ->
{xmlelement, Name, Attrs, SubEls};
_ ->
find_xdata_el1(Els)
end;
find_xdata_el1([_ | Els]) -> find_xdata_el1([_ | Els]) ->
find_xdata_el1(Els). find_xdata_el1(Els).
-define(LFIELD(Label, Var),
{xmlelement, "field", [{"label", translate:translate(Lang, Label)},
{"var", Var}], []}).
search_result(Lang, JID, ServerHost, Data) -> search_result(Lang, JID, ServerHost, Data) ->
[{xmlelement, "title", [], [#xmlel{ns = ?NS_DATA_FORMS, name = 'title', children =
[{xmlcdata, translate:translate(Lang, "Search Results for ") ++ [#xmlcdata{cdata = list_to_binary(
jlib:jid_to_string(JID)}]}, translate:translate(Lang, "Search Results for ") ++
{xmlelement, "reported", [], exmpp_jid:jid_to_string(JID))}]},
#xmlel{ns = ?NS_DATA_FORMS, name = 'reported', children =
[?TLFIELD("text-single", "Jabber ID", "jid"), [?TLFIELD("text-single", "Jabber ID", "jid"),
?TLFIELD("text-single", "Full Name", "fn"), ?TLFIELD("text-single", "Full Name", "fn"),
?TLFIELD("text-single", "Name", "first"), ?TLFIELD("text-single", "Name", "first"),
@ -472,13 +476,14 @@ search_result(Lang, JID, ServerHost, Data) ->
]}] ++ lists:map(fun record_to_item/1, search(ServerHost, Data)). ]}] ++ lists:map(fun record_to_item/1, search(ServerHost, Data)).
-define(FIELD(Var, Val), -define(FIELD(Var, Val),
{xmlelement, "field", [{"var", Var}], #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs =
[{xmlelement, "value", [], [#xmlattr{name = 'var', value = Var}], children =
[{xmlcdata, Val}]}]}). [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children =
[#xmlcdata{cdata = list_to_binary(Val)}]}]}).
record_to_item(R) -> record_to_item(R) ->
{User, Server} = R#vcard_search.user, {User, Server} = R#vcard_search.user,
{xmlelement, "item", [], #xmlel{ns = ?NS_DATA_FORMS, name = 'item', children =
[ [
?FIELD("jid", User ++ "@" ++ Server), ?FIELD("jid", User ++ "@" ++ Server),
?FIELD("fn", R#vcard_search.fn), ?FIELD("fn", R#vcard_search.fn),
@ -599,61 +604,60 @@ set_vcard_t(R, _) ->
User = US, User = US,
VCARD = R#vcard.vcard, VCARD = R#vcard.vcard,
FN = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]), FN = exmpp_xml:get_path(VCARD,
Family = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"}, cdata]), [{element, 'FN'}, cdata_as_list]),
Given = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "GIVEN"}, cdata]), Family = exmpp_xml:get_path(VCARD,
Middle = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "MIDDLE"}, cdata]), [{element, 'N'}, {element, 'FAMILY'}, cdata_as_list]),
Nickname = xml:get_path_s(VCARD, [{elem, "NICKNAME"}, cdata]), Given = exmpp_xml:get_path(VCARD,
BDay = xml:get_path_s(VCARD, [{elem, "BDAY"}, cdata]), [{element, 'N'}, {element, 'GIVEN'}, cdata_as_list]),
CTRY = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "CTRY"}, cdata]), Middle = exmpp_xml:get_path(VCARD,
Locality = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "LOCALITY"},cdata]), [{element, 'N'}, {element, 'MIDDLE'}, cdata_as_list]),
EMail = xml:get_path_s(VCARD, [{elem, "EMAIL"}, cdata]), Nickname = exmpp_xml:get_path(VCARD,
OrgName = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]), [{element, 'NICKNAME'}, cdata_as_list]),
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]), BDay = exmpp_xml:get_path(VCARD,
[{element, 'BDAY'}, cdata_as_list]),
CTRY = exmpp_xml:get_path(VCARD,
[{element, 'ADR'}, {element, 'CTRY'}, cdata_as_list]),
Locality = exmpp_xml:get_path(VCARD,
[{element, 'ADR'}, {element, 'LOCALITY'},cdata_as_list]),
EMail = exmpp_xml:get_path(VCARD,
[{element, 'EMAIL'}, cdata_as_list]),
OrgName = exmpp_xml:get_path(VCARD,
[{element, 'ORG'}, {element, 'ORGNAME'}, cdata_as_list]),
OrgUnit = exmpp_xml:get_path(VCARD,
[{element, 'ORG'}, {element, 'ORGUNIT'}, cdata_as_list]),
{LUser, _LServer} = US, try
LFN = stringprep:tolower(FN), {LUser, _LServer} = US,
LFamily = stringprep:tolower(Family), LFN = exmpp_stringprep:to_lower(FN),
LGiven = stringprep:tolower(Given), LFamily = exmpp_stringprep:to_lower(Family),
LMiddle = stringprep:tolower(Middle), LGiven = exmpp_stringprep:to_lower(Given),
LNickname = stringprep:tolower(Nickname), LMiddle = exmpp_stringprep:to_lower(Middle),
LBDay = stringprep:tolower(BDay), LNickname = exmpp_stringprep:to_lower(Nickname),
LCTRY = stringprep:tolower(CTRY), LBDay = exmpp_stringprep:to_lower(BDay),
LLocality = stringprep:tolower(Locality), LCTRY = exmpp_stringprep:to_lower(CTRY),
LEMail = stringprep:tolower(EMail), LLocality = exmpp_stringprep:to_lower(Locality),
LOrgName = stringprep:tolower(OrgName), LEMail = exmpp_stringprep:to_lower(EMail),
LOrgUnit = stringprep:tolower(OrgUnit), LOrgName = exmpp_stringprep:to_lower(OrgName),
LOrgUnit = exmpp_stringprep:to_lower(OrgUnit),
if mnesia:write(
(LUser == error) or #vcard_search{us = US,
(LFN == error) or user = User, luser = LUser,
(LFamily == error) or fn = FN, lfn = LFN,
(LGiven == error) or family = Family, lfamily = LFamily,
(LMiddle == error) or given = Given, lgiven = LGiven,
(LNickname == error) or middle = Middle, lmiddle = LMiddle,
(LBDay == error) or nickname = Nickname, lnickname = LNickname,
(LCTRY == error) or bday = BDay, lbday = LBDay,
(LLocality == error) or ctry = CTRY, lctry = LCTRY,
(LEMail == error) or locality = Locality, llocality = LLocality,
(LOrgName == error) or email = EMail, lemail = LEMail,
(LOrgUnit == error) -> orgname = OrgName, lorgname = LOrgName,
{error, badarg}; orgunit = OrgUnit, lorgunit = LOrgUnit
true -> })
mnesia:write( catch
#vcard_search{us = US, _ ->
user = User, luser = LUser, {error, badarg}
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. end.
@ -665,8 +669,8 @@ reindex_vcards() ->
remove_user(User, Server) -> remove_user(User, Server) ->
LUser = jlib:nodeprep(User), LUser = exmpp_jid:nodeprep(User),
LServer = jlib:nameprep(Server), LServer = exmpp_jid:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
mnesia:delete({vcard, US}), mnesia:delete({vcard, US}),