* src/mod_disco.erl: Disco publishing support (thanks to Magnus
Henoch) SVN Revision: 409
This commit is contained in:
parent
83191198a1
commit
a83c99805a
|
@ -1,9 +1,12 @@
|
||||||
2005-09-04 Alexey Shchepin <alexey@sevcom.net>
|
2005-09-04 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/mod_disco.erl: Disco publishing support (thanks to Magnus
|
||||||
|
Henoch)
|
||||||
|
|
||||||
* src/mod_disco.erl: Functions register_sm_feature and
|
* src/mod_disco.erl: Functions register_sm_feature and
|
||||||
register_sm_node replaced with hooks (thanks to Sergei Golovan)
|
register_sm_node replaced with hooks (thanks to Sergei Golovan)
|
||||||
* src/mod_vcard.erl:
|
* src/mod_vcard.erl: Updated
|
||||||
* src/mod_vcard_ldap.erl:
|
* src/mod_vcard_ldap.erl: Likewise
|
||||||
|
|
||||||
* src/mod_disco.erl: Now mod_disco doesn't depend on mod_configure
|
* src/mod_disco.erl: Now mod_disco doesn't depend on mod_configure
|
||||||
(thanks to Sergei Golovan)
|
(thanks to Sergei Golovan)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
get_sm_identity/5,
|
get_sm_identity/5,
|
||||||
get_sm_features/5,
|
get_sm_features/5,
|
||||||
get_sm_items/5,
|
get_sm_items/5,
|
||||||
|
get_publish_items/5,
|
||||||
register_feature/2,
|
register_feature/2,
|
||||||
unregister_feature/2,
|
unregister_feature/2,
|
||||||
register_extra_domain/2,
|
register_extra_domain/2,
|
||||||
|
@ -32,7 +33,15 @@
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
-record(disco_publish, {owner_node, jid, name, node}).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
|
mnesia:create_table(disco_publish,
|
||||||
|
[{disc_only_copies, [node()]},
|
||||||
|
{attributes, record_info(fields, disco_publish)},
|
||||||
|
{type, bag}]),
|
||||||
|
mnesia:add_table_index(disco_publish, owner_node),
|
||||||
|
|
||||||
ejabberd_local:refresh_iq_handlers(),
|
ejabberd_local:refresh_iq_handlers(),
|
||||||
|
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
|
@ -49,6 +58,7 @@ start(Host, Opts) ->
|
||||||
register_feature(Host, "iq"),
|
register_feature(Host, "iq"),
|
||||||
register_feature(Host, "presence"),
|
register_feature(Host, "presence"),
|
||||||
register_feature(Host, "presence-invisible"),
|
register_feature(Host, "presence-invisible"),
|
||||||
|
register_feature(Host, "http://jabber.org/protocol/disco#publish"),
|
||||||
|
|
||||||
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
||||||
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
||||||
|
@ -62,9 +72,11 @@ start(Host, Opts) ->
|
||||||
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
|
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
|
||||||
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
|
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
|
||||||
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
|
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
|
||||||
|
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_publish_items, 75),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
|
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_publish_items, 75),
|
||||||
ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
|
ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100),
|
||||||
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
|
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 100),
|
||||||
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
|
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 100),
|
||||||
|
@ -237,7 +249,24 @@ get_vh_services(Host) ->
|
||||||
process_sm_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
|
process_sm_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
|
#jid{user = User, luser = LTo, lserver = ToServer} = To,
|
||||||
|
#jid{luser = LFrom, lserver = LServer} = From,
|
||||||
|
Self = (LTo == LFrom) andalso (ToServer == LServer),
|
||||||
|
Node = xml:get_tag_attr_s("node", SubEl),
|
||||||
|
if
|
||||||
|
Self, Node /= [] ->
|
||||||
|
%% Here, we treat disco publish attempts to your own JID.
|
||||||
|
{xmlelement, _, _, Items} = SubEl,
|
||||||
|
case process_disco_publish({LFrom, LServer}, Node, Items) of
|
||||||
|
ok ->
|
||||||
|
IQ#iq{type = result, sub_el = []};
|
||||||
|
{error, Err} ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, Err]}
|
||||||
|
end;
|
||||||
|
|
||||||
|
true ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
||||||
|
end;
|
||||||
get ->
|
get ->
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
SNode = xml:get_tag_attr_s("node", SubEl),
|
SNode = xml:get_tag_attr_s("node", SubEl),
|
||||||
|
@ -265,7 +294,7 @@ get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
|
||||||
Acc;
|
Acc;
|
||||||
|
|
||||||
get_sm_items(Acc,
|
get_sm_items(Acc,
|
||||||
#jid{luser = LFrom, lserver = LSFrom} = _From,
|
#jid{luser = LFrom, lserver = LSFrom},
|
||||||
#jid{user = User, server = Server, luser = LTo, lserver = LSTo} = _To,
|
#jid{user = User, server = Server, luser = LTo, lserver = LSTo} = _To,
|
||||||
[], _Lang) ->
|
[], _Lang) ->
|
||||||
Items = case Acc of
|
Items = case Acc of
|
||||||
|
@ -349,3 +378,111 @@ get_user_resources(User, Server) ->
|
||||||
{"name", User}], []}
|
{"name", User}], []}
|
||||||
end, lists:sort(Rs)).
|
end, lists:sort(Rs)).
|
||||||
|
|
||||||
|
|
||||||
|
get_publish_items(empty,
|
||||||
|
#jid{luser = LFrom, lserver = LSFrom},
|
||||||
|
#jid{user = User, server = Server, luser = LTo, lserver = LSTo} = _To,
|
||||||
|
Node, _Lang) ->
|
||||||
|
if
|
||||||
|
(LFrom == LTo) and (LSFrom == LSTo) ->
|
||||||
|
% Hack
|
||||||
|
SNode = join(Node, "/"),
|
||||||
|
retrieve_disco_publish({LTo, LSTo}, SNode);
|
||||||
|
true ->
|
||||||
|
empty
|
||||||
|
end;
|
||||||
|
get_publish_items(Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
join(List, Sep) ->
|
||||||
|
lists:foldl(fun(A, "") -> A;
|
||||||
|
(A, Acc) -> Acc ++ Sep ++ A
|
||||||
|
end, "", List).
|
||||||
|
|
||||||
|
process_disco_publish(User, Node, Items) ->
|
||||||
|
F = fun() ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({xmlelement, _Name, _Attrs, _SubEls} = Item) ->
|
||||||
|
Action = xml:get_tag_attr_s("action", Item),
|
||||||
|
Jid = xml:get_tag_attr_s("jid", Item),
|
||||||
|
PNode = xml:get_tag_attr_s("node", Item),
|
||||||
|
Name = xml:get_tag_attr_s("name", Item),
|
||||||
|
?INFO_MSG("Disco publish: ~p ~p ~p ~p ~p ~p~n",
|
||||||
|
[User, Action, Node, Jid, PNode, Name]),
|
||||||
|
|
||||||
|
%% The disco_publish table isn't strictly a "bag" table, as
|
||||||
|
%% entries with same jid and node combination are considered
|
||||||
|
%% the same, even if they have different names. Therefore,
|
||||||
|
%% we find a list of items to supersede.
|
||||||
|
SupersededItems = mnesia:match_object(
|
||||||
|
#disco_publish{owner_node = {User, Node},
|
||||||
|
jid = Jid,
|
||||||
|
node = PNode,
|
||||||
|
_ = '_'}),
|
||||||
|
case Action of
|
||||||
|
"update" ->
|
||||||
|
lists:map(
|
||||||
|
fun(O) ->
|
||||||
|
mnesia:delete_object(O)
|
||||||
|
end, SupersededItems),
|
||||||
|
mnesia:write(
|
||||||
|
#disco_publish{owner_node = {User, Node},
|
||||||
|
jid = Jid,
|
||||||
|
name = Name,
|
||||||
|
node = PNode});
|
||||||
|
"remove" ->
|
||||||
|
case SupersededItems of
|
||||||
|
[] ->
|
||||||
|
mnesia:abort({error, ?ERR_ITEM_NOT_FOUND});
|
||||||
|
_ ->
|
||||||
|
lists:map(
|
||||||
|
fun(O) ->
|
||||||
|
mnesia:delete_object(O)
|
||||||
|
end, SupersededItems)
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
%% invalid "action" attribute - return an error
|
||||||
|
mnesia:abort({error, ?ERR_BAD_REQUEST})
|
||||||
|
end;
|
||||||
|
({xmlcdata, _CDATA}) ->
|
||||||
|
ok
|
||||||
|
end, Items)
|
||||||
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{aborted, {error, _} = Error} ->
|
||||||
|
Error;
|
||||||
|
{atomic, _} ->
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
|
end.
|
||||||
|
|
||||||
|
retrieve_disco_publish(User, Node) ->
|
||||||
|
case catch mnesia:dirty_read({disco_publish, {User, Node}}) of
|
||||||
|
{'EXIT', _Reason} ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
|
[] ->
|
||||||
|
empty;
|
||||||
|
Items ->
|
||||||
|
{result,
|
||||||
|
lists:map(
|
||||||
|
fun(#disco_publish{jid = Jid,
|
||||||
|
name = Name,
|
||||||
|
node = PNode}) ->
|
||||||
|
{xmlelement, "item",
|
||||||
|
lists:append([[{"jid", Jid}],
|
||||||
|
case Name of
|
||||||
|
"" ->
|
||||||
|
[];
|
||||||
|
_ ->
|
||||||
|
[{"name", Name}]
|
||||||
|
end,
|
||||||
|
case PNode of
|
||||||
|
"" ->
|
||||||
|
[];
|
||||||
|
_ ->
|
||||||
|
[{"node", PNode}]
|
||||||
|
end]), []}
|
||||||
|
end, Items)}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue