25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

does not use slash as default separator in nodename (EJAB-667)

SVN Revision: 2687
This commit is contained in:
Christophe Romain 2009-10-20 15:03:07 +00:00
parent a232d16ff4
commit 8ce1e790ac
22 changed files with 423 additions and 267 deletions

View File

@ -68,7 +68,9 @@ behaviour_info(callbacks) ->
{get_item, 7}, {get_item, 7},
{get_item, 2}, {get_item, 2},
{set_item, 1}, {set_item, 1},
{get_item_name, 3} {get_item_name, 3},
{node_to_path, 1},
{path_to_node, 1}
]; ];
behaviour_info(_Other) -> behaviour_info(_Other) ->
undefined. undefined.

View File

@ -51,7 +51,7 @@ behaviour_info(callbacks) ->
{get_parentnodes_tree, 3}, {get_parentnodes_tree, 3},
{get_subnodes, 3}, {get_subnodes, 3},
{get_subnodes_tree, 3}, {get_subnodes_tree, 3},
{create_node, 5}, {create_node, 6},
{delete_node, 2} {delete_node, 2}
]; ];
behaviour_info(_Other) -> behaviour_info(_Other) ->

View File

@ -268,11 +268,11 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
ok. ok.
init_nodes(Host, ServerHost, _NodeTree, Plugins) -> init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
%% TODO, this call should be done PLugin side %% TODO, this call should be done plugin side
case lists:member("hometree", Plugins) of case lists:member("hometree", Plugins) of
true -> true ->
create_node(Host, ServerHost, ["home"], service_jid(Host), "hometree"), create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree"),
create_node(Host, ServerHost, ["home", ServerHost], service_jid(Host), "hometree"); create_node(Host, ServerHost, string_to_node("/home/"++ServerHost), service_jid(Host), "hometree");
false -> false ->
ok ok
end. end.
@ -403,7 +403,28 @@ update_node_database(Host, ServerHost) ->
rename_default_nodeplugin(); rename_default_nodeplugin();
_ -> _ ->
ok ok
end. end,
mnesia:transaction(fun() ->
case catch mnesia:first(pubsub_node) of
{_, L} when is_list(L) ->
lists:foreach(
fun({H, N}) when is_list(N) ->
[Node] = mnesia:read({pubsub_node, {H, N}}),
Type = Node#pubsub_node.type,
BN = element(2, node_call(Type, path_to_node, [N])),
BP = case [element(2, node_call(Type, path_to_node, [P])) || P <- Node#pubsub_node.parents] of
[<<>>] -> [];
Parents -> Parents
end,
mnesia:write(Node#pubsub_node{nodeid={H, BN}, parents=BP}),
mnesia:delete({pubsub_node, {H, N}});
(_) ->
ok
end, mnesia:all_keys(pubsub_node));
_ ->
ok
end
end).
rename_default_nodeplugin() -> rename_default_nodeplugin() ->
lists:foreach(fun(Node) -> lists:foreach(fun(Node) ->
@ -548,7 +569,7 @@ send_loop(State) ->
on_sub_and_presence -> on_sub_and_presence ->
lists:foreach(fun({Resource, Caps}) -> lists:foreach(fun({Resource, Caps}) ->
CapsNotify = case catch mod_caps:get_features(ServerHost, Caps) of CapsNotify = case catch mod_caps:get_features(ServerHost, Caps) of
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features); Features when is_list(Features) -> lists:member(node_to_string(Node) ++ "+notify", Features);
_ -> false _ -> false
end, end,
case CapsNotify of case CapsNotify of
@ -644,7 +665,7 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
disco_sm_items(Acc, From, To, [], _Lang) -> disco_sm_items(Acc, From, To, [], _Lang) ->
Host = To#jid.lserver, Host = To#jid.lserver,
case tree_action(Host, get_subnodes, [Host, [], From]) of case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
[] -> [] ->
Acc; Acc;
Nodes -> Nodes ->
@ -662,8 +683,9 @@ disco_sm_items(Acc, From, To, [], _Lang) ->
{result, NodeItems ++ Items} {result, NodeItems ++ Items}
end; end;
disco_sm_items(Acc, From, To, Node, _Lang) -> disco_sm_items(Acc, From, To, SNode, _Lang) ->
Host = To#jid.lserver, Host = To#jid.lserver,
Node = string_to_node(SNode),
Action = fun(#pubsub_node{type = Type, id = NodeId}) -> Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
% TODO call get_items/6 instead for access control (EJAB-1033) % TODO call get_items/6 instead for access control (EJAB-1033)
case node_call(Type, get_items, [NodeId, From]) of case node_call(Type, get_items, [NodeId, From]) of
@ -677,13 +699,8 @@ disco_sm_items(Acc, From, To, Node, _Lang) ->
end, end,
NodeItems = lists:map( NodeItems = lists:map(
fun(#pubsub_item{itemid = {Id, _}}) -> fun(#pubsub_item{itemid = {Id, _}}) ->
%% "jid" is required by XEP-0030, and
%% "node" is forbidden by XEP-0060.
{result, Name} = node_call(Type, get_item_name, [Host, Node, Id]), {result, Name} = node_call(Type, get_item_name, [Host, Node, Id]),
{xmlelement, "item", {xmlelement, "item", [{"jid", SBJID}, {"name", Name}], []}
[{"jid", SBJID},
{"name", Name}],
[]}
end, AllItems), end, AllItems),
{result, NodeItems ++ Items}; {result, NodeItems ++ Items};
_ -> _ ->
@ -1066,7 +1083,7 @@ iq_disco_info(Host, SNode, From, Lang) ->
end, end,
Node = string_to_node(RealSNode), Node = string_to_node(RealSNode),
case Node of case Node of
[] -> <<>> ->
{result, {result,
[{xmlelement, "identity", [{xmlelement, "identity",
[{"category", "pubsub"}, [{"category", "pubsub"},
@ -1085,24 +1102,17 @@ iq_disco_info(Host, SNode, From, Lang) ->
iq_disco_items(Host, [], From) -> iq_disco_items(Host, [], From) ->
{result, lists:map( {result, lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}, type = Type}) ->
SN = node_to_string(SubNode), {result, Path} = node_call(Type, node_to_path, [SubNode]),
RN = lists:last(SubNode), [Name|_] = lists:reverse(Path),
%% remove name attribute {xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
{xmlelement, "item", [{"jid", Host}, end, tree_action(Host, get_subnodes, [Host, <<>>, From]))};
{"node", SN},
{"name", RN}], []}
end, tree_action(Host, get_subnodes, [Host, [], From]))};
iq_disco_items(Host, Item, From) -> iq_disco_items(Host, Item, From) ->
case string:tokens(Item, "!") of case string:tokens(Item, "!") of
[_SNode, _ItemID] -> [_SNode, _ItemID] ->
{result, []}; {result, []};
[SNode] -> [SNode] ->
Node = string_to_node(SNode), Node = string_to_node(SNode),
%% Note: Multiple Node Discovery not supported (mask on pubsub#type)
%% TODO this code is also back-compatible with pubsub v1.8 (for client issue)
%% TODO make it pubsub v1.12 compliant (breaks client compatibility ?)
%% TODO That is, remove name attribute (or node?, please check for 2.1)
Action = Action =
fun(#pubsub_node{type = Type, id = NodeId}) -> fun(#pubsub_node{type = Type, id = NodeId}) ->
% TODO call get_items/6 instead for access control (EJAB-1033) % TODO call get_items/6 instead for access control (EJAB-1033)
@ -1112,17 +1122,12 @@ iq_disco_items(Host, Item, From) ->
end, end,
Nodes = lists:map( Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}}) ->
SN = node_to_string(SubNode), {xmlelement, "item", [{"jid", Host}|nodeAttr(SubNode)], []}
RN = lists:last(SubNode),
{xmlelement, "item", [{"jid", Host}, {"node", SN},
{"name", RN}], []}
end, tree_call(Host, get_subnodes, [Host, Node, From])), end, tree_call(Host, get_subnodes, [Host, Node, From])),
Items = lists:map( Items = lists:map(
fun(#pubsub_item{itemid = {RN, _}}) -> fun(#pubsub_item{itemid = {RN, _}}) ->
SN = node_to_string(Node) ++ "!" ++ RN,
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{xmlelement, "item", [{"jid", Host}, {"node", SN}, {xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
{"name", Name}], []}
end, NodeItems), end, NodeItems),
{result, Nodes ++ Items} {result, Nodes ++ Items}
end, end,
@ -1178,10 +1183,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
{xmlelement, _, _, SubEls} = SubEl, {xmlelement, _, _, SubEls} = SubEl,
case xml:remove_cdata(SubEls) of case xml:remove_cdata(SubEls) of
[{xmlelement, Name, Attrs, Els} | Rest] -> [{xmlelement, Name, Attrs, Els} | Rest] ->
Node = case Host of Node = string_to_node(xml:get_attr_s("node", Attrs)),
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
case {IQType, Name} of case {IQType, Name} of
{set, "create"} -> {set, "create"} ->
Config = case Rest of Config = case Rest of
@ -1282,10 +1284,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
Action = xml:remove_cdata(SubEls), Action = xml:remove_cdata(SubEls),
case Action of case Action of
[{xmlelement, Name, Attrs, Els}] -> [{xmlelement, Name, Attrs, Els}] ->
Node = case Host of Node = string_to_node(xml:get_attr_s("node", Attrs)),
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
case {IQType, Name} of case {IQType, Name} of
{get, "configure"} -> {get, "configure"} ->
get_configure(Host, ServerHost, Node, From, Lang); get_configure(Host, ServerHost, Node, From, Lang);
@ -1521,7 +1520,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
end, end,
Stanza = event_stanza( Stanza = event_stanza(
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"node", SNode}, {"jid", jlib:jid_to_string(JID)}] ++ SubAttrs, [{"jid", jlib:jid_to_string(JID)}|nodeAttr(SNode)] ++ SubAttrs,
[]}]), []}]),
ejabberd_router ! {route, service_jid(Host), JID, Stanza}. ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
@ -1531,10 +1530,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
lists:keysearch("pubsub#allow", 1, XFields)} of lists:keysearch("pubsub#allow", 1, XFields)} of
{{value, {_, [SNode]}}, {value, {_, [SSubscriber]}}, {{value, {_, [SNode]}}, {value, {_, [SSubscriber]}},
{value, {_, [SAllow]}}} -> {value, {_, [SAllow]}}} ->
Node = case Host of Node = string_to_node(SNode),
{_, _, _} -> [SNode];
_ -> string:tokens(SNode, "/")
end,
Subscriber = jlib:string_to_jid(SSubscriber), Subscriber = jlib:string_to_jid(SSubscriber),
Allow = case SAllow of Allow = case SAllow of
"1" -> true; "1" -> true;
@ -1664,21 +1660,18 @@ update_auth(Host, Node, Type, NodeId, Subscriber,
%%</ul> %%</ul>
create_node(Host, ServerHost, Node, Owner, Type) -> create_node(Host, ServerHost, Node, Owner, Type) ->
create_node(Host, ServerHost, Node, Owner, Type, all, []). create_node(Host, ServerHost, Node, Owner, Type, all, []).
create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) -> create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) ->
case lists:member("instant-nodes", features(Type)) of case lists:member("instant-nodes", features(Type)) of
true -> true ->
{LOU, LOS, _} = jlib:jid_tolower(Owner), NewNode = string_to_node(randoms:get_string()),
HomeNode = ["home", LOS, LOU],
create_node(Host, ServerHost,
HomeNode, Owner, Type, Access, Configuration),
NewNode = HomeNode ++ [randoms:get_string()],
case create_node(Host, ServerHost, case create_node(Host, ServerHost,
NewNode, Owner, Type, Access, Configuration) of NewNode, Owner, Type, Access, Configuration) of
{result, []} -> {result, []} ->
{result, {result,
[{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(NewNode), []}]}]}; [{xmlelement, "create", nodeAttr(NewNode), []}]}]};
Error -> Error Error ->
Error
end; end;
false -> false ->
%% Service does not support instant nodes %% Service does not support instant nodes
@ -1686,7 +1679,6 @@ create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) ->
end; end;
create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
Type = select_type(ServerHost, Host, Node, GivenType), Type = select_type(ServerHost, Host, Node, GivenType),
Parent = lists:sublist(Node, length(Node) - 1),
%% TODO, check/set node_type = Type %% TODO, check/set node_type = Type
ParseOptions = case xml:remove_cdata(Configuration) of ParseOptions = case xml:remove_cdata(Configuration) of
[] -> [] ->
@ -1711,9 +1703,18 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
{result, NodeOptions} -> {result, NodeOptions} ->
CreateNode = CreateNode =
fun() -> fun() ->
SNode = node_to_string(Node),
Parent = case node_call(Type, node_to_path, [Node]) of
{result, [SNode]} -> <<>>;
{result, Path} -> element(2, node_call(Type, path_to_node, [lists:sublist(Path, length(Path)-1)]))
end,
Parents = case Parent of
<<>> -> [];
_ -> [Parent]
end,
case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of
{result, true} -> {result, true} ->
case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions]) of case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions, Parents]) of
{ok, NodeId} -> {ok, NodeId} ->
node_call(Type, create_node, [NodeId, Owner]); node_call(Type, create_node, [NodeId, Owner]);
{error, {virtual, NodeId}} -> {error, {virtual, NodeId}} ->
@ -2499,9 +2500,8 @@ read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; {error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
{result, #pubsub_subscription{options = Options}} -> {result, #pubsub_subscription{options = Options}} ->
{result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options), {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options),
OptionsEl = {xmlelement, "options", [{"node", node_to_string(Node)}, OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"jid", jlib:jid_to_string(Subscriber)}, {"subid", SubID}|nodeAttr(Node)],
{"subid", SubID}],
[XdataEl]}, [XdataEl]},
PubsubEl = {xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [OptionsEl]}, PubsubEl = {xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [OptionsEl]},
{result, PubsubEl} {result, PubsubEl}
@ -2591,7 +2591,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
[]; [];
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)], [{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
[]}]; []}];
@ -2606,7 +2606,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
[]; [];
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)}, [{"jid", jlib:jid_to_string(SubJID)},
{"subid", SubID}, {"subid", SubID},
@ -2623,7 +2623,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
end; end;
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)}, [{"jid", jlib:jid_to_string(SubJID)},
{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)], {"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
@ -2805,14 +2805,8 @@ subscription_to_string(_) -> "none".
%% Node = pubsubNode() %% Node = pubsubNode()
%% NodeStr = string() %% NodeStr = string()
%% @doc <p>Convert a node type from pubsubNode to string.</p> %% @doc <p>Convert a node type from pubsubNode to string.</p>
node_to_string([]) -> "/"; node_to_string(Node) -> binary_to_list(Node).
node_to_string(Node) -> string_to_node(SNode) -> list_to_binary(SNode).
case Node of
[[_ | _] | _] -> string:strip(lists:flatten(["/", lists:map(fun(S) -> [S, "/"] end, Node)]), right, $/);
[Head | _] when is_integer(Head) -> Node
end.
string_to_node(SNode) ->
string:tokens(SNode, "/").
%% @spec (Host) -> jid() %% @spec (Host) -> jid()
%% Host = host() %% Host = host()
@ -3044,7 +3038,7 @@ get_options_for_subs(NodeID, Subs) ->
% {result, []} -> % {result, []} ->
% {result, false}; % {result, false};
% {result, Subs} -> % {result, Subs} ->
% Stanza = event_stanza([{xmlelement, ElName, [{"node", node_to_string(Node)}], SubEls}]), % Stanza = event_stanza([{xmlelement, ElName, nodeAttr(Node), SubEls}]),
% broadcast_stanza(Host, Node, Type, NodeOptions, SubOpts, Stanza), % broadcast_stanza(Host, Node, Type, NodeOptions, SubOpts, Stanza),
% {result, true}; % {result, true};
% _ -> % _ ->
@ -3161,7 +3155,7 @@ is_caps_notify(Host, Node, LJID) ->
false; false;
Caps -> Caps ->
case catch mod_caps:get_features(Host, Caps) of case catch mod_caps:get_features(Host, Caps) of
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features); Features when is_list(Features) -> lists:member(node_to_string(Node) ++ "+notify", Features);
_ -> false _ -> false
end end
end. end.
@ -3689,6 +3683,8 @@ uniqid() ->
lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])).
% node attributes % node attributes
nodeAttr(Node) when is_list(Node) ->
[{"node", Node}];
nodeAttr(Node) -> nodeAttr(Node) ->
[{"node", node_to_string(Node)}]. [{"node", node_to_string(Node)}].

View File

@ -266,11 +266,11 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
ok. ok.
init_nodes(Host, ServerHost, _NodeTree, Plugins) -> init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
%% TODO, this call should be done PLugin side %% TODO, this call should be done plugin side
case lists:member("hometree", Plugins) of case lists:member("hometree_odbc", Plugins) of
true -> true ->
create_node(Host, ServerHost, ["home"], service_jid(Host), "hometree"), create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree_odbc"),
create_node(Host, ServerHost, ["home", ServerHost], service_jid(Host), "hometree"); create_node(Host, ServerHost, string_to_node("/home/"++ServerHost), service_jid(Host), "hometree_odbc");
false -> false ->
ok ok
end. end.
@ -372,7 +372,7 @@ send_loop(State) ->
on_sub_and_presence -> on_sub_and_presence ->
lists:foreach(fun({Resource, Caps}) -> lists:foreach(fun({Resource, Caps}) ->
CapsNotify = case catch mod_caps:get_features(ServerHost, Caps) of CapsNotify = case catch mod_caps:get_features(ServerHost, Caps) of
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features); Features when is_list(Features) -> lists:member(node_to_string(Node) ++ "+notify", Features);
_ -> false _ -> false
end, end,
case CapsNotify of case CapsNotify of
@ -468,7 +468,7 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
disco_sm_items(Acc, From, To, [], _Lang) -> disco_sm_items(Acc, From, To, [], _Lang) ->
Host = To#jid.lserver, Host = To#jid.lserver,
case tree_action(Host, get_subnodes, [Host, [], From]) of case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
[] -> [] ->
Acc; Acc;
Nodes -> Nodes ->
@ -486,8 +486,9 @@ disco_sm_items(Acc, From, To, [], _Lang) ->
{result, NodeItems ++ Items} {result, NodeItems ++ Items}
end; end;
disco_sm_items(Acc, From, To, Node, _Lang) -> disco_sm_items(Acc, From, To, SNode, _Lang) ->
Host = To#jid.lserver, Host = To#jid.lserver,
Node = string_to_node(SNode),
Action = fun(#pubsub_node{type = Type, id = NodeId}) -> Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
% TODO call get_items/6 instead for access control (EJAB-1033) % TODO call get_items/6 instead for access control (EJAB-1033)
case node_call(Type, get_items, [NodeId, From]) of case node_call(Type, get_items, [NodeId, From]) of
@ -501,13 +502,8 @@ disco_sm_items(Acc, From, To, Node, _Lang) ->
end, end,
NodeItems = lists:map( NodeItems = lists:map(
fun(#pubsub_item{itemid = {Id, _}}) -> fun(#pubsub_item{itemid = {Id, _}}) ->
%% "jid" is required by XEP-0030, and
%% "node" is forbidden by XEP-0060.
{result, Name} = node_call(Type, get_item_name, [Host, Node, Id]), {result, Name} = node_call(Type, get_item_name, [Host, Node, Id]),
{xmlelement, "item", {xmlelement, "item", [{"jid", SBJID}, {"name", Name}], []}
[{"jid", SBJID},
{"name", Name}],
[]}
end, AllItems), end, AllItems),
{result, NodeItems ++ Items}; {result, NodeItems ++ Items};
_ -> _ ->
@ -892,7 +888,7 @@ iq_disco_info(Host, SNode, From, Lang) ->
end, end,
Node = string_to_node(RealSNode), Node = string_to_node(RealSNode),
case Node of case Node of
[] -> <<>> ->
{result, {result,
[{xmlelement, "identity", [{xmlelement, "identity",
[{"category", "pubsub"}, [{"category", "pubsub"},
@ -912,24 +908,17 @@ iq_disco_info(Host, SNode, From, Lang) ->
iq_disco_items(Host, [], From, _RSM) -> iq_disco_items(Host, [], From, _RSM) ->
{result, lists:map( {result, lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}, type = Type}) ->
SN = node_to_string(SubNode), {result, Path} = node_call(Type, node_to_path, [SubNode]),
RN = lists:last(SubNode), [Name|_] = lists:reverse(Path),
%% remove name attribute {xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
{xmlelement, "item", [{"jid", Host}, end, tree_action(Host, get_subnodes, [Host, <<>>, From]))};
{"node", SN},
{"name", RN}], []}
end, tree_action(Host, get_subnodes, [Host, [], From]))};
iq_disco_items(Host, Item, From, RSM) -> iq_disco_items(Host, Item, From, RSM) ->
case string:tokens(Item, "!") of case string:tokens(Item, "!") of
[_SNode, _ItemID] -> [_SNode, _ItemID] ->
{result, []}; {result, []};
[SNode] -> [SNode] ->
Node = string_to_node(SNode), Node = string_to_node(SNode),
%% Note: Multiple Node Discovery not supported (mask on pubsub#type)
%% TODO this code is also back-compatible with pubsub v1.8 (for client issue)
%% TODO make it pubsub v1.12 compliant (breaks client compatibility ?)
%% TODO That is, remove name attribute (or node?, please check for 2.1)
Action = Action =
fun(#pubsub_node{type = Type, id = NodeId}) -> fun(#pubsub_node{type = Type, id = NodeId}) ->
%% TODO call get_items/6 instead for access control (EJAB-1033) %% TODO call get_items/6 instead for access control (EJAB-1033)
@ -939,17 +928,12 @@ iq_disco_items(Host, Item, From, RSM) ->
end, end,
Nodes = lists:map( Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}}) ->
SN = node_to_string(SubNode), {xmlelement, "item", [{"jid", Host}|nodeAttr(SubNode)], []}
RN = lists:last(SubNode),
{xmlelement, "item", [{"jid", Host}, {"node", SN},
{"name", RN}], []}
end, tree_call(Host, get_subnodes, [Host, Node, From])), end, tree_call(Host, get_subnodes, [Host, Node, From])),
Items = lists:map( Items = lists:map(
fun(#pubsub_item{itemid = {RN, _}}) -> fun(#pubsub_item{itemid = {RN, _}}) ->
SN = node_to_string(Node) ++ "!" ++ RN,
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{xmlelement, "item", [{"jid", Host}, {"node", SN}, {xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
{"name", Name}], []}
end, NodeItems), end, NodeItems),
{result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)} {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)}
end, end,
@ -1005,10 +989,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
{xmlelement, _, _, SubEls} = SubEl, {xmlelement, _, _, SubEls} = SubEl,
case xml:remove_cdata(SubEls) of case xml:remove_cdata(SubEls) of
[{xmlelement, Name, Attrs, Els} | Rest] -> [{xmlelement, Name, Attrs, Els} | Rest] ->
Node = case Host of Node = string_to_node(xml:get_attr_s("node", Attrs)),
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
case {IQType, Name} of case {IQType, Name} of
{set, "create"} -> {set, "create"} ->
Config = case Rest of Config = case Rest of
@ -1112,10 +1093,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
end, xml:remove_cdata(SubEls)), end, xml:remove_cdata(SubEls)),
case Action of case Action of
[{xmlelement, Name, Attrs, Els}] -> [{xmlelement, Name, Attrs, Els}] ->
Node = case Host of Node = string_to_node(xml:get_attr_s("node", Attrs)),
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
case {IQType, Name} of case {IQType, Name} of
{get, "configure"} -> {get, "configure"} ->
get_configure(Host, ServerHost, Node, From, Lang); get_configure(Host, ServerHost, Node, From, Lang);
@ -1352,7 +1330,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
end, end,
Stanza = event_stanza( Stanza = event_stanza(
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"node", SNode}, {"jid", jlib:jid_to_string(JID)}] ++ SubAttrs, [{"jid", jlib:jid_to_string(JID)}|nodeAttr(SNode)] ++ SubAttrs,
[]}]), []}]),
ejabberd_router ! {route, service_jid(Host), JID, Stanza}. ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
@ -1362,10 +1340,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
lists:keysearch("pubsub#allow", 1, XFields)} of lists:keysearch("pubsub#allow", 1, XFields)} of
{{value, {_, [SNode]}}, {value, {_, [SSubscriber]}}, {{value, {_, [SNode]}}, {value, {_, [SSubscriber]}},
{value, {_, [SAllow]}}} -> {value, {_, [SAllow]}}} ->
Node = case Host of Node = string_to_node(SNode),
{_, _, _} -> [SNode];
_ -> string:tokens(SNode, "/")
end,
Subscriber = jlib:string_to_jid(SSubscriber), Subscriber = jlib:string_to_jid(SSubscriber),
Allow = case SAllow of Allow = case SAllow of
"1" -> true; "1" -> true;
@ -1495,21 +1470,18 @@ update_auth(Host, Node, Type, NodeId, Subscriber,
%%</ul> %%</ul>
create_node(Host, ServerHost, Node, Owner, Type) -> create_node(Host, ServerHost, Node, Owner, Type) ->
create_node(Host, ServerHost, Node, Owner, Type, all, []). create_node(Host, ServerHost, Node, Owner, Type, all, []).
create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) -> create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) ->
case lists:member("instant-nodes", features(Type)) of case lists:member("instant-nodes", features(Type)) of
true -> true ->
{LOU, LOS, _} = jlib:jid_tolower(Owner), NewNode = string_to_node(randoms:get_string()),
HomeNode = ["home", LOS, LOU],
create_node(Host, ServerHost,
HomeNode, Owner, Type, Access, Configuration),
NewNode = HomeNode ++ [randoms:get_string()],
case create_node(Host, ServerHost, case create_node(Host, ServerHost,
NewNode, Owner, Type, Access, Configuration) of NewNode, Owner, Type, Access, Configuration) of
{result, []} -> {result, []} ->
{result, {result,
[{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(NewNode), []}]}]}; [{xmlelement, "create", nodeAttr(NewNode), []}]}]};
Error -> Error Error ->
Error
end; end;
false -> false ->
%% Service does not support instant nodes %% Service does not support instant nodes
@ -1517,7 +1489,6 @@ create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) ->
end; end;
create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
Type = select_type(ServerHost, Host, Node, GivenType), Type = select_type(ServerHost, Host, Node, GivenType),
Parent = lists:sublist(Node, length(Node) - 1),
%% TODO, check/set node_type = Type %% TODO, check/set node_type = Type
ParseOptions = case xml:remove_cdata(Configuration) of ParseOptions = case xml:remove_cdata(Configuration) of
[] -> [] ->
@ -1542,9 +1513,18 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
{result, NodeOptions} -> {result, NodeOptions} ->
CreateNode = CreateNode =
fun() -> fun() ->
SNode = node_to_string(Node),
Parent = case node_call(Type, node_to_path, [Node]) of
{result, [SNode]} -> <<>>;
{result, Path} -> element(2, node_call(Type, path_to_node, [lists:sublist(Path, length(Path)-1)]))
end,
Parents = case Parent of
<<>> -> [];
_ -> [Parent]
end,
case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of
{result, true} -> {result, true} ->
case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions]) of case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions, Parents]) of
{ok, NodeId} -> {ok, NodeId} ->
node_call(Type, create_node, [NodeId, Owner]); node_call(Type, create_node, [NodeId, Owner]);
{error, {virtual, NodeId}} -> {error, {virtual, NodeId}} ->
@ -2329,9 +2309,8 @@ read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; {error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
{result, #pubsub_subscription{options = Options}} -> {result, #pubsub_subscription{options = Options}} ->
{result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options),
OptionsEl = {xmlelement, "options", [{"node", node_to_string(Node)}, OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"jid", jlib:jid_to_string(Subscriber)}, {"subid", SubID}|nodeAttr(Node)],
{"subid", SubID}],
[XdataEl]}, [XdataEl]},
PubsubEl = {xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [OptionsEl]}, PubsubEl = {xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [OptionsEl]},
{result, PubsubEl} {result, PubsubEl}
@ -2421,7 +2400,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
[]; [];
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)], [{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
[]}]; []}];
@ -2436,7 +2415,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
[]; [];
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)}, [{"jid", jlib:jid_to_string(SubJID)},
{"subid", SubID}, {"subid", SubID},
@ -2453,7 +2432,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
end; end;
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) ->
case Node of case Node of
[] -> <<>> ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)}, [{"jid", jlib:jid_to_string(SubJID)},
{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)], {"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
@ -2635,14 +2614,8 @@ subscription_to_string(_) -> "none".
%% Node = pubsubNode() %% Node = pubsubNode()
%% NodeStr = string() %% NodeStr = string()
%% @doc <p>Convert a node type from pubsubNode to string.</p> %% @doc <p>Convert a node type from pubsubNode to string.</p>
node_to_string([]) -> "/"; node_to_string(Node) -> binary_to_list(Node).
node_to_string(Node) -> string_to_node(SNode) -> list_to_binary(SNode).
case Node of
[[_ | _] | _] -> string:strip(lists:flatten(["/", lists:map(fun(S) -> [S, "/"] end, Node)]), right, $/);
[Head | _] when is_integer(Head) -> Node
end.
string_to_node(SNode) ->
string:tokens(SNode, "/").
%% @spec (Host) -> jid() %% @spec (Host) -> jid()
%% Host = host() %% Host = host()
@ -2874,7 +2847,7 @@ get_options_for_subs(NodeID, Subs) ->
% {result, []} -> % {result, []} ->
% {result, false}; % {result, false};
% {result, Subs} -> % {result, Subs} ->
% Stanza = event_stanza([{xmlelement, ElName, [{"node", node_to_string(Node)}], SubEls}]), % Stanza = event_stanza([{xmlelement, ElName, nodeAttr(Node), SubEls}]),
% broadcast_stanza(Host, Node, Type, NodeOptions, SubOpts, Stanza), % broadcast_stanza(Host, Node, Type, NodeOptions, SubOpts, Stanza),
% {result, true}; % {result, true};
% _ -> % _ ->
@ -2991,7 +2964,7 @@ is_caps_notify(Host, Node, LJID) ->
false; false;
Caps -> Caps ->
case catch mod_caps:get_features(Host, Caps) of case catch mod_caps:get_features(Host, Caps) of
Features when is_list(Features) -> lists:member(Node ++ "+notify", Features); Features when is_list(Features) -> lists:member(node_to_string(Node) ++ "+notify", Features);
_ -> false _ -> false
end end
end. end.
@ -3575,6 +3548,8 @@ uniqid() ->
lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])).
% node attributes % node attributes
nodeAttr(Node) when is_list(Node) ->
[{"node", Node}];
nodeAttr(Node) -> nodeAttr(Node) ->
[{"node", node_to_string(Node)}]. [{"node", node_to_string(Node)}].

View File

@ -68,7 +68,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -193,3 +195,10 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).

View File

@ -68,7 +68,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -192,3 +194,10 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).

View File

@ -52,7 +52,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3]). get_item_name/3,
node_to_path/1,
path_to_node/1]).
init(Host, ServerHost, Opts) -> init(Host, ServerHost, Opts) ->
@ -173,3 +175,10 @@ set_item(Item) ->
get_item_name(Host, Node, ID) -> get_item_name(Host, Node, ID) ->
node_hometree:get_item_name(Host, Node, ID). node_hometree:get_item_name(Host, Node, ID).
node_to_path(Node) ->
node_hometree:node_to_path(Node).
path_to_node(Path) ->
node_hometree:path_to_node(Path).

View File

@ -66,7 +66,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -196,3 +198,10 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).

View File

@ -59,7 +59,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -179,3 +181,16 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
[binary_to_list(Node)].
path_to_node(Path) ->
case Path of
% default slot
[Node] -> list_to_binary(Node);
% handle old possible entries, used when migrating database content to new format
[Node|_] when is_list(Node) -> list_to_binary(string:join([""|Path], "/"));
% default case (used by PEP for example)
_ -> list_to_binary(Path)
end.

View File

@ -63,7 +63,9 @@
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3, get_item_name/3,
get_last_items/3 get_last_items/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -196,3 +198,16 @@ get_item_name(Host, Node, Id) ->
get_last_items(NodeId, From, Count) -> get_last_items(NodeId, From, Count) ->
node_hometree_odbc:get_last_items(NodeId, From, Count). node_hometree_odbc:get_last_items(NodeId, From, Count).
node_to_path(Node) ->
[binary_to_list(Node)].
path_to_node(Path) ->
case Path of
% default slot
[Node] -> list_to_binary(Node);
% handle old possible entries, used when migrating database content to new format
[Node|_] when is_list(Node) -> list_to_binary(string:join([""|Path], "/"));
% default case (used by PEP for example)
_ -> list_to_binary(Path)
end.

View File

@ -75,7 +75,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
%% ================ %% ================
@ -203,7 +205,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
_ -> _ ->
case acl:match_rule(ServerHost, Access, LOwner) of case acl:match_rule(ServerHost, Access, LOwner) of
allow -> allow ->
case Node of case node_to_path(Node) of
["home", Server, User | _] -> true; ["home", Server, User | _] -> true;
_ -> false _ -> false
end; end;
@ -989,6 +991,14 @@ del_items(NodeId, ItemIds) ->
get_item_name(_Host, _Node, Id) -> get_item_name(_Host, _Node, Id) ->
Id. Id.
node_to_path(Node) ->
string:tokens(binary_to_list(Node), "/").
path_to_node([]) ->
<<>>;
path_to_node(Path) ->
list_to_binary(string:join([""|Path], "/")).
%% @spec (Affiliation, Subscription) -> true | false %% @spec (Affiliation, Subscription) -> true | false
%% Affiliation = owner | member | publisher | outcast | none %% Affiliation = owner | member | publisher | outcast | none
%% Subscription = subscribed | none %% Subscription = subscribed | none
@ -1014,3 +1024,4 @@ first_in_list(Pred, [H | T]) ->
true -> {value, H}; true -> {value, H};
_ -> first_in_list(Pred, T) _ -> first_in_list(Pred, T)
end. end.

View File

@ -81,7 +81,9 @@
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3, get_item_name/3,
get_last_items/3 get_last_items/3,
path_to_node/1,
node_to_path/1
]). ]).
-export([ -export([
@ -210,7 +212,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
_ -> _ ->
case acl:match_rule(ServerHost, Access, LOwner) of case acl:match_rule(ServerHost, Access, LOwner) of
allow -> allow ->
case Node of case node_to_path(Node) of
["home", Server, User | _] -> true; ["home", Server, User | _] -> true;
_ -> false _ -> false
end; end;
@ -1209,6 +1211,14 @@ del_items(NodeId, ItemIds) ->
get_item_name(_Host, _Node, Id) -> get_item_name(_Host, _Node, Id) ->
Id. Id.
node_to_path(Node) ->
string:tokens(binary_to_list(Node), "/").
path_to_node([]) ->
<<>>;
path_to_node(Path) ->
list_to_binary(string:join([""|Path], "/")).
%% @spec (Affiliation, Subscription) -> true | false %% @spec (Affiliation, Subscription) -> true | false
%% Affiliation = owner | member | publisher | outcast | none %% Affiliation = owner | member | publisher | outcast | none
%% Subscription = subscribed | none %% Subscription = subscribed | none

View File

@ -71,7 +71,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
init(Host, ServerHost, Opts) -> init(Host, ServerHost, Opts) ->
@ -201,3 +203,9 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_pep:get_item_name(Host, Node, Id). node_pep:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_pep:node_to_path(Node).
path_to_node(Path) ->
node_pep:path_to_node(Path).

View File

@ -64,7 +64,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
init(Host, ServerHost, Opts) -> init(Host, ServerHost, Opts) ->
@ -268,6 +270,12 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).
%%% %%%
%%% Internal %%% Internal

View File

@ -70,7 +70,9 @@
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3, get_item_name/3,
get_last_items/3 get_last_items/3,
node_to_path/1,
path_to_node/1
]). ]).
init(Host, ServerHost, Opts) -> init(Host, ServerHost, Opts) ->
@ -305,6 +307,11 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree_odbc:get_item_name(Host, Node, Id). node_hometree_odbc:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat_odbc:node_to_path(Node).
path_to_node(Path) ->
node_flat_odbc:path_to_node(Path).
%%% %%%
%%% Internal %%% Internal

View File

@ -68,7 +68,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -196,3 +198,10 @@ set_item(Item) ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).

View File

@ -68,7 +68,9 @@
get_item/7, get_item/7,
get_item/2, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3,
node_to_path/1,
path_to_node/1
]). ]).
@ -194,3 +196,10 @@ set_item(Item) ->
%% node id.</p> %% node id.</p>
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
node_hometree:get_item_name(Host, Node, Id). node_hometree:get_item_name(Host, Node, Id).
node_to_path(Node) ->
node_flat:node_to_path(Node).
path_to_node(Path) ->
node_flat:path_to_node(Path).

View File

@ -32,7 +32,7 @@
get_parentnodes_tree/3, get_parentnodes_tree/3,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/3, get_subnodes_tree/3,
create_node/5, create_node/6,
delete_node/2]). delete_node/2]).
-include_lib("stdlib/include/qlc.hrl"). -include_lib("stdlib/include/qlc.hrl").
@ -53,14 +53,12 @@
%% API %% API
%%==================================================================== %%====================================================================
init(Host, ServerHost, Opts) -> init(Host, ServerHost, Opts) ->
nodetree_tree:init(Host, ServerHost, Opts), nodetree_tree:init(Host, ServerHost, Opts).
mnesia:transaction(fun create_node/5,
[Host, [], "default", service_jid(ServerHost), []]).
terminate(Host, ServerHost) -> terminate(Host, ServerHost) ->
nodetree_tree:terminate(Host, ServerHost). nodetree_tree:terminate(Host, ServerHost).
create_node(Key, NodeID, Type, Owner, Options) -> create_node(Key, NodeID, Type, Owner, Options, Parents) ->
OwnerJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), OwnerJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
case find_node(Key, NodeID) of case find_node(Key, NodeID) of
false -> false ->
@ -68,6 +66,7 @@ create_node(Key, NodeID, Type, Owner, Options) ->
N = #pubsub_node{nodeid = oid(Key, NodeID), N = #pubsub_node{nodeid = oid(Key, NodeID),
id = ID, id = ID,
type = Type, type = Type,
parents = Parents,
owners = [OwnerJID], owners = [OwnerJID],
options = Options}, options = Options},
case set_node(N) of case set_node(N) of

View File

@ -56,7 +56,7 @@
get_parentnodes_tree/3, get_parentnodes_tree/3,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/3, get_subnodes_tree/3,
create_node/5, create_node/6,
delete_node/2 delete_node/2
]). ]).
@ -160,13 +160,13 @@ get_parentnodes_tree(Host, Node, From) ->
%% From = mod_pubsub:jid() %% From = mod_pubsub:jid()
get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node, _From) ->
get_subnodes(Host, Node). get_subnodes(Host, Node).
get_subnodes(Host, <<>>) ->
Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _},
parents = Parents} = N <- mnesia:table(pubsub_node),
Host == NHost,
Parents == []]),
qlc:e(Q);
get_subnodes(Host, Node) -> get_subnodes(Host, Node) ->
% mnesia:foldl(fun(#pubsub_node{nodeid = {H, _}, parents = Parents} = N, Acc) ->
% case lists:member(Node, Parents) and (Host == H) of
% true -> [N | Acc];
% false -> Acc
% end
% end, [], pubsub_node).
Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _}, Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _},
parents = Parents} = N <- mnesia:table(pubsub_node), parents = Parents} = N <- mnesia:table(pubsub_node),
Host == NHost, Host == NHost,
@ -181,12 +181,21 @@ get_subnodes_tree(Host, Node, _From) ->
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% From = mod_pubsub:jid() %% From = mod_pubsub:jid()
get_subnodes_tree(Host, Node) -> get_subnodes_tree(Host, Node) ->
case get_node(Host, Node) of
{error, _} ->
[];
Rec ->
BasePlugin = list_to_atom("node_"++Rec#pubsub_node.type),
BasePath = BasePlugin:node_to_path(Node),
mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) -> mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) ->
case lists:prefix(Node, N) and (H == Host) of Plugin = list_to_atom("node_"++R#pubsub_node.type),
Path = Plugin:node_to_path(N),
case lists:prefix(BasePath, Path) and (H == Host) of
true -> [R | Acc]; true -> [R | Acc];
false -> Acc false -> Acc
end end
end, [], pubsub_node). end, [], pubsub_node)
end.
%% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason} %% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | mod_pubsub:jid()
@ -194,26 +203,27 @@ get_subnodes_tree(Host, Node) ->
%% NodeType = mod_pubsub:nodeType() %% NodeType = mod_pubsub:nodeType()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
%% Options = list() %% Options = list()
create_node(Host, Node, Type, Owner, Options) -> create_node(Host, Node, Type, Owner, Options, Parents) ->
BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
case catch mnesia:read({pubsub_node, {Host, Node}}) of case catch mnesia:read({pubsub_node, {Host, Node}}) of
[] -> [] ->
{ParentNode, ParentExists} = ParentExists =
case Host of case Host of
{_U, _S, _R} -> {_U, _S, _R} ->
%% This is special case for PEP handling %% This is special case for PEP handling
%% PEP does not uses hierarchy %% PEP does not uses hierarchy
{[], true}; true;
_ -> _ ->
case lists:sublist(Node, length(Node) - 1) of case Parents of
[] -> [] -> true;
{[], true}; [Parent|_] ->
Parent ->
case catch mnesia:read({pubsub_node, {Host, Parent}}) of case catch mnesia:read({pubsub_node, {Host, Parent}}) of
[#pubsub_node{owners = [{[], Host, []}]}] -> {Parent, true}; [#pubsub_node{owners = [{[], Host, []}]}] -> true;
[#pubsub_node{owners = Owners}] -> {Parent, lists:member(BJID, Owners)}; [#pubsub_node{owners = Owners}] -> lists:member(BJID, Owners);
_ -> {Parent, false} _ -> false
end end;
_ ->
false
end end
end, end,
case ParentExists of case ParentExists of
@ -221,7 +231,7 @@ create_node(Host, Node, Type, Owner, Options) ->
NodeId = pubsub_index:new(node), NodeId = pubsub_index:new(node),
mnesia:write(#pubsub_node{nodeid = {Host, Node}, mnesia:write(#pubsub_node{nodeid = {Host, Node},
id = NodeId, id = NodeId,
parents = [ParentNode], parents = Parents,
type = Type, type = Type,
owners = [BJID], owners = [BJID],
options = Options}), options = Options}),

View File

@ -57,7 +57,7 @@
get_parentnodes_tree/3, get_parentnodes_tree/3,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/3, get_subnodes_tree/3,
create_node/5, create_node/6,
delete_node/2 delete_node/2
]). ]).
@ -209,30 +209,39 @@ get_subnodes_tree(Host, Node) ->
%% NodeType = mod_pubsub:nodeType() %% NodeType = mod_pubsub:nodeType()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
%% Options = list() %% Options = list()
create_node(Host, Node, Type, _Owner, Options) -> %% Parents = list()
create_node(Host, Node, Type, Owner, Options, Parents) ->
BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
case nodeid(Host, Node) of case nodeid(Host, Node) of
{error, ?ERR_ITEM_NOT_FOUND} -> {error, ?ERR_ITEM_NOT_FOUND} ->
{ParentNode, ParentExists} = case Host of ParentExists =
case Host of
{_U, _S, _R} -> {_U, _S, _R} ->
%% This is special case for PEP handling %% This is special case for PEP handling
%% PEP does not uses hierarchy %% PEP does not uses hierarchy
{[], true}; true;
_ -> _ ->
case lists:sublist(Node, length(Node) - 1) of case Parents of
[] -> [] -> true;
{[], true}; [Parent|_] ->
Parent ->
case nodeid(Host, Parent) of case nodeid(Host, Parent) of
{result, _} -> {Parent, true}; {result, PNodeId} ->
_ -> {Parent, false} case nodeowners(PNodeId) of
end [{[], Host, []}] -> true;
Owners -> lists:member(BJID, Owners)
end;
_ ->
false
end;
_ ->
false
end end
end, end,
case ParentExists of case ParentExists of
true -> true ->
case set_node(#pubsub_node{ case set_node(#pubsub_node{
nodeid={Host, Node}, nodeid={Host, Node},
parents=[ParentNode], parents=Parents,
type=Type, type=Type,
options=Options}) of options=Options}) of
{result, NodeId} -> {ok, NodeId}; {result, NodeId} -> {ok, NodeId};
@ -285,8 +294,8 @@ raw_to_node(Host, {Node, Parent, Type, NodeId}) ->
[] []
end, end,
#pubsub_node{ #pubsub_node{
nodeid = {Host, string_to_node(Host, Node)}, nodeid = {Host, ?PUBSUB:string_to_node(Node)},
parents = [string_to_node(Host, Parent)], parents = [?PUBSUB:string_to_node(Parent)],
id = NodeId, id = NodeId,
type = Type, type = Type,
options = Options}. options = Options}.
@ -295,7 +304,10 @@ raw_to_node(Host, {Node, Parent, Type, NodeId}) ->
%% Record = mod_pubsub:pubsub_node() %% Record = mod_pubsub:pubsub_node()
set_node(Record) -> set_node(Record) ->
{Host, Node} = Record#pubsub_node.nodeid, {Host, Node} = Record#pubsub_node.nodeid,
[Parent] = Record#pubsub_node.parents, Parent = case Record#pubsub_node.parents of
[] -> <<>>;
[First|_] -> First
end,
Type = Record#pubsub_node.type, Type = Record#pubsub_node.type,
H = ?PUBSUB:escape(Host), H = ?PUBSUB:escape(Host),
N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)),
@ -352,5 +364,8 @@ nodeid(Host, Node) ->
{error, ?ERR_ITEM_NOT_FOUND} {error, ?ERR_ITEM_NOT_FOUND}
end. end.
string_to_node({_, _, _}, Node) -> Node; nodeowners(NodeId) ->
string_to_node(_, Node) -> ?PUBSUB:string_to_node(Node). {result, Res} = node_hometree_odbc:get_node_affiliations(NodeId),
lists:foldl(fun({LJID, owner}, Acc) -> [LJID|Acc];
(_, Acc) -> Acc
end, [], Res).

View File

@ -51,7 +51,7 @@
get_parentnodes_tree/3, get_parentnodes_tree/3,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/3, get_subnodes_tree/3,
create_node/5, create_node/6,
delete_node/2 delete_node/2
]). ]).
@ -157,7 +157,7 @@ get_subnodes_tree(_Host, _Node) ->
%% @doc <p>No node record is stored on database. Any valid node %% @doc <p>No node record is stored on database. Any valid node
%% is considered as already created.</p> %% is considered as already created.</p>
%% <p>default allowed nodes: /home/host/user/any/node/name</p> %% <p>default allowed nodes: /home/host/user/any/node/name</p>
create_node(Host, Node, _Type, _Owner, _Options) -> create_node(Host, Node, _Type, _Owner, _Options, _Parents) ->
{error, {virtual, {Host, Node}}}. {error, {virtual, {Host, Node}}}.
%% @spec (Host, Node) -> [mod_pubsub:node()] %% @spec (Host, Node) -> [mod_pubsub:node()]

View File

@ -1,5 +1,5 @@
--- mod_pubsub.erl 2009-10-13 18:30:32.000000000 +0200 --- mod_pubsub.erl 2009-10-20 16:33:47.000000000 +0200
+++ mod_pubsub_odbc.erl 2009-10-13 18:30:47.000000000 +0200 +++ mod_pubsub_odbc.erl 2009-10-20 16:33:26.000000000 +0200
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
%%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see
%%% XEP-0060 section 12.18. %%% XEP-0060 section 12.18.
@ -49,7 +49,18 @@
init_nodes(Host, ServerHost, NodeTree, Plugins), init_nodes(Host, ServerHost, NodeTree, Plugins),
State = #state{host = Host, State = #state{host = Host,
server_host = ServerHost, server_host = ServerHost,
@@ -277,178 +275,6 @@ @@ -269,207 +267,14 @@
init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
%% TODO, this call should be done plugin side
- case lists:member("hometree", Plugins) of
+ case lists:member("hometree_odbc", Plugins) of
true ->
- create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree"),
- create_node(Host, ServerHost, string_to_node("/home/"++ServerHost), service_jid(Host), "hometree");
+ create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree_odbc"),
+ create_node(Host, ServerHost, string_to_node("/home/"++ServerHost), service_jid(Host), "hometree_odbc");
false ->
ok ok
end. end.
@ -179,7 +190,28 @@
- rename_default_nodeplugin(); - rename_default_nodeplugin();
- _ -> - _ ->
- ok - ok
- end. - end,
- mnesia:transaction(fun() ->
- case catch mnesia:first(pubsub_node) of
- {_, L} when is_list(L) ->
- lists:foreach(
- fun({H, N}) when is_list(N) ->
- [Node] = mnesia:read({pubsub_node, {H, N}}),
- Type = Node#pubsub_node.type,
- BN = element(2, node_call(Type, path_to_node, [N])),
- BP = case [element(2, node_call(Type, path_to_node, [P])) || P <- Node#pubsub_node.parents] of
- [<<>>] -> [];
- Parents -> Parents
- end,
- mnesia:write(Node#pubsub_node{nodeid={H, BN}, parents=BP}),
- mnesia:delete({pubsub_node, {H, N}});
- (_) ->
- ok
- end, mnesia:all_keys(pubsub_node));
- _ ->
- ok
- end
- end).
- -
-rename_default_nodeplugin() -> -rename_default_nodeplugin() ->
- lists:foreach(fun(Node) -> - lists:foreach(fun(Node) ->
@ -228,7 +260,7 @@
send_queue(State, Msg) -> send_queue(State, Msg) ->
Pid = State#state.send_loop, Pid = State#state.send_loop,
case is_process_alive(Pid) of case is_process_alive(Pid) of
@@ -471,17 +297,15 @@ @@ -492,17 +297,15 @@
%% for each node From is subscribed to %% for each node From is subscribed to
%% and if the node is so configured, send the last published item to From %% and if the node is so configured, send the last published item to From
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
@ -252,7 +284,7 @@
true -> true ->
% resource not concerned about that subscription % resource not concerned about that subscription
ok ok
@@ -808,10 +632,10 @@ @@ -825,10 +628,10 @@
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]),
lists:foreach(fun lists:foreach(fun
({Node, subscribed, _, JID}) -> ({Node, subscribed, _, JID}) ->
@ -265,7 +297,7 @@
true -> true ->
node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]);
false -> false ->
@@ -926,7 +750,8 @@ @@ -943,7 +746,8 @@
sub_el = SubEl} = IQ -> sub_el = SubEl} = IQ ->
{xmlelement, _, QAttrs, _} = SubEl, {xmlelement, _, QAttrs, _} = SubEl,
Node = xml:get_attr_s("node", QAttrs), Node = xml:get_attr_s("node", QAttrs),
@ -275,7 +307,7 @@
{result, IQRes} -> {result, IQRes} ->
jlib:iq_to_xml( jlib:iq_to_xml(
IQ#iq{type = result, IQ#iq{type = result,
@@ -1031,7 +856,7 @@ @@ -1048,7 +852,7 @@
[] -> [] ->
["leaf"]; %% No sub-nodes: it's a leaf node ["leaf"]; %% No sub-nodes: it's a leaf node
_ -> _ ->
@ -284,7 +316,7 @@
{result, []} -> ["collection"]; {result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"]; {result, _} -> ["leaf", "collection"];
_ -> [] _ -> []
@@ -1047,8 +872,9 @@ @@ -1064,8 +868,9 @@
[]; [];
true -> true ->
[{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} | [{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} |
@ -296,7 +328,7 @@
end, features(Type))] end, features(Type))]
end, end,
%% TODO: add meta-data info (spec section 5.4) %% TODO: add meta-data info (spec section 5.4)
@@ -1076,14 +902,15 @@ @@ -1093,21 +898,22 @@
{xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []}, {xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []}, {xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++ {xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++
@ -313,19 +345,18 @@
-iq_disco_items(Host, [], From) -> -iq_disco_items(Host, [], From) ->
+iq_disco_items(Host, [], From, _RSM) -> +iq_disco_items(Host, [], From, _RSM) ->
{result, lists:map( {result, lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}, type = Type}) ->
SN = node_to_string(SubNode), {result, Path} = node_call(Type, node_to_path, [SubNode]),
@@ -1093,7 +920,7 @@ [Name|_] = lists:reverse(Path),
{"node", SN}, {xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
{"name", RN}], []} end, tree_action(Host, get_subnodes, [Host, <<>>, From]))};
end, tree_action(Host, get_subnodes, [Host, [], From]))};
-iq_disco_items(Host, Item, From) -> -iq_disco_items(Host, Item, From) ->
+iq_disco_items(Host, Item, From, RSM) -> +iq_disco_items(Host, Item, From, RSM) ->
case string:tokens(Item, "!") of case string:tokens(Item, "!") of
[_SNode, _ItemID] -> [_SNode, _ItemID] ->
{result, []}; {result, []};
@@ -1105,10 +932,10 @@ @@ -1115,10 +921,10 @@
%% TODO That is, remove name attribute (or node?, please check for 2.1) Node = string_to_node(SNode),
Action = Action =
fun(#pubsub_node{type = Type, id = NodeId}) -> fun(#pubsub_node{type = Type, id = NodeId}) ->
- % TODO call get_items/6 instead for access control (EJAB-1033) - % TODO call get_items/6 instead for access control (EJAB-1033)
@ -338,16 +369,16 @@
end, end,
Nodes = lists:map( Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) -> fun(#pubsub_node{nodeid = {_, SubNode}}) ->
@@ -1124,7 +951,7 @@ @@ -1129,7 +935,7 @@
{xmlelement, "item", [{"jid", Host}, {"node", SN}, {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{"name", Name}], []} {xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
end, NodeItems), end, NodeItems),
- {result, Nodes ++ Items} - {result, Nodes ++ Items}
+ {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)} + {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)}
end, end,
case transaction(Host, Node, Action, sync_dirty) of case transaction(Host, Node, Action, sync_dirty) of
{result, {_, Result}} -> {result, Result}; {result, {_, Result}} -> {result, Result};
@@ -1256,7 +1083,8 @@ @@ -1258,7 +1064,8 @@
(_, Acc) -> (_, Acc) ->
Acc Acc
end, [], xml:remove_cdata(Els)), end, [], xml:remove_cdata(Els)),
@ -357,7 +388,7 @@
{get, "subscriptions"} -> {get, "subscriptions"} ->
get_subscriptions(Host, Node, From, Plugins); get_subscriptions(Host, Node, From, Plugins);
{get, "affiliations"} -> {get, "affiliations"} ->
@@ -1279,7 +1107,9 @@ @@ -1281,7 +1088,9 @@
iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
{xmlelement, _, _, SubEls} = SubEl, {xmlelement, _, _, SubEls} = SubEl,
@ -367,8 +398,8 @@
+ end, xml:remove_cdata(SubEls)), + end, xml:remove_cdata(SubEls)),
case Action of case Action of
[{xmlelement, Name, Attrs, Els}] -> [{xmlelement, Name, Attrs, Els}] ->
Node = case Host of Node = string_to_node(xml:get_attr_s("node", Attrs)),
@@ -1405,7 +1235,8 @@ @@ -1404,7 +1213,8 @@
_ -> [] _ -> []
end end
end, end,
@ -378,7 +409,7 @@
sync_dirty) of sync_dirty) of
{result, Res} -> Res; {result, Res} -> Res;
Err -> Err Err -> Err
@@ -1445,7 +1276,7 @@ @@ -1444,7 +1254,7 @@
%%% authorization handling %%% authorization handling
@ -387,7 +418,7 @@
Lang = "en", %% TODO fix Lang = "en", %% TODO fix
Stanza = {xmlelement, "message", Stanza = {xmlelement, "message",
[], [],
@@ -1474,7 +1305,7 @@ @@ -1473,7 +1283,7 @@
[{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]}, [{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]},
lists:foreach(fun(Owner) -> lists:foreach(fun(Owner) ->
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza} ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza}
@ -396,7 +427,7 @@
find_authorization_response(Packet) -> find_authorization_response(Packet) ->
{xmlelement, _Name, _Attrs, Els} = Packet, {xmlelement, _Name, _Attrs, Els} = Packet,
@@ -1541,8 +1372,8 @@ @@ -1537,8 +1347,8 @@
"true" -> true; "true" -> true;
_ -> false _ -> false
end, end,
@ -407,7 +438,7 @@
{result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]),
if if
not IsApprover -> not IsApprover ->
@@ -1728,7 +1559,7 @@ @@ -1729,7 +1539,7 @@
Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(Node), [{xmlelement, "create", nodeAttr(Node),
[]}]}], []}]}],
@ -416,7 +447,7 @@
{result, {Result, broadcast}} -> {result, {Result, broadcast}} ->
%%Lang = "en", %% TODO: fix %%Lang = "en", %% TODO: fix
%%OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), %%OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
@@ -1836,7 +1667,7 @@ @@ -1837,7 +1647,7 @@
%%<li>The node does not exist.</li> %%<li>The node does not exist.</li>
%%</ul> %%</ul>
subscribe_node(Host, Node, From, JID, Configuration) -> subscribe_node(Host, Node, From, JID, Configuration) ->
@ -425,7 +456,7 @@
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -1844,7 +1675,7 @@ @@ -1845,7 +1655,7 @@
error -> {"", "", ""}; error -> {"", "", ""};
J -> jlib:jid_tolower(J) J -> jlib:jid_tolower(J)
end, end,
@ -434,7 +465,7 @@
Features = features(Type), Features = features(Type),
SubscribeFeature = lists:member("subscribe", Features), SubscribeFeature = lists:member("subscribe", Features),
OptionsFeature = lists:member("subscription-options", Features), OptionsFeature = lists:member("subscription-options", Features),
@@ -1863,9 +1694,13 @@ @@ -1864,9 +1674,13 @@
{"", "", ""} -> {"", "", ""} ->
{false, false}; {false, false};
_ -> _ ->
@ -451,7 +482,7 @@
end end
end, end,
if if
@@ -2196,7 +2031,7 @@ @@ -2197,7 +2011,7 @@
%% <p>The permission are not checked in this function.</p> %% <p>The permission are not checked in this function.</p>
%% @todo We probably need to check that the user doing the query has the right %% @todo We probably need to check that the user doing the query has the right
%% to read the items. %% to read the items.
@ -460,7 +491,7 @@
MaxItems = MaxItems =
if if
SMaxItems == "" -> get_max_items_node(Host); SMaxItems == "" -> get_max_items_node(Host);
@@ -2235,11 +2070,11 @@ @@ -2236,11 +2050,11 @@
node_call(Type, get_items, node_call(Type, get_items,
[NodeId, From, [NodeId, From,
AccessModel, PresenceSubscription, RosterGroup, AccessModel, PresenceSubscription, RosterGroup,
@ -474,7 +505,7 @@
SendItems = case ItemIDs of SendItems = case ItemIDs of
[] -> [] ->
Items; Items;
@@ -2252,7 +2087,8 @@ @@ -2253,7 +2067,8 @@
%% number of items sent to MaxItems: %% number of items sent to MaxItems:
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "items", nodeAttr(Node), [{xmlelement, "items", nodeAttr(Node),
@ -484,7 +515,7 @@
Error -> Error ->
Error Error
end end
@@ -2284,16 +2120,27 @@ @@ -2285,16 +2100,27 @@
%% @doc <p>Resend the items of a node to the user.</p> %% @doc <p>Resend the items of a node to the user.</p>
%% @todo use cache-last-item feature %% @todo use cache-last-item feature
send_items(Host, Node, NodeId, Type, LJID, last) -> send_items(Host, Node, NodeId, Type, LJID, last) ->
@ -518,7 +549,7 @@
send_items(Host, Node, NodeId, Type, LJID, Number) -> send_items(Host, Node, NodeId, Type, LJID, Number) ->
ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of
{result, []} -> {result, []} ->
@@ -2419,29 +2266,12 @@ @@ -2420,29 +2246,12 @@
error -> error ->
{error, ?ERR_BAD_REQUEST}; {error, ?ERR_BAD_REQUEST};
_ -> _ ->
@ -551,7 +582,7 @@
end, Entities), end, Entities),
{result, []}; {result, []};
_ -> _ ->
@@ -2494,11 +2324,11 @@ @@ -2495,11 +2304,11 @@
end. end.
read_sub(Subscriber, Node, NodeID, SubID, Lang) -> read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
@ -562,10 +593,10 @@
{result, #pubsub_subscription{options = Options}} -> {result, #pubsub_subscription{options = Options}} ->
- {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options), - {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options),
+ {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), + {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options),
OptionsEl = {xmlelement, "options", [{"node", node_to_string(Node)}, OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"jid", jlib:jid_to_string(Subscriber)}, {"subid", SubID}|nodeAttr(Node)],
{"subid", SubID}], [XdataEl]},
@@ -2525,7 +2355,7 @@ @@ -2525,7 +2334,7 @@
end. end.
set_options_helper(Configuration, JID, NodeID, SubID, Type) -> set_options_helper(Configuration, JID, NodeID, SubID, Type) ->
@ -574,7 +605,7 @@
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -2554,7 +2384,7 @@ @@ -2554,7 +2363,7 @@
write_sub(_Subscriber, _NodeID, _SubID, invalid) -> write_sub(_Subscriber, _NodeID, _SubID, invalid) ->
{error, extended_error(?ERR_BAD_REQUEST, "invalid-options")}; {error, extended_error(?ERR_BAD_REQUEST, "invalid-options")};
write_sub(Subscriber, NodeID, SubID, Options) -> write_sub(Subscriber, NodeID, SubID, Options) ->
@ -583,7 +614,7 @@
{error, notfound} -> {error, notfound} ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; {error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
{result, _} -> {result, _} ->
@@ -2722,8 +2552,8 @@ @@ -2722,8 +2531,8 @@
{"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]}, {"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]},
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza} ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza}
end, end,
@ -594,7 +625,7 @@
true -> true ->
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
@@ -3013,7 +2843,7 @@ @@ -3007,7 +2816,7 @@
{Depth, [{N, get_node_subs(N)} || N <- Nodes]} {Depth, [{N, get_node_subs(N)} || N <- Nodes]}
end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))}
end, end,
@ -603,7 +634,7 @@
{result, CollSubs} -> CollSubs; {result, CollSubs} -> CollSubs;
_ -> [] _ -> []
end. end.
@@ -3027,9 +2857,9 @@ @@ -3021,9 +2830,9 @@
get_options_for_subs(NodeID, Subs) -> get_options_for_subs(NodeID, Subs) ->
lists:foldl(fun({JID, subscribed, SubID}, Acc) -> lists:foldl(fun({JID, subscribed, SubID}, Acc) ->
@ -615,7 +646,7 @@
_ -> Acc _ -> Acc
end; end;
(_, Acc) -> (_, Acc) ->
@@ -3227,6 +3057,30 @@ @@ -3221,6 +3030,30 @@
Result Result
end. end.
@ -646,7 +677,7 @@
%% @spec (Host, Options) -> MaxItems %% @spec (Host, Options) -> MaxItems
%% Host = host() %% Host = host()
%% Options = [Option] %% Options = [Option]
@@ -3613,7 +3467,13 @@ @@ -3607,7 +3440,13 @@
tree_action(Host, Function, Args) -> tree_action(Host, Function, Args) ->
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]), ?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
Fun = fun() -> tree_call(Host, Function, Args) end, Fun = fun() -> tree_call(Host, Function, Args) end,
@ -661,7 +692,7 @@
%% @doc <p>node plugin call.</p> %% @doc <p>node plugin call.</p>
node_call(Type, Function, Args) -> node_call(Type, Function, Args) ->
@@ -3633,13 +3493,13 @@ @@ -3627,13 +3466,13 @@
node_action(Host, Type, Function, Args) -> node_action(Host, Type, Function, Args) ->
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]), ?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
@ -677,7 +708,7 @@
case tree_call(Host, get_node, [Host, Node]) of case tree_call(Host, get_node, [Host, Node]) of
N when is_record(N, pubsub_node) -> N when is_record(N, pubsub_node) ->
case Action(N) of case Action(N) of
@@ -3652,8 +3512,14 @@ @@ -3646,8 +3485,14 @@
end end
end, Trans). end, Trans).
@ -694,7 +725,7 @@
{result, Result} -> {result, Result}; {result, Result} -> {result, Result};
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{atomic, {result, Result}} -> {result, Result}; {atomic, {result, Result}} -> {result, Result};
@@ -3661,6 +3527,15 @@ @@ -3655,6 +3500,15 @@
{aborted, Reason} -> {aborted, Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR}; {error, ?ERR_INTERNAL_SERVER_ERROR};
@ -710,7 +741,7 @@
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR}; {error, ?ERR_INTERNAL_SERVER_ERROR};
@@ -3669,6 +3544,17 @@ @@ -3663,6 +3517,17 @@
{error, ?ERR_INTERNAL_SERVER_ERROR} {error, ?ERR_INTERNAL_SERVER_ERROR}
end. end.