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, 2},
{set_item, 1},
{get_item_name, 3}
{get_item_name, 3},
{node_to_path, 1},
{path_to_node, 1}
];
behaviour_info(_Other) ->
undefined.

View File

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

View File

@ -268,11 +268,11 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
ok.
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
true ->
create_node(Host, ServerHost, ["home"], service_jid(Host), "hometree"),
create_node(Host, ServerHost, ["home", ServerHost], service_jid(Host), "hometree");
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");
false ->
ok
end.
@ -403,7 +403,28 @@ update_node_database(Host, ServerHost) ->
rename_default_nodeplugin();
_ ->
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() ->
lists:foreach(fun(Node) ->
@ -548,7 +569,7 @@ send_loop(State) ->
on_sub_and_presence ->
lists:foreach(fun({Resource, Caps}) ->
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
end,
case CapsNotify of
@ -644,7 +665,7 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
disco_sm_items(Acc, From, To, [], _Lang) ->
Host = To#jid.lserver,
case tree_action(Host, get_subnodes, [Host, [], From]) of
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
[] ->
Acc;
Nodes ->
@ -662,8 +683,9 @@ disco_sm_items(Acc, From, To, [], _Lang) ->
{result, NodeItems ++ Items}
end;
disco_sm_items(Acc, From, To, Node, _Lang) ->
disco_sm_items(Acc, From, To, SNode, _Lang) ->
Host = To#jid.lserver,
Node = string_to_node(SNode),
Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
% TODO call get_items/6 instead for access control (EJAB-1033)
case node_call(Type, get_items, [NodeId, From]) of
@ -677,13 +699,8 @@ disco_sm_items(Acc, From, To, Node, _Lang) ->
end,
NodeItems = lists:map(
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]),
{xmlelement, "item",
[{"jid", SBJID},
{"name", Name}],
[]}
{xmlelement, "item", [{"jid", SBJID}, {"name", Name}], []}
end, AllItems),
{result, NodeItems ++ Items};
_ ->
@ -1066,7 +1083,7 @@ iq_disco_info(Host, SNode, From, Lang) ->
end,
Node = string_to_node(RealSNode),
case Node of
[] ->
<<>> ->
{result,
[{xmlelement, "identity",
[{"category", "pubsub"},
@ -1085,24 +1102,17 @@ iq_disco_info(Host, SNode, From, Lang) ->
iq_disco_items(Host, [], From) ->
{result, lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) ->
SN = node_to_string(SubNode),
RN = lists:last(SubNode),
%% remove name attribute
{xmlelement, "item", [{"jid", Host},
{"node", SN},
{"name", RN}], []}
end, tree_action(Host, get_subnodes, [Host, [], From]))};
fun(#pubsub_node{nodeid = {_, SubNode}, type = Type}) ->
{result, Path} = node_call(Type, node_to_path, [SubNode]),
[Name|_] = lists:reverse(Path),
{xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
end, tree_action(Host, get_subnodes, [Host, <<>>, From]))};
iq_disco_items(Host, Item, From) ->
case string:tokens(Item, "!") of
[_SNode, _ItemID] ->
{result, []};
[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 =
fun(#pubsub_node{type = Type, id = NodeId}) ->
% TODO call get_items/6 instead for access control (EJAB-1033)
@ -1112,17 +1122,12 @@ iq_disco_items(Host, Item, From) ->
end,
Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) ->
SN = node_to_string(SubNode),
RN = lists:last(SubNode),
{xmlelement, "item", [{"jid", Host}, {"node", SN},
{"name", RN}], []}
{xmlelement, "item", [{"jid", Host}|nodeAttr(SubNode)], []}
end, tree_call(Host, get_subnodes, [Host, Node, From])),
Items = lists:map(
fun(#pubsub_item{itemid = {RN, _}}) ->
SN = node_to_string(Node) ++ "!" ++ RN,
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{xmlelement, "item", [{"jid", Host}, {"node", SN},
{"name", Name}], []}
{xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
end, NodeItems),
{result, Nodes ++ Items}
end,
@ -1178,10 +1183,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
{xmlelement, _, _, SubEls} = SubEl,
case xml:remove_cdata(SubEls) of
[{xmlelement, Name, Attrs, Els} | Rest] ->
Node = case Host of
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
Node = string_to_node(xml:get_attr_s("node", Attrs)),
case {IQType, Name} of
{set, "create"} ->
Config = case Rest of
@ -1282,10 +1284,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
Action = xml:remove_cdata(SubEls),
case Action of
[{xmlelement, Name, Attrs, Els}] ->
Node = case Host of
{_, _, _} -> xml:get_attr_s("node", Attrs);
_ -> string_to_node(xml:get_attr_s("node", Attrs))
end,
Node = string_to_node(xml:get_attr_s("node", Attrs)),
case {IQType, Name} of
{get, "configure"} ->
get_configure(Host, ServerHost, Node, From, Lang);
@ -1521,7 +1520,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
end,
Stanza = event_stanza(
[{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}.
@ -1531,10 +1530,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) ->
lists:keysearch("pubsub#allow", 1, XFields)} of
{{value, {_, [SNode]}}, {value, {_, [SSubscriber]}},
{value, {_, [SAllow]}}} ->
Node = case Host of
{_, _, _} -> [SNode];
_ -> string:tokens(SNode, "/")
end,
Node = string_to_node(SNode),
Subscriber = jlib:string_to_jid(SSubscriber),
Allow = case SAllow of
"1" -> true;
@ -1664,21 +1660,18 @@ update_auth(Host, Node, Type, NodeId, Subscriber,
%%</ul>
create_node(Host, ServerHost, Node, Owner, Type) ->
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
true ->
{LOU, LOS, _} = jlib:jid_tolower(Owner),
HomeNode = ["home", LOS, LOU],
create_node(Host, ServerHost,
HomeNode, Owner, Type, Access, Configuration),
NewNode = HomeNode ++ [randoms:get_string()],
NewNode = string_to_node(randoms:get_string()),
case create_node(Host, ServerHost,
NewNode, Owner, Type, Access, Configuration) of
{result, []} ->
{result,
[{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(NewNode), []}]}]};
Error -> Error
Error ->
Error
end;
false ->
%% Service does not support instant nodes
@ -1686,7 +1679,6 @@ create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) ->
end;
create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
Type = select_type(ServerHost, Host, Node, GivenType),
Parent = lists:sublist(Node, length(Node) - 1),
%% TODO, check/set node_type = Type
ParseOptions = case xml:remove_cdata(Configuration) of
[] ->
@ -1711,9 +1703,18 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
{result, NodeOptions} ->
CreateNode =
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
{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} ->
node_call(Type, create_node, [NodeId, Owner]);
{error, {virtual, NodeId}} ->
@ -2499,9 +2500,8 @@ read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
{result, #pubsub_subscription{options = Options}} ->
{result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options),
OptionsEl = {xmlelement, "options", [{"node", node_to_string(Node)},
{"jid", jlib:jid_to_string(Subscriber)},
{"subid", SubID}],
OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"subid", SubID}|nodeAttr(Node)],
[XdataEl]},
PubsubEl = {xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [OptionsEl]},
{result, PubsubEl}
@ -2591,7 +2591,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
[];
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) ->
case Node of
[] ->
<<>> ->
[{xmlelement, "subscription",
[{"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}) ->
case Node of
[] ->
<<>> ->
[{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)},
{"subid", SubID},
@ -2623,7 +2623,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
end;
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) ->
case Node of
[] ->
<<>> ->
[{xmlelement, "subscription",
[{"jid", jlib:jid_to_string(SubJID)},
{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
@ -2805,14 +2805,8 @@ subscription_to_string(_) -> "none".
%% Node = pubsubNode()
%% NodeStr = string()
%% @doc <p>Convert a node type from pubsubNode to string.</p>
node_to_string([]) -> "/";
node_to_string(Node) ->
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, "/").
node_to_string(Node) -> binary_to_list(Node).
string_to_node(SNode) -> list_to_binary(SNode).
%% @spec (Host) -> jid()
%% Host = host()
@ -3044,7 +3038,7 @@ get_options_for_subs(NodeID, Subs) ->
% {result, []} ->
% {result, false};
% {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),
% {result, true};
% _ ->
@ -3161,7 +3155,7 @@ is_caps_notify(Host, Node, LJID) ->
false;
Caps ->
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
end
end.
@ -3689,6 +3683,8 @@ uniqid() ->
lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])).
% node attributes
nodeAttr(Node) when is_list(Node) ->
[{"node", Node}];
nodeAttr(Node) ->
[{"node", node_to_string(Node)}].

View File

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

View File

@ -68,7 +68,9 @@
get_item/7,
get_item/2,
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) ->
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/2,
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) ->
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/2,
set_item/1,
get_item_name/3]).
get_item_name/3,
node_to_path/1,
path_to_node/1]).
init(Host, ServerHost, Opts) ->
@ -173,3 +175,10 @@ set_item(Item) ->
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/2,
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) ->
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/2,
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) ->
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,
set_item/1,
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) ->
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/2,
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
allow ->
case Node of
case node_to_path(Node) of
["home", Server, User | _] -> true;
_ -> false
end;
@ -989,6 +991,14 @@ del_items(NodeId, ItemIds) ->
get_item_name(_Host, _Node, 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
%% Affiliation = owner | member | publisher | outcast | none
%% Subscription = subscribed | none
@ -1014,3 +1024,4 @@ first_in_list(Pred, [H | T]) ->
true -> {value, H};
_ -> first_in_list(Pred, T)
end.

View File

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

View File

@ -71,7 +71,9 @@
get_item/7,
get_item/2,
set_item/1,
get_item_name/3
get_item_name/3,
node_to_path/1,
path_to_node/1
]).
init(Host, ServerHost, Opts) ->
@ -201,3 +203,9 @@ set_item(Item) ->
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/2,
set_item/1,
get_item_name/3
get_item_name/3,
node_to_path/1,
path_to_node/1
]).
init(Host, ServerHost, Opts) ->
@ -268,6 +270,12 @@ set_item(Item) ->
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

View File

@ -70,7 +70,9 @@
get_item/2,
set_item/1,
get_item_name/3,
get_last_items/3
get_last_items/3,
node_to_path/1,
path_to_node/1
]).
init(Host, ServerHost, Opts) ->
@ -305,6 +307,11 @@ set_item(Item) ->
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

View File

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

View File

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

View File

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