%%%---------------------------------------------------------------------- %%% File : mod_vcard.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Created : 2 Jan 2003 by Alexey Shchepin %%% Id : $Id$ %%%---------------------------------------------------------------------- -module(mod_vcard). -author('alexey@sevcom.net'). -vsn('$Revision$ '). -export([start/0, init/0, process_local_iq/3, process_sm_iq/3]). -include("ejabberd.hrl"). -include("namespaces.hrl"). -record(vcard_search, {user, fn, family, given, middle, nickname, bday, ctry, locality, email, orgname, orgunit}). -record(vcard, {user, vcard}). start() -> 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)}]), %mnesia:add_table_index(vcard_search, fn), %mnesia:add_table_index(vcard_search, n), %mnesia:add_table_index(vcard_search, nickname), %mnesia:add_table_index(vcard_search, bday), %mnesia:add_table_index(vcard_search, ctry), %mnesia:add_table_index(vcard_search, locality), %mnesia:add_table_index(vcard_search, email), %mnesia:add_table_index(vcard_search, orgname), %mnesia:add_table_index(vcard_search, orgunit), ejabberd_local:register_iq_handler(?NS_VCARD, ?MODULE, process_local_iq), ejabberd_sm:register_iq_handler(?NS_VCARD, ?MODULE, process_sm_iq), spawn(?MODULE, init, []). init() -> ejabberd_router:register_local_route("ejud." ++ ?MYNAME), loop(). loop() -> receive {route, From, To, Packet} -> do_route(From, To, Packet), loop(); _ -> loop() end. process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> case Type of set -> {User, Server, _} = From, LUser = jlib:tolower(User), LServer = jlib:tolower(Server), case ?MYNAME of LServer -> set_vcard(LUser, SubEl), {iq, ID, result, XMLNS, []}; _ -> {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error", [{"code", "405"}], [{xmlcdata, "Not Allowed"}]}]} end; get -> {iq, ID, result, XMLNS, [{xmlelement, "vCard", [{"xmlns", ?NS_VCARD}], [{xmlelement, "FN", [], [{xmlcdata, "ejabberd"}]}, {xmlelement, "URL", [], [{xmlcdata, "http://www.jabber.ru/projects/ejabberd/"}]}, {xmlelement, "DESC", [], [{xmlcdata, "Erlang Jabber Server\n" "Copyright (c) 2002, 2003 Alexey Shchepin"}]}, {xmlelement, "BDAY", [], [{xmlcdata, "20021116"}]} ]}]} end. process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> case Type of set -> {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error", [{"code", "405"}], [{xmlcdata, "Not Allowed"}]}]}; get -> {User, _, _} = To, LUser = jlib:tolower(User), F = fun() -> mnesia:read({vcard, LUser}) end, Els = case mnesia:transaction(F) of {atomic, Rs} -> lists:map(fun(R) -> R#vcard.vcard end, Rs); {aborted, Reason} -> [] end, {iq, ID, result, XMLNS, Els} end. set_vcard(LUser, VCARD) -> FN = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]), Family = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"}, cdata]), Given = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "GIVEN"}, cdata]), Middle = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "MIDDLE"}, cdata]), Nickname = xml:get_path_s(VCARD, [{elem, "NICKNAME"}, cdata]), BDay = xml:get_path_s(VCARD, [{elem, "BDAY"}, cdata]), %ctry = xml:get_path_s(VCARD, [{elem, "CTRY"}, cdata]), %locality = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]), EMail = xml:get_path_s(VCARD, [{elem, "EMAIL"}, cdata]), OrgName = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]), OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]), F = fun() -> mnesia:write(#vcard{user = LUser, vcard = VCARD}), mnesia:write(#vcard_search{user = LUser, fn = FN, family = Family, given = Given, middle = Middle, nickname = Nickname, bday = BDay, %ctry = CTRY, %locality = Locality, email = EMail, orgname = OrgName, orgunit = OrgUnit }) end, mnesia:transaction(F). -define(FORM, [{xmlelement, "instructions", [], [{xmlcdata, "You need a x:data capable client to search"}]}, {xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], [{xmlelement, "title", [], [{xmlcdata, "Users Search"}]}, {xmlelement, "instructions", [], [{xmlcdata, "Fill in fields to search " "for any matching Jabber User"}]}, {xmlelement, "field", [{"type", "text-single"}, {"label", "Full Name"}, {"var", "fn"}], []} ]}]). do_route(From, To, Packet) -> {User, Server, Resource} = To, if (User /= "") or (Resource /= "") -> Err = jlib:make_error_reply(Packet, "503", "Service Unavailable"), ejabberd_router ! {route, To, From, Err}; true -> IQ = jlib:iq_query_info(Packet), case IQ of {iq, ID, Type, ?NS_SEARCH, SubEl} -> case Type of set -> % TODO Err = jlib:make_error_reply( Packet, "501", "Not Implemented"), ejabberd_router:route(To, From, Err); get -> ResIQ = {iq, ID, result, ?NS_SEARCH, [{xmlelement, "query", [{"xmlns", ?NS_SEARCH}], ?FORM }]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; {iq, ID, Type, ?NS_DISCO_INFO, SubEl} -> case Type of set -> Err = jlib:make_error_reply( Packet, "405", "Not Allowed"), ejabberd_router:route(To, From, Err); get -> ResIQ = {iq, ID, result, ?NS_DISCO_INFO, [{xmlelement, "query", [{"xmlns", ?NS_DISCO_INFO}], [{xmlelement, "identity", [{"category", "directory"}, {"type", "user"}, {"name", "EJUD"}], []}, {xmlelement, "feature", [{"var", ?NS_SEARCH}], []} ] }]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; {iq, ID, Type, ?NS_DISCO_ITEMS, SubEl} -> case Type of set -> Err = jlib:make_error_reply( Packet, "405", "Not Allowed"), ejabberd_router:route(To, From, Err); get -> ResIQ = {iq, ID, result, ?NS_DISCO_INFO, [{xmlelement, "query", [{"xmlns", ?NS_DISCO_INFO}], []}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; _ -> Err = jlib:make_error_reply(Packet, "503", "Service Unavailable"), ejabberd_router:route(To, From, Err) end end.