aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2003-01-02 21:01:12 +0000
committerAlexey Shchepin <alexey@process-one.net>2003-01-02 21:01:12 +0000
commit44797c9524663c38600743ce3947d80472c849ae (patch)
treeaa710dfb3c7c36615ba214320ee065a0cc1d6fff /src
parent*** empty log message *** (diff)
*** empty log message ***
SVN Revision: 25
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_c2s.erl23
-rw-r--r--src/ejabberd_local.erl1
-rw-r--r--src/ejabberd_router.erl13
-rw-r--r--src/jlib.erl17
-rw-r--r--src/mod_disco.erl13
-rw-r--r--src/mod_register.erl6
-rw-r--r--src/mod_vcard.erl239
-rw-r--r--src/namespaces.hrl14
-rw-r--r--src/xml.erl33
9 files changed, 330 insertions, 29 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 170cfcec8..a61890356 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -24,6 +24,7 @@
terminate/3]).
-include("ejabberd.hrl").
+-include("namespaces.hrl").
-define(SETS, gb_sets).
@@ -288,6 +289,18 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
StateData
end,
{false, Attrs, NewSt};
+ "iq" ->
+ IQ = jlib:iq_query_info(Packet),
+ case IQ of
+ {iq, ID, Type, ?NS_VCARD, SubEl} ->
+ ResIQ = mod_vcard:process_sm_iq(From, To, IQ),
+ ejabberd_router:route(To,
+ From,
+ jlib:iq_to_xml(ResIQ)),
+ {false, Attrs, StateData};
+ _ ->
+ {true, Attrs, StateData}
+ end;
_ ->
{true, Attrs, StateData}
end,
@@ -315,6 +328,14 @@ terminate(Reason, StateName, StateData) ->
ejabberd_sm:close_session(StateData#state.user,
StateData#state.resource)
end,
+ From = {StateData#state.user,
+ StateData#state.server,
+ StateData#state.resource},
+ Packet = {xmlelement, "presence", [{"type", "unavailable"}], []},
+ ejabberd_sm:unset_presence(StateData#state.user,
+ StateData#state.resource),
+ presence_broadcast(From, StateData#state.pres_a, Packet),
+ presence_broadcast(From, StateData#state.pres_i, Packet),
StateData#state.sender ! close,
ok.
@@ -463,7 +484,7 @@ presence_update(From, Packet, StateData) ->
"unsubscribed" ->
StateData;
_ ->
- update_priority(jlib:get_subtag(Packet, "priority"), StateData),
+ update_priority(xml:get_subtag(Packet, "priority"), StateData),
FromUnavail = (StateData#state.pres_last == undefined) or
StateData#state.pres_invis,
?DEBUG("from unavail = ~p~n", [FromUnavail]),
diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl
index c42a8a019..0bb2181ea 100644
--- a/src/ejabberd_local.erl
+++ b/src/ejabberd_local.erl
@@ -23,6 +23,7 @@ start() ->
mod_register:start(),
mod_roster:start(),
mod_disco:start(),
+ mod_vcard:start(),
ok.
init() ->
diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl
index e28eeb741..b58bbdb9a 100644
--- a/src/ejabberd_router.erl
+++ b/src/ejabberd_router.erl
@@ -10,7 +10,8 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([route/3, register_route/1, register_local_route/1]).
+-export([route/3, register_route/1, register_local_route/1,
+ dirty_get_all_routes/0]).
-export([start/0, init/0]).
@@ -90,7 +91,7 @@ do_route(From, To, Packet) ->
[] ->
case mnesia:read({route, DstDomain}) of
[] ->
- error;
+ false;
[R] ->
{ok, R#route.node, R#route.pid}
end;
@@ -99,7 +100,7 @@ do_route(From, To, Packet) ->
end
end,
case mnesia:transaction(F) of
- {atomic, error} ->
+ {atomic, false} ->
ejabberd_s2s ! {route, From, To, Packet};
{atomic, {ok, Node, Pid}} ->
case node() of
@@ -125,3 +126,9 @@ register_route(Domain) ->
register_local_route(Domain) ->
ejabberd_router ! {register_local_route, Domain, self()}.
+
+dirty_get_all_routes() ->
+ lists:delete(?MYNAME,
+ lists:umerge(lists:sort(mnesia:dirty_all_keys(route)),
+ lists:sort(mnesia:dirty_all_keys(local_route)))).
+
diff --git a/src/jlib.erl b/src/jlib.erl
index 974117fde..6cafb9598 100644
--- a/src/jlib.erl
+++ b/src/jlib.erl
@@ -25,8 +25,7 @@
get_iq_namespace/1,
iq_query_info/1,
is_iq_request_type/1,
- iq_to_xml/1,
- get_subtag/2]).
+ iq_to_xml/1]).
%send_iq(From, To, ID, SubTags) ->
@@ -249,17 +248,3 @@ iq_to_xml({iq, ID, Type, _, SubEl}) ->
end.
-get_subtag({xmlelement, _, _, Els}, Name) ->
- get_subtag1(Els, Name).
-
-get_subtag1([El | Els], Name) ->
- case El of
- {xmlelement, Name, _, _} ->
- El;
- _ ->
- get_subtag1(Els, Name)
- end;
-get_subtag1([], _) ->
- false.
-
-
diff --git a/src/mod_disco.erl b/src/mod_disco.erl
index 16512ddf5..b49ef1be8 100644
--- a/src/mod_disco.erl
+++ b/src/mod_disco.erl
@@ -2,7 +2,7 @@
%%% File : mod_disco.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
-%%% Created : 1 Jan 2003 by Alexey Shchepin <alex@alex.sevcom.net>
+%%% Created : 1 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
@@ -18,9 +18,7 @@
register_feature/1]).
-include("ejabberd.hrl").
-
--define(NS_DISCO_ITEMS, "http://jabber.org/protocol/disco#items").
--define(NS_DISCO_INFO, "http://jabber.org/protocol/disco#info").
+-include("namespaces.hrl").
-define(EMPTY_INFO_RESULT,
{iq, ID, result, XMLNS, [{xmlelement, "query",
@@ -56,7 +54,9 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
get ->
case xml:get_tag_attr_s("node", SubEl) of
"" ->
- Domains = [],
+ Domains =
+ lists:map(fun domain_to_xml/1,
+ ejabberd_router:dirty_get_all_routes()),
{iq, ID, result, XMLNS,
[{xmlelement,
"query",
@@ -124,6 +124,9 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
feature_to_xml({Feature}) ->
{xmlelement, "feature", [{"var", Feature}], []}.
+domain_to_xml(Domain) ->
+ {xmlelement, "item", [{"jid", Domain}], []}.
+
get_online_users() ->
case catch ejabberd_sm:dirty_get_sessions_list() of
diff --git a/src/mod_register.erl b/src/mod_register.erl
index b9d5be87f..457ca31fc 100644
--- a/src/mod_register.erl
+++ b/src/mod_register.erl
@@ -25,9 +25,9 @@ init() ->
process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of
set ->
- UTag = jlib:get_subtag(SubEl, "username"),
- PTag = jlib:get_subtag(SubEl, "password"),
- RTag = jlib:get_subtag(SubEl, "remove"),
+ UTag = xml:get_subtag(SubEl, "username"),
+ PTag = xml:get_subtag(SubEl, "password"),
+ RTag = xml:get_subtag(SubEl, "remove"),
if
(UTag /= false) and (RTag /= false) ->
{iq, ID, error, XMLNS,
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
new file mode 100644
index 000000000..bdef5db63
--- /dev/null
+++ b/src/mod_vcard.erl
@@ -0,0 +1,239 @@
+%%%----------------------------------------------------------------------
+%%% File : mod_vcard.erl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose :
+%%% Created : 2 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% 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.
+
diff --git a/src/namespaces.hrl b/src/namespaces.hrl
new file mode 100644
index 000000000..15b3353ca
--- /dev/null
+++ b/src/namespaces.hrl
@@ -0,0 +1,14 @@
+%%%----------------------------------------------------------------------
+%%% File : namespaces.hrl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose :
+%%% Created : 2 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%%----------------------------------------------------------------------
+
+-define(NS_DISCO_ITEMS, "http://jabber.org/protocol/disco#items").
+-define(NS_DISCO_INFO, "http://jabber.org/protocol/disco#info").
+-define(NS_VCARD, "vcard-temp").
+-define(NS_SEARCH, "jabber:iq:search").
+-define(NS_XDATA, "jabber:x:data").
+
+
diff --git a/src/xml.erl b/src/xml.erl
index 171607361..00b7087d5 100644
--- a/src/xml.erl
+++ b/src/xml.erl
@@ -13,7 +13,9 @@
-export([element_to_string/1, crypt/1, remove_cdata/1,
get_cdata/1, get_tag_cdata/1,
get_attr/2, get_attr_s/2,
- get_tag_attr/2, get_tag_attr_s/2]).
+ get_tag_attr/2, get_tag_attr_s/2,
+ get_subtag/2,
+ get_path_s/2]).
element_to_string(El) ->
case El of
@@ -100,3 +102,32 @@ get_tag_attr(AttrName, {xmlelement, Name, Attrs, Els}) ->
get_tag_attr_s(AttrName, {xmlelement, Name, Attrs, Els}) ->
get_attr_s(AttrName, Attrs).
+
+get_subtag({xmlelement, _, _, Els}, Name) ->
+ get_subtag1(Els, Name).
+
+get_subtag1([El | Els], Name) ->
+ case El of
+ {xmlelement, Name, _, _} ->
+ El;
+ _ ->
+ get_subtag1(Els, Name)
+ end;
+get_subtag1([], _) ->
+ false.
+
+
+get_path_s(El, []) ->
+ El;
+get_path_s(El, [{elem, Name} | Path]) ->
+ case get_subtag(El, Name) of
+ false ->
+ "";
+ SubEl ->
+ get_path_s(SubEl, Path)
+ end;
+get_path_s(El, [{attr, Name}]) ->
+ get_tag_attr_s(Name, El);
+get_path_s(El, [cdata]) ->
+ get_tag_cdata(El).
+