summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2003-01-01 19:54:44 +0000
committerAlexey Shchepin <alexey@process-one.net>2003-01-01 19:54:44 +0000
commit201b4c602f241f7633be4f1b7f9dce0dabb1820c (patch)
treedbbe876124e3b29589ddd07a544d80f7b96518a4 /src
parent*** empty log message *** (diff)
*** empty log message ***
SVN Revision: 24
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_auth.erl6
-rw-r--r--src/ejabberd_local.erl4
-rw-r--r--src/ejabberd_sm.erl47
-rw-r--r--src/mod_disco.erl202
-rw-r--r--src/xml.erl8
5 files changed, 263 insertions, 4 deletions
diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl
index 86b6d3b4..63d136a2 100644
--- a/src/ejabberd_auth.erl
+++ b/src/ejabberd_auth.erl
@@ -23,7 +23,8 @@
try_register/2]).
%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ dirty_get_registered_users/0]).
-record(state, {}).
@@ -158,3 +159,6 @@ try_register(User, Password) ->
end,
mnesia:transaction(F).
+dirty_get_registered_users() ->
+ mnesia:dirty_all_keys(passwd).
+
diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl
index b75ffe08..c42a8a01 100644
--- a/src/ejabberd_local.erl
+++ b/src/ejabberd_local.erl
@@ -22,13 +22,14 @@ start() ->
register(ejabberd_local, spawn(ejabberd_local, init, [])),
mod_register:start(),
mod_roster:start(),
+ mod_disco:start(),
ok.
init() ->
MyDomain = ?MYNAME,
ejabberd_router:register_local_route(MyDomain),
loop(#state{mydomain = MyDomain,
- iqtable = ets:new(iqtable, [])}).
+ iqtable = ets:new(local_iqtable, [named_table])}).
loop(State) ->
receive
@@ -37,6 +38,7 @@ loop(State) ->
loop(State);
{register_iq_handler, XMLNS, Module, Function} ->
ets:insert(State#state.iqtable, {XMLNS, Module, Function}),
+ mod_disco:register_feature(XMLNS),
loop(State)
end.
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index 9ca41680..8c092eb3 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -13,7 +13,9 @@
-export([start/0, init/0, open_session/2, close_session/2,
get_user_resources/1,
set_presence/3,
- unset_presence/2]).
+ unset_presence/2,
+ dirty_get_sessions_list/0,
+ register_iq_handler/3]).
-include_lib("mnemosyne/include/mnemosyne.hrl").
-include("ejabberd.hrl").
@@ -41,6 +43,7 @@ init() ->
{attributes, record_info(fields, presence)}]),
mnesia:add_table_index(presence, user),
mnesia:subscribe(system),
+ ets:new(sm_iqtable, [named_table]),
loop().
loop() ->
@@ -61,6 +64,9 @@ loop() ->
{route, From, To, Packet} ->
do_route(From, To, Packet),
loop();
+ {register_iq_handler, XMLNS, Module, Function} ->
+ ets:insert(sm_iqtable, {XMLNS, Module, Function}),
+ loop();
_ ->
loop()
end.
@@ -231,6 +237,7 @@ do_route(From, To, Packet) ->
Packet}
end;
"iq" ->
+ process_iq(From, To, Packet),
% TODO
ok;
"broadcast" ->
@@ -313,3 +320,41 @@ get_user_present_resources(User) ->
[]
end.
+dirty_get_sessions_list() ->
+ mnesia:dirty_all_keys(session).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+process_iq(From, To, Packet) ->
+ IQ = jlib:iq_query_info(Packet),
+ case IQ of
+ {iq, ID, Type, XMLNS, SubEl} ->
+ case ets:lookup(sm_iqtable, XMLNS) of
+ [{_, Module, Function}] ->
+ ResIQ = apply(Module, Function, [From, To, IQ]),
+ if
+ ResIQ /= ignore ->
+ ejabberd_router ! {route,
+ To,
+ From,
+ jlib:iq_to_xml(ResIQ)};
+ true ->
+ ok
+ end;
+ [] ->
+ Err = jlib:make_error_reply(
+ Packet, "501", "Not Implemented"),
+ ejabberd_router ! {route, To, From, Err}
+ end;
+ reply ->
+ ok;
+ _ ->
+ Err = jlib:make_error_reply(Packet, "400", "Bad Request"),
+ ejabberd_router ! {route, To, From, Err},
+ ok
+ end.
+
+register_iq_handler(XMLNS, Module, Fun) ->
+ ejabberd_sm ! {register_iq_handler, XMLNS, Module, Fun}.
+
diff --git a/src/mod_disco.erl b/src/mod_disco.erl
new file mode 100644
index 00000000..16512ddf
--- /dev/null
+++ b/src/mod_disco.erl
@@ -0,0 +1,202 @@
+%%%----------------------------------------------------------------------
+%%% File : mod_disco.erl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose :
+%%% Created : 1 Jan 2003 by Alexey Shchepin <alex@alex.sevcom.net>
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(mod_disco).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-export([start/0, init/0,
+ process_local_iq_items/3,
+ process_local_iq_info/3,
+ process_sm_iq_items/3,
+ process_sm_iq_info/3,
+ 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").
+
+-define(EMPTY_INFO_RESULT,
+ {iq, ID, result, XMLNS, [{xmlelement, "query",
+ [{"xmlns", ?NS_DISCO_INFO}], []}]}).
+
+start() ->
+ ejabberd_local:register_iq_handler(?NS_DISCO_ITEMS,
+ ?MODULE, process_local_iq_items),
+ ejabberd_local:register_iq_handler(?NS_DISCO_INFO,
+ ?MODULE, process_local_iq_info),
+ ejabberd_sm:register_iq_handler(?NS_DISCO_ITEMS,
+ ?MODULE, process_sm_iq_items),
+ ejabberd_sm:register_iq_handler(?NS_DISCO_INFO,
+ ?MODULE, process_sm_iq_info),
+ register_feature("iq"),
+ register_feature("presence"),
+ register_feature("presence-invisible"),
+ ok.
+
+init() ->
+ ok.
+
+register_feature(Feature) ->
+ catch ets:new(disco_features, [named_table, ordered_set, public]),
+ ets:insert(disco_features, {Feature}).
+
+process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
+ [{"code", "405"}],
+ [{xmlcdata, "Not Allowed"}]}]};
+ get ->
+ case xml:get_tag_attr_s("node", SubEl) of
+ "" ->
+ Domains = [],
+ {iq, ID, result, XMLNS,
+ [{xmlelement,
+ "query",
+ [{"xmlns", ?NS_DISCO_ITEMS}],
+ Domains ++
+ [{xmlelement, "item",
+ [{"jid", jlib:jid_to_string(To)},
+ {"name", "Online Users"},
+ {"node", "online users"}], []},
+ {xmlelement, "item",
+ [{"jid", jlib:jid_to_string(To)},
+ {"name", "All Users"},
+ {"node", "all users"}], []}]
+ }]};
+ "online users" ->
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
+ get_online_users()
+ }]};
+ "all users" ->
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
+ get_all_users()
+ }]};
+ _ ->
+ {iq, ID, error, XMLNS,
+ [SubEl, {xmlelement, "error",
+ [{"code", "501"}],
+ [{xmlcdata, "Not Implemented"}]}]}
+ end
+ end.
+
+
+process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
+ [{"code", "405"}],
+ [{xmlcdata, "Not Allowed"}]}]};
+ get ->
+ case xml:get_tag_attr_s("node", SubEl) of
+ "" ->
+ Features = lists:map(fun feature_to_xml/1,
+ ets:tab2list(disco_features)),
+ {iq, ID, result, XMLNS, [{xmlelement,
+ "query",
+ [{"xmlns", ?NS_DISCO_INFO}],
+ [{xmlelement, "identity",
+ [{"category", "service"},
+ {"type", "jabber"},
+ {"name", "ejabberd"}], []}] ++
+ Features
+ }]};
+ "online users" -> ?EMPTY_INFO_RESULT;
+ "all users" -> ?EMPTY_INFO_RESULT;
+ _ ->
+ {iq, ID, error, XMLNS,
+ [SubEl, {xmlelement, "error",
+ [{"code", "501"}],
+ [{xmlcdata, "Not Implemented"}]}]}
+ end
+ end.
+
+
+feature_to_xml({Feature}) ->
+ {xmlelement, "feature", [{"var", Feature}], []}.
+
+
+get_online_users() ->
+ case catch ejabberd_sm:dirty_get_sessions_list() of
+ {'EXIT', Reason} ->
+ [];
+ URs ->
+ lists:map(fun({U, R}) ->
+ {xmlelement, "item",
+ [{"jid", U ++ "@" ++ ?MYNAME ++ "/" ++ R},
+ {"name", U}], []}
+ end, lists:sort(URs))
+ end.
+
+get_all_users() ->
+ case catch ejabberd_auth:dirty_get_registered_users() of
+ {'EXIT', Reason} ->
+ [];
+ Users ->
+ lists:map(fun(U) ->
+ {xmlelement, "item",
+ [{"jid", U ++ "@" ++ ?MYNAME},
+ {"name", U}], []}
+ end, lists:sort(Users))
+ end.
+
+
+process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ {User, _, _} = To,
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
+ [{"code", "405"}],
+ [{xmlcdata, "Not Allowed"}]}]};
+ get ->
+ case xml:get_tag_attr_s("node", SubEl) of
+ "" ->
+ {iq, ID, result, XMLNS,
+ [{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
+ get_user_resources(User)
+ }]};
+ _ ->
+ {iq, ID, error, XMLNS,
+ [SubEl, {xmlelement, "error",
+ [{"code", "501"}],
+ [{xmlcdata, "Not Implemented"}]}]}
+ end
+ end.
+
+
+process_sm_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+ case Type of
+ set ->
+ {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
+ [{"code", "405"}],
+ [{xmlcdata, "Not Allowed"}]}]};
+ get ->
+ case xml:get_tag_attr_s("node", SubEl) of
+ "" -> ?EMPTY_INFO_RESULT;
+ _ ->
+ {iq, ID, error, XMLNS,
+ [SubEl, {xmlelement, "error",
+ [{"code", "501"}],
+ [{xmlcdata, "Not Implemented"}]}]}
+ end
+ end.
+
+
+
+get_user_resources(User) ->
+ Rs = ejabberd_sm:get_user_resources(User),
+ lists:map(fun(R) ->
+ {xmlelement, "item",
+ [{"jid", User ++ "@" ++ ?MYNAME ++ "/" ++ R},
+ {"name", User}], []}
+ end, lists:sort(Rs)).
+
diff --git a/src/xml.erl b/src/xml.erl
index 3bdcb62f..17160736 100644
--- a/src/xml.erl
+++ b/src/xml.erl
@@ -12,7 +12,8 @@
-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_attr/2, get_attr_s/2,
+ get_tag_attr/2, get_tag_attr_s/2]).
element_to_string(El) ->
case El of
@@ -93,4 +94,9 @@ get_attr_s(AttrName, Attrs) ->
""
end.
+get_tag_attr(AttrName, {xmlelement, Name, Attrs, Els}) ->
+ get_attr(AttrName, Attrs).
+
+get_tag_attr_s(AttrName, {xmlelement, Name, Attrs, Els}) ->
+ get_attr_s(AttrName, Attrs).