mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
parent
12573ed8d2
commit
306cff729c
@ -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.
|
||||||
|
@ -49,7 +49,7 @@ behaviour_info(callbacks) ->
|
|||||||
{get_nodes, 1},
|
{get_nodes, 1},
|
||||||
{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) ->
|
||||||
|
@ -277,11 +277,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.
|
||||||
@ -412,8 +412,29 @@ 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) ->
|
||||||
mnesia:dirty_write(Node#pubsub_node{type = "hometree"})
|
mnesia:dirty_write(Node#pubsub_node{type = "hometree"})
|
||||||
@ -557,7 +578,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
|
||||||
@ -653,7 +674,7 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
|
|||||||
|
|
||||||
disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
||||||
Host = exmpp_jid:prep_domain_as_list(To),
|
Host = exmpp_jid:prep_domain_as_list(To),
|
||||||
case tree_action(Host, get_subnodes, [Host, [], From]) of
|
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
|
||||||
[] ->
|
[] ->
|
||||||
Acc;
|
Acc;
|
||||||
Nodes ->
|
Nodes ->
|
||||||
@ -671,7 +692,8 @@ disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
disco_sm_items(Acc, From, To, NodeB, _Lang) ->
|
disco_sm_items(Acc, From, To, NodeB, _Lang) ->
|
||||||
Node = binary_to_list(NodeB),
|
SNode = binary_to_list(NodeB),
|
||||||
|
Node = string_to_node(SNode),
|
||||||
%% TODO, use iq_disco_items(Host, Node, From)
|
%% TODO, use iq_disco_items(Host, Node, From)
|
||||||
Host = exmpp_jid:prep_domain_as_list(To),
|
Host = exmpp_jid:prep_domain_as_list(To),
|
||||||
LJID = jlib:short_prepd_bare_jid(To),
|
LJID = jlib:short_prepd_bare_jid(To),
|
||||||
@ -687,8 +709,6 @@ disco_sm_items(Acc, From, To, NodeB, _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]),
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs =
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs =
|
||||||
[?XMLATTR('jid', exmpp_jid:to_binary(LJID)),
|
[?XMLATTR('jid', exmpp_jid:to_binary(LJID)),
|
||||||
@ -1085,7 +1105,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,
|
||||||
[#xmlel{ns = ?NS_DISCO_INFO, name = 'identity', attrs =
|
[#xmlel{ns = ?NS_DISCO_INFO, name = 'identity', attrs =
|
||||||
[?XMLATTR('category', "pubsub"),
|
[?XMLATTR('category', "pubsub"),
|
||||||
@ -1104,13 +1124,11 @@ 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
|
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host),
|
||||||
?XMLATTR('node', SN),
|
?XMLATTR('name', Name) | nodeAttr(SubNode)]}
|
||||||
?XMLATTR('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) ->
|
||||||
case string:tokens(Item, "!") of
|
case string:tokens(Item, "!") of
|
||||||
@ -1118,10 +1136,6 @@ iq_disco_items(Host, Item, From) ->
|
|||||||
{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)
|
||||||
@ -1131,17 +1145,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),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host) | nodeAttr(SubNode)]}
|
||||||
RN = lists:last(SubNode),
|
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('node', SN),
|
|
||||||
?XMLATTR('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, [NodeId, RN]),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]}
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('node', SN),
|
|
||||||
?XMLATTR('name', Name)]}
|
|
||||||
end, NodeItems),
|
end, NodeItems),
|
||||||
{result, Nodes ++ Items}
|
{result, Nodes ++ Items}
|
||||||
end,
|
end,
|
||||||
@ -1199,10 +1208,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) ->
|
|||||||
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
|
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
|
||||||
case exmpp_xml:remove_cdata_from_list(SubEl#xmlel.children) of
|
case exmpp_xml:remove_cdata_from_list(SubEl#xmlel.children) of
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] ->
|
[#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] ->
|
||||||
Node = case Host of
|
Node = string_to_node(exmpp_xml:get_attribute_from_list_as_list(attrs, 'node', false)),
|
||||||
{_, _, _} -> exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', false);
|
|
||||||
_ -> string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', false))
|
|
||||||
end,
|
|
||||||
case {IQType, Name} of
|
case {IQType, Name} of
|
||||||
{set, 'create'} ->
|
{set, 'create'} ->
|
||||||
Config = case Rest of
|
Config = case Rest of
|
||||||
@ -1303,10 +1309,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
|
|||||||
Action = exmpp_xml:remove_cdata_from_list(SubEls),
|
Action = exmpp_xml:remove_cdata_from_list(SubEls),
|
||||||
case Action of
|
case Action of
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els}] ->
|
[#xmlel{name = Name, attrs = Attrs, children = Els}] ->
|
||||||
Node = case Host of
|
Node = string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', "")),
|
||||||
{_, _, _} -> exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', "");
|
|
||||||
_ -> string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', ""))
|
|
||||||
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);
|
||||||
@ -1547,8 +1550,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
|
|||||||
end,
|
end,
|
||||||
Stanza = event_stanza(
|
Stanza = event_stanza(
|
||||||
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', SNode),
|
[ ?XMLATTR('jid', exmpp_jid:to_binary(JID)) | nodeAttr(SNode)] ++ SubAttrs
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(JID))] ++ SubAttrs
|
|
||||||
}]),
|
}]),
|
||||||
ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
|
ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
|
||||||
|
|
||||||
@ -1558,10 +1560,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 = exmpp_jid:parse(SSubscriber),
|
Subscriber = exmpp_jid:parse(SSubscriber),
|
||||||
Allow = case SAllow of
|
Allow = case SAllow of
|
||||||
"1" -> true;
|
"1" -> true;
|
||||||
@ -1696,21 +1695,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:short_prepd_jid(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,
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(NewNode)}]}]};
|
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(NewNode)}]}]};
|
||||||
Error -> Error
|
Error ->
|
||||||
|
Error
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
%% Service does not support instant nodes
|
%% Service does not support instant nodes
|
||||||
@ -1718,7 +1714,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 exmpp_xml:remove_cdata_from_list(Configuration) of
|
ParseOptions = case exmpp_xml:remove_cdata_from_list(Configuration) of
|
||||||
[] ->
|
[] ->
|
||||||
@ -1743,9 +1738,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}} ->
|
||||||
@ -2543,9 +2547,8 @@ read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
|
|||||||
{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 = #xmlel{ns = ?NS_PUBSUB, name = 'options',
|
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
|
||||||
attrs = [?XMLATTR('node', node_to_string(Node)),
|
attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)),
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)),
|
?XMLATTR('Subid', SubID) | nodeAttr(Node)],
|
||||||
?XMLATTR('Subid', SubID)],
|
|
||||||
children = [XdataEl]},
|
children = [XdataEl]},
|
||||||
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
|
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
|
||||||
{result, PubsubEl}
|
{result, PubsubEl}
|
||||||
@ -2636,7 +2639,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', node_to_string(SubsNode)),
|
[?XMLATTR('node', node_to_string(SubsNode)),
|
||||||
?XMLATTR('subscription', subscription_to_string(Subscription))]}];
|
?XMLATTR('subscription', subscription_to_string(Subscription))]}];
|
||||||
@ -2650,7 +2653,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name='subscription',
|
[#xmlel{ns = ?NS_PUBSUB, name='subscription',
|
||||||
attrs = [?XMLATTR('jid', exmpp_jid:jid_to_binary(SubJID)),
|
attrs = [?XMLATTR('jid', exmpp_jid:jid_to_binary(SubJID)),
|
||||||
?XMLATTR('subid', SubID),
|
?XMLATTR('subid', SubID),
|
||||||
@ -2665,7 +2668,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', node_to_string(SubsNode)),
|
[?XMLATTR('node', node_to_string(SubsNode)),
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(SubJID)),
|
?XMLATTR('jid', exmpp_jid:to_binary(SubJID)),
|
||||||
@ -2857,14 +2860,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()
|
||||||
@ -3093,6 +3090,7 @@ get_options_for_subs(NodeID, Subs) ->
|
|||||||
end, [], Subs).
|
end, [], Subs).
|
||||||
|
|
||||||
% TODO: merge broadcast code that way
|
% TODO: merge broadcast code that way
|
||||||
|
% TODO: pablo: Why is this commented? Seems to be present on trunk.
|
||||||
%broadcast(Host, Node, NodeId, Type, NodeOptions, Feature, Force, ElName, SubEls) ->
|
%broadcast(Host, Node, NodeId, Type, NodeOptions, Feature, Force, ElName, SubEls) ->
|
||||||
% case (get_option(NodeOptions, Feature) or Force) of
|
% case (get_option(NodeOptions, Feature) or Force) of
|
||||||
% true ->
|
% true ->
|
||||||
@ -3100,7 +3098,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};
|
||||||
% _ ->
|
% _ ->
|
||||||
@ -3217,7 +3215,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.
|
||||||
@ -3748,6 +3746,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) ->
|
||||||
|
[?XMLATTR('node', Node)];
|
||||||
nodeAttr(Node) ->
|
nodeAttr(Node) ->
|
||||||
[?XMLATTR('node', node_to_string(Node))].
|
[?XMLATTR('node', node_to_string(Node))].
|
||||||
|
|
||||||
|
@ -275,11 +275,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.
|
||||||
@ -383,7 +383,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
|
||||||
@ -479,7 +479,7 @@ disco_sm_features(Acc, From, To, Node, _Lang) ->
|
|||||||
|
|
||||||
disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
||||||
Host = exmpp_jid:prep_domain_as_list(To),
|
Host = exmpp_jid:prep_domain_as_list(To),
|
||||||
case tree_action(Host, get_subnodes, [Host, [], From]) of
|
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
|
||||||
[] ->
|
[] ->
|
||||||
Acc;
|
Acc;
|
||||||
Nodes ->
|
Nodes ->
|
||||||
@ -497,7 +497,7 @@ disco_sm_items(Acc, From, To, <<>>, _Lang) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
disco_sm_items(Acc, From, To, NodeB, _Lang) ->
|
disco_sm_items(Acc, From, To, NodeB, _Lang) ->
|
||||||
Node = binary_to_list(NodeB),
|
Node = string_to_node(binary_to_list(NodeB)),
|
||||||
%% TODO, use iq_disco_items(Host, Node, From)
|
%% TODO, use iq_disco_items(Host, Node, From)
|
||||||
Host = exmpp_jid:prep_domain_as_list(To),
|
Host = exmpp_jid:prep_domain_as_list(To),
|
||||||
LJID = jlib:short_prepd_bare_jid(To),
|
LJID = jlib:short_prepd_bare_jid(To),
|
||||||
@ -513,8 +513,6 @@ disco_sm_items(Acc, From, To, NodeB, _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]),
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs =
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs =
|
||||||
[?XMLATTR('jid', exmpp_jid:to_binary(LJID)),
|
[?XMLATTR('jid', exmpp_jid:to_binary(LJID)),
|
||||||
@ -913,7 +911,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,
|
||||||
[#xmlel{ns = ?NS_DISCO_INFO, name = 'identity', attrs =
|
[#xmlel{ns = ?NS_DISCO_INFO, name = 'identity', attrs =
|
||||||
[?XMLATTR('category', "pubsub"),
|
[?XMLATTR('category', "pubsub"),
|
||||||
@ -933,24 +931,18 @@ 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_path, [SubNode]),
|
||||||
RN = lists:last(SubNode),
|
[Name | _] = lists:reverse(Path),
|
||||||
%% remove name attribute
|
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host),
|
||||||
?XMLATTR('node', SN),
|
?XMLATTR('name', Name) | nodeAttr(SubNode)]}
|
||||||
?XMLATTR('name', RN)]}
|
end, tree_action(Host, get_subnodes, [Host, <<>>, From]))};
|
||||||
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)
|
||||||
@ -960,17 +952,13 @@ 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),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host) | nodeAttr(SubNode)]}
|
||||||
RN = lists:last(SubNode),
|
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('node', SN),
|
|
||||||
?XMLATTR('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, [NodeId, RN]),
|
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host),
|
||||||
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('node', SN),
|
?XMLATTR('name', Name)]}
|
||||||
?XMLATTR('name', Name)]}
|
|
||||||
end, NodeItems),
|
end, NodeItems),
|
||||||
{result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)}
|
{result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)}
|
||||||
end,
|
end,
|
||||||
@ -1028,10 +1016,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) ->
|
|||||||
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
|
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) ->
|
||||||
case exmpp_xml:remove_cdata_from_list(SubEl#xmlel.children) of
|
case exmpp_xml:remove_cdata_from_list(SubEl#xmlel.children) of
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] ->
|
[#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] ->
|
||||||
Node = case Host of
|
Node = string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', false)),
|
||||||
{_, _, _} -> exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', false);
|
|
||||||
_ -> string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', false))
|
|
||||||
end,
|
|
||||||
case {IQType, Name} of
|
case {IQType, Name} of
|
||||||
{set, 'create'} ->
|
{set, 'create'} ->
|
||||||
Config = case Rest of
|
Config = case Rest of
|
||||||
@ -1134,10 +1119,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
|
|||||||
end, exmpp_xml:get_child_elements(SubEl)),
|
end, exmpp_xml:get_child_elements(SubEl)),
|
||||||
case Action of
|
case Action of
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els}] ->
|
[#xmlel{name = Name, attrs = Attrs, children = Els}] ->
|
||||||
Node = case Host of
|
Node = string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', "")),
|
||||||
{_, _, _} -> exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', "");
|
|
||||||
_ -> string_to_node(exmpp_xml:get_attribute_from_list_as_list(Attrs, 'node', ""))
|
|
||||||
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);
|
||||||
@ -1379,8 +1361,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
|
|||||||
end,
|
end,
|
||||||
Stanza = event_stanza(
|
Stanza = event_stanza(
|
||||||
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', SNode),
|
[?XMLATTR('jid', exmpp_jid:to_binary(JID)) | nodeAttr(SNode)] ++ SubAttrs
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(JID))] ++ SubAttrs
|
|
||||||
}]),
|
}]),
|
||||||
ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
|
ejabberd_router ! {route, service_jid(Host), JID, Stanza}.
|
||||||
|
|
||||||
@ -1390,11 +1371,8 @@ 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];
|
Subscriber = exmpp_jid:parse(SSubscriber),
|
||||||
_ -> string:tokens(SNode, "/")
|
|
||||||
end,
|
|
||||||
Subscriber = exmpp_jid:parse(SSubscriber),
|
|
||||||
Allow = case SAllow of
|
Allow = case SAllow of
|
||||||
"1" -> true;
|
"1" -> true;
|
||||||
"true" -> true;
|
"true" -> true;
|
||||||
@ -1528,21 +1506,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:short_prepd_jid(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,
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(NewNode)}]}]};
|
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(NewNode)}]}]};
|
||||||
Error -> Error
|
Error ->
|
||||||
|
Error
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
%% Service does not support instant nodes
|
%% Service does not support instant nodes
|
||||||
@ -1550,7 +1525,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 exmpp_xml:remove_cdata_from_list(Configuration) of
|
ParseOptions = case exmpp_xml:remove_cdata_from_list(Configuration) of
|
||||||
[] ->
|
[] ->
|
||||||
@ -1575,9 +1549,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}} ->
|
||||||
@ -2374,9 +2357,8 @@ read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
|
|||||||
{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 = #xmlel{ns = ?NS_PUBSUB, name = 'options',
|
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
|
||||||
attrs = [?XMLATTR('node', node_to_string(Node)),
|
attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)),
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)),
|
?XMLATTR('Subid', SubID) | nodeAttr(Node)],
|
||||||
?XMLATTR('Subid', SubID)],
|
|
||||||
children = [XdataEl]},
|
children = [XdataEl]},
|
||||||
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
|
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
|
||||||
{result, PubsubEl}
|
{result, PubsubEl}
|
||||||
@ -2467,7 +2449,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', node_to_string(SubsNode)),
|
[?XMLATTR('node', node_to_string(SubsNode)),
|
||||||
?XMLATTR('subscription', subscription_to_string(Subscription))]}];
|
?XMLATTR('subscription', subscription_to_string(Subscription))]}];
|
||||||
@ -2481,7 +2463,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name='subscription',
|
[#xmlel{ns = ?NS_PUBSUB, name='subscription',
|
||||||
attrs = [?XMLATTR('jid', exmpp_jid:jid_to_binary(SubJID)),
|
attrs = [?XMLATTR('jid', exmpp_jid:jid_to_binary(SubJID)),
|
||||||
?XMLATTR('subid', SubID),
|
?XMLATTR('subid', SubID),
|
||||||
@ -2496,7 +2478,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
|
||||||
[] ->
|
<<>> ->
|
||||||
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
[#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs =
|
||||||
[?XMLATTR('node', node_to_string(SubsNode)),
|
[?XMLATTR('node', node_to_string(SubsNode)),
|
||||||
?XMLATTR('jid', exmpp_jid:to_binary(SubJID)),
|
?XMLATTR('jid', exmpp_jid:to_binary(SubJID)),
|
||||||
@ -2688,14 +2670,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()
|
||||||
@ -2924,6 +2900,7 @@ get_options_for_subs(NodeID, Subs) ->
|
|||||||
end, [], Subs).
|
end, [], Subs).
|
||||||
|
|
||||||
% TODO: merge broadcast code that way
|
% TODO: merge broadcast code that way
|
||||||
|
% TODO: pablo: why is this commented?
|
||||||
%broadcast(Host, Node, NodeId, Type, NodeOptions, Feature, Force, ElName, SubEls) ->
|
%broadcast(Host, Node, NodeId, Type, NodeOptions, Feature, Force, ElName, SubEls) ->
|
||||||
% case (get_option(NodeOptions, Feature) or Force) of
|
% case (get_option(NodeOptions, Feature) or Force) of
|
||||||
% true ->
|
% true ->
|
||||||
@ -2931,7 +2908,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};
|
||||||
% _ ->
|
% _ ->
|
||||||
@ -3048,7 +3025,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.
|
||||||
@ -3635,6 +3612,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) ->
|
||||||
|
[?XMLATTR('node', Node)];
|
||||||
nodeAttr(Node) ->
|
nodeAttr(Node) ->
|
||||||
[?XMLATTR('node', node_to_string(Node))].
|
[?XMLATTR('node', node_to_string(Node))].
|
||||||
|
|
||||||
|
@ -69,7 +69,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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
@ -195,3 +197,9 @@ 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).
|
||||||
|
@ -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,9 @@ 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).
|
||||||
|
@ -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,9 @@ 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).
|
||||||
|
@ -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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
@ -197,3 +199,8 @@ 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).
|
||||||
|
@ -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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
@ -180,3 +182,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.
|
||||||
|
@ -60,7 +60,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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
@ -186,3 +188,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.
|
||||||
|
@ -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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% ================
|
%% ================
|
||||||
@ -204,7 +206,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
|
|||||||
{LU, LS, LR} = LOwner,
|
{LU, LS, LR} = LOwner,
|
||||||
case acl:match_rule(ServerHost, Access, exmpp_jid:make(LU, LS, LR)) of
|
case acl:match_rule(ServerHost, Access, exmpp_jid:make(LU, LS, LR)) of
|
||||||
allow ->
|
allow ->
|
||||||
case Node of
|
case node_to_path(Node) of
|
||||||
["home", Server, User | _] -> true;
|
["home", Server, User | _] -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end;
|
end;
|
||||||
@ -981,6 +983,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
|
||||||
@ -1006,3 +1016,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.
|
||||||
|
|
||||||
|
@ -80,7 +80,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([
|
||||||
@ -209,7 +211,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
|
|||||||
{LU, LS, LR} = LOwner,
|
{LU, LS, LR} = LOwner,
|
||||||
case acl:match_rule(ServerHost, Access, exmpp_jid:make(LU, LS, LR)) of
|
case acl:match_rule(ServerHost, Access, exmpp_jid:make(LU, LS, LR)) of
|
||||||
allow ->
|
allow ->
|
||||||
case Node of
|
case node_to_path(Node) of
|
||||||
["home", Server, User | _] -> true;
|
["home", Server, User | _] -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end;
|
end;
|
||||||
@ -1372,3 +1374,11 @@ i2l(L, N) when is_list(L) ->
|
|||||||
C when C > N -> L;
|
C when C > N -> L;
|
||||||
_ -> i2l([$0|L], N)
|
_ -> i2l([$0|L], N)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
node_to_path(Node) ->
|
||||||
|
string:tokens(binary_to_list(Node), "/").
|
||||||
|
|
||||||
|
path_to_node([]) ->
|
||||||
|
<<>>;
|
||||||
|
path_to_node(Path) ->
|
||||||
|
list_to_binary(string:join([""|Path], "/")).
|
||||||
|
@ -72,7 +72,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) ->
|
||||||
@ -202,3 +204,8 @@ 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).
|
||||||
|
@ -65,7 +65,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) ->
|
||||||
@ -270,6 +272,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
|
||||||
|
@ -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) ->
|
||||||
@ -306,6 +308,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
|
||||||
|
@ -69,7 +69,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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
|
||||||
@ -197,3 +199,9 @@ 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).
|
||||||
|
@ -69,7 +69,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,9 @@ 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).
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@ -158,6 +158,12 @@ 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) ->
|
||||||
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),
|
||||||
@ -172,12 +178,21 @@ get_subnodes(Host, Node) ->
|
|||||||
get_subnodes_tree(Host, Node, _From) ->
|
get_subnodes_tree(Host, Node, _From) ->
|
||||||
get_subnodes_tree(Host, Node).
|
get_subnodes_tree(Host, Node).
|
||||||
get_subnodes_tree(Host, Node) ->
|
get_subnodes_tree(Host, Node) ->
|
||||||
mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) ->
|
case get_node(Host, Node) of
|
||||||
case lists:prefix(Node, N) and (H == Host) of
|
{error, _} ->
|
||||||
true -> [R | Acc];
|
[];
|
||||||
_ -> Acc
|
Rec ->
|
||||||
end
|
BasePlugin = list_to_atom("node_"++Rec#pubsub_node.type),
|
||||||
end, [], pubsub_node).
|
BasePath = BasePlugin:node_to_path(Node),
|
||||||
|
mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) ->
|
||||||
|
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.
|
||||||
|
|
||||||
%% @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()
|
||||||
@ -185,26 +200,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:short_prepd_bare_jid(Owner),
|
BJID = jlib:short_prepd_bare_jid(Owner),
|
||||||
case mnesia:read({pubsub_node, {Host, Node}}) of
|
case 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;
|
||||||
_ ->
|
_ ->
|
||||||
Parent = lists:sublist(Node, length(Node) - 1),
|
case Parents of
|
||||||
case Parent of
|
[] -> true;
|
||||||
[] ->
|
[Parent | _] ->
|
||||||
{[], true};
|
|
||||||
_ ->
|
|
||||||
case mnesia:read({pubsub_node, {Host, Parent}}) of
|
case mnesia:read({pubsub_node, {Host, Parent}}) of
|
||||||
[] -> {Parent, false};
|
[#pubsub_node{owners = [{[], Host, []}]}] -> true;
|
||||||
_ -> {Parent, lists:member(BJID, Parent#pubsub_node.owners)}
|
[#pubsub_node{owners = Owners}] -> lists:member(BJID, Owners);
|
||||||
end
|
_ -> false
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
case ParentExists of
|
case ParentExists of
|
||||||
@ -212,7 +228,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}),
|
||||||
|
@ -59,7 +59,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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@ -208,30 +208,37 @@ 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:short_prepd_bare_jid(Owner),
|
||||||
case nodeid(Host, Node) of
|
case nodeid(Host, Node) of
|
||||||
{error, 'item_not_found'} ->
|
{error, 'item_not_found'} ->
|
||||||
{ParentNode, ParentExists} = case Host of
|
ParentExists = case Host of
|
||||||
{_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};
|
||||||
@ -286,8 +293,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}.
|
||||||
@ -296,7 +303,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)),
|
||||||
@ -353,5 +363,8 @@ nodeid(Host, Node) ->
|
|||||||
{error, 'item_not_found'}
|
{error, '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).
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
get_nodes/1,
|
get_nodes/1,
|
||||||
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
|
||||||
]).
|
]).
|
||||||
|
|
||||||
@ -133,7 +133,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) ->
|
||||||
UserName = exmpp_jid:prep_node_as_list(Owner),
|
UserName = exmpp_jid:prep_node_as_list(Owner),
|
||||||
UserHost = exmpp_jid:prep_domain_as_list(Owner),
|
UserHost = exmpp_jid:prep_domain_as_list(Owner),
|
||||||
case Node of
|
case Node of
|
||||||
|
Loading…
Reference in New Issue
Block a user