mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-24 17:29:28 +01:00
Merge branch '2.1.x' into 2.2.x
Conflicts: src/ejabberd_c2s.erl
This commit is contained in:
commit
41fad8956b
@ -66,6 +66,7 @@
|
|||||||
\newcommand{\module}[1]{\texttt{#1}}
|
\newcommand{\module}[1]{\texttt{#1}}
|
||||||
\newcommand{\modadhoc}{\module{mod\_adhoc}}
|
\newcommand{\modadhoc}{\module{mod\_adhoc}}
|
||||||
\newcommand{\modannounce}{\module{mod\_announce}}
|
\newcommand{\modannounce}{\module{mod\_announce}}
|
||||||
|
\newcommand{\modblocking}{\module{mod\_blocking}}
|
||||||
\newcommand{\modcaps}{\module{mod\_caps}}
|
\newcommand{\modcaps}{\module{mod\_caps}}
|
||||||
\newcommand{\modconfigure}{\module{mod\_configure}}
|
\newcommand{\modconfigure}{\module{mod\_configure}}
|
||||||
\newcommand{\moddisco}{\module{mod\_disco}}
|
\newcommand{\moddisco}{\module{mod\_disco}}
|
||||||
@ -1870,6 +1871,7 @@ The following LDAP servers are tested with \ejabberd{}:
|
|||||||
\item \footahref{http://www.microsoft.com/activedirectory/}{Active Directory}
|
\item \footahref{http://www.microsoft.com/activedirectory/}{Active Directory}
|
||||||
(see section~\ref{ad})
|
(see section~\ref{ad})
|
||||||
\item \footahref{http://www.openldap.org/}{OpenLDAP}
|
\item \footahref{http://www.openldap.org/}{OpenLDAP}
|
||||||
|
\item \footahref{http://www.communigate.com/}{CommuniGate Pro}
|
||||||
\item Normally any LDAP compatible server should work; inform us about your
|
\item Normally any LDAP compatible server should work; inform us about your
|
||||||
success with a not-listed server so that we can list it here.
|
success with a not-listed server so that we can list it here.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
@ -2533,6 +2535,7 @@ The following table lists all modules included in \ejabberd{}.
|
|||||||
\hline
|
\hline
|
||||||
\hline \modadhoc{} & Ad-Hoc Commands (\xepref{0050}) & \\
|
\hline \modadhoc{} & Ad-Hoc Commands (\xepref{0050}) & \\
|
||||||
\hline \ahrefloc{modannounce}{\modannounce{}} & Manage announcements & recommends \modadhoc{} \\
|
\hline \ahrefloc{modannounce}{\modannounce{}} & Manage announcements & recommends \modadhoc{} \\
|
||||||
|
\hline \modblocking{} & Simple Communications Blocking (\xepref{0191}) & \modprivacy{} \\
|
||||||
\hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\
|
\hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\
|
||||||
\hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\
|
\hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\
|
||||||
\hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\
|
\hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\
|
||||||
@ -2548,8 +2551,8 @@ The following table lists all modules included in \ejabberd{}.
|
|||||||
\hline \ahrefloc{modoffline}{\modofflineodbc{}} & Offline message storage (\xepref{0160}) & supported DB (*) \\
|
\hline \ahrefloc{modoffline}{\modofflineodbc{}} & Offline message storage (\xepref{0160}) & supported DB (*) \\
|
||||||
\hline \ahrefloc{modping}{\modping{}} & XMPP Ping and periodic keepalives (\xepref{0199}) & \\
|
\hline \ahrefloc{modping}{\modping{}} & XMPP Ping and periodic keepalives (\xepref{0199}) & \\
|
||||||
\hline \ahrefloc{modprescounter}{\modprivacy{}} & Detect presence subscription flood & \\
|
\hline \ahrefloc{modprescounter}{\modprivacy{}} & Detect presence subscription flood & \\
|
||||||
\hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (XMPP IM) & \\
|
\hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (\xepref{0016}) & \\
|
||||||
\hline \ahrefloc{modprivacy}{\modprivacyodbc{}} & Blocking Communication (XMPP IM) & supported DB (*) \\
|
\hline \ahrefloc{modprivacy}{\modprivacyodbc{}} & Blocking Communication (\xepref{0016}) & supported DB (*) \\
|
||||||
\hline \ahrefloc{modprivate}{\modprivate{}} & Private XML Storage (\xepref{0049}) & \\
|
\hline \ahrefloc{modprivate}{\modprivate{}} & Private XML Storage (\xepref{0049}) & \\
|
||||||
\hline \ahrefloc{modprivate}{\modprivateodbc{}} & Private XML Storage (\xepref{0049}) & supported DB (*) \\
|
\hline \ahrefloc{modprivate}{\modprivateodbc{}} & Private XML Storage (\xepref{0049}) & supported DB (*) \\
|
||||||
\hline \ahrefloc{modproxy}{\modproxy{}} & SOCKS5 Bytestreams (\xepref{0065}) & \\
|
\hline \ahrefloc{modproxy}{\modproxy{}} & SOCKS5 Bytestreams (\xepref{0065}) & \\
|
||||||
|
@ -213,6 +213,7 @@ install: all
|
|||||||
sed -e "s*@ctlscriptpath@*$(SBINDIR)*" \
|
sed -e "s*@ctlscriptpath@*$(SBINDIR)*" \
|
||||||
-e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \
|
-e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \
|
||||||
> ejabberd.init
|
> ejabberd.init
|
||||||
|
chmod 755 ejabberd.init
|
||||||
#
|
#
|
||||||
# Binary Erlang files
|
# Binary Erlang files
|
||||||
install -d $(BEAMDIR)
|
install -d $(BEAMDIR)
|
||||||
|
@ -494,6 +494,7 @@
|
|||||||
[
|
[
|
||||||
{mod_adhoc, []},
|
{mod_adhoc, []},
|
||||||
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
|
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
|
||||||
|
{mod_blocking,[]}, % requires mod_privacy
|
||||||
{mod_caps, []},
|
{mod_caps, []},
|
||||||
{mod_configure,[]}, % requires mod_adhoc
|
{mod_configure,[]}, % requires mod_adhoc
|
||||||
{mod_disco, []},
|
{mod_disco, []},
|
||||||
|
@ -1,6 +1,20 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: ejabberd
|
||||||
|
# Required-Start: $remote_fs $network $named $time
|
||||||
|
# Required-Stop: $remote_fs $network $named $time
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: Starts ejabberd jabber server
|
||||||
|
# Description: Starts ejabberd jabber server, an XMPP
|
||||||
|
# compliant server written in Erlang.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
# chkconfig: 2345 90 10
|
||||||
|
# description: ejabberd XMPP server
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
DIR=@ctlscriptpath@
|
DIR=@ctlscriptpath@
|
||||||
CTL="$DIR"/ejabberdctl
|
CTL="$DIR"/ejabberdctl
|
||||||
@ -32,14 +46,17 @@ case "$1" in
|
|||||||
su - $USER -c "$CTL stopped"
|
su - $USER -c "$CTL stopped"
|
||||||
echo "done."
|
echo "done."
|
||||||
;;
|
;;
|
||||||
|
status)
|
||||||
|
test -x "$CTL" || exit 0
|
||||||
|
echo "Getting ejabberd status..."
|
||||||
|
su - $USER -c "$CTL status"
|
||||||
|
;;
|
||||||
force-reload|restart)
|
force-reload|restart)
|
||||||
"$0" stop
|
"$0" stop
|
||||||
"$0" start
|
"$0" start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Usage: $0 {start|stop|restart|force-reload}"
|
echo "Usage: $0 {start|stop|restart|force-reload|status}"
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) ->
|
|||||||
AuthModule = xml:get_attr_s(auth_module, Info),
|
AuthModule = xml:get_attr_s(auth_module, Info),
|
||||||
case AuthModule == ?MODULE of
|
case AuthModule == ?MODULE of
|
||||||
true ->
|
true ->
|
||||||
|
ejabberd_hooks:run(register_user, LServer, [LUser, LServer]),
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
mnesia:async_dirty(
|
mnesia:async_dirty(
|
||||||
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
|
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
|
||||||
@ -231,8 +232,8 @@ try_register(_User, _Server, _Password) ->
|
|||||||
dirty_get_registered_users() ->
|
dirty_get_registered_users() ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
get_vh_registered_users(_Server) ->
|
get_vh_registered_users(Server) ->
|
||||||
[].
|
[{U, S} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(Server)].
|
||||||
|
|
||||||
|
|
||||||
%% Return password of permanent user or false for anonymous users
|
%% Return password of permanent user or false for anonymous users
|
||||||
|
@ -1211,7 +1211,9 @@ session_established2(El, StateData) ->
|
|||||||
end;
|
end;
|
||||||
"iq" ->
|
"iq" ->
|
||||||
case jlib:iq_query_info(NewEl) of
|
case jlib:iq_query_info(NewEl) of
|
||||||
#iq{xmlns = ?NS_PRIVACY} = IQ ->
|
#iq{xmlns = Xmlns} = IQ
|
||||||
|
when Xmlns == ?NS_PRIVACY;
|
||||||
|
Xmlns == ?NS_BLOCKING ->
|
||||||
ejabberd_hooks:run(
|
ejabberd_hooks:run(
|
||||||
user_send_packet,
|
user_send_packet,
|
||||||
Server,
|
Server,
|
||||||
@ -1469,6 +1471,9 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
|
|||||||
send_element(StateData, PrivPushEl),
|
send_element(StateData, PrivPushEl),
|
||||||
{false, Attrs, StateData#state{privacy_list = NewPL}}
|
{false, Attrs, StateData#state{privacy_list = NewPL}}
|
||||||
end;
|
end;
|
||||||
|
[{blocking, What}] ->
|
||||||
|
route_blocking(What, StateData),
|
||||||
|
{false, Attrs, StateData};
|
||||||
_ ->
|
_ ->
|
||||||
{false, Attrs, StateData}
|
{false, Attrs, StateData}
|
||||||
end;
|
end;
|
||||||
@ -3356,6 +3361,51 @@ bounce_messages() ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% XEP-0191
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
|
route_blocking(What, StateData) ->
|
||||||
|
SubEl =
|
||||||
|
case What of
|
||||||
|
{block, JIDs} ->
|
||||||
|
{xmlelement, "block",
|
||||||
|
[{"xmlns", ?NS_BLOCKING}],
|
||||||
|
lists:map(
|
||||||
|
fun(JID) ->
|
||||||
|
{xmlelement, "item",
|
||||||
|
[{"jid", jlib:jid_to_string(JID)}],
|
||||||
|
[]}
|
||||||
|
end, JIDs)};
|
||||||
|
{unblock, JIDs} ->
|
||||||
|
{xmlelement, "unblock",
|
||||||
|
[{"xmlns", ?NS_BLOCKING}],
|
||||||
|
lists:map(
|
||||||
|
fun(JID) ->
|
||||||
|
{xmlelement, "item",
|
||||||
|
[{"jid", jlib:jid_to_string(JID)}],
|
||||||
|
[]}
|
||||||
|
end, JIDs)};
|
||||||
|
unblock_all ->
|
||||||
|
{xmlelement, "unblock",
|
||||||
|
[{"xmlns", ?NS_BLOCKING}], []}
|
||||||
|
end,
|
||||||
|
PrivPushIQ =
|
||||||
|
#iq{type = set, xmlns = ?NS_BLOCKING,
|
||||||
|
id = "push",
|
||||||
|
sub_el = [SubEl]},
|
||||||
|
PrivPushEl =
|
||||||
|
jlib:replace_from_to(
|
||||||
|
jlib:jid_remove_resource(
|
||||||
|
StateData#state.jid),
|
||||||
|
StateData#state.jid,
|
||||||
|
jlib:iq_to_xml(PrivPushIQ)),
|
||||||
|
send_element(StateData, PrivPushEl),
|
||||||
|
%% No need to replace active privacy list here,
|
||||||
|
%% blocking pushes are always accompanied by
|
||||||
|
%% Privacy List pushes
|
||||||
|
ok.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% JID Set memory footprint reduction code
|
%%% JID Set memory footprint reduction code
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
@ -523,15 +523,16 @@ is_feature_available() ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
check_captcha_setup() ->
|
check_captcha_setup() ->
|
||||||
AbleToGenerateCaptcha = case create_image() of
|
case is_feature_available() of
|
||||||
{ok, _, _, _} -> true;
|
|
||||||
_Error -> false
|
|
||||||
end,
|
|
||||||
case is_feature_available() andalso not AbleToGenerateCaptcha of
|
|
||||||
true ->
|
true ->
|
||||||
?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, "
|
case create_image() of
|
||||||
"but it can't generate images.", []),
|
{ok, _, _, _} ->
|
||||||
throw({error, captcha_cmd_enabled_but_fails});
|
ok;
|
||||||
|
_Err ->
|
||||||
|
?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, "
|
||||||
|
"but it can't generate images.", []),
|
||||||
|
throw({error, captcha_cmd_enabled_but_fails})
|
||||||
|
end;
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
@ -132,6 +132,16 @@ void *erlXML_StartNamespaceDeclHandler(expat_data *d,
|
|||||||
int prefix_len;
|
int prefix_len;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
|
/* From the expat documentation:
|
||||||
|
"For a default namespace declaration (xmlns='...'),
|
||||||
|
the prefix will be null ...
|
||||||
|
... The URI will be null for the case where
|
||||||
|
the default namespace is being unset."
|
||||||
|
|
||||||
|
FIXME: I'm not quite sure what all that means */
|
||||||
|
if (uri == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
ei_x_encode_list_header(&xmlns_buf, 1);
|
ei_x_encode_list_header(&xmlns_buf, 1);
|
||||||
ei_x_encode_tuple_header(&xmlns_buf, 2);
|
ei_x_encode_tuple_header(&xmlns_buf, 2);
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
|
@ -70,11 +70,24 @@ start_module(Host, Module, Opts) ->
|
|||||||
catch Class:Reason ->
|
catch Class:Reason ->
|
||||||
del_module_mnesia(Host, Module),
|
del_module_mnesia(Host, Module),
|
||||||
ets:delete(ejabberd_modules, {Module, Host}),
|
ets:delete(ejabberd_modules, {Module, Host}),
|
||||||
?ERROR_MSG("Problem starting the module ~p for host ~p with options:~n ~p~n ~p: ~p",
|
ErrorText = io_lib:format("Problem starting the module ~p for host ~p ~n options: ~p~n ~p: ~p",
|
||||||
[Module, Host, Opts, Class, Reason]),
|
[Module, Host, Opts, Class, Reason]),
|
||||||
erlang:raise(Class, Reason, erlang:get_stacktrace())
|
?CRITICAL_MSG(ErrorText, []),
|
||||||
|
case is_app_running(ejabberd) of
|
||||||
|
true ->
|
||||||
|
erlang:raise(Class, Reason, erlang:get_stacktrace());
|
||||||
|
false ->
|
||||||
|
?CRITICAL_MSG("ejabberd initialization was aborted because a module start failed.", []),
|
||||||
|
timer:sleep(3000),
|
||||||
|
erlang:halt(lists:flatten(ErrorText))
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
is_app_running(AppName) ->
|
||||||
|
%% Use a high timeout to prevent a false positive in a high load system
|
||||||
|
Timeout = 15000,
|
||||||
|
lists:keymember(AppName, 1, application:which_applications(Timeout)).
|
||||||
|
|
||||||
%% @doc Stop the module in a host, and forget its configuration.
|
%% @doc Stop the module in a host, and forget its configuration.
|
||||||
stop_module(Host, Module) ->
|
stop_module(Host, Module) ->
|
||||||
case stop_module_keep_config(Host, Module) of
|
case stop_module_keep_config(Host, Module) of
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
-define(NS_ROSTER, "jabber:iq:roster").
|
-define(NS_ROSTER, "jabber:iq:roster").
|
||||||
-define(NS_ROSTER_VER, "urn:xmpp:features:rosterver").
|
-define(NS_ROSTER_VER, "urn:xmpp:features:rosterver").
|
||||||
-define(NS_PRIVACY, "jabber:iq:privacy").
|
-define(NS_PRIVACY, "jabber:iq:privacy").
|
||||||
|
-define(NS_BLOCKING, "urn:xmpp:blocking").
|
||||||
-define(NS_PRIVATE, "jabber:iq:private").
|
-define(NS_PRIVATE, "jabber:iq:private").
|
||||||
-define(NS_VERSION, "jabber:iq:version").
|
-define(NS_VERSION, "jabber:iq:version").
|
||||||
-define(NS_TIME90, "jabber:iq:time"). % TODO: Remove once XEP-0090 is Obsolete
|
-define(NS_TIME90, "jabber:iq:time"). % TODO: Remove once XEP-0090 is Obsolete
|
||||||
|
333
src/mod_blocking.erl
Normal file
333
src/mod_blocking.erl
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% File : mod_blocking.erl
|
||||||
|
%%% Author : Stephan Maka
|
||||||
|
%%% Purpose : XEP-0191: Simple Communications Blocking
|
||||||
|
%%% Created : 24 Aug 2008 by Stephan Maka <stephan@spaceboyz.net>
|
||||||
|
%%%
|
||||||
|
%%%
|
||||||
|
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
|
||||||
|
%%%
|
||||||
|
%%% This program is free software; you can redistribute it and/or
|
||||||
|
%%% modify it under the terms of the GNU General Public License as
|
||||||
|
%%% published by the Free Software Foundation; either version 2 of the
|
||||||
|
%%% License, or (at your option) any later version.
|
||||||
|
%%%
|
||||||
|
%%% This program is distributed in the hope that it will be useful,
|
||||||
|
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
%%% General Public License for more details.
|
||||||
|
%%%
|
||||||
|
%%% You should have received a copy of the GNU General Public License
|
||||||
|
%%% along with this program; if not, write to the Free Software
|
||||||
|
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
%%% 02111-1307 USA
|
||||||
|
%%%
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(mod_blocking).
|
||||||
|
|
||||||
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
|
-export([start/2, stop/1,
|
||||||
|
process_iq/3,
|
||||||
|
process_iq_set/4,
|
||||||
|
process_iq_get/5]).
|
||||||
|
|
||||||
|
-include("ejabberd.hrl").
|
||||||
|
-include("jlib.hrl").
|
||||||
|
-include("mod_privacy.hrl").
|
||||||
|
|
||||||
|
start(Host, Opts) ->
|
||||||
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
|
ejabberd_hooks:add(privacy_iq_get, Host,
|
||||||
|
?MODULE, process_iq_get, 40),
|
||||||
|
ejabberd_hooks:add(privacy_iq_set, Host,
|
||||||
|
?MODULE, process_iq_set, 40),
|
||||||
|
mod_disco:register_feature(Host, ?NS_BLOCKING),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
|
||||||
|
?MODULE, process_iq, IQDisc).
|
||||||
|
|
||||||
|
stop(Host) ->
|
||||||
|
ejabberd_hooks:delete(privacy_iq_get, Host,
|
||||||
|
?MODULE, process_iq_get, 40),
|
||||||
|
ejabberd_hooks:delete(privacy_iq_set, Host,
|
||||||
|
?MODULE, process_iq_set, 40),
|
||||||
|
mod_disco:unregister_feature(Host, ?NS_BLOCKING),
|
||||||
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
|
||||||
|
|
||||||
|
process_iq(_From, _To, IQ) ->
|
||||||
|
SubEl = IQ#iq.sub_el,
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
|
||||||
|
|
||||||
|
process_iq_get(_, From, _To,
|
||||||
|
#iq{xmlns = ?NS_BLOCKING,
|
||||||
|
sub_el = {xmlelement, "blocklist", _, _}},
|
||||||
|
_) ->
|
||||||
|
#jid{luser = LUser, lserver = LServer} = From,
|
||||||
|
process_blocklist_get(LUser, LServer);
|
||||||
|
|
||||||
|
process_iq_get(Acc, _, _, _, _) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
process_iq_set(_, From, _To, #iq{xmlns = ?NS_BLOCKING,
|
||||||
|
sub_el = {xmlelement, SubElName, _, SubEls}}) ->
|
||||||
|
#jid{luser = LUser, lserver = LServer} = From,
|
||||||
|
case {SubElName, xml:remove_cdata(SubEls)} of
|
||||||
|
{"block", []} ->
|
||||||
|
{error, ?ERR_BAD_REQUEST};
|
||||||
|
{"block", Els} ->
|
||||||
|
JIDs = parse_blocklist_items(Els, []),
|
||||||
|
process_blocklist_block(LUser, LServer, JIDs);
|
||||||
|
{"unblock", []} ->
|
||||||
|
process_blocklist_unblock_all(LUser, LServer);
|
||||||
|
{"unblock", Els} ->
|
||||||
|
JIDs = parse_blocklist_items(Els, []),
|
||||||
|
process_blocklist_unblock(LUser, LServer, JIDs);
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_BAD_REQUEST}
|
||||||
|
end;
|
||||||
|
|
||||||
|
process_iq_set(Acc, _, _, _) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
is_list_needdb(Items) ->
|
||||||
|
lists:any(
|
||||||
|
fun(X) ->
|
||||||
|
case X#listitem.type of
|
||||||
|
subscription -> true;
|
||||||
|
group -> true;
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end, Items).
|
||||||
|
|
||||||
|
list_to_blocklist_jids([], JIDs) ->
|
||||||
|
JIDs;
|
||||||
|
|
||||||
|
list_to_blocklist_jids([#listitem{type = jid,
|
||||||
|
action = deny,
|
||||||
|
value = JID} = Item | Items], JIDs) ->
|
||||||
|
case Item of
|
||||||
|
#listitem{match_all = true} ->
|
||||||
|
Match = true;
|
||||||
|
#listitem{match_iq = true,
|
||||||
|
match_message = true,
|
||||||
|
match_presence_in = true,
|
||||||
|
match_presence_out = true} ->
|
||||||
|
Match = true;
|
||||||
|
_ ->
|
||||||
|
Match = false
|
||||||
|
end,
|
||||||
|
if
|
||||||
|
Match ->
|
||||||
|
list_to_blocklist_jids(Items, [JID | JIDs]);
|
||||||
|
true ->
|
||||||
|
list_to_blocklist_jids(Items, JIDs)
|
||||||
|
end;
|
||||||
|
|
||||||
|
% Skip Privacy List items than cannot be mapped to Blocking items
|
||||||
|
list_to_blocklist_jids([_ | Items], JIDs) ->
|
||||||
|
list_to_blocklist_jids(Items, JIDs).
|
||||||
|
|
||||||
|
parse_blocklist_items([], JIDs) ->
|
||||||
|
JIDs;
|
||||||
|
|
||||||
|
parse_blocklist_items([{xmlelement, "item", Attrs, _} | Els], JIDs) ->
|
||||||
|
case xml:get_attr("jid", Attrs) of
|
||||||
|
{value, JID1} ->
|
||||||
|
JID = jlib:jid_tolower(jlib:string_to_jid(JID1)),
|
||||||
|
parse_blocklist_items(Els, [JID | JIDs]);
|
||||||
|
false ->
|
||||||
|
% Tolerate missing jid attribute
|
||||||
|
parse_blocklist_items(Els, JIDs)
|
||||||
|
end;
|
||||||
|
|
||||||
|
parse_blocklist_items([_ | Els], JIDs) ->
|
||||||
|
% Tolerate unknown elements
|
||||||
|
parse_blocklist_items(Els, JIDs).
|
||||||
|
|
||||||
|
process_blocklist_block(LUser, LServer, JIDs) ->
|
||||||
|
F =
|
||||||
|
fun() ->
|
||||||
|
case mnesia:wread({privacy, {LUser, LServer}}) of
|
||||||
|
[] ->
|
||||||
|
% No lists yet
|
||||||
|
P = #privacy{us = {LUser, LServer}},
|
||||||
|
% TODO: i18n here:
|
||||||
|
NewDefault = "Blocked contacts",
|
||||||
|
NewLists1 = [],
|
||||||
|
List = [];
|
||||||
|
[#privacy{default = Default,
|
||||||
|
lists = Lists} = P] ->
|
||||||
|
case lists:keysearch(Default, 1, Lists) of
|
||||||
|
{value, {_, List}} ->
|
||||||
|
% Default list exists
|
||||||
|
NewDefault = Default,
|
||||||
|
NewLists1 = lists:keydelete(Default, 1, Lists);
|
||||||
|
false ->
|
||||||
|
% No default list yet, create one
|
||||||
|
% TODO: i18n here:
|
||||||
|
NewDefault = "Blocked contacts",
|
||||||
|
NewLists1 = Lists,
|
||||||
|
List = []
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
AlreadyBlocked = list_to_blocklist_jids(List, []),
|
||||||
|
NewList =
|
||||||
|
lists:foldr(fun(JID, List1) ->
|
||||||
|
case lists:member(JID, AlreadyBlocked) of
|
||||||
|
true ->
|
||||||
|
List1;
|
||||||
|
false ->
|
||||||
|
[#listitem{type = jid,
|
||||||
|
value = JID,
|
||||||
|
action = deny,
|
||||||
|
order = 0,
|
||||||
|
match_all = true
|
||||||
|
} | List1]
|
||||||
|
end
|
||||||
|
end, List, JIDs),
|
||||||
|
NewLists = [{NewDefault, NewList} | NewLists1],
|
||||||
|
mnesia:write(P#privacy{default = NewDefault,
|
||||||
|
lists = NewLists}),
|
||||||
|
{ok, NewDefault, NewList}
|
||||||
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{atomic, {error, _} = Error} ->
|
||||||
|
Error;
|
||||||
|
{atomic, {ok, Default, List}} ->
|
||||||
|
broadcast_list_update(LUser, LServer, Default, List),
|
||||||
|
broadcast_blocklist_event(LUser, LServer, {block, JIDs}),
|
||||||
|
{result, []};
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
|
end.
|
||||||
|
|
||||||
|
process_blocklist_unblock_all(LUser, LServer) ->
|
||||||
|
F =
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read({privacy, {LUser, LServer}}) of
|
||||||
|
[] ->
|
||||||
|
% No lists, nothing to unblock
|
||||||
|
ok;
|
||||||
|
[#privacy{default = Default,
|
||||||
|
lists = Lists} = P] ->
|
||||||
|
case lists:keysearch(Default, 1, Lists) of
|
||||||
|
{value, {_, List}} ->
|
||||||
|
% Default list, remove all deny items
|
||||||
|
NewList =
|
||||||
|
lists:filter(
|
||||||
|
fun(#listitem{action = A}) ->
|
||||||
|
A =/= deny
|
||||||
|
end, List),
|
||||||
|
|
||||||
|
NewLists1 = lists:keydelete(Default, 1, Lists),
|
||||||
|
NewLists = [{Default, NewList} | NewLists1],
|
||||||
|
mnesia:write(P#privacy{lists = NewLists}),
|
||||||
|
|
||||||
|
{ok, Default, NewList};
|
||||||
|
false ->
|
||||||
|
% No default list, nothing to unblock
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{atomic, {error, _} = Error} ->
|
||||||
|
Error;
|
||||||
|
{atomic, ok} ->
|
||||||
|
{result, []};
|
||||||
|
{atomic, {ok, Default, List}} ->
|
||||||
|
broadcast_list_update(LUser, LServer, Default, List),
|
||||||
|
broadcast_blocklist_event(LUser, LServer, unblock_all),
|
||||||
|
{result, []};
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
|
end.
|
||||||
|
|
||||||
|
process_blocklist_unblock(LUser, LServer, JIDs) ->
|
||||||
|
F =
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read({privacy, {LUser, LServer}}) of
|
||||||
|
[] ->
|
||||||
|
% No lists, nothing to unblock
|
||||||
|
ok;
|
||||||
|
[#privacy{default = Default,
|
||||||
|
lists = Lists} = P] ->
|
||||||
|
case lists:keysearch(Default, 1, Lists) of
|
||||||
|
{value, {_, List}} ->
|
||||||
|
% Default list, remove matching deny items
|
||||||
|
NewList =
|
||||||
|
lists:filter(
|
||||||
|
fun(#listitem{action = deny,
|
||||||
|
type = jid,
|
||||||
|
value = JID}) ->
|
||||||
|
not(lists:member(JID, JIDs));
|
||||||
|
(_) ->
|
||||||
|
true
|
||||||
|
end, List),
|
||||||
|
|
||||||
|
NewLists1 = lists:keydelete(Default, 1, Lists),
|
||||||
|
NewLists = [{Default, NewList} | NewLists1],
|
||||||
|
mnesia:write(P#privacy{lists = NewLists}),
|
||||||
|
|
||||||
|
{ok, Default, NewList};
|
||||||
|
false ->
|
||||||
|
% No default list, nothing to unblock
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case mnesia:transaction(F) of
|
||||||
|
{atomic, {error, _} = Error} ->
|
||||||
|
Error;
|
||||||
|
{atomic, ok} ->
|
||||||
|
{result, []};
|
||||||
|
{atomic, {ok, Default, List}} ->
|
||||||
|
broadcast_list_update(LUser, LServer, Default, List),
|
||||||
|
broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}),
|
||||||
|
{result, []};
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
|
end.
|
||||||
|
|
||||||
|
broadcast_list_update(LUser, LServer, Name, List) ->
|
||||||
|
NeedDb = is_list_needdb(List),
|
||||||
|
ejabberd_router:route(
|
||||||
|
jlib:make_jid(LUser, LServer, ""),
|
||||||
|
jlib:make_jid(LUser, LServer, ""),
|
||||||
|
{xmlelement, "broadcast", [],
|
||||||
|
[{privacy_list,
|
||||||
|
#userlist{name = Name, list = List, needdb = NeedDb},
|
||||||
|
Name}]}).
|
||||||
|
|
||||||
|
broadcast_blocklist_event(LUser, LServer, Event) ->
|
||||||
|
JID = jlib:make_jid(LUser, LServer, ""),
|
||||||
|
ejabberd_router:route(
|
||||||
|
JID, JID,
|
||||||
|
{xmlelement, "broadcast", [],
|
||||||
|
[{blocking, Event}]}).
|
||||||
|
|
||||||
|
process_blocklist_get(LUser, LServer) ->
|
||||||
|
case catch mnesia:dirty_read(privacy, {LUser, LServer}) of
|
||||||
|
{'EXIT', _Reason} ->
|
||||||
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
|
[] ->
|
||||||
|
{result, [{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}], []}]};
|
||||||
|
[#privacy{default = Default, lists = Lists}] ->
|
||||||
|
case lists:keysearch(Default, 1, Lists) of
|
||||||
|
{value, {_, List}} ->
|
||||||
|
JIDs = list_to_blocklist_jids(List, []),
|
||||||
|
Items = lists:map(
|
||||||
|
fun(JID) ->
|
||||||
|
?DEBUG("JID: ~p",[JID]),
|
||||||
|
{xmlelement, "item",
|
||||||
|
[{"jid", jlib:jid_to_string(JID)}], []}
|
||||||
|
end, JIDs),
|
||||||
|
{result,
|
||||||
|
[{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}],
|
||||||
|
Items}]};
|
||||||
|
_ ->
|
||||||
|
{result, [{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}], []}]}
|
||||||
|
end
|
||||||
|
end.
|
@ -116,7 +116,9 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
|
|||||||
roster_get_jid_info, Server,
|
roster_get_jid_info, Server,
|
||||||
{none, []}, [User, Server, From]),
|
{none, []}, [User, Server, From]),
|
||||||
if
|
if
|
||||||
(Subscription == both) or (Subscription == from) ->
|
(Subscription == both) or (Subscription == from)
|
||||||
|
or ((From#jid.luser == To#jid.luser)
|
||||||
|
and (From#jid.lserver == To#jid.lserver)) ->
|
||||||
UserListRecord = ejabberd_hooks:run_fold(
|
UserListRecord = ejabberd_hooks:run_fold(
|
||||||
privacy_get_user_list, Server,
|
privacy_get_user_list, Server,
|
||||||
#userlist{},
|
#userlist{},
|
||||||
|
@ -584,10 +584,10 @@ delete_item(NodeIdx, Publisher, PublishModel, ItemId) ->
|
|||||||
false ->
|
false ->
|
||||||
case Affiliation of
|
case Affiliation of
|
||||||
owner ->
|
owner ->
|
||||||
%% Owner can delete other publishers items as well
|
%% Owner can delete any items from its own node
|
||||||
{result, States} = get_states(NodeIdx),
|
{result, States} = get_states(NodeIdx),
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(#pubsub_state{items = PI, affiliation = publisher} = S, Res) ->
|
fun(#pubsub_state{items = PI} = S, Res) ->
|
||||||
case lists:member(ItemId, PI) of
|
case lists:member(ItemId, PI) of
|
||||||
true ->
|
true ->
|
||||||
del_item(NodeIdx, ItemId),
|
del_item(NodeIdx, ItemId),
|
||||||
|
@ -93,6 +93,8 @@ start(Host, _Opts) ->
|
|||||||
?MODULE, unset_presence, 50),
|
?MODULE, unset_presence, 50),
|
||||||
ejabberd_hooks:add(register_user, Host,
|
ejabberd_hooks:add(register_user, Host,
|
||||||
?MODULE, register_user, 50),
|
?MODULE, register_user, 50),
|
||||||
|
ejabberd_hooks:add(anonymous_purge_hook, Host,
|
||||||
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:add(remove_user, Host,
|
ejabberd_hooks:add(remove_user, Host,
|
||||||
?MODULE, remove_user, 50).
|
?MODULE, remove_user, 50).
|
||||||
%%ejabberd_hooks:add(remove_user, Host,
|
%%ejabberd_hooks:add(remove_user, Host,
|
||||||
@ -121,6 +123,8 @@ stop(Host) ->
|
|||||||
?MODULE, unset_presence, 50),
|
?MODULE, unset_presence, 50),
|
||||||
ejabberd_hooks:delete(register_user, Host,
|
ejabberd_hooks:delete(register_user, Host,
|
||||||
?MODULE, register_user, 50),
|
?MODULE, register_user, 50),
|
||||||
|
ejabberd_hooks:delete(anonymous_purge_hook, Host,
|
||||||
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(remove_user, Host,
|
ejabberd_hooks:delete(remove_user, Host,
|
||||||
?MODULE, remove_user, 50).
|
?MODULE, remove_user, 50).
|
||||||
%%ejabberd_hooks:delete(remove_user, Host,
|
%%ejabberd_hooks:delete(remove_user, Host,
|
||||||
|
@ -156,10 +156,10 @@ queue(N) ->
|
|||||||
dump(N, lists:reverse(lists:ukeysort(1, all_pids(queue)))).
|
dump(N, lists:reverse(lists:ukeysort(1, all_pids(queue)))).
|
||||||
|
|
||||||
memory(N) ->
|
memory(N) ->
|
||||||
dump(N, lists:reverse(lists:ukeysort(2, all_pids(memory)))).
|
dump(N, lists:reverse(lists:ukeysort(3, all_pids(memory)))).
|
||||||
|
|
||||||
reds(N) ->
|
reds(N) ->
|
||||||
dump(N, lists:reverse(lists:ukeysort(3, all_pids(reductions)))).
|
dump(N, lists:reverse(lists:ukeysort(4, all_pids(reductions)))).
|
||||||
|
|
||||||
trace(Pid) ->
|
trace(Pid) ->
|
||||||
erlang:trace(Pid, true, [send, 'receive']),
|
erlang:trace(Pid, true, [send, 'receive']),
|
||||||
@ -299,10 +299,17 @@ all_pids(Type) ->
|
|||||||
registered_name]) of
|
registered_name]) of
|
||||||
[{_, Len}, {_, Memory}, {_, Reds},
|
[{_, Len}, {_, Memory}, {_, Reds},
|
||||||
{_, Dict}, {_, CurFun}, {_, RegName}] ->
|
{_, Dict}, {_, CurFun}, {_, RegName}] ->
|
||||||
if Type == queue andalso Len == 0 ->
|
IntQLen = case lists:keysearch('$internal_queue_len', 1, Dict) of
|
||||||
|
{value, {_, N}} ->
|
||||||
|
N;
|
||||||
|
_ ->
|
||||||
|
0
|
||||||
|
end,
|
||||||
|
if Type == queue andalso Len == 0 andalso IntQLen == 0 ->
|
||||||
Acc;
|
Acc;
|
||||||
true ->
|
true ->
|
||||||
[{Len, Memory, Reds, Dict, CurFun, P, RegName}|Acc]
|
MaxLen = lists:max([Len, IntQLen]),
|
||||||
|
[{MaxLen, Len, Memory, Reds, Dict, CurFun, P, RegName}|Acc]
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Acc
|
Acc
|
||||||
@ -311,7 +318,7 @@ all_pids(Type) ->
|
|||||||
|
|
||||||
dump(N, Rs) ->
|
dump(N, Rs) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({MsgQLen, Memory, Reds, Dict, CurFun, Pid, RegName}) ->
|
fun({_, MsgQLen, Memory, Reds, Dict, CurFun, Pid, RegName}) ->
|
||||||
PidStr = pid_to_list(Pid),
|
PidStr = pid_to_list(Pid),
|
||||||
[_, Maj, Min] = string:tokens(
|
[_, Maj, Min] = string:tokens(
|
||||||
string:substr(
|
string:substr(
|
||||||
|
@ -2030,7 +2030,7 @@ get_node(global, Node, ["backup"], Query, Lang) ->
|
|||||||
ok -> [?XREST("Submitted")];
|
ok -> [?XREST("Submitted")];
|
||||||
{error, Error} -> [?XRES(?T("Error") ++": " ++ io_lib:format("~p", [Error]))]
|
{error, Error} -> [?XRES(?T("Error") ++": " ++ io_lib:format("~p", [Error]))]
|
||||||
end,
|
end,
|
||||||
[?XC("h1", ?T("Backup of ") ++ atom_to_list(Node))] ++
|
?H1GL(?T("Backup of ") ++ atom_to_list(Node), "list-eja-commands", "List of ejabberd Commands") ++
|
||||||
ResS ++
|
ResS ++
|
||||||
[?XCT("p", "Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
|
[?XCT("p", "Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
|
||||||
?XAE("form", [{"action", ""}, {"method", "post"}],
|
?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
|
Loading…
Reference in New Issue
Block a user