Compare commits

...

21 Commits

Author SHA1 Message Date
Badlop 23bf45e881 Create tag for ejabberd 2.1.0 final release.
SVN Revision: 2737
2009-11-13 16:01:44 +00:00
Badlop 1511a5dc82 Fix EDoc errors
SVN Revision: 2735
2009-11-06 18:26:06 +00:00
Badlop 041d947e83 Fix bug that forgot listener options when using R12 or older.
SVN Revision: 2734
2009-11-06 18:24:54 +00:00
Christophe Romain 2007b3d496 typo fix that breaks pep
SVN Revision: 2731
2009-11-06 11:01:40 +00:00
Christophe Romain 09e847b97d fix root node deletion match
SVN Revision: 2729
2009-11-05 17:36:15 +00:00
Badlop b9f911554c Fix ProcessOne name in comments.
SVN Revision: 2724
2009-11-04 20:14:22 +00:00
Badlop 24323e8b3b Extend explanation of ldap_encrypt tls (thanks to Konstantin Khomoutov)
SVN Revision: 2723
2009-11-04 20:12:54 +00:00
Badlop 1a5eb4f73d Fix disco on root node, add commands to disco (thanks to Brian Cully)(EJAB-1094)
SVN Revision: 2722
2009-11-04 19:54:15 +00:00
Badlop 3930715712 Send authorization messages outside of get-pending transaction (thanks to Brian Cully)(EJAB-1090)
SVN Revision: 2721
2009-11-04 19:52:33 +00:00
Badlop 64bc97d471 Send authorization messages outside of get-pending transaction (thanks to Brian Cully)(EJAB-1090)
SVN Revision: 2719
2009-11-04 17:38:51 +00:00
Badlop 4aec8dda48 Extend explanation of mod_pubsub "default" rename to "hometree".
SVN Revision: 2718
2009-11-04 09:42:54 +00:00
Badlop 9192c75e1a Fix stringprep Bidi checking (thanks to Alexey Shchepin)(EJAB-1087)
SVN Revision: 2717
2009-11-01 12:15:34 +00:00
Christophe Romain 512d701ef8 minor bugfix, thanks to brian Cully (EJAB-1089)
SVN Revision: 2713
2009-10-27 14:26:22 +00:00
Christophe Romain ef3dd090c7 backport previous patch to pubsub odbc
SVN Revision: 2711
2009-10-27 14:13:18 +00:00
Christophe Romain 3d5fe6a337 fix disco bugs, thanks to Brian Cully (EJAB-1088)
SVN Revision: 2710
2009-10-27 14:07:35 +00:00
Badlop 0906a68c27 Mention in Release Notes the three changes in SQL databases (EJAB-1078)
SVN Revision: 2707
2009-10-23 17:32:12 +00:00
Badlop 798853abb6 Fix mistake that disallowed s2s_out connections when using Erlang R12 or older.
SVN Revision: 2694
2009-10-21 21:11:09 +00:00
Badlop 5e3fdbeeed Mention the change in nodename slash separation in release notes.
SVN Revision: 2689
2009-10-20 15:39:57 +00:00
Badlop 04545f2668 Create branch for ejabberd 2.1.x release line.
SVN Revision: 2688
2009-10-20 15:28:48 +00:00
Christophe Romain f383511e0d add release_notes_2.0.1
SVN Revision: 1338
2008-05-19 22:35:01 +00:00
Jérôme Sautret 2f65188edb Created ejabberd 2.1.X branch.
SVN Revision: 1274
2008-04-03 13:38:34 +00:00
15 changed files with 208 additions and 103 deletions
+2 -1
View File
@@ -1620,7 +1620,8 @@ create accounts, change password or edit vCard that is stored in LDAP.</P><P> <A
LDAP servers. This option is required.
</DD><DT CLASS="dt-description"><B><TT>{ldap_encrypt, none|tls}</TT></B></DT><DD CLASS="dd-description"> Type of connection encryption to the LDAP server.
Allowed values are: <TT>none</TT>, <TT>tls</TT>.
Note that STARTTLS is not supported.
The value <TT>tls</TT> enables encryption by using LDAP over SSL.
Note that STARTTLS encryption is not supported.
The default value is: <TT>none</TT>.
</DD><DT CLASS="dt-description"><B><TT>{ldap_port, Number}</TT></B></DT><DD CLASS="dd-description"> Port to connect to your LDAP server.
The default port is&#XA0;389 if encryption is disabled; and 636 if encryption is enabled.
+2 -1
View File
@@ -2163,7 +2163,8 @@ Parameters:
LDAP servers. This option is required.
\titem{\{ldap\_encrypt, none|tls\}} \ind{options!ldap\_encrypt}Type of connection encryption to the LDAP server.
Allowed values are: \term{none}, \term{tls}.
Note that STARTTLS is not supported.
The value \term{tls} enables encryption by using LDAP over SSL.
Note that STARTTLS encryption is not supported.
The default value is: \term{none}.
\titem{\{ldap\_port, Number\}} \ind{options!ldap\_port}Port to connect to your LDAP server.
The default port is~389 if encryption is disabled; and 636 if encryption is enabled.
+17 -5
View File
@@ -135,6 +135,8 @@
- Implicit item deletion is not notified when deleting node
- Make PubSub x-data configuration form handles list value
- Make default node name convention XEP-compatible, document usage of hierarchy
- Node names are used verbatim, without separating by slash, unless a
node plugin uses its own separator
- Send authorization update event (XEP-0060, 8.6)
- Support of collection node subscription options
- Support ODBC storage. Experimental, needs more testing.
@@ -207,14 +209,24 @@
Upgrading From ejabberd 2.0.x:
- The database schemas didn't change since ejabberd 1.1.4.
Anyway, it is recommended to backup the Mnesia spool directory and
- The database schemas have three changes since ejabberd 2.0.x.
Check the database creation SQL files and update your database.
1) New table roster_version to support roster versioning.
2) Six new tables for optional pubsub ODBC storage.
3) Some tables in the MySQL database have a new created_at column.
- As usual, it is recommended to backup the Mnesia spool directory and
your SQL database (if used) before upgrading ejabberd.
- The plugin of mod_pubsub "default" is renamed to "flat". You need
to edit the ejabberd configuration file and replace those names.
- Between ejabberd 2.0.0 and 2.0.5, mod_pubsub used "default" as the
default node plugin. But in 2.1.0 this is renamed to "hometree".
You have to edit your ejabberd config file and replace those names.
If you used ejabberd 2.0.5 or older, the database will be updated
automatically. But if you were using ejabberd from SVN, you must
manually run ejabberdctl with the command: rename_default_nodeplugin.
Running this command on already updated database does nothing.
- The listener options 'ip' and inet6' are not documented anymore
- The listener options 'ip' and 'inet6' are not documented anymore
but they are supported and you can continue using them.
There is a new syntax to define IP address and IP version.
As usual, check the ejabberd Guide for more information.
+1 -1
View File
@@ -129,7 +129,7 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
SockOpts2 = case erlang:system_info(otp_release) >= "R13B" of
true -> [{send_timeout_close, true} | SockOpts];
false -> []
false -> SockOpts
end,
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
-1
View File
@@ -272,7 +272,6 @@ open_socket2(Type, Addr, Port) ->
case (catch ejabberd_socket:connect(Addr, Port,
[binary, {packet, 0},
{send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{active, false}, Type | SockOpts],
Timeout)) of
{ok, _Socket} = R -> R;
+1 -1
View File
@@ -22,7 +22,7 @@
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%% 2009, improvements from Process-One to support correct PEP handling
%%% 2009, improvements from ProcessOne to support correct PEP handling
%%% through s2s, use less memory, and speedup global caps handling
%%%----------------------------------------------------------------------
+57 -20
View File
@@ -191,8 +191,8 @@ init([ServerHost, Opts]) ->
ets:insert(gen_mod:get_module_proc(Host, config), {max_items_node, MaxItemsNode}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {nodetree, NodeTree}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {plugins, Plugins}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, Plugins}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, LastItemCache}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, LastItemCache}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, MaxItemsNode}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {pep_mapping, PepMapping}),
ejabberd_hooks:add(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
@@ -1030,6 +1030,18 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
end
end.
command_disco_info(_Host, <<?NS_COMMANDS>>, _From) ->
IdentityEl = {xmlelement, "identity", [{"category", "automation"},
{"type", "command-list"}],
[]},
{result, [IdentityEl]};
command_disco_info(_Host, <<?NS_PUBSUB_GET_PENDING>>, _From) ->
IdentityEl = {xmlelement, "identity", [{"category", "automation"},
{"type", "command-node"}],
[]},
FeaturesEl = {xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{result, [IdentityEl, FeaturesEl]}.
node_disco_info(Host, Node, From) ->
node_disco_info(Host, Node, From, true, true).
node_disco_identity(Host, Node, From) ->
@@ -1092,21 +1104,38 @@ iq_disco_info(Host, SNode, From, Lang) ->
{xmlelement, "feature", [{"var", ?NS_DISCO_INFO}], []},
{xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++
lists:map(fun(Feature) ->
{xmlelement, "feature", [{"var", ?NS_PUBSUB++"#"++Feature}], []}
end, features(Host, Node))};
<<?NS_COMMANDS>> ->
command_disco_info(Host, Node, From);
<<?NS_PUBSUB_GET_PENDING>> ->
command_disco_info(Host, Node, From);
_ ->
node_disco_info(Host, Node, From)
end.
iq_disco_items(Host, [], From) ->
{result, lists:map(
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]))};
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
Nodes when is_list(Nodes) ->
{result, lists:map(
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, Nodes)};
Other ->
Other
end;
iq_disco_items(Host, ?NS_COMMANDS, _From) ->
%% TODO: support localization of this string
CommandItems = [{xmlelement, "item", [{"jid", Host}, {"node", ?NS_PUBSUB_GET_PENDING}, {"name", "Get Pending"}], []}],
{result, CommandItems};
iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From) ->
CommandItems = [],
{result, CommandItems};
iq_disco_items(Host, Item, From) ->
case string:tokens(Item, "!") of
[_SNode, _ItemID] ->
@@ -1122,7 +1151,9 @@ iq_disco_items(Host, Item, From) ->
end,
Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) ->
{xmlelement, "item", [{"jid", Host}|nodeAttr(SubNode)], []}
{result, Path} = node_call(Type, node_to_path, [SubNode]),
[Name|_] = lists:reverse(Path),
{xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
end, tree_call(Host, get_subnodes, [Host, Node, From])),
Items = lists:map(
fun(#pubsub_item{itemid = {RN, _}}) ->
@@ -1174,7 +1205,7 @@ iq_get_vcard(Lang) ->
[{xmlcdata,
translate:translate(Lang,
"ejabberd Publish-Subscribe module") ++
"\nCopyright (c) 2004-2009 Process-One"}]}].
"\nCopyright (c) 2004-2009 ProcessOne"}]}].
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) ->
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(ServerHost)).
@@ -1366,6 +1397,13 @@ adhoc_request(Host, _ServerHost, Owner,
Error ->
Error
end;
adhoc_request(_Host, _ServerHost, _Owner, #adhoc_request{action = "cancel"},
_Access, _Plugins) ->
#adhoc_response{status = canceled};
adhoc_request(Host, ServerHost, Owner, #adhoc_request{action = []} = R,
Access, Plugins) ->
adhoc_request(Host, ServerHost, Owner, R#adhoc_request{action = "execute"},
Access, Plugins);
adhoc_request(_Host, _ServerHost, _Owner, Other, _Access, _Plugins) ->
?DEBUG("Couldn't process ad hoc command:~n~p", [Other]),
{error, ?ERR_ITEM_NOT_FOUND}.
@@ -1417,17 +1455,12 @@ send_pending_auth_events(Host, Node, Owner) ->
?DEBUG("Sending pending auth events for ~s on ~s:~s",
[jlib:jid_to_string(Owner), Host, node_to_string(Node)]),
Action =
fun (#pubsub_node{id = NodeID, type = Type} = N) ->
fun (#pubsub_node{id = NodeID, type = Type}) ->
case lists:member("get-pending", features(Type)) of
true ->
case node_call(Type, get_affiliation, [NodeID, Owner]) of
{result, owner} ->
{result, Subscriptions} = node_call(Type, get_node_subscriptions, [NodeID]),
lists:foreach(fun({J, pending, _SubID}) -> send_authorization_request(N, jlib:make_jid(J));
({J, pending}) -> send_authorization_request(N, jlib:make_jid(J));
(_) -> ok
end, Subscriptions),
{result, ok};
node_call(Type, get_node_subscriptions, [NodeID]);
_ ->
{error, ?ERR_FORBIDDEN}
end;
@@ -1436,7 +1469,11 @@ send_pending_auth_events(Host, Node, Owner) ->
end
end,
case transaction(Host, Node, Action, sync_dirty) of
{result, _} ->
{result, {N, Subscriptions}} ->
lists:foreach(fun({J, pending, _SubID}) -> send_authorization_request(N, jlib:make_jid(J));
({J, pending}) -> send_authorization_request(N, jlib:make_jid(J));
(_) -> ok
end, Subscriptions),
#adhoc_response{};
Err ->
Err
@@ -1768,7 +1805,7 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
%%<li>The node is the root collection node, which cannot be deleted.</li>
%%<li>The specified node does not exist.</li>
%%</ul>
delete_node(_Host, [], _Owner) ->
delete_node(_Host, <<>>, _Owner) ->
%% Node is the root
{error, ?ERR_NOT_ALLOWED};
delete_node(Host, Node, Owner) ->
@@ -3583,7 +3620,7 @@ features(Type) ->
{'EXIT', {undef, _}} -> [];
Result -> Result
end.
features(Host, []) ->
features(Host, <<>>) ->
lists:usort(lists:foldl(fun(Plugin, Acc) ->
Acc ++ features(Plugin)
end, [], plugins(Host)));
+57 -20
View File
@@ -191,8 +191,8 @@ init([ServerHost, Opts]) ->
ets:insert(gen_mod:get_module_proc(Host, config), {max_items_node, MaxItemsNode}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {nodetree, NodeTree}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {plugins, Plugins}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, Plugins}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, LastItemCache}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, LastItemCache}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, MaxItemsNode}),
ets:insert(gen_mod:get_module_proc(ServerHost, config), {pep_mapping, PepMapping}),
ejabberd_hooks:add(disco_sm_identity, ServerHost, ?MODULE, disco_sm_identity, 75),
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
@@ -834,6 +834,18 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
end
end.
command_disco_info(_Host, <<?NS_COMMANDS>>, _From) ->
IdentityEl = {xmlelement, "identity", [{"category", "automation"},
{"type", "command-list"}],
[]},
{result, [IdentityEl]};
command_disco_info(_Host, <<?NS_PUBSUB_GET_PENDING>>, _From) ->
IdentityEl = {xmlelement, "identity", [{"category", "automation"},
{"type", "command-node"}],
[]},
FeaturesEl = {xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{result, [IdentityEl, FeaturesEl]}.
node_disco_info(Host, Node, From) ->
node_disco_info(Host, Node, From, true, true).
node_disco_identity(Host, Node, From) ->
@@ -897,22 +909,39 @@ iq_disco_info(Host, SNode, From, Lang) ->
{xmlelement, "feature", [{"var", ?NS_DISCO_INFO}], []},
{xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++
lists:map(fun
("rsm")-> {xmlelement, "feature", [{"var", ?NS_RSM}], []};
(T) -> {xmlelement, "feature", [{"var", ?NS_PUBSUB++"#"++T}], []}
end, features(Host, Node))};
<<?NS_COMMANDS>> ->
command_disco_info(Host, Node, From);
<<?NS_PUBSUB_GET_PENDING>> ->
command_disco_info(Host, Node, From);
_ ->
node_disco_info(Host, Node, From)
end.
iq_disco_items(Host, [], From, _RSM) ->
{result, lists:map(
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]))};
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
Nodes when is_list(Nodes) ->
{result, lists:map(
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, Nodes)};
Other ->
Other
end;
iq_disco_items(Host, ?NS_COMMANDS, _From, _RSM) ->
%% TODO: support localization of this string
CommandItems = [{xmlelement, "item", [{"jid", Host}, {"node", ?NS_PUBSUB_GET_PENDING}, {"name", "Get Pending"}], []}],
{result, CommandItems};
iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) ->
CommandItems = [],
{result, CommandItems};
iq_disco_items(Host, Item, From, RSM) ->
case string:tokens(Item, "!") of
[_SNode, _ItemID] ->
@@ -928,7 +957,9 @@ iq_disco_items(Host, Item, From, RSM) ->
end,
Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) ->
{xmlelement, "item", [{"jid", Host}|nodeAttr(SubNode)], []}
{result, Path} = node_call(Type, node_to_path, [SubNode]),
[Name|_] = lists:reverse(Path),
{xmlelement, "item", [{"jid", Host}, {"name", Name}|nodeAttr(SubNode)], []}
end, tree_call(Host, get_subnodes, [Host, Node, From])),
Items = lists:map(
fun(#pubsub_item{itemid = {RN, _}}) ->
@@ -980,7 +1011,7 @@ iq_get_vcard(Lang) ->
[{xmlcdata,
translate:translate(Lang,
"ejabberd Publish-Subscribe module") ++
"\nCopyright (c) 2004-2009 Process-One"}]}].
"\nCopyright (c) 2004-2009 ProcessOne"}]}].
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) ->
iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(ServerHost)).
@@ -1175,6 +1206,13 @@ adhoc_request(Host, _ServerHost, Owner,
Error ->
Error
end;
adhoc_request(_Host, _ServerHost, _Owner, #adhoc_request{action = "cancel"},
_Access, _Plugins) ->
#adhoc_response{status = canceled};
adhoc_request(Host, ServerHost, Owner, #adhoc_request{action = []} = R,
Access, Plugins) ->
adhoc_request(Host, ServerHost, Owner, R#adhoc_request{action = "execute"},
Access, Plugins);
adhoc_request(_Host, _ServerHost, _Owner, Other, _Access, _Plugins) ->
?DEBUG("Couldn't process ad hoc command:~n~p", [Other]),
{error, ?ERR_ITEM_NOT_FOUND}.
@@ -1227,17 +1265,12 @@ send_pending_auth_events(Host, Node, Owner) ->
?DEBUG("Sending pending auth events for ~s on ~s:~s",
[jlib:jid_to_string(Owner), Host, node_to_string(Node)]),
Action =
fun (#pubsub_node{id = NodeID, type = Type} = N) ->
fun (#pubsub_node{id = NodeID, type = Type}) ->
case lists:member("get-pending", features(Type)) of
true ->
case node_call(Type, get_affiliation, [NodeID, Owner]) of
{result, owner} ->
{result, Subscriptions} = node_call(Type, get_node_subscriptions, [NodeID]),
lists:foreach(fun({J, pending, _SubID}) -> send_authorization_request(N, jlib:make_jid(J));
({J, pending}) -> send_authorization_request(N, jlib:make_jid(J));
(_) -> ok
end, Subscriptions),
{result, ok};
node_call(Type, get_node_subscriptions, [NodeID]);
_ ->
{error, ?ERR_FORBIDDEN}
end;
@@ -1246,7 +1279,11 @@ send_pending_auth_events(Host, Node, Owner) ->
end
end,
case transaction(Host, Node, Action, sync_dirty) of
{result, _} ->
{result, {N, Subscriptions}} ->
lists:foreach(fun({J, pending, _SubID}) -> send_authorization_request(N, jlib:make_jid(J));
({J, pending}) -> send_authorization_request(N, jlib:make_jid(J));
(_) -> ok
end, Subscriptions),
#adhoc_response{};
Err ->
Err
@@ -1578,7 +1615,7 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
%%<li>The node is the root collection node, which cannot be deleted.</li>
%%<li>The specified node does not exist.</li>
%%</ul>
delete_node(_Host, [], _Owner) ->
delete_node(_Host, <<>>, _Owner) ->
%% Node is the root
{error, ?ERR_NOT_ALLOWED};
delete_node(Host, Node, Owner) ->
@@ -3416,7 +3453,7 @@ features(Type) ->
{'EXIT', {undef, _}} -> [];
Result -> Result
end.
features(Host, []) ->
features(Host, <<>>) ->
lists:usort(lists:foldl(fun(Plugin, Acc) ->
Acc ++ features(Plugin)
end, [], plugins(Host)));
+12 -6
View File
@@ -154,17 +154,21 @@ get_parentnodes_tree(Host, NodeID, _From) ->
get_subnodes(Host, NodeID, _From) ->
get_subnodes(Host, NodeID).
get_subnodes(Host, <<>>) ->
get_subnodes_helper(Host, <<>>);
get_subnodes(Host, NodeID) ->
case find_node(Host, NodeID) of
false -> {error, ?ERR_ITEM_NOT_FOUND};
_ ->
Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _},
parents = Parents} = Node <- mnesia:table(pubsub_node),
Host == NHost,
lists:member(NodeID, Parents)]),
qlc:e(Q)
_ -> get_subnodes_helper(Host, NodeID)
end.
get_subnodes_helper(Host, NodeID) ->
Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _},
parents = Parents} = Node <- mnesia:table(pubsub_node),
Host == NHost,
lists:member(NodeID, Parents)]),
qlc:e(Q).
get_subnodes_tree(Host, NodeID, From) ->
Pred = fun (NID, #pubsub_node{parents = Parents}) ->
lists:member(NID, Parents)
@@ -224,6 +228,8 @@ validate_parentage(_Key, _Owners, []) ->
true;
validate_parentage(Key, Owners, [[] | T]) ->
validate_parentage(Key, Owners, T);
validate_parentage(Key, Owners, [<<>> | T]) ->
validate_parentage(Key, Owners, T);
validate_parentage(Key, Owners, [ParentID | T]) ->
case find_node(Key, ParentID) of
false -> {error, ?ERR_ITEM_NOT_FOUND};
+1 -1
View File
@@ -197,7 +197,7 @@ get_subnodes_tree(Host, Node) ->
end, [], pubsub_node)
end.
%% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason}
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid()
%% Node = mod_pubsub:pubsubNode()
%% NodeType = mod_pubsub:nodeType()
+1 -1
View File
@@ -203,7 +203,7 @@ get_subnodes_tree(Host, Node) ->
[]
end.
%% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason}
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid()
%% Node = mod_pubsub:pubsubNode()
%% NodeType = mod_pubsub:nodeType()
+1 -1
View File
@@ -148,7 +148,7 @@ get_subnodes_tree(Host, Node, _From) ->
get_subnodes_tree(_Host, _Node) ->
[].
%% @spec (Host, Node, Type, Owner, Options) -> ok
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok
%% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode()
%% Type = mod_pubsub:nodeType()
+54 -42
View File
@@ -1,5 +1,5 @@
--- mod_pubsub.erl 2009-10-20 16:33:47.000000000 +0200
+++ mod_pubsub_odbc.erl 2009-10-20 16:33:26.000000000 +0200
--- mod_pubsub.erl 2009-11-06 12:01:44.000000000 +0100
+++ mod_pubsub_odbc.erl 2009-11-06 12:01:53.000000000 +0100
@@ -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.
@@ -307,7 +307,7 @@
{result, IQRes} ->
jlib:iq_to_xml(
IQ#iq{type = result,
@@ -1048,7 +852,7 @@
@@ -1060,7 +864,7 @@
[] ->
["leaf"]; %% No sub-nodes: it's a leaf node
_ ->
@@ -316,7 +316,7 @@
{result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"];
_ -> []
@@ -1064,8 +868,9 @@
@@ -1076,8 +880,9 @@
[];
true ->
[{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} |
@@ -328,9 +328,9 @@
end, features(Type))]
end,
%% TODO: add meta-data info (spec section 5.4)
@@ -1093,21 +898,22 @@
{xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []},
@@ -1106,8 +911,9 @@
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++
- lists:map(fun(Feature) ->
- {xmlelement, "feature", [{"var", ?NS_PUBSUB++"#"++Feature}], []}
@@ -338,24 +338,36 @@
+ ("rsm")-> {xmlelement, "feature", [{"var", ?NS_RSM}], []};
+ (T) -> {xmlelement, "feature", [{"var", ?NS_PUBSUB++"#"++T}], []}
end, features(Host, Node))};
_ ->
<<?NS_COMMANDS>> ->
command_disco_info(Host, Node, From);
@@ -1117,7 +923,7 @@
node_disco_info(Host, Node, From)
end.
-iq_disco_items(Host, [], From) ->
+iq_disco_items(Host, [], From, _RSM) ->
{result, lists:map(
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]))};
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
Nodes when is_list(Nodes) ->
{result, lists:map(
@@ -1129,14 +935,14 @@
Other ->
Other
end;
-iq_disco_items(Host, ?NS_COMMANDS, _From) ->
+iq_disco_items(Host, ?NS_COMMANDS, _From, _RSM) ->
%% TODO: support localization of this string
CommandItems = [{xmlelement, "item", [{"jid", Host}, {"node", ?NS_PUBSUB_GET_PENDING}, {"name", "Get Pending"}], []}],
{result, CommandItems};
-iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From) ->
+iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) ->
CommandItems = [],
{result, CommandItems};
-iq_disco_items(Host, Item, From) ->
+iq_disco_items(Host, Item, From, RSM) ->
case string:tokens(Item, "!") of
[_SNode, _ItemID] ->
{result, []};
@@ -1115,10 +921,10 @@
@@ -1144,10 +950,10 @@
Node = string_to_node(SNode),
Action =
fun(#pubsub_node{type = Type, id = NodeId}) ->
@@ -369,7 +381,7 @@
end,
Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}}) ->
@@ -1129,7 +935,7 @@
@@ -1160,7 +966,7 @@
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
end, NodeItems),
@@ -378,7 +390,7 @@
end,
case transaction(Host, Node, Action, sync_dirty) of
{result, {_, Result}} -> {result, Result};
@@ -1258,7 +1064,8 @@
@@ -1289,7 +1095,8 @@
(_, Acc) ->
Acc
end, [], xml:remove_cdata(Els)),
@@ -388,7 +400,7 @@
{get, "subscriptions"} ->
get_subscriptions(Host, Node, From, Plugins);
{get, "affiliations"} ->
@@ -1281,7 +1088,9 @@
@@ -1312,7 +1119,9 @@
iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
{xmlelement, _, _, SubEls} = SubEl,
@@ -399,7 +411,7 @@
case Action of
[{xmlelement, Name, Attrs, Els}] ->
Node = string_to_node(xml:get_attr_s("node", Attrs)),
@@ -1404,7 +1213,8 @@
@@ -1442,7 +1251,8 @@
_ -> []
end
end,
@@ -409,7 +421,7 @@
sync_dirty) of
{result, Res} -> Res;
Err -> Err
@@ -1444,7 +1254,7 @@
@@ -1481,7 +1291,7 @@
%%% authorization handling
@@ -418,7 +430,7 @@
Lang = "en", %% TODO fix
Stanza = {xmlelement, "message",
[],
@@ -1473,7 +1283,7 @@
@@ -1510,7 +1320,7 @@
[{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]},
lists:foreach(fun(Owner) ->
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza}
@@ -427,7 +439,7 @@
find_authorization_response(Packet) ->
{xmlelement, _Name, _Attrs, Els} = Packet,
@@ -1537,8 +1347,8 @@
@@ -1574,8 +1384,8 @@
"true" -> true;
_ -> false
end,
@@ -438,7 +450,7 @@
{result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]),
if
not IsApprover ->
@@ -1729,7 +1539,7 @@
@@ -1766,7 +1576,7 @@
Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(Node),
[]}]}],
@@ -447,7 +459,7 @@
{result, {Result, broadcast}} ->
%%Lang = "en", %% TODO: fix
%%OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
@@ -1837,7 +1647,7 @@
@@ -1874,7 +1684,7 @@
%%<li>The node does not exist.</li>
%%</ul>
subscribe_node(Host, Node, From, JID, Configuration) ->
@@ -456,7 +468,7 @@
{result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid
end,
@@ -1845,7 +1655,7 @@
@@ -1882,7 +1692,7 @@
error -> {"", "", ""};
J -> jlib:jid_tolower(J)
end,
@@ -465,7 +477,7 @@
Features = features(Type),
SubscribeFeature = lists:member("subscribe", Features),
OptionsFeature = lists:member("subscription-options", Features),
@@ -1864,9 +1674,13 @@
@@ -1901,9 +1711,13 @@
{"", "", ""} ->
{false, false};
_ ->
@@ -482,7 +494,7 @@
end
end,
if
@@ -2197,7 +2011,7 @@
@@ -2234,7 +2048,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.
@@ -491,7 +503,7 @@
MaxItems =
if
SMaxItems == "" -> get_max_items_node(Host);
@@ -2236,11 +2050,11 @@
@@ -2273,11 +2087,11 @@
node_call(Type, get_items,
[NodeId, From,
AccessModel, PresenceSubscription, RosterGroup,
@@ -505,7 +517,7 @@
SendItems = case ItemIDs of
[] ->
Items;
@@ -2253,7 +2067,8 @@
@@ -2290,7 +2104,8 @@
%% number of items sent to MaxItems:
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "items", nodeAttr(Node),
@@ -515,7 +527,7 @@
Error ->
Error
end
@@ -2285,16 +2100,27 @@
@@ -2322,16 +2137,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) ->
@@ -549,7 +561,7 @@
send_items(Host, Node, NodeId, Type, LJID, Number) ->
ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of
{result, []} ->
@@ -2420,29 +2246,12 @@
@@ -2457,29 +2283,12 @@
error ->
{error, ?ERR_BAD_REQUEST};
_ ->
@@ -582,7 +594,7 @@
end, Entities),
{result, []};
_ ->
@@ -2495,11 +2304,11 @@
@@ -2532,11 +2341,11 @@
end.
read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
@@ -596,7 +608,7 @@
OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"subid", SubID}|nodeAttr(Node)],
[XdataEl]},
@@ -2525,7 +2334,7 @@
@@ -2562,7 +2371,7 @@
end.
set_options_helper(Configuration, JID, NodeID, SubID, Type) ->
@@ -605,7 +617,7 @@
{result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid
end,
@@ -2554,7 +2363,7 @@
@@ -2591,7 +2400,7 @@
write_sub(_Subscriber, _NodeID, _SubID, invalid) ->
{error, extended_error(?ERR_BAD_REQUEST, "invalid-options")};
write_sub(Subscriber, NodeID, SubID, Options) ->
@@ -614,7 +626,7 @@
{error, notfound} ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
{result, _} ->
@@ -2722,8 +2531,8 @@
@@ -2759,8 +2568,8 @@
{"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]},
ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza}
end,
@@ -625,7 +637,7 @@
true ->
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
@@ -3007,7 +2816,7 @@
@@ -3044,7 +2853,7 @@
{Depth, [{N, get_node_subs(N)} || N <- Nodes]}
end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))}
end,
@@ -634,7 +646,7 @@
{result, CollSubs} -> CollSubs;
_ -> []
end.
@@ -3021,9 +2830,9 @@
@@ -3058,9 +2867,9 @@
get_options_for_subs(NodeID, Subs) ->
lists:foldl(fun({JID, subscribed, SubID}, Acc) ->
@@ -646,7 +658,7 @@
_ -> Acc
end;
(_, Acc) ->
@@ -3221,6 +3030,30 @@
@@ -3258,6 +3067,30 @@
Result
end.
@@ -677,7 +689,7 @@
%% @spec (Host, Options) -> MaxItems
%% Host = host()
%% Options = [Option]
@@ -3607,7 +3440,13 @@
@@ -3644,7 +3477,13 @@
tree_action(Host, Function, Args) ->
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
Fun = fun() -> tree_call(Host, Function, Args) end,
@@ -692,7 +704,7 @@
%% @doc <p>node plugin call.</p>
node_call(Type, Function, Args) ->
@@ -3627,13 +3466,13 @@
@@ -3664,13 +3503,13 @@
node_action(Host, Type, Function, Args) ->
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
@@ -708,7 +720,7 @@
case tree_call(Host, get_node, [Host, Node]) of
N when is_record(N, pubsub_node) ->
case Action(N) of
@@ -3646,8 +3485,14 @@
@@ -3683,8 +3522,14 @@
end
end, Trans).
@@ -725,7 +737,7 @@
{result, Result} -> {result, Result};
{error, Error} -> {error, Error};
{atomic, {result, Result}} -> {result, Result};
@@ -3655,6 +3500,15 @@
@@ -3692,6 +3537,15 @@
{aborted, Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR};
@@ -741,7 +753,7 @@
{'EXIT', Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR};
@@ -3663,6 +3517,17 @@
@@ -3700,6 +3554,17 @@
{error, ?ERR_INTERNAL_SERVER_ERROR}
end.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* ejabberd, Copyright (C) 2002-2009 Process-one
* ejabberd, Copyright (C) 2002-2009 ProcessOne
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
+1 -1
View File
@@ -369,7 +369,7 @@ static int stringprep_erl_control(ErlDrvData drv_data,
}
last_ral = info & D1Mask;
have_ral = have_ral || last_ral;
have_l = info & D2Mask;
have_l |= info & D2Mask;
ADD_UCHAR(ruc);
}