Compare commits

...

47 Commits

Author SHA1 Message Date
Badlop 7248ee1dbc Fix some typos in the Guide 2011-05-31 21:13:20 +02:00
Christophe Romain 75b6162b44 Pubsub node maxitem forced to 0 if non persistent node (thanks to Karim Gemayel)(EJAB-1434) 2011-05-31 16:09:27 +02:00
Christophe Romain 75510a4b1b apply filtered notification to PEP last items (thanks to karim Gemayel)(EJAB-1456) 2011-05-31 16:08:25 +02:00
Badlop 4a4f3eb8c5 Fix minor English error 2011-05-31 12:51:09 +02:00
Badlop 8168526f01 New ERL_EPMD_ADDRESS that works since Erlang/OTP R14B03 2011-05-31 12:51:05 +02:00
Badlop 09b4e36457 Cut the string when calling halt/1 2011-05-30 17:11:51 +02:00
Christophe Romain dfd7936ea6 PubSub: NodeIdx variable name cleanup 2011-05-30 14:04:42 +02:00
Badlop 970f74288b Fix a recent commit about "Set script as executable" 2011-05-30 11:46:31 +02:00
Badlop b8e9c6a7a2 Add link in the Backup page to the Guide 2011-05-30 11:01:49 +02:00
Badlop 6c08c53d74 Fix get_queue_length argument type 2011-05-27 11:54:52 +02:00
Badlop 82296c277a Support XEP-0191 Simple Communications Blocking (thanks to Stephan Maka)(EJAB-695) 2011-05-27 11:54:50 +02:00
Badlop 806d5497c4 A user can query his own Last activity, even if not subscribed to oneself 2011-05-27 11:54:30 +02:00
Badlop b0bf89e319 Several fixes and improvements in ejabberd.init.template
Changes:
* Set script as executable
* Add LSB tags and overrides, copied from Debian's ejabberd package
* Add chkconfig support (thanks to Ivan Martinez)(EJAB-1450)
* Don't use nounset, as that breaks when no argument is provided
* Add status command
2011-05-24 23:46:25 +02:00
Badlop 9d9a4d1bc7 Fix errors reported by dialyzer 2011-05-18 19:46:56 +02:00
Badlop c55aa9be7b Store privacy list user_host and name as binary, not string 2011-05-18 19:46:54 +02:00
Badlop 4d2408c9c9 When module start fails during server start, stop erlang (EJAB-1446) 2011-05-16 22:33:51 +02:00
Evgeniy Khramtsov bd25bd465c Note that ejabberd works with CGP LDAP server 2011-05-07 10:33:32 +10:00
Christophe Romain 6898553afd Owner can delete any items from its own node (EJAB-1445) 2011-05-06 14:02:37 +02:00
Badlop a8dd91512c Simplify and particularize the code of previous commit (EJAB-1333) 2011-05-04 23:14:41 +02:00
Badlop 05d95f2dd7 Support in BOSH for stanzas without jabber:client (EJAB-1333) 2011-05-04 23:05:06 +02:00
Badlop f839b1c6ff Log this cached exception as DEBUG in ejabberd log file 2011-05-04 23:04:07 +02:00
Badlop b8026d8df7 Reorganize the push_item function, and handle version not_found (EJAB-1420) 2011-04-29 20:34:38 +02:00
Badlop c611361bbe No need to inform that XEP-0237 is optional; clarified in XEP version 1.2 2011-04-29 20:34:36 +02:00
Badlop 7fe05e67a7 Show configuration for HTTPS http_bind 2011-04-28 13:24:37 +02:00
Badlop 0c7ce8b7fe mod_register Access now also controls account unregistrations 2011-04-26 22:54:28 +02:00
Badlop 34fc5d82b3 Try to improve support for roster_version in MSSQL (EJAB-1437) 2011-04-14 23:10:47 +02:00
Badlop 7436ef1fb1 The responses to HEAD must have empty Body 2011-04-13 10:32:26 +02:00
Badlop 099f7d6521 Support as read-only HTTP method not only GET, also HEAD 2011-04-13 10:32:24 +02:00
Badlop 545162a283 If extauth script crashes, ejabberd should restart it (EJAB-1428) 2011-04-11 21:27:36 +02:00
Badlop a2d60a1977 Support more captcha_host value formats (EJAB-1418) 2011-04-11 19:58:37 +02:00
Badlop 33745954a9 Store packet table field as binary, not as string 2011-04-11 15:49:06 +02:00
Badlop 028d158e13 Show result of message deletion with colour box 2011-04-11 13:39:48 +02:00
Badlop b684e90292 First delete messages, and then get the remaining messages 2011-04-11 13:39:46 +02:00
Badlop 191187a279 Store user_host table field as binaries instead of strings 2011-04-11 13:39:43 +02:00
Badlop 80483d8fd1 Migrate MUC tables from 2.1 mnesia to 3.0 gen_storage (EJAB-1372) 2011-04-07 23:55:24 +02:00
Badlop 4689b0d861 Document the mod_muc 2.1.x mnesia tables (EJAB-1372) 2011-04-07 23:55:15 +02:00
Badlop c73aeca393 Send jid attribute when occupant is banned (EJAB-1432) 2011-04-07 13:12:52 +02:00
Badlop f893669d91 mod_ping uses iqdisc no_queue by default (thanks to Chris Moos)(EJAB-1435) 2011-04-07 12:09:53 +02:00
Badlop 3c549bca4e Clarify {iqdisc, no_queue} 2011-04-07 12:08:51 +02:00
Badlop 198298df2c Fix minor comment typo 2011-04-04 17:36:31 +02:00
Badlop 5a876dfd33 Store user_host as binaries in vcard table. Fix migration from old ejabberd 2 tables schema 2011-03-30 19:16:05 +02:00
Christophe Romain 9cf43ffc9e apply pubsub efficiency patch to ODBC code (TECH-1293) 2011-03-23 09:59:10 +01:00
Christophe Romain 8d2def619d add indexes to improve pubsub efficiency (TECH-1293) 2011-03-23 09:36:03 +01:00
Badlop 25a6493e1b Fix typo (thanks to Krzee) 2011-03-17 12:16:54 +01:00
Badlop 71bfa17354 Fix crash when SASL PLAIN denies auth (EJAB-1425) 2011-03-16 18:38:44 +01:00
Badlop dedd2a7f59 Update the changed string in the PO translation files 2011-03-13 18:41:43 +01:00
Badlop 415a50921f Change string in WebAdmin to reuse an existing one 2011-03-13 18:36:27 +01:00
93 changed files with 1124 additions and 459 deletions
+1 -1
View File
@@ -137,7 +137,7 @@ session manager, else it is processed depending on it's content.
\subsection{Session Manager}
This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
packet must be sent via presence table. If this resource is connected to
this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.
+29 -22
View File
@@ -66,6 +66,7 @@
\newcommand{\module}[1]{\texttt{#1}}
\newcommand{\modadhoc}{\module{mod\_adhoc}}
\newcommand{\modannounce}{\module{mod\_announce}}
\newcommand{\modblocking}{\module{mod\_blocking}}
\newcommand{\modcaps}{\module{mod\_caps}}
\newcommand{\modconfigure}{\module{mod\_configure}}
\newcommand{\moddisco}{\module{mod\_disco}}
@@ -1017,7 +1018,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
\item Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4.
\item Port 3478 listens for STUN requests over UDP.
\item Port 5280 listens for HTTP requests, and serves the HTTP Poll service.
\item Port 5281 listens for HTTP requests, and serves the Web Admin using HTTPS as explained in
\item Port 5281 listens for HTTP requests, using HTTPS to serve HTTP-Bind (BOSH) and the Web Admin as explained in
section~\ref{webadmin}. The socket only listens connections to the IP address 127.0.0.1.
\end{itemize}
\begin{verbatim}
@@ -1046,6 +1047,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
]},
{{5281, "127.0.0.1"}, ejabberd_http, [
web_admin,
http_bind,
tls, {certfile, "/etc/ejabberd/server.pem"},
]}
]
@@ -1550,7 +1552,7 @@ declarations of ACLs in the configuration file have the following syntax:
with a name that matches \term{UserRegexp} at any server that matches
\term{ServerRegexp}. Example:
\begin{verbatim}
{acl, yohzik, {node_regexp, "^yohzik$", "^example.(com|org)$"}}.
{acl, yozhik, {node_regexp, "^yozhik$", "^example.(com|org)$"}}.
\end{verbatim}
\titem{\{user\_glob, Glob\}}
\titem{\{user\_glob, Glob, Server\}}
@@ -1710,13 +1712,13 @@ The configurable options are:
Full path to a script that generates the image.
The default value is an empty string: \term{""}
\titem{\{captcha\_host, ProtocolHostPort\}}
Host part of the URL sent to the user,
and the port number where ejabberd listens for CAPTCHA requests.
The URL sent to the user is formed by: \term{http://Host:Port/captcha/}
The default value is: the first hostname configured, and port 5280.
If the port number you specify does not match exactly an ejabberd listener
ProtocolHostPort is a string with the host, and optionally the Protocol and Port number.
It must identify where ejabberd listens for CAPTCHA requests.
The URL sent to the user is formed by: \term{Protocol://Host:Port/captcha/}
The default value is: protocol \term{http}, the first hostname configured, and port \term{80}.
If you specify a port number that does not match exactly an ejabberd listener
(because you are using a reverse proxy or other port-forwarding tool),
then specify also the transfer protocol, as seen in the example below.
then you must specify the transfer protocol, as seen in the example below.
\end{description}
Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option.
@@ -1729,6 +1731,7 @@ Example configuration:
{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
{captcha_host, "example.org:5280"}.
%% {captcha_host, "https://example.org:443"}.
%% {captcha_host, "http://example.com"}.
{listen,
[
@@ -1943,6 +1946,7 @@ The following LDAP servers are tested with \ejabberd{}:
\item \footahref{http://www.microsoft.com/activedirectory/}{Active Directory}
(see section~\ref{ad})
\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
success with a not-listed server so that we can list it here.
\end{itemize}
@@ -2579,6 +2583,7 @@ The following table lists all modules included in \ejabberd{}.
\hline
\hline \modadhoc{} & Ad-Hoc Commands (\xepref{0050}) & \\
\hline \ahrefloc{modannounce}{\modannounce{}} & Manage announcements & recommends \modadhoc{} \\
\hline \modblocking{} & Simple Communications Blocking (\xepref{0191}) & \modprivacy{} \\
\hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\
\hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\
\hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\
@@ -2666,15 +2671,16 @@ The syntax is:
Possible \term{Value} are:
\begin{description}
\titem{no\_queue} All queries of a namespace with this processing discipline are
processed immediately. This also means that no other packets can be processed
processed directly. This means that the XMPP connection that sends this IQ query gets blocked:
no other packets can be processed
until this one has been completely processed. Hence this discipline is not
recommended if the processing of a query can take a relatively long time.
\titem{one\_queue} In this case a separate queue is created for the processing
of IQ queries of a namespace with this discipline. In addition, the processing
of this queue is done in parallel with that of other packets. This discipline
is most recommended.
\titem{\{queues, N\}} N separate queues are created to process the
queries. The queries are thus process in parallel, but in a
\titem{\{queues, N\}} N separate queues are created to process the
queries. The queries are thus processed in parallel, but in a
controlled way.
\titem{parallel} For every packet with this discipline a separate Erlang process
is spawned. Consequently, all these packets are processed in parallel.
@@ -3836,10 +3842,11 @@ enables end users to use a \XMPP{} client to:
Options:
\begin{description}
\titem{\{access, AccessName\}} \ind{options!access}This option can be configured to specify
rules to restrict registration. If a rule returns `deny' on the requested
user name, registration for that user name is denied. (there are no
restrictions by default).
\titem{\{access, AccessName\}} \ind{options!access}
Specify rules to restrict what usernames can be registered and unregistered.
If a rule returns `deny' on the requested username,
registration and unregistration of that user name is denied.
There are no restrictions by default.
\titem{\{access\_from, AccessName\}} \ind{options!access\_from}By default, \ejabberd{}
doesn't allow to register new accounts from s2s or existing c2s sessions. You can
change it by defining access rule in this option. Use with care: allowing registration
@@ -4664,7 +4671,7 @@ Examples:
\makesubsection{modvcardldap}{\modvcardldap{}}
\ind{modules!\modvcardldap{}}\ind{JUD}\ind{Jabber User Directory}\ind{vCard}\ind{protocols!XEP-0054: vcard-temp}
%TODO: verify if the referers to the LDAP section are still correct
%TODO: verify if the referrers to the LDAP section are still correct
\ejabberd{} can map LDAP attributes to vCard fields. This behaviour is
implemented in the \modvcardldap{} module. This module does not depend on the
@@ -5016,6 +5023,8 @@ The environment variables:
This path is used to read the file \term{.erlang.cookie}.
\titem{ERL\_CRASH\_DUMP}
Path to the file where crash reports will be dumped.
\titem{ERL\_EPMD\_ADDRESS}
IP address where epmd listens for connections (see section \ref{epmd}).
\titem{ERL\_INETRC}
Indicates which IP name resolution to use.
If using \term{-sname}, specify either this option or \term{-kernel inetrc filepath}.
@@ -5044,10 +5053,10 @@ The command line parameters:
connections (see section \ref{epmd}).
\titem{-detached}
Starts the Erlang system detached from the system console.
Useful for running daemons and backgrounds processes.
Useful for running daemons and background processes.
\titem{-noinput}
Ensures that the Erlang system never tries to read any input.
Useful for running daemons and backgrounds processes.
Useful for running daemons and background processes.
\titem{-pa /var/lib/ejabberd/ebin}
Specify the directory where Erlang binary files (*.beam) are located.
\titem{-s ejabberd}
@@ -5437,6 +5446,8 @@ In order for this communication to work,
\term{epmd} must be running and listening for name requests in the port 4369.
You should block the port 4369 in the firewall in such a way that
only the programs in your machine can access it.
or configure the option \term{ERL\_EPMD\_ADDRESS} in the file \term{ejabberdctl.cfg}
(this option works only in Erlang/OTP R14B03 or higher).
If you build a cluster of several \ejabberd{} instances,
each \ejabberd{} instance is called an \ejabberd{} node.
@@ -5844,10 +5855,6 @@ The Web Admin also supports the \verb|Accept-Language| HTTP header.
\end{figure}
%\section{Ultra Complex Example}
%\label{ultracomplexexample}
%TODO: a very big example covering the whole guide, with a good explanation before the example: different authenticaton mechanisms, transports, ACLs, multple virtual hosts, virtual host specific settings and general settings, modules,...
\makechapter{releasenotes}{Release Notes}
\ind{release notes}
+1
View File
@@ -196,6 +196,7 @@ install: all
sed -e "s*@ctlscriptpath@*$(SBINDIR)*" \
-e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \
> ejabberd.init
chmod 755 ejabberd.init
#
# Binary Erlang files
install -d $(BEAMDIR)
+5 -4
View File
@@ -204,7 +204,7 @@ server_new(Service, ServerFQDN, UserRealm, _SecFlags,
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
%% Username = string()
@@ -236,8 +236,9 @@ server_start(State, Mech, ClientIn) ->
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Error = {error, Reason} | {error, Reason, Text, Username}
%% Reason = term()
%% Text = string()
%% Username = string()
server_step(State, ClientIn) ->
@@ -254,8 +255,8 @@ server_step(State, ClientIn) ->
{continue, ServerOut, NewMechState} ->
{continue, ServerOut,
State#sasl_state{mech_state = NewMechState}};
{error, Error, Username} ->
{error, Error, Username};
{error, Error, Text, Username} ->
{error, Error, Text, Username};
{error, Error} ->
{error, Error}
end.
+5 -5
View File
@@ -80,7 +80,7 @@ mech_new(#sasl_params{host=Host, get_password=GetPassword,
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = mechstate()
%% Error = {error, Reason} | {error, Reason, Username}
%% Error = {error, Reason} | {error, Reason, Text, Username}
%% Reason = term()
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
@@ -99,12 +99,12 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
false ->
?DEBUG("User login not authorized because digest-uri "
"seems invalid: ~p", [DigestURI]),
{error, 'not-authorized', UserName};
{error, 'not-authorized', "", UserName};
true ->
AuthzId = proplists:get_value("authzid", KeyVals, ""),
case (State#state.get_password)(UserName) of
{false, _} ->
{error, 'not-authorized', UserName};
{error, 'not-authorized', "", UserName};
{Passwd, AuthModule} ->
case (State#state.check_password)(UserName, "",
proplists:get_value("response", KeyVals, ""),
@@ -121,9 +121,9 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
username = UserName,
authzid = AuthzId}};
false ->
{error, 'not-authorized', UserName};
{error, 'not-authorized', "", UserName};
{false, _} ->
{error, 'not-authorized', UserName}
{error, 'not-authorized', "", UserName}
end
end
end
+4 -4
View File
@@ -128,13 +128,13 @@ do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
{needsmore, RspAuth} ->
?DEBUG("needsmore~n", []),
if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) ->
{error, "not-authorized"};
{error, 'not-authorized'};
true ->
{continue, binary_to_list(RspAuth),
State#state{step=Step+1}}
end;
{error, _} ->
{error, "not-authorized"}
{error, 'not-authorized'}
end.
handle_step_ok(State, []) ->
@@ -147,7 +147,7 @@ check_user(#state{authid=Authid,authzid=Authzid,
authrealm=Auth_realm,host=Host,realm=Realm}) ->
if Realm =/= Auth_realm ->
?DEBUG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
throw({error, "not-authorized"});
throw({error, 'not-authorized'});
true ->
ok
end,
@@ -155,7 +155,7 @@ check_user(#state{authid=Authid,authzid=Authzid,
case ejabberd_auth:is_user_exists(Authid, Host) of
false ->
?DEBUG("bad user ~p~n",[Authid]),
throw({error, "not-authorized"});
throw({error, 'not-authorized'});
true ->
ok
end,
+3 -4
View File
@@ -62,8 +62,7 @@ mech_new(#sasl_params{check_password = CheckPassword}) ->
%% Username = string()
%% AuthzId = string()
%% AuthModule = atom()
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
%% Error = {error, Reason} | {error, Reason, Text, Username}
mech_step(State, ClientIn) ->
case prepare(ClientIn) of
@@ -73,9 +72,9 @@ mech_step(State, ClientIn) ->
{ok, [{username, User}, {authzid, AuthzId},
{auth_module, AuthModule}]};
{false, ReasonAuthFail} when is_list(ReasonAuthFail) ->
{error, ReasonAuthFail, User};
{error, 'not-authorized', ReasonAuthFail, User};
_ ->
{error, 'not-authorized', User}
{error, 'not-authorized', "", User}
end;
_ ->
{error, 'bad-protocol'}
+1
View File
@@ -513,6 +513,7 @@
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
{mod_blocking,[]}, % requires mod_privacy
{mod_caps, []}, % 1 proc/host
{mod_configure,[]}, % requires mod_adhoc
{mod_disco, []},
+21 -4
View File
@@ -1,6 +1,20 @@
#! /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 nounset
DIR=@ctlscriptpath@
CTL="$DIR"/ejabberdctl
@@ -32,14 +46,17 @@ case "$1" in
su - $USER -c "$CTL stopped"
echo "done."
;;
status)
test -x "$CTL" || exit 0
echo "Getting ejabberd status..."
su - $USER -c "$CTL status"
;;
force-reload|restart)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload}"
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
esac
+2 -1
View File
@@ -141,7 +141,8 @@ check_password(User, Server, Password, Digest, DigestGen)
%% {true, AuthModule} | {false, Reason::string()}
%% where
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
%% | ejabberd_auth_ldap | ejabberd_auth_pam | ejabberd_auth_storage
%% | ejabberd_auth_internal | ejabberd_auth_ldap
%% | ejabberd_auth_odbc | ejabberd_auth_pam
%% @doc Check if the user and password can login in server.
%% The user can login if at least an authentication method accepts the user
%% and the password.
+49 -10
View File
@@ -716,13 +716,13 @@ wait_for_feature_request({xmlstreamelement, #xmlel{ns = NS, name = Name} = El},
fsm_next_state(wait_for_sasl_response,
StateData#state{
sasl_state = NewSASLState});
{error, Error, Username} when is_list(Error) ->
{error, Error, Text, Username} ->
?INFO_MSG(
"(~w) Failed authentication for ~s@~s due to ~s",
"(~w) Failed authentication for ~s@~s due to ~p ~s",
[StateData#state.socket,
Username, StateData#state.server, Error]),
Username, StateData#state.server, Error, Text]),
send_element(StateData,
exmpp_server_sasl:failure(Error)),
exmpp_server_sasl:failure(Error, Text)),
{next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT};
{error, Error} ->
@@ -834,13 +834,13 @@ wait_for_sasl_response({xmlstreamelement, #xmlel{ns = NS, name = Name} = El},
exmpp_server_sasl:challenge(ServerOut)),
fsm_next_state(wait_for_sasl_response,
StateData#state{sasl_state = NewSASLState});
{error, Error, Username} ->
{error, Error, Text, Username} ->
?INFO_MSG(
"(~w) Failed authentication for ~s@~s",
"(~w) Failed authentication for ~s@~s due to ~p ~s",
[StateData#state.socket,
Username, StateData#state.server]),
Username, StateData#state.server, Error, Text]),
send_element(StateData,
exmpp_server_sasl:failure(Error)),
exmpp_server_sasl:failure(Error, Text)),
fsm_next_state(wait_for_feature_request, StateData);
{error, Error} ->
send_element(StateData,
@@ -894,7 +894,8 @@ wait_for_bind({xmlstreamelement, El}, StateData) ->
Err = exmpp_server_binding:error(El, 'bad-request'),
send_element(StateData, Err),
fsm_next_state(wait_for_bind, StateData);
throw:_Exception ->
throw:Exception ->
?DEBUG("When processing:~n ~p~nThis exception was catched:~n ~p", [El, Exception]),
fsm_next_state(wait_for_bind, StateData)
end;
@@ -1076,7 +1077,9 @@ session_established2(El, StateData) ->
end;
#xmlel{ns = ?NS_JABBER_CLIENT, name = 'iq'} ->
case exmpp_iq:xmlel_to_iq(El) of
#iq{kind = request, ns = ?NS_PRIVACY} = IQ_Rec ->
#iq{kind = request, ns = Xmlns} = IQ_Rec
when Xmlns == ?NS_PRIVACY;
Xmlns == ?NS_BLOCKING ->
process_privacy_iq(
FromJID, ToJID, IQ_Rec, StateData);
_ ->
@@ -1341,6 +1344,13 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
send_element(StateData, PrivPushEl),
{false, Attrs, StateData#state{privacy_list = NewPL}}
end;
blocking ->
CDataString = exmpp_xml:get_cdata_as_list(Packet),
{ok, A2, _} = erl_scan:string(CDataString),
{_, W} = erl_parse:parse_exprs(A2),
{value, What, []} = erl_eval:exprs(W, []),
route_blocking(What, StateData),
{false, Attrs, StateData};
_ ->
{false, Attrs, StateData}
end;
@@ -2273,6 +2283,35 @@ bounce_messages() ->
end.
%%%----------------------------------------------------------------------
%%% XEP-0191
%%%----------------------------------------------------------------------
route_blocking(What, StateData) ->
SubEl =
case What of
{Action, JIDs} when (Action == block) or (Action == unblock) ->
UnblockJids =
lists:map(
fun(JidString) ->
exmpp_xml:set_attribute(#xmlel{ns = ?NS_BLOCKING,
name = item},
<<"jid">>,
JidString)
end, JIDs),
#xmlel{ns = ?NS_BLOCKING, name = Action,
children = UnblockJids};
unblock_all ->
#xmlel{ns = ?NS_BLOCKING, name = 'unblock'}
end,
El1 = exmpp_iq:set(?NS_BLOCKING, SubEl, random),
El2 = exmpp_stanza:set_sender(El1, exmpp_jid:bare(StateData#state.jid)),
El3 = exmpp_stanza:set_recipient(El2, StateData#state.jid),
send_element(StateData, El3),
%% No need to replace active privacy list here,
%% blocking pushes are always accompanied by
%% Privacy List pushes
ok.
%%%----------------------------------------------------------------------
%%% JID Set memory footprint reduction code
+7 -3
View File
@@ -627,13 +627,17 @@ get_prog_name() ->
get_url(Str) ->
CaptchaHost = ejabberd_config:get_local_option(captcha_host),
case string:tokens(CaptchaHost, ":") of
[TransferProt, Host, PortString] ->
TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
[Host] ->
"http://" ++ Host ++ "/captcha/" ++ Str;
["http"++_ = TransferProt, Host] ->
TransferProt ++ ":" ++ Host ++ "/captcha/" ++ Str;
[Host, PortString] ->
TransferProt = atom_to_list(get_transfer_protocol(PortString)),
TransferProt ++ "://" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
[TransferProt, Host, PortString] ->
TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
_ ->
"http://" ++ ?MYNAME ++ ":5280/captcha/" ++ Str
"http://" ++ ?MYNAME ++ "/captcha/" ++ Str
end.
get_transfer_protocol(PortString) ->
+1 -1
View File
@@ -263,7 +263,7 @@ exit_or_halt(ExitText) ->
case [Vsn || {ejabberd, _Desc, Vsn} <- application:which_applications()] of
[] ->
timer:sleep(1000),
halt(ExitText);
halt(string:substr(ExitText, 1, 199));
[_] ->
exit(ExitText)
end.
+17 -1
View File
@@ -61,12 +61,28 @@
#
INET_DIST_INTERFACE={127,0,0,1}
#.
#' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections
#
# IMPORTANT: This option works only in Erlang/OTP R14B03 and newer.
#
# This environment variable may be set to a comma-separated
# list of IP addresses, in which case the epmd daemon
# will listen only on the specified address(es) and on the
# loopback address (which is implicitly added to the list if it
# has not been specified). The default behaviour is to listen on
# all available IP addresses.
#
# Default: 0.0.0.0
#
#ERL_EPMD_ADDRESS=127.0.0.1
#.
#' ERL_PROCESSES: Maximum number of Erlang processes
#
# Erlang consumes a lot of lightweight processes. If there is a lot of activity
# on ejabberd so that the maximum number of processes is reached, people will
# experiment greater latency times. As these processes are implemented in
# experience greater latency times. As these processes are implemented in
# Erlang, and therefore not related to the operating system processes, you do
# not have to worry about allowing a huge number of them.
#
+1
View File
@@ -133,6 +133,7 @@ export EJABBERD_BIN_PATH
export EJABBERD_DOC_PATH
export EJABBERD_PID_PATH
export ERL_CRASH_DUMP
export ERL_EPMD_ADDRESS
export ERL_INETRC
export ERL_MAX_PORTS
export ERL_MAX_ETS_TABLES
+12 -4
View File
@@ -45,11 +45,18 @@
start(Host, ExtPrg) ->
lists:foreach(
fun(This) ->
spawn(?MODULE, init, [get_process_name(Host, This), ExtPrg])
start_instance(get_process_name(Host, This), ExtPrg)
end,
lists:seq(0, get_instances(Host)-1)
).
start_instance(ProcessName, ExtPrg) ->
spawn(?MODULE, init, [ProcessName, ExtPrg]).
restart_instance(ProcessName, ExtPrg) ->
unregister(ProcessName),
start_instance(ProcessName, ExtPrg).
init(ProcessName, ExtPrg) ->
register(ProcessName, self()),
process_flag(trap_exit,true),
@@ -125,8 +132,7 @@ loop(Port, Timeout, ProcessName, ExtPrg) ->
Timeout ->
?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]),
Caller ! {eauth, false},
unregister(ProcessName),
Pid = spawn(?MODULE, init, [ProcessName, ExtPrg]),
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
end;
@@ -137,7 +143,9 @@ loop(Port, Timeout, ProcessName, ExtPrg) ->
exit(normal)
end;
{'EXIT', Port, Reason} ->
?CRITICAL_MSG("~p ~n", [Reason]),
?CRITICAL_MSG("extauth script has exitted abruptly with reason '~p'", [Reason]),
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
end.
+15 -2
View File
@@ -85,11 +85,24 @@ start_module2(Host, Module, Opts) ->
catch Class:Reason ->
del_module_mnesia(Host, Module),
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]),
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(string:substr(lists:flatten(ErrorText), 1, 199))
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.
stop_module(Host, Module) ->
case stop_module_keep_config(Host, Module) of
+349
View File
@@ -0,0 +1,349 @@
%%%----------------------------------------------------------------------
%%% 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_lib("exmpp/include/exmpp.hrl").
-include("mod_privacy.hrl").
start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
ejabberd_hooks:add(privacy_iq_get, HostB,
?MODULE, process_iq_get, 40),
ejabberd_hooks:add(privacy_iq_set, HostB,
?MODULE, process_iq_set, 40),
mod_disco:register_feature(HostB, ?NS_BLOCKING),
gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_BLOCKING,
?MODULE, process_iq, IQDisc).
stop(Host) ->
HostB = list_to_binary(Host),
ejabberd_hooks:delete(privacy_iq_get, HostB,
?MODULE, process_iq_get, 40),
ejabberd_hooks:delete(privacy_iq_set, HostB,
?MODULE, process_iq_set, 40),
mod_disco:unregister_feature(HostB, ?NS_BLOCKING),
gen_iq_handler:remove_iq_handler(ejabberd_sm, HostB, ?NS_BLOCKING).
process_iq(_From, _To, IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'not-allowed').
process_iq_get(_, From, _To, #iq{ns = ?NS_BLOCKING, payload = SubEl}, _) ->
case SubEl#xmlel.name == blocklist of
true ->
LUser = exmpp_jid:prep_node(From),
LServer = exmpp_jid:prep_domain(From),
process_blocklist_get(LUser, LServer);
false ->
{error, 'bad-request'}
end;
process_iq_get(Acc, _, _, _, _) ->
Acc.
process_iq_set(_, From, _To, #iq{ns = ?NS_BLOCKING,
payload = #xmlel{name = SubElName,
children = SubEls}}) ->
LUser = exmpp_jid:prep_node(From),
LServer = exmpp_jid:prep_domain(From),
case {SubElName, exmpp_xml:remove_cdata_from_list(SubEls)} of
{block, []} ->
{error, '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, '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).
get_list_blocklist_jids(LUser, LServer, Name) ->
Tuples = gen_storage:dirty_select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name},
{'=', type, jid}]),
[Tuple#privacy_list_data.value ||
Tuple <- Tuples, Tuple#privacy_list_data.match_all == true].
parse_blocklist_items([], JIDs) ->
JIDs;
parse_blocklist_items([#xmlel{name = item} = El | Els], JIDs) ->
case exmpp_xml:get_attribute(El, <<"jid">>, false) of
false ->
%% Tolerate missing jid attribute
parse_blocklist_items(Els, JIDs);
JID1 ->
JID = exmpp_jid:to_binary(exmpp_jid:parse(JID1)),
parse_blocklist_items(Els, [JID | JIDs])
end;
parse_blocklist_items([_ | Els], JIDs) ->
%% Tolerate unknown elements
parse_blocklist_items(Els, JIDs).
process_blocklist_block(LUser, LServer, JIDs) ->
F =
fun() ->
case gen_storage:read(LServer, {privacy_list, {LUser, LServer}}) of
[] ->
%% No lists yet
%% TODO: i18n here:
Default = <<"Blocked contacts">>,
gen_storage:write(LServer,
#privacy_list{
user_host = {LUser, LServer},
name = Default}),
gen_storage:write(LServer,
#privacy_default_list{
user_host = {LUser, LServer},
name = Default}),
ok;
_Lists ->
case gen_storage:read(LServer,
{privacy_default_list, {LUser, LServer}}) of
[#privacy_default_list{name = Default}] ->
%% Default list exists
Default;
[] ->
%% No default list yet, create one
%% TODO: i18n here:
Default = <<"Blocked contacts">>,
gen_storage:write(LServer,
#privacy_list{
user_host = {LUser, LServer},
name = Default}),
gen_storage:write(LServer,
#privacy_default_list{
user_host = {LUser, LServer},
name = Default})
end
end,
AlreadyBlocked = get_list_blocklist_jids(LUser, LServer, Default),
NewItems = lists:foldr(fun(JID, Res) ->
case lists:member(JID, AlreadyBlocked) of
true ->
Res;
false ->
Data = #privacy_list_data{
user_host = {LUser, LServer},
name = Default,
type = jid,
value = JID,
action = deny,
order = 0,
match_all = true
},
gen_storage:write(LServer, Data),
[Data | Res]
end
end, [], JIDs),
{ok, Default, NewItems}
end,
case gen_storage:transaction(LServer, privacy_list_data, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, {ok, Default, Data}} ->
%% Data = gen_storage:select(LServer, privacy_list_data,
%% [{'=', user_host, {LUser, LServer}},
%% {'=', name, Default}]),
List = list_data_to_items(Data),
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, {block, JIDs}),
{result, []};
Error ->
?DEBUG("Error ~n~p", [Error]),
{error, 'internal-server-error'}
end.
%%Copied from mod_privacy
%% storage representation to ejabberd representation
list_data_to_items(Data) ->
List =
lists:map(
fun(Data1) ->
#listitem{type = Data1#privacy_list_data.type,
value = Data1#privacy_list_data.value,
action = Data1#privacy_list_data.action,
order = Data1#privacy_list_data.order,
match_all = Data1#privacy_list_data.match_all,
match_iq = Data1#privacy_list_data.match_iq,
match_message = Data1#privacy_list_data.match_message,
match_presence_in = Data1#privacy_list_data.match_presence_in,
match_presence_out = Data1#privacy_list_data.match_presence_out}
end, Data),
SortedList = lists:keysort(#listitem.order, List),
SortedList.
process_blocklist_unblock_all(LUser, LServer) ->
F =
fun() ->
case gen_storage:read(LServer, {privacy_list, {LUser, LServer}}) of
[] ->
%% No lists, nothing to unblock
ok;
_ ->
case gen_storage:read(LServer, {privacy_default_list, {LUser, LServer}}) of
[#privacy_default_list{name = Default}] ->
%% Default list, remove all deny items
gen_storage:delete_where(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Default},
{'=', action, deny},
{'=', match_all, true},
{'=', type, jid}]),
Data = gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Default}]),
{ok, Default, Data};
[] ->
%% No default list, nothing to unblock
ok
end
end
end,
case gen_storage:transaction(LServer, privacy_list_data, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, ok} ->
{result, []};
{atomic, {ok, Default, Data}} ->
List = list_data_to_items(Data),
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, unblock_all),
{result, []};
_ ->
{error, 'internal-server-error'}
end.
process_blocklist_unblock(LUser, LServer, JIDs) ->
F =
fun() ->
case gen_storage:read(LServer, {privacy_list, {LUser, LServer}}) of
[] ->
%% No lists, nothing to unblock
ok;
_ ->
case gen_storage:read(LServer, {privacy_default_list, {LUser, LServer}}) of
[#privacy_default_list{name = Default}] ->
%% Default list, remove matching deny items
lists:foreach(
fun(JID) ->
gen_storage:delete_where(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Default},
{'=', action, deny},
{'=', match_all, true},
{'=', value, JID},
{'=', type, jid}])
end, JIDs),
Data = gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Default}]),
{ok, Default, Data};
[] ->
%% No default list, nothing to unblock
ok
end
end
end,
case gen_storage:transaction(LServer, privacy_list_data, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, ok} ->
{result, []};
{atomic, {ok, Default, Data}} ->
List = list_data_to_items(Data),
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}),
{result, []};
_ ->
{error, 'internal-server-error'}
end.
broadcast_list_update(LUser, LServer, Name, List) ->
NeedDb = is_list_needdb(List),
JID = exmpp_jid:make(LUser, LServer),
ListString = lists:flatten(io_lib:format("~p.", [#userlist{name = Name, list = List, needdb = NeedDb}])),
ejabberd_router:route(
JID,
JID,
#xmlel{name = 'broadcast', ns = privacy_list,
attrs = [?XMLATTR(<<"list_name">>, Name)],
children = [exmpp_xml:cdata(ListString)]}).
broadcast_blocklist_event(LUser, LServer, Event) ->
JID = exmpp_jid:make(LUser, LServer),
EventString = lists:flatten(io_lib:format("~p.", [Event])),
ejabberd_router:route(
JID, JID,
#xmlel{name = 'broadcast', ns = blocking,
children = [exmpp_xml:cdata(EventString)]}).
process_blocklist_get(LUser, LServer) ->
case catch gen_storage:dirty_read(LServer, privacy_default_list, {LUser, LServer}) of
{'EXIT', _Reason} ->
{error, 'internal-server-error'};
[] ->
{result, #xmlel{name = 'blocklist', ns = ?NS_BLOCKING}};
[#privacy_default_list{name = Default}] ->
JIDs = get_list_blocklist_jids(LUser, LServer, Default),
Items = lists:map(
fun(JID) ->
?DEBUG("JID: ~p",[JID]),
#xmlel{name = item, ns = privacy_list,
attrs = [?XMLATTR(<<"jid">>, JID)]}
end, JIDs),
{result,
#xmlel{name = 'blocklist', ns = ?NS_BLOCKING, children = Items}}
end.
+4 -4
View File
@@ -186,7 +186,7 @@ user_receive_packet(_JID, _From, _To, _Packet) ->
caps_stream_features(Acc, MyHost) ->
case make_my_disco_hash(MyHost) of
"" ->
<<"">> ->
Acc;
Hash ->
[#xmlel{name = c,
@@ -470,7 +470,7 @@ make_my_disco_hash(Host) ->
end, Features),
make_disco_hash(Identities ++ Info ++ Feats, sha1);
_Err ->
""
<<"">>
end.
-ifdef(HAVE_MD2).
@@ -478,7 +478,7 @@ make_disco_hash(DiscoEls, Algo) ->
Concat = [concat_identities(DiscoEls),
concat_features(DiscoEls),
concat_info(DiscoEls)],
base64:encode_to_string(
base64:encode(
if Algo == md2 ->
sha:md2(Concat);
Algo == md5 ->
@@ -519,7 +519,7 @@ make_disco_hash(DiscoEls, Algo) ->
Concat = [concat_identities(DiscoEls),
concat_features(DiscoEls),
concat_info(DiscoEls)],
base64:encode_to_string(
base64:encode(
if Algo == md5 ->
crypto:md5(Concat);
Algo == sha1 ->
+2 -1
View File
@@ -142,8 +142,9 @@ process_sm_iq(From, To, #iq{type = get} = IQ_Rec) ->
ejabberd_hooks:run_fold(
roster_get_jid_info, exmpp_jid:prep_domain(To),
{none, []}, [exmpp_jid:prep_node(To), exmpp_jid:prep_domain(To), From]),
SameUser = exmpp_jid:bare_compare(From, To),
if
(Subscription == both) or (Subscription == from) ->
(Subscription == both) or (Subscription == from) or SameUser ->
UserListRecord = ejabberd_hooks:run_fold(
privacy_get_user_list, exmpp_jid:prep_domain(To),
#userlist{},
+54
View File
@@ -26,6 +26,16 @@
%%% Database schema (version / storage / table)
%%%
%%% 2.1.x / mnesia / muc_online_room
%%% name_host = {Name::string(), Host::string()}
%%% pid = pid()
%%% 2.1.x / mnesia / muc_registered
%%% us_host = {{Username::string, Hostname::string()}, Host::string()}}
%%% nick = string()
%%% 2.1.x / mnesia / muc_room
%%% name_host = {Name::string(), Host::string()}
%%% opts = [{Option::atom(), Value::any()}
%%%
%%% 3.0.0-alpha / mnesia / muc_online_room
%%% name_host = {Name::binary(), Host::binary()}
%%% pid = pid()
@@ -333,6 +343,7 @@ init([Host, Opts]) ->
gen_storage:add_table_copy(MyHost, muc_online_room, node(), ram_copies),
catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]),
gen_storage:add_table_index(MyHost, muc_registered, nick),
update_tables(MyHost_L, Backend),
Access = gen_mod:get_opt(access, Opts, all),
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
@@ -1013,3 +1024,46 @@ get_vh_rooms_all_nodes(Host) ->
get_vh_rooms(Host) when is_binary(Host) ->
gen_storage:dirty_select(Host, muc_online_room,
[{'=', name_host, {'_', Host}}]).
%%%%%
%%%%% Database migration from ejabberd 2.1.x
%%%%%
update_tables(Host, mnesia) ->
HostB = list_to_binary(Host),
gen_storage_migration:migrate_mnesia(
Host, muc_registered,
[{muc_registered, [us_host, nick],
fun({muc_registered, {{UserS, ServerS}, HostS}, NickS}) ->
#muc_registered{user_host = {exmpp_jid:make(UserS, ServerS),
list_to_binary(HostS)},
nick = list_to_binary(NickS)}
end}]),
gen_storage_migration:migrate_mnesia(
Host, muc_room_opt,
[{muc_room, [name_host, opts],
fun({muc_room, {NameString, HostString}, Options}) ->
NameHost = {list_to_binary(NameString),
list_to_binary(HostString)},
lists:foreach(
fun({affiliations, Affiliations}) ->
lists:foreach(
fun({{Username, Hostname, Resource}, AffiliationIni}) ->
UserJid = exmpp_jid:make(Username, Hostname, Resource),
{Affiliation, Reason} = case AffiliationIni of
Aff when is_atom(Aff) -> {Aff, ""};
{Aff, Reas} -> {Aff, Reas}
end,
gen_storage:write(HostB,
#muc_room_affiliation{name_host = NameHost,
jid = UserJid,
affiliation = Affiliation,
reason = Reason})
end, Affiliations);
({Opt, Val}) ->
gen_storage:write(HostB,
#muc_room_opt{name_host = NameHost,
opt = Opt,
val = Val})
end, Options)
end}]).
+9 -2
View File
@@ -2756,13 +2756,20 @@ send_kickban_presence(JID, Reason, Code, NewAffiliation, StateData) ->
end, LJIDs).
send_kickban_presence1(UJID, Reason, Code, Affiliation, StateData) ->
{ok, #user{jid = _RealJID,
{ok, #user{jid = RealJID,
nick = Nick}} = ?DICT:find(UJID, StateData#state.users),
SAffiliation = affiliation_to_binary(Affiliation),
BannedJID = exmpp_jid:to_binary(RealJID),
lists:foreach(
fun({_LJID, Info}) ->
JidAttrList = case (Info#user.role == moderator) orelse
((StateData#state.config)#config.anonymous
== false) of
true -> [?XMLATTR(<<"jid">>, BannedJID)];
false -> []
end,
ItemAttrs = [?XMLATTR(<<"affiliation">>, SAffiliation),
?XMLATTR(<<"role">>, <<"none">>)],
?XMLATTR(<<"role">>, <<"none">>)] ++ JidAttrList,
ItemEls = case Reason of
"" ->
[];
+46 -39
View File
@@ -56,12 +56,12 @@
%%% Same as 2.1.x
%%%
%%% 3.0.0-alpha / mnesia / offline_msg
%%% user_host = {Username::string(), Host::string()}
%%% user_host = {Username::binary(), Host::binary()}
%%% timestamp = integer()
%%% expire = 0 | integer()
%%% from = jid()
%%% to = jid()
%%% packet = string()
%%% packet = binary()
%%%
%%% 3.0.0-alpha / odbc / offline_msg
%%% user = varchar150
@@ -98,8 +98,7 @@
-include("web/ejabberd_http.hrl").
-include("web/ejabberd_web_admin.hrl").
%% The packet is stored serialized as a string
%% TODO: packet always handled serialized?
%% The packet is stored serialized as a binary
-record(offline_msg, {user_host, timestamp, expire, from, to, packet}).
-define(PROCNAME, ejabberd_offline).
@@ -149,6 +148,12 @@ start(Host, Opts) ->
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, loop, [AccessMaxOfflineMsgs])).
stanza_to_store(Stanza) ->
exmpp_xml:document_to_binary(Stanza).
store_to_stanza(StoreBinary) ->
[Xml] = exmpp_xml:parse_document(StoreBinary),
Xml.
loop(AccessMaxOfflineMsgs) ->
receive
#offline_msg{user_host=US} = Msg ->
@@ -156,8 +161,6 @@ loop(AccessMaxOfflineMsgs) ->
Len = length(Msgs),
%% TODO: is lower?
{User, Host} = US,
MsgsSerialized = [M#offline_msg{packet = exmpp_xml:document_to_list(P)}
|| #offline_msg{packet = P} = M <- Msgs],
MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs,
User, Host),
F = fun() ->
@@ -180,7 +183,7 @@ loop(AccessMaxOfflineMsgs) ->
end,
lists:foreach(fun(M) ->
gen_storage:write(Host, M)
end, MsgsSerialized)
end, Msgs)
end
end,
gen_storage:transaction(Host, offline_msg, F),
@@ -251,8 +254,8 @@ store_packet(From, To, Packet) ->
(Type /= <<"headline">>) ->
case check_event_chatstates(From, To, Packet) of
true ->
LUser = exmpp_jid:prep_node_as_list(To),
LServer = exmpp_jid:prep_domain_as_list(To),
LUser = exmpp_jid:prep_node(To),
LServer = exmpp_jid:prep_domain(To),
TimeStamp = make_timestamp(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
gen_mod:get_module_proc(LServer, ?PROCNAME) !
@@ -261,7 +264,7 @@ store_packet(From, To, Packet) ->
expire = Expire,
from = From,
to = To,
packet = Packet},
packet = stanza_to_store(Packet)},
stop;
_ ->
ok
@@ -338,10 +341,11 @@ find_x_expire(TimeStamp, [_ | Els]) ->
find_x_expire(TimeStamp, Els).
%% @spec(User::string(), Server::string()) -> ok
resend_offline_messages(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
LUser = exmpp_stringprep:nodeprep(list_to_binary(User)),
LServer = exmpp_stringprep:nameprep(list_to_binary(Server)),
US = {LUser, LServer},
F = fun() ->
Rs = gen_storage:read(LServer, offline_msg, US, write),
@@ -352,7 +356,7 @@ resend_offline_messages(User, Server) ->
{atomic, Rs} ->
lists:foreach(
fun(R) ->
Packet = R#offline_msg.packet,
Packet = store_to_stanza(R#offline_msg.packet),
TimeXml = timestamp_to_xml(R#offline_msg.timestamp, Server),
TimeXml91 = timestamp_to_xml(R#offline_msg.timestamp),
ejabberd_sm !
@@ -373,12 +377,11 @@ resend_offline_messages(User, Server) ->
ok
end.
%% @spec(Ls::list(), User::binary(), Server::binary()) -> list()
pop_offline_messages(Ls, User, Server)
when is_binary(User), is_binary(Server) ->
try
LUser = binary_to_list(User),
LServer = binary_to_list(Server),
US = {LUser, LServer},
US = {User, Server},
F = fun() ->
Rs = gen_storage:read(Server, offline_msg, US, write),
gen_storage:delete(Server, {offline_msg, US}),
@@ -389,7 +392,7 @@ pop_offline_messages(Ls, User, Server)
TS = make_timestamp(),
Ls ++ lists:map(
fun(R) ->
[Packet] = exmpp_xml:parse_document(R#offline_msg.packet),
Packet = store_to_stanza(R#offline_msg.packet),
TimeXml = timestamp_to_xml(R#offline_msg.timestamp, Server),
TimeXml91 = timestamp_to_xml(R#offline_msg.timestamp),
{route,
@@ -444,6 +447,7 @@ remove_old_messages(Days) ->
{atomic, _} = gen_storage:transaction(HostB, offline_msg, F)
end, gen_storage:all_table_hosts(offline_msg)).
%% @spec(User::binary(), Server::binary()) -> ok
remove_user(User, Server) when is_binary(User), is_binary(Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@@ -486,7 +490,7 @@ update_table(Host, mnesia) ->
end,
PacketXmlel = exmpp_xml:xmlelement_to_xmlel(
Packet, [?DEFAULT_NS], ?PREFIXED_NS),
Packet1 = exmpp_xml:document_to_list(PacketXmlel),
Packet1 = stanza_to_store(PacketXmlel),
OM#offline_msg{user_host = {US_U1, US_S1},
timestamp = TsMegaSecs * 1000000000 + TsSecs * 1000 + TsMicroSecs div 1000,
expire = Expire1,
@@ -515,7 +519,7 @@ update_table(Host, odbc) ->
end}]).
convert_jid_to_exmpp("") -> undefined;
convert_jid_to_exmpp(V) -> V.
convert_jid_to_exmpp(V) -> list_to_binary(V).
%% Return the current timestamp in milliseconds
make_timestamp() ->
@@ -570,7 +574,8 @@ find_x_timestamp([_ | Els]) ->
%% Warn senders that their messages have been discarded:
discard_warn_sender(Msgs) ->
lists:foreach(
fun(#offline_msg{from=From, to=To, packet=Packet}) ->
fun(#offline_msg{from=From, to=To, packet=PacketStored}) ->
Packet = store_to_stanza(PacketStored),
ErrText = "Your contact offline message queue is full. The message has been discarded.",
Error = exmpp_stanza:error(Packet#xmlel.ns, 'resource-constraint',
{"en", ErrText}),
@@ -592,31 +597,32 @@ webadmin_page(_, Host,
webadmin_page(Acc, _, _) -> Acc.
user_queue(User, Server, Query, Lang) ->
ServerB = list_to_binary(Server),
US0 = {
exmpp_stringprep:nodeprep(User),
exmpp_stringprep:nameprep(Server)
exmpp_stringprep:nodeprep(list_to_binary(User)),
exmpp_stringprep:nameprep(list_to_binary(Server))
},
{US, MsgsAll, Res} = try
{US, Res, MsgsAll} = try
{
US0,
lists:keysort(#offline_msg.timestamp,
gen_storage:dirty_read(Server, {offline_msg, US0})),
user_queue_parse_query(US0, Query)
user_queue_parse_query(US0, Query),
lists:keysort(#offline_msg.timestamp,
gen_storage:dirty_read(ServerB, {offline_msg, US0}))
}
catch
_ ->
{{"invalid", "invalid"}, [], nothing}
{{"invalid", "invalid"}, [], []}
end,
Msgs = get_messages_subset(User, Server, MsgsAll),
FMsgs =
lists:map(
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
packet = PacketInitialString} = Msg) ->
packet = PacketStored} = Msg) ->
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
Time = timestamp_to_isostring(TimeStamp),
SFrom = exmpp_jid:to_list(From),
STo = exmpp_jid:to_list(To),
[Packet] = exmpp_xmlstream:parse_element(PacketInitialString),
Packet = store_to_stanza(PacketStored),
Packet1 = exmpp_stanza:set_jids(Packet, SFrom, STo),
FPacket = exmpp_xml:node_to_list(
exmpp_xml:indent_document(Packet1, <<" ">>),
@@ -632,7 +638,7 @@ user_queue(User, Server, Query, Lang) ->
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
[us_to_list(US)]))] ++
case Res of
ok -> [?CT("Submitted"), ?P];
ok -> [?XREST("Submitted")];
nothing -> []
end ++
[?XAE("form", [?XMLATTR(<<"action">>, <<"">>), ?XMLATTR(<<"method">>, <<"post">>)],
@@ -687,10 +693,9 @@ user_queue_parse_query(US, Query) ->
us_to_list({User, Server}) ->
exmpp_jid:to_list(User, Server).
%% @spec (User::string(), Host::string()) -> integer()
%% @spec (User::binary(), Host::binary()) -> integer()
get_queue_length(User, Host) ->
HostB = list_to_binary(Host),
gen_storage:dirty_count_records(HostB, offline_msg, [{'=', user_host, {User, Host}}]).
gen_storage:dirty_count_records(Host, offline_msg, [{'=', user_host, {User, Host}}]).
get_messages_subset(User, Host, MsgsAll) ->
Access = gen_mod:get_module_opt(Host, ?MODULE, access_max_user_messages,
@@ -711,7 +716,7 @@ get_messages_subset2(Max, Length, MsgsAll) ->
NoJID = exmpp_jid:make("...", "...", ""),
TimeStamp = make_timestamp(),
IntermediateMsg = #offline_msg{timestamp = TimeStamp, from = NoJID, to = NoJID,
packet = exmpp_xml:element("...")},
packet = <<"...">>},
MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN.
webadmin_user(Acc, User, Server, Lang) ->
@@ -722,15 +727,17 @@ webadmin_user(Acc, User, Server, Lang) ->
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen ++ [?C(" "), ?INPUTT("submit", "removealloffline", "Remove All Offline Messages")].
webadmin_user_parse_query(_, "removealloffline", User, Server, _Query) ->
US = {User, Server},
UserB = list_to_binary(User),
ServerB = list_to_binary(Server),
US = {UserB, ServerB},
F = fun() ->
gen_storage:write_lock_table(Server, offline_msg),
gen_storage:write_lock_table(ServerB, offline_msg),
lists:foreach(
fun(Msg) ->
gen_storage:delete_object(Server, Msg)
end, gen_storage:read(Server, {offline_msg, US}))
gen_storage:delete_object(ServerB, Msg)
end, gen_storage:read(ServerB, {offline_msg, US}))
end,
case gen_storage:transaction(Server, offline_msg, F) of
case gen_storage:transaction(ServerB, offline_msg, F) of
{aborted, Reason} ->
?ERROR_MSG("Failed to remove offline messages: ~p", [Reason]),
{stop, error};
+1 -1
View File
@@ -95,7 +95,7 @@ init([Host, Opts]) ->
SendPings = gen_mod:get_opt(send_pings, Opts, ?DEFAULT_SEND_PINGS),
PingInterval = gen_mod:get_opt(ping_interval, Opts, ?DEFAULT_PING_INTERVAL),
TimeoutAction = gen_mod:get_opt(timeout_action, Opts, none),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
IQDisc = gen_mod:get_opt(iqdisc, Opts, no_queue),
mod_disco:register_feature(HostB, ?NS_PING),
gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_PING,
?MODULE, iq_ping, IQDisc),
+62 -70
View File
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : mod_privacy.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : jabber:iq:privacy support
%%% Purpose : XEP-0016: Privacy Lists
%%% Created : 21 Jul 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
@@ -59,16 +59,16 @@
%%% Same as 2.1.x
%%%
%%% 3.0.0-alpha / mnesia / privacy_default_list
%%% user_host = {Username::string(), Server::string()}
%%% name = string()
%%% user_host = {Username::binary(), Server::binary()}
%%% name = binary()
%%% 3.0.0-alpha / mnesia / privacy_list
%%% user_host = {Username::string(), Server::string()}
%%% name = string()
%%% user_host = {Username::binary(), Server::binary()}
%%% name = binary()
%%% 3.0.0-alpha / mnesia / privacy_list_data
%%% user_host = {Username::string(), Server::string()}
%%% name = string()
%%% user_host = {Username::binary(), Server::binary()}
%%% name = binary()
%%% type = jid | group | subscription | none
%%% value = JID::binary() | Group::binary() | <<"none">> | <<"both">> | <<"from">> | <<"to">>
%%% value = JID::binary() | Group::binary() | <<"none">> | <<"both">> | <<"from">> | <<"to">> | none
%%% action = allow | deny
%%% order = integer()
%%% match_all = boolean()
@@ -118,13 +118,6 @@
-include("ejabberd.hrl").
-include("mod_privacy.hrl").
-record(privacy_list, {user_host, name}).
-record(privacy_default_list, {user_host, name}).
-record(privacy_list_data, {user_host, name,
type, value, action, order,
match_all, match_iq, match_message,
match_presence_in, match_presence_out}).
start(Host, Opts) ->
HostB = list_to_binary(Host),
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
@@ -194,41 +187,42 @@ process_iq(_From, _To, IQ_Rec) ->
exmpp_iq:error(IQ_Rec, 'not-allowed').
process_iq_get(_, From, _To, #iq{payload = SubEl},
process_iq_get(_, From, _To, #iq{ns = ?NS_PRIVACY, payload = SubEl},
#userlist{name = Active}) ->
LUser = exmpp_jid:prep_node_as_list(From),
LServer = exmpp_jid:prep_domain_as_list(From),
LUser = exmpp_jid:prep_node(From),
LServer = exmpp_jid:prep_domain(From),
case exmpp_xml:get_child_elements(SubEl) of
[] ->
process_lists_get(LUser, LServer, Active);
[#xmlel{name = Name} = Child] ->
case Name of
list ->
ListName = exmpp_xml:get_attribute_as_list(Child, <<"name">>, false),
ListName = exmpp_xml:get_attribute_as_binary(Child, <<"name">>, false),
process_list_get(LUser, LServer, ListName);
_ ->
{error, 'bad-request'}
end;
_ ->
{error, 'bad-request'}
end.
end;
process_iq_get(Acc, _, _, _, _) ->
Acc.
process_lists_get(LUser, LServer, Active) ->
LServerB = list_to_binary(LServer),
F = fun() ->
Default =
case gen_storage:read(LServerB, {privacy_default_list, {LUser, LServer}}) of
case gen_storage:read(LServer, {privacy_default_list, {LUser, LServer}}) of
[#privacy_default_list{name = Name}] ->
Name;
_ ->
none
end,
Lists = [List#privacy_list.name
|| List <- gen_storage:read(LServerB, {privacy_list, {LUser, LServer}})],
|| List <- gen_storage:read(LServer, {privacy_list, {LUser, LServer}})],
{Default, Lists}
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{aborted, _Reason} ->
{error, 'internal-server-error'};
{atomic, {Default, Lists}} ->
@@ -259,20 +253,19 @@ process_list_get(_LUser, _LServer, false) ->
{error, 'bad-request'};
process_list_get(LUser, LServer, Name) ->
LServerB = list_to_binary(LServer),
F = fun() ->
case gen_storage:select(LServerB, privacy_list,
case gen_storage:select(LServer, privacy_list,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]) of
[] ->
none;
[#privacy_list{}] ->
gen_storage:select(LServerB, privacy_list_data,
gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}])
end
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{aborted, _Reason} ->
{error, 'internal-server-error'};
{atomic, none} ->
@@ -354,12 +347,12 @@ list_to_action(S) ->
process_iq_set(_, From, _To, #iq{payload = SubEl}) ->
LUser = exmpp_jid:prep_node_as_list(From),
LServer = exmpp_jid:prep_domain_as_list(From),
process_iq_set(_, From, _To, #iq{ns = ?NS_PRIVACY, payload = SubEl}) ->
LUser = exmpp_jid:prep_node(From),
LServer = exmpp_jid:prep_domain(From),
case exmpp_xml:get_child_elements(SubEl) of
[#xmlel{name = Name} = Child] ->
ListName = exmpp_xml:get_attribute_as_list(Child, <<"name">>, false),
ListName = exmpp_xml:get_attribute_as_binary(Child, <<"name">>, false),
case Name of
list ->
process_list_set(LUser, LServer, ListName,
@@ -373,15 +366,17 @@ process_iq_set(_, From, _To, #iq{payload = SubEl}) ->
end;
_ ->
{error, 'bad-request'}
end.
end;
process_iq_set(Acc, _, _, _) ->
Acc.
process_default_set(LUser, LServer, false) ->
LServerB = list_to_binary(LServer),
F = fun() ->
gen_storage:delete(LServerB, {privacy_default_list, {LUser, LServer}})
gen_storage:delete(LServer, {privacy_default_list, {LUser, LServer}})
end,
case gen_storage:transaction(LServerB, privacy_default_list, F) of
case gen_storage:transaction(LServer, privacy_default_list, F) of
{atomic, _} ->
{result, []};
_ ->
@@ -389,21 +384,20 @@ process_default_set(LUser, LServer, false) ->
end;
process_default_set(LUser, LServer, Name) ->
LServerB = list_to_binary(LServer),
F = fun() ->
case gen_storage:select(LServerB, privacy_list,
case gen_storage:select(LServer, privacy_list,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]) of
[] ->
{error, 'item-not-found'};
[#privacy_list{}] ->
gen_storage:write(LServerB,
gen_storage:write(LServer,
#privacy_default_list{user_host = {LUser, LServer},
name = Name}),
{result, []}
end
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, {result, _} = Res} ->
@@ -417,13 +411,12 @@ process_active_set(_LUser, _LServer, false) ->
{result, [], #userlist{}};
process_active_set(LUser, LServer, Name) ->
LServerB = list_to_binary(LServer),
F = fun() ->
case gen_storage:select(LServerB, privacy_list,
case gen_storage:select(LServer, privacy_list,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]) of
[#privacy_list{}] ->
Data = gen_storage:select(LServerB, privacy_list_data,
Data = gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]),
List = list_data_to_items(Data),
@@ -435,7 +428,7 @@ process_active_set(LUser, LServer, Name) ->
{error, 'item-not-found'}
end
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{atomic, Res} ->
Res;
_ ->
@@ -448,27 +441,26 @@ process_list_set(_LUser, _LServer, false, _Els) ->
{error, 'bad-request'};
process_list_set(LUser, LServer, Name, Els) ->
LServerB = list_to_binary(LServer),
case parse_items(Els) of
false ->
{error, 'bad-request'};
remove ->
F = fun() ->
case gen_storage:read(LServerB,
case gen_storage:read(LServer,
{privacy_default_list, {LUser, LServer}}) of
[#privacy_default_list{name = Default}] when Name == Default ->
{error, 'conflict'};
_ ->
gen_storage:delete_where(LServerB, privacy_list,
gen_storage:delete_where(LServer, privacy_list,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]),
gen_storage:delete_where(LServerB, privacy_list_data,
gen_storage:delete_where(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]),
{result, []}
end
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, {result, _} = Res} ->
@@ -486,24 +478,24 @@ process_list_set(LUser, LServer, Name, Els) ->
List ->
F = fun() ->
OldData =
gen_storage:select(LServerB, privacy_list_data,
gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Name}]),
lists:foreach(
fun(Data1) ->
gen_storage:delete_object(LServerB, Data1)
gen_storage:delete_object(LServer, Data1)
end, OldData),
gen_storage:write(LServerB, #privacy_list{user_host = {LUser, LServer},
gen_storage:write(LServer, #privacy_list{user_host = {LUser, LServer},
name = Name}),
NewData = list_items_to_data(LUser, LServer, Name, List),
lists:foreach(
fun(Data1) ->
gen_storage:write(LServerB, Data1)
gen_storage:write(LServer, Data1)
end, NewData),
{result, []}
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, {result, _} = Res} ->
@@ -656,17 +648,15 @@ is_list_needdb(Items) ->
end
end, Items).
get_user_list(_, User, LServerB)
when is_binary(User), is_binary(LServerB) ->
LUser = binary_to_list(User),
LServer = binary_to_list(LServerB),
get_user_list(_, LUser, LServer)
when is_binary(LUser), is_binary(LServer) ->
F = fun() ->
case gen_storage:read(LServerB,
case gen_storage:read(LServer,
{privacy_default_list, {LUser, LServer}}) of
[] ->
#userlist{};
[#privacy_default_list{name = Default}] ->
Data = gen_storage:select(LServerB, privacy_list_data,
Data = gen_storage:select(LServer, privacy_list_data,
[{'=', user_host, {LUser, LServer}},
{'=', name, Default}]),
List = list_data_to_items(Data),
@@ -676,7 +666,7 @@ get_user_list(_, User, LServerB)
list = List}
end
end,
{atomic, Res} = gen_storage:transaction(LServerB, privacy_default_list, F),
{atomic, Res} = gen_storage:transaction(LServer, privacy_default_list, F),
Res.
@@ -789,16 +779,15 @@ is_type_match(group, Value, _JID, _Subscription, Groups) ->
%% The ejabberd hook provides the arguments as binaries,
%% but the mod_privacy internal functions provide them as strings.
%% Once this module stores information as binaries, this incoherence will be solved.
remove_user(User, Server) when is_binary(User) and is_binary(Server) ->
remove_user(binary_to_list(User), binary_to_list(Server));
remove_user(User, Server) when is_list(User) and is_list(Server) ->
remove_user(list_to_binary(User), list_to_binary(Server));
remove_user(User, Server) when is_binary(User) and is_binary(Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
LServerB = list_to_binary(LServer),
F = fun() ->
gen_storage:delete(LServerB, {privacy_list, {LUser, LServer}})
gen_storage:delete(LServer, {privacy_list, {LUser, LServer}})
end,
case gen_storage:transaction(LServerB, privacy_list, F) of
case gen_storage:transaction(LServer, privacy_list, F) of
{atomic, _} ->
{result, []};
_ ->
@@ -823,9 +812,11 @@ update_tables(Host, mnesia) ->
gen_storage_migration:migrate_mnesia(
Host, privacy_default_list,
[{privacy, [us, default, lists],
fun({privacy, US, Default, Lists}) ->
fun({privacy, {U, S}, Default, Lists}) ->
US = {list_to_binary(U), list_to_binary(S)},
lists:foreach(
fun({Name, List}) ->
NameBin = list_to_binary(Name),
lists:foreach(
fun(#listitem{type = Type,
value = Value,
@@ -839,7 +830,7 @@ update_tables(Host, mnesia) ->
ValueBin = convert_value_to_binary(Value),
gen_storage:write(HostB,
#privacy_list_data{user_host = US,
name = Name,
name = NameBin,
type = Type,
value = ValueBin,
action = Action,
@@ -852,12 +843,13 @@ update_tables(Host, mnesia) ->
end, List),
gen_storage:write(HostB,
#privacy_list{user_host = US,
name = Name})
name = NameBin})
end, Lists),
if
is_list(Default) ->
DefaultBin = list_to_binary(Default),
#privacy_default_list{user_host = US,
name = Default};
name = DefaultBin};
true -> null
end
end}]);
+10
View File
@@ -19,10 +19,19 @@
%%%
%%%----------------------------------------------------------------------
-record(privacy_list, {user_host, name}).
-record(privacy_default_list, {user_host, name}).
-record(privacy_list_data, {user_host, name,
type, value, action, order,
match_all, match_iq, match_message,
match_presence_in, match_presence_out}).
%% ejabberd 2 format:
-record(privacy, {user_host,
default = none,
lists = []}).
%% ejabberd 2 format:
-record(listitem, {type = none,
value = none,
action,
@@ -35,3 +44,4 @@
}).
-record(userlist, {name = none, list = [], needdb = false }).
+86 -51
View File
@@ -594,10 +594,10 @@ send_loop(State) ->
lists:foreach(
fun({Node, subscribed, _, SubJID}) ->
if (SubJID == LJID) or (SubJID == BJID) ->
#pubsub_node{id = {H, NodeId}, type = Type, idx = NodeIdx, options = Options} = Node,
#pubsub_node{id = {H, NodeId}, type = Type, idx = Nidx, options = Options} = Node,
case get_option(Options, 'send_last_published_item') of
'on_sub_and_presence' ->
send_items(H, NodeId, NodeIdx, Type, LJID, 'last');
send_items(H, NodeId, Nidx, Type, LJID, 'last');
_ ->
ok
end;
@@ -646,7 +646,7 @@ send_loop(State) ->
spawn(fun() ->
Host = State#state.host,
Owner = {U,S,undefined},
lists:foreach(fun(#pubsub_node{id = {_, NodeId}, type = Type, idx = NodeIdx, options = Options}) ->
lists:foreach(fun(#pubsub_node{id = {_, NodeId}, type = Type, idx = Nidx, options = Options}) ->
case get_option(Options, 'send_last_published_item') of
'on_sub_and_presence' ->
lists:foreach(fun(Resource) ->
@@ -660,7 +660,7 @@ send_loop(State) ->
RosterGroups = get_option(Options, 'roster_groups_allowed', []),
element(2, get_roster_info(U, S, LJID, RosterGroups))
end,
if Subscribed -> send_items(Owner, NodeId, NodeIdx, Type, LJID, 'last');
if Subscribed -> send_items(Owner, NodeId, Nidx, Type, LJID, 'last');
true -> ok
end
end, Resources);
@@ -763,8 +763,8 @@ disco_identity(_Host, <<>> = _NodeId, _From) ->
[#xmlel{name = 'identity', ns = ?NS_DISCO_INFO,
attrs = [?XMLATTR(<<"category">>, <<"pubsub">>), ?XMLATTR(<<"type">>, <<"pep">>)]}];
disco_identity(#jid{node = U, domain = S, resource = R} = Host, NodeId, From) ->
Action = fun(#pubsub_node{idx = NodeIdx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) of
Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} ->
{result,
[#xmlel{name = 'identity', ns = ?NS_DISCO_INFO,
@@ -813,8 +813,8 @@ disco_features(_Host, <<>> = _NodeId, _From) ->
[?NS_PUBSUB_s
| [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]];
disco_features(#jid{node = U, domain = S, resource = R} = Host, NodeId, From) ->
Action = fun(#pubsub_node{idx = NodeIdx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) of
Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} ->
{result, [?NS_PUBSUB_s
| [?NS_PUBSUB_s ++ "#" ++ Feature || Feature <- features("pep")]]};
@@ -853,8 +853,8 @@ disco_sm_items({result, OtherItems} = _Acc, From, To, NodeId, _Lang) ->
).
disco_items(#jid{raw = JID, node = U, domain = S, resource = R} = Host, <<>>, From) ->
Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = NodeIdx, owners = Owners}, Acc) ->
case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) of
Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx, owners = Owners}, Acc) ->
case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} ->
[#xmlel{name = 'item', ns = ?NS_DISCO_INFO,
attrs = [?XMLATTR(<<"jid">>, JID),
@@ -873,8 +873,8 @@ disco_items(#jid{raw = JID, node = U, domain = S, resource = R} = Host, <<>>, Fr
end;
disco_items(#jid{raw = JID, node = U, domain = S, resource = R} = Host, NodeId, From) ->
Action = fun(#pubsub_node{idx = NodeIdx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) of
Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, Items} ->
{result,
[#xmlel{name = 'item', ns = ?NS_DISCO_INFO,
@@ -1331,11 +1331,11 @@ command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING_b = _NodeId, _From) ->
).
node_disco_info(Host, NodeId, From) ->
Action = fun(#pubsub_node{type = Plugin, idx = NodeIdx}) ->
Action = fun(#pubsub_node{type = Plugin, idx = Nidx}) ->
Types = case tree_call(Host, get_subnodes, [Host, NodeId, From]) of
[] -> ["leaf"];
_ ->
case node_call(Plugin, get_items, [NodeIdx, From]) of
case node_call(Plugin, get_items, [Nidx, From]) of
{result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"];
_ -> []
@@ -1449,8 +1449,8 @@ iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING_b = _NodeId, _From) ->
%% TODO
{result, []};
iq_disco_items(Host, NodeId, From) ->
Action = fun(#pubsub_node{idx = NodeIdx, type = Type, options = Options, owners = Owners}) ->
NodeItems = case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) of
Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
NodeItems = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, R} -> R;
_ -> []
end,
@@ -2417,9 +2417,12 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
Features = features(Type),
PublishFeature = lists:member("publish", Features),
PublishModel = get_option(Options, publish_model),
MaxItems = max_items(Host, Options),
DeliverPayloads = get_option(Options, deliver_payloads),
PersistItems = get_option(Options, persist_items),
MaxItems = case PersistItems of
0 -> 0;
1 -> max_items(Host, Options)
end,
{PayloadCount, PayloadNS} = payload_els_ns(Payload),
PayloadSize = size(term_to_binary(Payload))-2, % size(term_to_binary([])) == 2
PayloadMaxSize = get_option(Options, max_payload_size),
@@ -2698,8 +2701,8 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIds) ->
).
get_items(Host, NodeId) ->
Action = fun(#pubsub_node{type = Type, idx = NodeIdx}) ->
node_call(Type, get_items, [NodeIdx, service_jid(Host)])
Action = fun(#pubsub_node{type = Type, idx = Nidx}) ->
node_call(Type, get_items, [Nidx, service_jid(Host)])
end,
case transaction(Host, NodeId, Action, sync_dirty) of
{result, {_, Items}} -> Items
@@ -2716,8 +2719,8 @@ get_items(Host, NodeId) ->
).
get_item(Host, NodeId, ItemId) ->
Action = fun(#pubsub_node{type = Type, idx = NodeIdx}) ->
node_call(Type, get_item, [NodeIdx, ItemId])
Action = fun(#pubsub_node{type = Type, idx = Nidx}) ->
node_call(Type, get_item, [Nidx, ItemId])
end,
case transaction(Host, NodeId, Action, sync_dirty) of
{result, {_, Items}} -> Items;
@@ -2733,19 +2736,32 @@ get_item(Host, NodeId, ItemId) ->
%% Number = last | integer()
%% @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') ->
case get_cached_item(Host, NodeId) of
send_items(Host, Node, Nidx, Type, {U,S,R} = LJID, 'last') ->
case get_cached_item(Host, Nidx) of
undefined ->
send_items(Host, Node, NodeId, Type, LJID, 1);
send_items(Host, Node, Nidx, Type, LJID, 1);
LastItem ->
{ModifNow, ModifUSR} = LastItem#pubsub_item.modification,
Stanza = event_stanza_with_delay(
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'items', attrs = nodeAttr(Node),
children = itemsEls([LastItem])}], ModifNow, ModifUSR),
ejabberd_router:route(service_jid(Host), exmpp_jid:make(LJID), Stanza)
case is_tuple(Host) of
false ->
ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza);
true ->
case ejabberd_sm:get_session_pid(U,S,R) of
C2SPid when is_pid(C2SPid) ->
ejabberd_c2s:broadcast(C2SPid,
{pep_message, << Node/binary, <<"+notify">>/binary >>},
_Sender = service_jid(Host),
Stanza);
_ ->
ok
end
end
end;
send_items(Host, Node, NodeId, Type, {LU, LS, LR} = LJID, Number) ->
ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of
send_items(Host, Node, Nidx, Type, {U,S,R} = LJID, Number) ->
ToSend = case node_action(Host, Type, get_items, [Nidx, LJID]) of
{result, []} ->
[];
{result, Items} ->
@@ -2767,7 +2783,20 @@ send_items(Host, Node, NodeId, Type, {LU, LS, LR} = LJID, Number) ->
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'items', attrs = nodeAttr(Node), children =
itemsEls(ToSend)}])
end,
ejabberd_router:route(service_jid(Host), exmpp_jid:make(LU, LS, LR), Stanza).
case is_tuple(Host) of
false ->
ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza);
true ->
case ejabberd_sm:get_session_pid(U,S,R) of
C2SPid when is_pid(C2SPid) ->
ejabberd_c2s:broadcast(C2SPid,
{pep_message, << Node/binary, <<"+notify">>/binary >>},
_Sender = service_jid(Host),
Stanza);
_ ->
ok
end
end.
%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response}
%% Host = host()
@@ -2926,7 +2955,7 @@ get_options(Host, Node, JID, SubId, Lang) ->
Error -> Error
end.
get_options_helper(JID, Lang, Node, NodeId, SubId, Type) ->
get_options_helper(JID, Lang, Node, Nidx, SubId, Type) ->
Subscriber = try exmpp_jid:parse(JID) of
J -> jlib:short_jid(J)
catch
@@ -2934,7 +2963,7 @@ get_options_helper(JID, Lang, Node, NodeId, SubId, Type) ->
exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of ""
end,
{result, Subs} = node_call(Type, get_subscriptions,
[NodeId, Subscriber]),
[Nidx, Subscriber]),
SubIds = lists:foldl(fun({subscribed, SID}, Acc) ->
[SID | Acc];
(_, Acc) ->
@@ -2944,17 +2973,15 @@ get_options_helper(JID, Lang, Node, NodeId, SubId, Type) ->
{_, []} ->
{error, extended_error('not-acceptable', "not-subscribed")};
{[], [SID]} ->
read_sub(Subscriber, Node, NodeId, SID, Lang);
read_sub(Subscriber, Node, Nidx, SID, Lang);
{[], _} ->
{error, extended_error('not-acceptable', "subid-required")};
{_, _} ->
read_sub(Subscriber, Node, NodeId, SubId, Lang)
read_sub(Subscriber, Node, Nidx, SubId, Lang)
end.
read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
case pubsub_subscription:get_subscription(Subscriber, NodeId, SubId) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
read_sub(Subscriber, Node, Nidx, SubId, Lang) ->
case pubsub_subscription:get_subscription(Subscriber, Nidx, SubId) of
{result, #pubsub_subscription{options = Options}} ->
{result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options),
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
@@ -2962,6 +2989,12 @@ read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)],
children = [XdataEl]},
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
{result, PubsubEl};
_ ->
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
attrs = [?XMLATTR(<<"jid">>, exmpp_jid:to_binary(Subscriber)),
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)]},
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
{result, PubsubEl}
end.
@@ -2982,7 +3015,7 @@ set_options(Host, Node, JID, SubId, Configuration) ->
Error -> Error
end.
set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
set_options_helper(Configuration, JID, Nidx, SubId, Type) ->
SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of
{result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid
@@ -2993,7 +3026,7 @@ set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
_ -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of ""
end,
{result, Subs} = node_call(Type, get_subscriptions,
[NodeId, Subscriber]),
[Nidx, Subscriber]),
SubIds = lists:foldl(fun({subscribed, SID}, Acc) ->
[SID | Acc];
(_, Acc) ->
@@ -3003,21 +3036,23 @@ set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
{_, []} ->
{error, extended_error('not-acceptable', "not-subscribed")};
{[], [SID]} ->
write_sub(Subscriber, NodeId, SID, SubOpts);
write_sub(Subscriber, Nidx, SID, SubOpts);
{[], _} ->
{error, extended_error('not-acceptable', "subid-required")};
{_, _} ->
write_sub(Subscriber, NodeId, SubId, SubOpts)
write_sub(Subscriber, Nidx, SubId, SubOpts)
end.
write_sub(_Subscriber, _NodeId, _SubId, invalid) ->
write_sub(_Subscriber, _Nidx, _SubId, invalid) ->
{error, extended_error('bad-request', "invalid-options")};
write_sub(Subscriber, NodeId, SubId, Options) ->
case pubsub_subscription:set_subscription(Subscriber, NodeId, SubId, Options) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
write_sub(_Subscriber, _Nidx, _SubId, []) ->
{result, []};
write_sub(Subscriber, Nidx, SubId, Options) ->
case pubsub_subscription:set_subscription(Subscriber, Nidx, SubId, Options) of
{result, _} ->
{result, []}
{result, []};
{error, _} ->
{error, extended_error('not-acceptable', "invalid-subid")}
end.
%% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response}
@@ -3600,18 +3635,18 @@ node_subscriptions_full(Host, Node, NotifyType) ->
{_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth),
JIDSubs.
sub_with_options(#pubsub_node{type = Type, id = NodeId}) ->
case node_call(Type, get_node_subscriptions, [NodeId]) of
sub_with_options(#pubsub_node{type = Type, idx = Nidx}) ->
case node_call(Type, get_node_subscriptions, [Nidx]) of
{result, Subs} ->
lists:foldl(
fun({JID, subscribed, SubId}, Acc) -> [sub_with_options(JID, NodeId, SubId) | Acc];
fun({JID, subscribed, SubId}, Acc) -> [sub_with_options(JID, Nidx, SubId) | Acc];
(_, Acc) -> Acc
end, [], Subs);
_ ->
[]
end.
sub_with_options(JID, NodeId, SubId) ->
case pubsub_subscription:read_subscription(JID, NodeId, SubId) of
sub_with_options(JID, Nidx, SubId) ->
case pubsub_subscription:read_subscription(JID, Nidx, SubId) of
#pubsub_subscription{options = Options} -> {JID, SubId, Options};
_ -> {JID, SubId, []}
end.
+12 -6
View File
@@ -2758,8 +2758,6 @@ get_options_helper(JID, Lang, Node, NodeId, SubId, Type) ->
read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
case pubsub_subscription_odbc:get_subscription(Subscriber, NodeId, SubId) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
{result, #pubsub_subscription{options = Options}} ->
{result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options),
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
@@ -2767,6 +2765,12 @@ read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)],
children = [XdataEl]},
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
{result, PubsubEl};
_ ->
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
attrs = [?XMLATTR(<<"jid">>, exmpp_jid:to_binary(Subscriber)),
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)]},
PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]},
{result, PubsubEl}
end.
@@ -2817,12 +2821,14 @@ set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
write_sub(_Subscriber, _NodeId, _SubId, invalid) ->
{error, extended_error('bad-request', "invalid-options")};
write_sub(_Subscriber, _NodeID, _SubID, []) ->
{result, []};
write_sub(Subscriber, NodeId, SubId, Options) ->
case pubsub_subscription_odbc:set_subscription(Subscriber, NodeId, SubId, Options) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
{result, _} ->
{result, []}
{result, []};
{error, _} ->
{error, extended_error('not-acceptable', "invalid-subid")}
end.
%% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response}
@@ -3288,7 +3294,7 @@ broadcast({U, S, R}, Node, NodeId, Type, NodeOptions, Subscriptions, Stanza, SHI
%% set the from address on the notification to the bare JID of the account owner
%% Also, add "replyto" if entity has presence subscription to the account owner
%% See XEP-0163 1.1 section 4.3.1
Event = {pep_message, binary_to_list(Node)++"+notify"},
Event = {pep_message, << Node/binary, <<"+notify">>/binary >>},
Message = case get_option(NodeOptions, notification_type, headline) of
normal -> Stanza;
MsgType -> add_message_type(Stanza, atom_to_list(MsgType))
+9 -6
View File
@@ -107,9 +107,11 @@ init(_Host, _ServerHost, _Opts) ->
pubsub_subscription:init(),
mnesia:create_table(pubsub_state,
[{disc_copies, [node()]},
{index, [nodeidx]},
{attributes, record_info(fields, pubsub_state)}]),
mnesia:create_table(pubsub_item,
[{disc_only_copies, [node()]},
{index, [nodeidx]},
{attributes, record_info(fields, pubsub_item)}]),
ItemsFields = record_info(fields, pubsub_item),
case mnesia:table_info(pubsub_item, attributes) of
@@ -234,7 +236,7 @@ create_node_permission(Host, ServerHost, _NodeId, _ParentNodeId, #jid{node = U,
).
create_node(NodeIdx, #jid{node = U, domain = S} = _JID) ->
set_state(#pubsub_state{id = {{U,S,undefined}, NodeIdx}, affiliation = 'owner'}),
set_state(#pubsub_state{id = {{U,S,undefined}, NodeIdx}, nodeidx = NodeIdx, affiliation = 'owner'}),
{'result', {'default', 'broadcast'}}.
%% @spec (Removed) -> ok
@@ -557,6 +559,7 @@ publish_item(NodeIdx, #jid{node = U, domain = S, resource = R} = _JID, PublishMo
_ ->
#pubsub_item{
id = {ItemId, NodeIdx},
nodeidx = NodeIdx,
creation = {Now, GenKey}, % TODO, better use {Now, SubKey} ?
modification = Modification,
payload = Payload}
@@ -648,10 +651,10 @@ delete_item(NodeIdx, #jid{node = U, domain = S} = _JID, PublishModel, ItemId) ->
false ->
case Affiliation of
'owner' ->
%% Owner can delete other publishers items as well
%% Owner can delete any items from its own node
{'result', States} = get_states(NodeIdx),
lists:foldl(fun
(#pubsub_state{items = ItemIds, affiliation = publisher} = State, Result) ->
(#pubsub_state{items = ItemIds} = State, Result) ->
case lists:member(ItemId, ItemIds) of
true ->
del_item(NodeIdx, ItemId),
@@ -1024,7 +1027,7 @@ end.
get_states(NodeIdx) ->
States = case
catch mnesia:match_object(#pubsub_state{id = {'_', NodeIdx}, _ = '_'})
catch mnesia:index_read(pubsub_state, NodeIdx, #pubsub_state.nodeidx)
of
PubsubStates when is_list(PubsubStates) -> PubsubStates; %% is_list(PubsubStates) useful ?
_ -> []
@@ -1046,7 +1049,7 @@ get_states(NodeIdx) ->
get_state(NodeIdx, Entity) ->
case catch mnesia:read({pubsub_state, {Entity, NodeIdx}}) of
[#pubsub_state{} = State] -> State;
_ -> #pubsub_state{id = {Entity, NodeIdx}}
_ -> #pubsub_state{id = {Entity, NodeIdx}, nodeidx=NodeIdx}
end.
%% @spec (State) -> ok | {error, Reason::stanzaError()}
@@ -1094,7 +1097,7 @@ del_state(NodeIdx, Entity) ->
).
get_items(NodeIdx, _Entity) ->
Items = mnesia:match_object(#pubsub_item{id = {'_', NodeIdx}, _ = '_'}),
Items = mnesia:index_read(pubsub_item, NodeIdx, #pubsub_item.nodeidx),
{result, lists:reverse(lists:keysort(#pubsub_item.modification, Items))}.
+6 -2
View File
@@ -307,8 +307,9 @@
-type(pubsubNode() :: #pubsub_node{}).
%%% @type pubsubState() = {pubsub_state, Id, Items, Affiliation, Subscriptions}
%%% @type pubsubState() = {pubsub_state, Id, NodeIdx, Items, Affiliation, Subscriptions}
%%% Id = {fullUsr(), nodeIdx()}
%%% NodeIdx = nodeIdx(),
%%% Items = [itemId()]
%%% Affiliation = affiliation()
%%% Subscriptions = [{subscription(), subId()}].
@@ -319,6 +320,7 @@
-record(pubsub_state,
{
id :: {fullUsr(), nodeIdx()},
nodeidx :: nodeIdx(),
items = [] :: [itemId()],
affiliation = 'none' :: affiliation(),
subscriptions = [] :: [{subscription(), subId()}]
@@ -327,8 +329,9 @@
-type(pubsubState() :: #pubsub_state{}).
%%% @type pubsubItem() = {pubsub_item, Id, Creation, Modification, Payload}
%%% @type pubsubItem() = {pubsub_item, Id, NodeIdx, Creation, Modification, Payload}
%%% Id = {itemId(), nodeIdx()}
%%% NodeIdx = nodeIdx()
%%% Creation = {now(), bareUsr()}
%%% Modification = {now(), fullUsr()}
%%% Payload = payload().
@@ -339,6 +342,7 @@
-record(pubsub_item,
{
id :: {itemId(), nodeIdx()},
nodeidx :: nodeIdx(),
creation = {unknown,unknown} :: {now(), bareUsr()},
modification = {unknown,unknown} :: {now(), fullUsr()},
payload = [] :: payload()
-3
View File
@@ -38,9 +38,6 @@ read_subscription(SubId) ->
["select opt_name, opt_value "
"from pubsub_subscription_opt "
"where subid = '", ejabberd_odbc:escape(SubId), "'"]) of
{selected, ["opt_name", "opt_value"], []} ->
notfound;
{selected, ["opt_name", "opt_value"], Options} ->
{ok, #pubsub_subscription{subid = SubId,
+20 -22
View File
@@ -1,5 +1,5 @@
--- mod_pubsub.erl 2011-02-21 15:11:24.000000000 +0100
+++ mod_pubsub_odbc.erl 2011-02-21 15:12:03.000000000 +0100
--- mod_pubsub.erl 2011-03-23 09:31:16.000000000 +0100
+++ mod_pubsub_odbc.erl 2011-03-23 09:51:43.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.
@@ -705,21 +705,19 @@
end, FilteredEntities),
{result, []};
_ ->
@@ -2952,11 +2757,11 @@
@@ -2952,9 +2757,9 @@
end.
read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
- case pubsub_subscription:get_subscription(Subscriber, NodeId, SubId) of
+ case pubsub_subscription_odbc:get_subscription(Subscriber, NodeId, SubId) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
{result, #pubsub_subscription{options = Options}} ->
- {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options),
+ {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options),
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
attrs = [ ?XMLATTR(<<"jid">>, exmpp_jid:to_binary(Subscriber)),
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)],
@@ -2983,7 +2788,7 @@
@@ -2987,7 +2792,7 @@
end.
set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
@@ -728,16 +726,16 @@
{result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid
end,
@@ -3013,7 +2818,7 @@
write_sub(_Subscriber, _NodeId, _SubId, invalid) ->
{error, extended_error('bad-request', "invalid-options")};
@@ -3019,7 +2824,7 @@
write_sub(_Subscriber, _NodeID, _SubID, []) ->
{result, []};
write_sub(Subscriber, NodeId, SubId, Options) ->
- case pubsub_subscription:set_subscription(Subscriber, NodeId, SubId, Options) of
+ case pubsub_subscription_odbc:set_subscription(Subscriber, NodeId, SubId, Options) of
{error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")};
{result, _} ->
@@ -3187,8 +2992,8 @@
{result, []};
{error, _} ->
@@ -3193,8 +2998,8 @@
?XMLATTR(<<"subsription">>, subscription_to_string(Sub)) | nodeAttr(Node)]}]}]},
ejabberd_router:route(service_jid(Host), JID, Stanza)
end,
@@ -748,7 +746,7 @@
true ->
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
@@ -3542,7 +3347,7 @@
@@ -3548,7 +3353,7 @@
Collection = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]),
{result, [{Depth, [{N, sub_with_options(N)} || N <- Nodes]} || {Depth, Nodes} <- Collection]}
end,
@@ -757,7 +755,7 @@
{result, CollSubs} -> subscribed_nodes_by_jid(NotifyType, CollSubs);
_ -> []
end.
@@ -3611,8 +3416,8 @@
@@ -3617,8 +3422,8 @@
[]
end.
sub_with_options(JID, NodeId, SubId) ->
@@ -768,7 +766,7 @@
_ -> {JID, SubId, []}
end.
@@ -3724,6 +3529,30 @@
@@ -3730,6 +3535,30 @@
Result
end.
@@ -799,7 +797,7 @@
%% @spec (Host, Options) -> MaxItems
%% Host = host()
%% Options = [Option]
@@ -4247,9 +4076,14 @@
@@ -4253,9 +4082,14 @@
tree_action(Host, Function, Args) ->
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
@@ -817,7 +815,7 @@
%% @doc <p>node plugin call.</p>
-spec(node_call/3 ::
@@ -4287,7 +4121,7 @@
@@ -4293,7 +4127,7 @@
node_action(Host, Type, Function, Args) ->
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
@@ -826,7 +824,7 @@
node_call(Type, Function, Args)
end, sync_dirty).
@@ -4302,7 +4136,7 @@
@@ -4308,7 +4142,7 @@
).
transaction(Host, NodeId, Action, Trans) ->
@@ -835,7 +833,7 @@
case tree_call(Host, get_node, [Host, NodeId]) of
#pubsub_node{} = Node ->
case Action(Node) of
@@ -4316,7 +4150,7 @@
@@ -4322,7 +4156,7 @@
end, Trans).
@@ -844,7 +842,7 @@
(
Host :: string() | host(),
Action :: fun(),
@@ -4324,21 +4158,28 @@
@@ -4330,21 +4164,28 @@
-> {'result', Nodes :: [] | [Node::pubsubNode()]}
).
@@ -878,7 +876,7 @@
{result, Result} -> {result, Result};
{error, Error} -> {error, Error};
{atomic, {result, Result}} -> {result, Result};
@@ -4346,6 +4187,15 @@
@@ -4352,6 +4193,15 @@
{aborted, Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
{error, 'internal-server-error'};
@@ -894,7 +892,7 @@
{'EXIT', Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
{error, 'internal-server-error'};
@@ -4354,6 +4204,16 @@
@@ -4360,6 +4210,16 @@
{error, 'internal-server-error'}
end.
+6 -7
View File
@@ -223,6 +223,8 @@ create_table() ->
-> SubId::subId()
).
add_subscription(_JID, _NodeID, []) ->
make_subid();
add_subscription(_Entity, _NodeIdx, Options) ->
SubId = make_subid(),
mnesia:write(#pubsub_subscription{subid = SubId, options = Options}),
@@ -262,14 +264,11 @@ read_subscription(_Entity, _NodeIdx, SubId) ->
NodeIdx :: nodeIdx(),
SubId :: subId(),
Options :: [nodeOption()])
-> 'ok' | {'error', 'notfound'}
).
-> 'ok'
).
write_subscription(Entity, NodeIdx, SubId, Options) ->
case read_subscription(Entity, NodeIdx, SubId) of
{error, 'notfound'} -> {error, 'notfound'};
Subscription -> mnesia:write(Subscription#pubsub_subscription{options = Options})
end.
write_subscription(_Entity, _NodeIdx, SubId, Options) ->
mnesia:write(#pubsub_subscription{subid = SubId, options = Options}).
-spec(make_subid/0 :: () -> SubId::subId()).
+4 -2
View File
@@ -108,8 +108,10 @@ process_iq(From, To,
PTag = exmpp_xml:get_element(SubEl, 'password'),
RTag = exmpp_xml:get_element(SubEl, 'remove'),
Server = exmpp_jid:prep_domain_as_list(To),
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
AllowRemove = (allow == acl:match_rule(Server, Access, From)),
if
(UTag /= undefined) and (RTag /= undefined) ->
(UTag /= undefined) and (RTag /= undefined) and AllowRemove ->
User = exmpp_xml:get_cdata_as_list(UTag),
case {exmpp_jid:node_as_list(From), exmpp_jid:prep_domain_as_list(From)} of
{User, Server} ->
@@ -144,7 +146,7 @@ process_iq(From, To,
exmpp_iq:error(IQ_Rec, 'bad-request')
end
end;
(UTag == undefined) and (RTag /= undefined) ->
(UTag == undefined) and (RTag /= undefined) and AllowRemove ->
case {exmpp_jid:node_as_list(From),
exmpp_jid:prep_domain_as_list(From),
exmpp_jid:resource_as_list(From)}of
+11 -14
View File
@@ -258,8 +258,7 @@ roster_version_on_db(Host) ->
get_versioning_feature(Acc, Host) ->
case roster_versioning_enabled(Host) of
true ->
Feature = exmpp_xml:element(?NS_ROSTER_VER_s, 'ver', [],
[exmpp_xml:element(?NS_ROSTER_VER_s, 'optional')]),
Feature = exmpp_xml:element(?NS_ROSTER_VER_s, 'ver'),
[Feature | Acc];
false -> []
end.
@@ -658,10 +657,18 @@ push_item(User, Server, From, Item)
%% Item = rosteritem()
% TODO: don't push to those who didn't load roster
push_item(User, Server, Resource, From, Item)
push_item(User, Server, Resource, From, Item) ->
push_item(User, Server, Resource, From, Item, not_found).
push_item(User, Server, Resource, From, Item, RosterVersion)
when is_binary(User), is_binary(Server), is_binary(Resource),
?IS_JID(From) ->
ExtraAttrs = case RosterVersion of
not_found -> [];
_ -> [?XMLATTR(<<"ver">>, RosterVersion)]
end,
Request = #xmlel{ns = ?NS_ROSTER, name = 'query',
attrs = ExtraAttrs,
children = [item_to_xml(Item)]},
ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request,
"push" ++ randoms:get_string()),
@@ -674,19 +681,9 @@ push_item(User, Server, Resource, From, Item)
%% TODO: don't push to those who didn't load roster
push_item_version(Server, User, From, Item, RosterVersion) ->
lists:foreach(fun(Resource) ->
push_item_version(User, Server, Resource, From, Item, RosterVersion)
push_item(User, Server, Resource, From, Item, RosterVersion)
end, ejabberd_sm:get_user_resources(User, Server)).
push_item_version(User, Server, Resource, From, Item, RosterVersion) ->
Request = #xmlel{ns = ?NS_ROSTER, name = 'query', attrs = [?XMLATTR(<<"ver">>, RosterVersion)],
children = [mod_roster:item_to_xml(Item)]},
ResIQ = exmpp_iq:set(?NS_JABBER_CLIENT, Request,
"push" ++ randoms:get_string()),
ejabberd_router:route(
From,
exmpp_jid:make(User, Server, Resource),
ResIQ).
%% @spec (Ignored, User, Server) -> Subscription_Lists
%% Ignored = term()
%% User = binary()
+1 -1
View File
@@ -300,7 +300,7 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
%% For a given user, map all his shared roster contacts to groups they are
%% members of. Skip the user himself iff SkipUS is true.
%% members of. Skip the user himself if SkipUS is true.
get_user_to_groups_map({_, Server} = US, SkipUS) ->
DisplayedGroups = get_user_displayed_groups(US),
lists:foldl(
+37 -25
View File
@@ -29,6 +29,12 @@
%%% 2.1.x / mnesia / vcard
%%% us = {Username::string(), Host::string()}
%%% vcard = xmlelement()
%%% 2.1.x / mnesia / vcard_search
%%% us = {Username::string(), Host::string()}
%%% user = {Username::string(), Host::string()}
%%% luser = Username::string()
%%% fn = string()
%%% ... = string()
%%%
%%% 2.1.x / odbc / vcard
%%% username = varchar250
@@ -42,8 +48,14 @@
%%% Same as 2.1.x
%%%
%%% 3.0.0-alpha / mnesia / vcard
%%% user_host = {Username::string(), Host::string()}
%%% user_host = {Username::binary(), Host::binary()}
%%% vcard = xmlel()
%%% 3.0.0-alpha / mnesia / vcard_search
%%% user_host = {Username::binary(), Host::binary()}
%%% username = string()
%%% lusername = string()
%%% fn = string()
%%% ... = string()
%%%
%%% 3.0.0-alpha / odbc / vcard
%%% user = varchar150
@@ -231,12 +243,12 @@ process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
exmpp_iq:result(IQ_Rec)
end;
process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) ->
User = exmpp_jid:node_as_list(From),
LServer = exmpp_jid:prep_domain_as_list(From),
LServerB = exmpp_jid:prep_domain(From),
case ?IS_MY_HOST(LServer) of
User = exmpp_jid:node(From),
Server = exmpp_jid:prep_domain(From),
ServerS = exmpp_jid:prep_domain_as_list(From),
case ?IS_MY_HOST(ServerS) of
true ->
set_vcard(User, LServer, LServerB, Request),
set_vcard(User, Server, Request),
exmpp_iq:result(IQ_Rec);
false ->
exmpp_iq:error(IQ_Rec, 'not-allowed')
@@ -258,7 +270,7 @@ get_vcard(User, Host) ->
end.
set_vcard(User, LServer, LServerB, VCARD) ->
set_vcard(User, Server, VCARD) ->
FN = exmpp_xml:get_path(VCARD,
[{element, 'FN'}, cdata_as_list]),
Family = exmpp_xml:get_path(VCARD,
@@ -291,7 +303,8 @@ set_vcard(User, LServer, LServerB, VCARD) ->
end,
try
LUser = exmpp_stringprep:nodeprep(User),
UserStr = binary_to_list(User),
LUser = binary_to_list(exmpp_stringprep:nodeprep(User)),
LFN = exmpp_stringprep:to_lower(FN),
LFamily = exmpp_stringprep:to_lower(Family),
LGiven = exmpp_stringprep:to_lower(Given),
@@ -304,18 +317,18 @@ set_vcard(User, LServer, LServerB, VCARD) ->
LOrgName = exmpp_stringprep:to_lower(OrgName),
LOrgUnit = exmpp_stringprep:to_lower(OrgUnit),
US = {LUser, LServer},
US = {User, Server},
VcardToStore = case gen_storage:table_info(LServerB, vcard, backend) of
VcardToStore = case gen_storage:table_info(Server, vcard, backend) of
mnesia -> VCARD;
odbc -> lists:flatten(exmpp_xml:document_to_list(VCARD))
end,
F = fun() ->
gen_storage:write(LServerB, #vcard{user_host = US, vcard = VcardToStore}),
gen_storage:write(LServerB,
gen_storage:write(Server, #vcard{user_host = US, vcard = VcardToStore}),
gen_storage:write(Server,
#vcard_search{user_host=US,
username = User, lusername = LUser,
username = UserStr, lusername = LUser,
fn = FN, lfn = LFN,
family = Family, lfamily = LFamily,
given = Given, lgiven = LGiven,
@@ -329,9 +342,8 @@ set_vcard(User, LServer, LServerB, VCARD) ->
orgunit = OrgUnit, lorgunit = LOrgUnit
})
end,
LServerB = list_to_binary(LServer),
gen_storage:transaction(LServerB, vcard, F),
ejabberd_hooks:run(vcard_set, LServerB, [list_to_binary(LUser), LServerB, VCARD])
gen_storage:transaction(Server, vcard, F),
ejabberd_hooks:run(vcard_set, Server, [LUser, Server, VCARD])
catch
_ ->
{error, badarg}
@@ -536,7 +548,7 @@ record_to_item(R) ->
{User, Server} = R#vcard_search.user_host,
#xmlel{ns = ?NS_DATA_FORMS, name = 'item', children =
[
?FIELD(<<"jid">>, list_to_binary(User ++ "@" ++ Server)),
?FIELD(<<"jid">>, exmpp_jid:to_binary(User, Server)),
?FIELD(<<"fn">>, list_to_binary(R#vcard_search.fn)),
?FIELD(<<"last">>, list_to_binary(R#vcard_search.family)),
?FIELD(<<"first">>, list_to_binary(R#vcard_search.given)),
@@ -729,8 +741,8 @@ reindex_vcards() ->
remove_user(User, Server) when is_binary(User), is_binary(Server) ->
LUser = binary_to_list(exmpp_stringprep:nodeprep(User)),
LServer = binary_to_list(exmpp_stringprep:nameprep(Server)),
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
gen_storage:delete(Server, {vcard, US}),
@@ -747,14 +759,14 @@ update_tables(Host, mnesia) ->
gen_storage_migration:migrate_mnesia(
Host, vcard,
[{vcard, [us, vcard],
fun({vcard, US, Vcard}) ->
#vcard{user_host = US,
fun({vcard, {UserS, ServerS}, Vcard}) ->
#vcard{user_host = {list_to_binary(UserS), list_to_binary(ServerS)},
vcard = convert_vcard_element(Vcard)}
end}]),
gen_storage_migration:migrate_mnesia(
Host, vcard_search,
[{vcard_search, [us,
username, lusername,
user, luser,
fn, lfn,
family, lfamily,
given, lgiven,
@@ -766,8 +778,9 @@ update_tables(Host, mnesia) ->
email, lemail,
orgname, lorgname,
orgunit, lorgunit],
fun(Record) ->
Record
fun(#vcard_search{user_host = {UserS, ServerS}} = Record) ->
UserHost = {list_to_binary(UserS), list_to_binary(ServerS)},
Record#vcard_search{user_host = UserHost, username = UserS}
end}]);
update_tables(Host, odbc) ->
@@ -896,7 +909,6 @@ get_user_photo(User, Host) ->
user_queue_parse_query(US, Query) ->
{User, Server} = US,
?INFO_MSG("Query vcard: ~p", [Query]), %+++
case lists:keysearch("removevcard", 1, Query) of
{value, _} ->
case remove_user(list_to_binary(User), list_to_binary(Server)) of
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Mòdul ejannerd Publicar-Subscriure"}.
{"ejabberd SOCKS5 Bytestreams module","mòdul ejabberd SOCKS5 Bytestreams"}.
{"ejabberd vCard module","Mòdul ejabberd vCard"}.
{"ejabberd virtual hosts","Hosts virtuals del ejabberd"}.
{"ejabberd Web Admin","Web d'administració del ejabberd"}.
{"Elements","Elements"}.
{"Email","Email"}.
@@ -321,6 +320,7 @@
{"User","Usuari"}.
{"Validate","Validar"}.
{"vCard User Search","Recerca de vCard d'usuari"}.
{"Virtual Hosts","Hosts virtuals"}.
{"Visitors are not allowed to change their nicknames in this room","Els visitants no tenen permés canviar el seus Nicknames en esta sala"}.
{"Visitors are not allowed to send messages to all occupants","Els visitants no poden enviar missatges a tots els ocupants"}.
{"Wednesday","Dimecres"}.
+3 -3
View File
@@ -1237,9 +1237,9 @@ msgstr "en format text"
msgid "~s access rule configuration"
msgstr "Configuració de les Regles d'Accés ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Hosts virtuals del ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Hosts virtuals"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}.
{"ejabberd vCard module","ejabberd vCard modul"}.
{"ejabberd virtual hosts","Virtuální hostitelé ejabberd"}.
{"ejabberd Web Admin","Webová administrace ejabberd"}.
{"Elements","Položek"}.
{"Email","E-mail"}.
@@ -321,6 +320,7 @@
{"User","Uživatel"}.
{"Validate","Ověřit"}.
{"vCard User Search","Hledání uživatelů podle vizitek"}.
{"Virtual Hosts","Virtuální hostitelé"}.
{"Visitors are not allowed to change their nicknames in this room","Návštěvníkům této místnosti je zakázáno měnit přezdívku"}.
{"Visitors are not allowed to send messages to all occupants","Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference"}.
{"Wednesday","Středa"}.
+3 -3
View File
@@ -1227,9 +1227,9 @@ msgstr "Zdroj"
msgid "~s access rule configuration"
msgstr "~s konfigurace pravidla přístupu"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Virtuální hostitelé ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuální hostitelé"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe-Modul"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5-Bytestreams-Modul"}.
{"ejabberd vCard module","ejabberd vCard-Modul"}.
{"ejabberd virtual hosts","ejabberd virtuelle Hosts"}.
{"ejabberd Web Admin","ejabberd Web-Admin"}.
{"Elements","Elemente"}.
{"Email","E-Mail"}.
@@ -321,6 +320,7 @@
{"Users Last Activity","Letzte Benutzeraktivität"}.
{"Validate","Validieren"}.
{"vCard User Search","vCard-Benutzer-Suche"}.
{"Virtual Hosts","Virtuelle Hosts"}.
{"Visitors are not allowed to change their nicknames in this room","Besucher dürfen in diesem Raum ihren Spitznamen nicht ändern"}.
{"Visitors are not allowed to send messages to all occupants","Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken"}.
{"Wednesday","Mittwoch"}.
+3 -3
View File
@@ -1249,9 +1249,9 @@ msgstr "Unformatiert"
msgid "~s access rule configuration"
msgstr "~s Zugangsregel-Konfiguration"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd virtuelle Hosts"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuelle Hosts"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+2 -2
View File
@@ -1208,8 +1208,8 @@ msgstr ""
msgid "~s access rule configuration"
msgstr ""
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr ""
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd module Δημοσίευσης-Εγγραφής"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","ejabberd vCard module"}.
{"ejabberd virtual hosts","εικονικοί κεντρικοί υπολογιστές ejabberd"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Στοιχεία"}.
{"Email","Email"}.
@@ -321,6 +320,7 @@
{"User","Χρήστης"}.
{"Validate","Επαληθεύστε"}.
{"vCard User Search","vCard Αναζήτηση χρηστών"}.
{"Virtual Hosts","εικονικοί κεντρικοί υπολογιστές"}.
{"Visitors are not allowed to change their nicknames in this room","Οι επισκέπτες δεν επιτρέπεται να αλλάξουν τα ψευδώνυμα τους σε αυτή την αίθουσα"}.
{"Visitors are not allowed to send messages to all occupants","Οι επισκέπτες δεν επιτρέπεται να στείλουν μηνύματα σε όλους τους συμμετέχωντες"}.
{"Wednesday","Τετάρτη"}.
+3 -3
View File
@@ -1256,9 +1256,9 @@ msgstr "Ακατέργαστο"
msgid "~s access rule configuration"
msgstr "~s διαμόρφωση κανόνα πρόσβασης"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "εικονικοί κεντρικοί υπολογιστές ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "εικονικοί κεντρικοί υπολογιστές"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Public-Abonada modulo"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bajtfluo modulo"}.
{"ejabberd vCard module","ejabberd vCard-modulo"}.
{"ejabberd virtual hosts","ejabberd virtual-gastigoj"}.
{"ejabberd Web Admin","ejabberd Teksaĵa Administro"}.
{"Elements","Eroj"}.
{"Email","Retpoŝto"}.
@@ -321,6 +320,7 @@
{"User","Uzanto"}.
{"Validate","Validigu"}.
{"vCard User Search","Serĉado de vizitkartoj"}.
{"Virtual Hosts","Virtual-gastigoj"}.
{"Visitors are not allowed to change their nicknames in this room","Ne estas permesata al vizitantoj ŝanĝi siajn kaŝnomojn en ĉi tiu ĉambro"}.
{"Visitors are not allowed to send messages to all occupants","Vizitantoj ne rajtas sendi mesaĝojn al ĉiuj partoprenantoj"}.
{"Wednesday","Merkredo"}.
+3 -6
View File
@@ -1234,9 +1234,9 @@ msgstr "Kruda"
msgid "~s access rule configuration"
msgstr "Agordo de atingo-reguloj de ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd virtual-gastigoj"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtual-gastigoj"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1683,9 +1683,6 @@ msgstr "Startu"
#~ msgid "(Raw)"
#~ msgstr "(Kruda)"
#~ msgid "Virtual Hosts"
#~ msgstr "Virtual-gastigoj"
#~ msgid "Specified nickname is already registered"
#~ msgstr "Donita kaŝnomo jam estas registrita"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","Módulo SOCKS5 Bytestreams para ejabberd"}.
{"ejabberd vCard module","Módulo vCard para ejabberd"}.
{"ejabberd virtual hosts","Dominios de ejabberd"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Elementos"}.
{"Email","correo"}.
@@ -321,6 +320,7 @@
{"User","Usuario"}.
{"Validate","Validar"}.
{"vCard User Search","Buscar vCard de usuario"}.
{"Virtual Hosts","Dominios Virtuales"}.
{"Visitors are not allowed to change their nicknames in this room","Los visitantes no tienen permitido cambiar sus apodos en esta sala"}.
{"Visitors are not allowed to send messages to all occupants","Los visitantes no pueden enviar mensajes a todos los ocupantes"}.
{"Wednesday","miércoles"}.
+3 -3
View File
@@ -1242,9 +1242,9 @@ msgstr "Crudo"
msgid "~s access rule configuration"
msgstr "Configuración de las Regla de Acceso ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Dominios de ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Dominios Virtuales"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Module Publish-Subscribe d'ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","Module vCard ejabberd"}.
{"ejabberd virtual hosts","Serveurs virtuels d'ejabberd"}.
{"ejabberd Web Admin","Console Web d'administration de ejabberd"}.
{"Elements","Éléments"}.
{"Email","Email"}.
@@ -321,6 +320,7 @@
{"User","Utilisateur"}.
{"Validate","Valider"}.
{"vCard User Search","Recherche dans l'annnuaire"}.
{"Virtual Hosts","Serveurs virtuels"}.
{"Visitors are not allowed to change their nicknames in this room","Les visiteurs ne sont pas autorisés à changer de pseudo dans ce salon"}.
{"Visitors are not allowed to send messages to all occupants","Les visiteurs ne sont pas autorisés à envoyer des messages à tout les occupants"}.
{"Wednesday","Mercredi"}.
+3 -6
View File
@@ -1252,9 +1252,9 @@ msgstr "Brut"
msgid "~s access rule configuration"
msgstr "Configuration des règles d'accès ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Serveurs virtuels d'ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Serveurs virtuels"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1711,6 +1711,3 @@ msgstr "Démarrer"
#~ msgid "(Raw)"
#~ msgstr "(Brut)"
#~ msgid "Virtual Hosts"
#~ msgstr "Serveurs virtuels"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","Módulo vCard para ejabberd"}.
{"ejabberd virtual hosts","Hosts virtuais de ejabberd"}.
{"ejabberd Web Admin","Ejabberd Administrador Web"}.
{"Elements","Elementos"}.
{"Email","Email"}.
@@ -319,6 +318,7 @@
{"User","Usuario"}.
{"Validate","Validar"}.
{"vCard User Search","Procura de usuario en vCard"}.
{"Virtual Hosts","Hosts Virtuais"}.
{"Visitors are not allowed to change their nicknames in this room","Os visitantes non están autorizados a cambiar os seus That alcumes nesta sala"}.
{"Visitors are not allowed to send messages to all occupants","Os visitantes non poden enviar mensaxes a todos os ocupantes"}.
{"Wednesday","Mércores"}.
+3 -6
View File
@@ -1236,9 +1236,9 @@ msgstr "Cru"
msgid "~s access rule configuration"
msgstr "Configuración das Regra de Acceso ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Hosts virtuais de ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Hosts Virtuais"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1694,9 +1694,6 @@ msgstr "Iniciar"
#~ msgid "(Raw)"
#~ msgstr "(Cru)"
#~ msgid "Virtual Hosts"
#~ msgstr "Hosts Virtuais"
#~ msgid "Specified nickname is already registered"
#~ msgstr "O alcume especificado xa está rexistrado, terás que buscar outro"
+1 -1
View File
@@ -80,7 +80,6 @@
{"ejabberd Publish-Subscribe module","Modul ejabberd Setujui-Pertemanan"}.
{"ejabberd SOCKS5 Bytestreams module","modul ejabberd SOCKS5 Bytestreams"}.
{"ejabberd vCard module","Modul ejabberd vCard"}.
{"ejabberd virtual hosts","ejabberd virtual hosts"}.
{"ejabberd Web Admin","Admin Web ejabberd"}.
{"Elements","Elemen-elemen"}.
{"Email","Email"}.
@@ -388,6 +387,7 @@
{"Users","Pengguna"}.
{"Validate","Mengesahkan"}.
{"vCard User Search","vCard Pencarian Pengguna"}.
{"Virtual Hosts","Virtual Hosts"}.
{"Visitors are not allowed to change their nicknames in this room","Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini"}.
{"Visitors are not allowed to send messages to all occupants","Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni"}.
{"Wednesday","Rabu"}.
+2 -2
View File
@@ -1362,8 +1362,8 @@ msgid "~s access rule configuration"
msgstr "~s aturan akses konfigurasi"
#: web/ejabberd_web_admin.erl:1031
msgid "ejabberd virtual hosts"
msgstr "ejabberd virtual hosts"
msgid "Virtual Hosts"
msgstr "Virtual Hosts"
#: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","Modulo SOCKS5 Bytestreams per ejabberd"}.
{"ejabberd vCard module","Modulo vCard per ejabberd"}.
{"ejabberd virtual hosts","Host virtuali di ejabberd"}.
{"ejabberd Web Admin","Amministrazione web ejabberd"}.
{"Elements","Elementi"}.
{"Email","E-mail"}.
@@ -321,6 +320,7 @@
{"User","Utente"}.
{"Validate","Validare"}.
{"vCard User Search","Ricerca di utenti per vCard"}.
{"Virtual Hosts","Host Virtuali"}.
{"Visitors are not allowed to change their nicknames in this room","Non è consentito ai visitatori cambiare il nickname in questa stanza"}.
{"Visitors are not allowed to send messages to all occupants","Non è consentito ai visitatori l'invio di messaggi a tutti i presenti"}.
{"Wednesday","Mercoledì"}.
+3 -3
View File
@@ -1243,9 +1243,9 @@ msgstr "Grezzo"
msgid "~s access rule configuration"
msgstr "Configurazione delle regole di accesso per ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Host virtuali di ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Host Virtuali"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","ejabberd vCard module"}.
{"ejabberd virtual hosts","ejabberd ヴァーチャルホスト"}.
{"ejabberd Web Admin","ejabberd Web 管理"}.
{"Elements","要素"}.
{"Email","メールアドレス"}.
@@ -321,6 +320,7 @@
{"Users Last Activity","ユーザーの活動履歴"}.
{"Validate","検証"}.
{"vCard User Search","vCard ユーザー検索"}.
{"Virtual Hosts","ヴァーチャルホスト"}.
{"Visitors are not allowed to change their nicknames in this room","ビジターはこのチャットルームでニックネームを変更することは許可されていません"}.
{"Visitors are not allowed to send messages to all occupants","ビジターが移住者ににメッセージを送ることは許可されていません"}.
{"Wednesday","水曜日"}.
+3 -6
View File
@@ -1232,9 +1232,9 @@ msgstr "Raw"
msgid "~s access rule configuration"
msgstr "~s アクセスルール設定"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd ヴァーチャルホスト"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "ヴァーチャルホスト"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1680,9 +1680,6 @@ msgstr "開始"
#~ msgid "(Raw)"
#~ msgstr "(Raw)"
#~ msgid "Virtual Hosts"
#~ msgstr "ヴァーチャルホスト"
#~ msgid "Specified nickname is already registered"
#~ msgstr "指定されたニックネームは既に登録されています"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","ejabberd's vCard-module"}.
{"ejabberd virtual hosts","Virtuele hosts"}.
{"ejabberd Web Admin","ejabberd Webbeheer"}.
{"Elements","Elementen"}.
{"Email","E-mail"}.
@@ -321,6 +320,7 @@
{"Users Last Activity","Laatste activiteit van gebruikers"}.
{"Validate","Bevestigen"}.
{"vCard User Search","Gebruikers zoeken"}.
{"Virtual Hosts","Virtuele hosts"}.
{"Visitors are not allowed to change their nicknames in this room","Het is bezoekers niet toegestaan hun naam te veranderen in dit kanaal"}.
{"Visitors are not allowed to send messages to all occupants","Bezoekers mogen geen berichten verzenden naar alle aanwezigen"}.
{"Wednesday","Woensdag"}.
+2 -2
View File
@@ -1246,8 +1246,8 @@ msgstr "Ruw"
msgid "~s access rule configuration"
msgstr "Access rules op ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuele hosts"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}.
{"ejabberd vCard module","ejabberd vCard modul"}.
{"ejabberd virtual hosts","virtuella ejabberd maskiner"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Elementer"}.
{"Email","Epost"}.
@@ -321,6 +320,7 @@
{"Users Last Activity","Brukers Siste Aktivitet"}.
{"Validate","Bekrefte gyldighet"}.
{"vCard User Search","vCard Bruker Søk"}.
{"Virtual Hosts","Virtuella Maskiner"}.
{"Visitors are not allowed to change their nicknames in this room","Besøkende får ikke lov å endre kallenavn i dette "}.
{"Visitors are not allowed to send messages to all occupants","Besøkende får ikke sende meldinger til alle deltakere"}.
{"Wednesday","onsdag"}.
+3 -3
View File
@@ -1229,9 +1229,9 @@ msgstr "Rå"
msgid "~s access rule configuration"
msgstr "tilgangsregel konfigurasjon for ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "virtuella ejabberd maskiner"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuella Maskiner"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Moduł Publish-Subscribe"}.
{"ejabberd SOCKS5 Bytestreams module","Moduł SOCKS5 Bytestreams"}.
{"ejabberd vCard module","Moduł vCard ejabberd"}.
{"ejabberd virtual hosts","wirtualne hosty ejabberd"}.
{"ejabberd Web Admin","ejabberd: Panel Administracyjny"}.
{"Elements","Elementy"}.
{"Email","Email"}.
@@ -321,6 +320,7 @@
{"User","Użytkownik"}.
{"Validate","Potwierdź"}.
{"vCard User Search","Wyszukiwanie vCard użytkowników"}.
{"Virtual Hosts","Wirtualne Hosty"}.
{"Visitors are not allowed to change their nicknames in this room","Uczestnicy tego pokoju nie mogą zmieniać swoich nicków"}.
{"Visitors are not allowed to send messages to all occupants","Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych"}.
{"Wednesday","Środa"}.
+3 -3
View File
@@ -1240,9 +1240,9 @@ msgstr "Żródło"
msgid "~s access rule configuration"
msgstr "~s konfiguracja zasad dostępu"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "wirtualne hosty ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Wirtualne Hosty"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Módulo para Publicar Tópicos do ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","Modulo ejabberd SOCKS5 Bytestreams"}.
{"ejabberd vCard module","Módulo vCard para ejabberd"}.
{"ejabberd virtual hosts","Maquinas virtuais de ejabberd"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Elementos"}.
{"Email","e-mail"}.
@@ -321,6 +320,7 @@
{"User","Usuário"}.
{"Validate","Validar"}.
{"vCard User Search","Busca de Usuário vCard"}.
{"Virtual Hosts","Hosts virtuais"}.
{"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não pode mudar seus apelidos"}.
{"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens a todos os ocupantes"}.
{"Wednesday","Quarta"}.
+3 -3
View File
@@ -1239,9 +1239,9 @@ msgstr "Intocado"
msgid "~s access rule configuration"
msgstr "Configuração da Regra de Acesso ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Maquinas virtuais de ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Hosts virtuais"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+2 -2
View File
@@ -1292,8 +1292,8 @@ msgstr "Configuração das Regra de Acesso ~s"
#: web/ejabberd_web_admin.erl:1038
#, fuzzy
msgid "ejabberd virtual hosts"
msgstr "Estatísticas do ejabberd"
msgid "Virtual Hosts"
msgstr "Servidores virtuales"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Модуль ejabberd Публикации-Подписки"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}.
{"ejabberd vCard module","ejabberd vCard модуль"}.
{"ejabberd virtual hosts","Виртуальные хосты ejabberd"}.
{"ejabberd Web Admin","Web-интерфейс администрирования ejabberd"}.
{"Elements","Элементы"}.
{"Email","Электронная почта"}.
@@ -321,6 +320,7 @@
{"User","Пользователь"}.
{"Validate","Утвердить"}.
{"vCard User Search","Поиск пользователей по vCard"}.
{"Virtual Hosts","Виртуальные хосты"}.
{"Visitors are not allowed to change their nicknames in this room","Посетителям запрещено изменять свои псевдонимы в этой комнате"}.
{"Visitors are not allowed to send messages to all occupants","Посетителям не разрешается посылать сообщения всем присутствующим"}.
{"Wednesday","Среда"}.
+3 -3
View File
@@ -1235,9 +1235,9 @@ msgstr "Необработанный формат"
msgid "~s access rule configuration"
msgstr "Конфигурация правила доступа ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Виртуальные хосты ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Виртуальные хосты"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}.
{"ejabberd vCard module","ejabberd vCard modul"}.
{"ejabberd virtual hosts","ejabberd virtuálne servery"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Prvky"}.
{"Email","E-mail"}.
@@ -321,6 +320,7 @@
{"User","Užívateľ"}.
{"Validate","Overiť"}.
{"vCard User Search","Hľadať užívateľov vo vCard"}.
{"Virtual Hosts","Virtuálne servery"}.
{"Visitors are not allowed to change their nicknames in this room","V tejto miestnosti nieje povolené meniť prezývky"}.
{"Visitors are not allowed to send messages to all occupants","Návštevníci nemajú povolené zasielať správy všetkým prihláseným do konferencie"}.
{"Wednesday","Streda"}.
+3 -6
View File
@@ -1232,9 +1232,9 @@ msgstr "Raw"
msgid "~s access rule configuration"
msgstr "~s konfigurácia prístupového pravidla"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd virtuálne servery"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuálne servery"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1681,9 +1681,6 @@ msgstr "Štart"
#~ msgid "(Raw)"
#~ msgstr "(Raw)"
#~ msgid "Virtual Hosts"
#~ msgstr "Virtuálne servery"
#~ msgid "Specified nickname is already registered"
#~ msgstr "Zadaná prezývka je už registrovaná"
+1 -1
View File
@@ -65,7 +65,6 @@
{"ejabberd Publish-Subscribe module","ejabberd publikprenumerations modul"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestrem modul"}.
{"ejabberd vCard module","ejabberd vCard-modul"}.
{"ejabberd virtual hosts","Virtuella ejabberd-servrar"}.
{"ejabberd Web Admin","ejabberd Web Admin"}.
{"Elements","Elements"}.
{"Email","Email"}.
@@ -312,6 +311,7 @@
{"Users Last Activity","Användarens senaste aktivitet"}.
{"Validate","Validera"}.
{"vCard User Search","vCard användare sök"}.
{"Virtual Hosts","Virtuella servrar"}.
{"Visitors are not allowed to change their nicknames in this room","Det är inte tillåtet for gäster att ändra sina smeknamn i detta rummet"}.
{"Visitors are not allowed to send messages to all occupants","Besökare får inte skicka medelande till alla"}.
{"Wednesday","Onsdag"}.
+3 -3
View File
@@ -1245,9 +1245,9 @@ msgstr "Ra"
msgid "~s access rule configuration"
msgstr "Åtkomstregelkonfiguration för ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Virtuella ejabberd-servrar"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Virtuella servrar"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -60,7 +60,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}.
{"ejabberd vCard module","ejabberd vCard module"}.
{"ejabberd virtual hosts","โฮสต์เสมือน ejabberd"}.
{"Email","อีเมล"}.
{"Enable logging","เปิดใช้งานการบันทึก"}.
{"End User Session","สิ้นสุดเซสชันของผู้ใช้"}.
@@ -277,6 +276,7 @@
{"Users Last Activity","กิจกรรมล่าสุดของผู้ใช้"}.
{"Validate","ตรวจสอบ"}.
{"vCard User Search","ค้นหาผู้ใช้ vCard "}.
{"Virtual Hosts","โฮสต์เสมือน"}.
{"Visitors are not allowed to send messages to all occupants","ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด"}.
{"Wednesday","วันพุธ"}.
{"When to send the last published item","เวลาที่ส่งรายการที่เผยแพร่ครั้งล่าสุด"}.
+3 -6
View File
@@ -1243,9 +1243,9 @@ msgstr "ข้อมูลดิบ"
msgid "~s access rule configuration"
msgstr "~s การกำหนดค่ากฎการเข้าถึง"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "โฮสต์เสมือน ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "โฮสต์เสมือน"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1673,9 +1673,6 @@ msgstr "เริ่ม"
#~ msgid "(Raw)"
#~ msgstr "(ข้อมูลดิบ)"
#~ msgid "Virtual Hosts"
#~ msgstr "โฮสต์เสมือน"
#~ msgid "Specified nickname is already registered"
#~ msgstr "ชื่อเล่นที่ระบุได้รับการลงได้ทะเบียนแล้ว"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modülü"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modülü"}.
{"ejabberd vCard module","ejabberd vCard modülü"}.
{"ejabberd virtual hosts","ejabberd sanal sunucuları"}.
{"ejabberd Web Admin","ejabberd Web Yöneticisi"}.
{"Elements","Elementler"}.
{"Email","E-posta"}.
@@ -319,6 +318,7 @@
{"Users Last Activity","Kullanıcıların Son Aktiviteleri"}.
{"Validate","Geçerli"}.
{"vCard User Search","vCard Kullanıcı Araması"}.
{"Virtual Hosts","Sanal Sunucuları"}.
{"Visitors are not allowed to change their nicknames in this room","Bu odada ziyaretçilerin takma isimlerini değiştirmesine izin verilmiyor"}.
{"Visitors are not allowed to send messages to all occupants","Ziyaretçilerin odadaki tüm sakinlere mesaj göndermesine izin verilmiyor"}.
{"Wednesday","Çarşamba"}.
+3 -3
View File
@@ -1244,9 +1244,9 @@ msgstr "Ham"
msgid "~s access rule configuration"
msgstr "~s erişim kuralları ayarları"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd sanal sunucuları"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Sanal Sunucuları"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","Модуль ejabberd Публікації-Абонування"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}.
{"ejabberd vCard module","ejabberd vCard модуль"}.
{"ejabberd virtual hosts","віртуальні хости ejabberd"}.
{"ejabberd Web Admin","Веб-інтерфейс Адміністрування ejabberd"}.
{"Elements","Елементи"}.
{"Email","Електронна пошта"}.
@@ -321,6 +320,7 @@
{"User","Користувач"}.
{"Validate","Затвердити"}.
{"vCard User Search","Пошук користувачів по vCard"}.
{"Virtual Hosts","віртуальні хости"}.
{"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}.
{"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}.
{"Wednesday","Середа"}.
+3 -3
View File
@@ -1244,9 +1244,9 @@ msgstr "необроблений формат"
msgid "~s access rule configuration"
msgstr "Конфігурація правила доступу ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "віртуальні хости ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "віртуальні хости"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
+1 -1
View File
@@ -60,7 +60,6 @@
{"ejabberd Publish-Subscribe module","Môdun ejabberd Xuất Bản-Đăng Ký Bản quyền"}.
{"ejabberd SOCKS5 Bytestreams module","Môdun SOCKS5 Bytestreams Bản quyền"}.
{"ejabberd vCard module","Môdun ejabberd vCard Bản quyền"}.
{"ejabberd virtual hosts","Máy chủ ảo ejabberd"}.
{"Email","Email"}.
{"Enable logging","Cho phép ghi nhật ký"}.
{"End User Session","Kết Thúc Phiên Giao Dịch Người Sử Dụng"}.
@@ -277,6 +276,7 @@
{"Users","Người sử dụng"}.
{"Validate","Xác nhận hợp lệ"}.
{"vCard User Search","Tìm Kiếm Người Sử Dụng vCard"}.
{"Virtual Hosts","Máy Chủ Ảo"}.
{"Visitors are not allowed to send messages to all occupants","Người ghé thăm không được phép gửi thư đến tất cả các người tham dự"}.
{"Wednesday","Thứ Tư"}.
{"When to send the last published item","Khi cần gửi mục được xuất bản cuối cùng"}.
+3 -6
View File
@@ -1257,9 +1257,9 @@ msgstr "Thô"
msgid "~s access rule configuration"
msgstr "~s cấu hình quy tắc truy cập"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Máy chủ ảo ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Máy Chủ Ảo"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1697,9 +1697,6 @@ msgstr "Khởi động"
#~ msgid "(Raw)"
#~ msgstr "(Thô)"
#~ msgid "Virtual Hosts"
#~ msgstr "Máy Chủ Ảo"
#~ msgid "Specified nickname is already registered"
#~ msgstr "Bí danh xác định đã đăng ký rồi"
+1 -1
View File
@@ -63,7 +63,6 @@
{"ejabberd Publish-Subscribe module","Module d' eplaidaedje-abounmint po ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","Module SOCKS5 Bytestreams po ejabberd"}.
{"ejabberd vCard module","Module vCard ejabberd"}.
{"ejabberd virtual hosts","Forveyous sierveus da ejabberd"}.
{"ejabberd Web Admin","Manaedjeu waibe ejabberd"}.
{"Email","Emile"}.
{"Enable logging","Mete en alaedje li djournå"}.
@@ -290,6 +289,7 @@
{"User","Uzeu"}.
{"Validate","Valider"}.
{"vCard User Search","Calpin des uzeus"}.
{"Virtual Hosts","Forveyous sierveus"}.
{"Visitors are not allowed to change their nicknames in this room","Les viziteus èn polèt nén candjî leus metous no po ç' såle ci"}.
{"Visitors are not allowed to send messages to all occupants","Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints"}.
{"Wednesday","mierkidi"}.
+3 -6
View File
@@ -1254,9 +1254,9 @@ msgstr "Dinêyes brutes"
msgid "~s access rule configuration"
msgstr "Apontiaedje des rîles d' accès a ~s"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "Forveyous sierveus da ejabberd"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "Forveyous sierveus"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1697,9 +1697,6 @@ msgstr "Enonder"
#~ msgid "(Raw)"
#~ msgstr "(Dinêyes brutes)"
#~ msgid "Virtual Hosts"
#~ msgstr "Forveyous sierveus"
#~ msgid "Specified nickname is already registered"
#~ msgstr "Li no metou dné est ddja edjîstré"
+1 -1
View File
@@ -66,7 +66,6 @@
{"ejabberd Publish-Subscribe module","ejabberd 发行-订阅模块"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 字节流模块"}.
{"ejabberd vCard module","ejabberd vCard 模块"}.
{"ejabberd virtual hosts","ejabberd 虚拟主机"}.
{"ejabberd Web Admin","ejabberd 网页管理"}.
{"Elements","元素"}.
{"Email","电子邮件"}.
@@ -321,6 +320,7 @@
{"User","用户"}.
{"Validate","确认"}.
{"vCard User Search","vCard 用户搜索"}.
{"Virtual Hosts","虚拟主机"}.
{"Visitors are not allowed to change their nicknames in this room","此房间不允许用户更改昵称"}.
{"Visitors are not allowed to send messages to all occupants","不允许访客给所有占有者发送消息"}.
{"Wednesday","星期三"}.
+3 -6
View File
@@ -1223,9 +1223,9 @@ msgstr "原始格式"
msgid "~s access rule configuration"
msgstr "~s 访问规则配置"
#: web/ejabberd_web_admin.erl:1038
msgid "ejabberd virtual hosts"
msgstr "ejabberd 虚拟主机"
#: web/ejabberd_web_admin.erl:1031
msgid "Virtual Hosts"
msgstr "虚拟主机"
#: web/ejabberd_web_admin.erl:1046 web/ejabberd_web_admin.erl:1053
msgid "Users"
@@ -1663,9 +1663,6 @@ msgstr "开始"
#~ msgid "(Raw)"
#~ msgstr "(原始格式)"
#~ msgid "Virtual Hosts"
#~ msgstr "虚拟主机"
#~ msgid "Specified nickname is already registered"
#~ msgstr "指定的昵称已被注册"
+34
View File
@@ -600,6 +600,40 @@ BEGIN
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_roster_version] **/
/** Update users roster_version **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_roster_version]
@Username varchar(200),
@Version varchar(50)
AS
BEGIN
IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username;
END
ELSE
BEGIN
INSERT INTO roster_version (username, version) VALUES (@Username, @Version);
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_version] **/
/** Retrive the user roster_version **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_version]
@Username varchar(200)
AS
BEGIN
SELECT roster_version.version as version
FROM roster_version WITH (NOLOCK)
WHERE username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/
/** Delete messages older that 3 days from spool **/
+34
View File
@@ -923,6 +923,40 @@ BEGIN
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_roster_version] **/
/** Update users roster_version **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_roster_version]
@Username varchar(200),
@Version varchar(8000)
AS
BEGIN
IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username;
END
ELSE
BEGIN
INSERT INTO roster_version (username, version) VALUES (@Username, @Version);
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_version] **/
/** Retrive the user roster_version **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_version]
@Username varchar(200)
AS
BEGIN
SELECT roster_version.version as version
FROM roster_version WITH (NOLOCK)
WHERE username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/
/** Delete messages older that 3 days from spool **/
+12 -4
View File
@@ -92,6 +92,8 @@
-define(generic, true).
-endif.
-include("ejabberd.hrl").
%% -----------------
%% Generic queries
-ifdef(generic).
@@ -909,8 +911,14 @@ count_records_where(LServer, Table, WhereClause) ->
["select count(*) from ", Table, " with (nolock) ", WhereClause]).
get_roster_version(LServer, LUser) ->
ejabberd_odbc:sql_query(LServer,
["select version from dbo.roster_version with (nolock) where username = '", LUser, "'"]).
set_roster_version(LUser, Version) ->
update_t("dbo.roster_version", ["username", "version"], [LUser, Version], ["username = '", LUser, "'"]).
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_version '", LUser, "'"]).
set_roster_version(Username, Version) ->
%% This function doesn't know the vhost, so we hope it's the first one defined:
LServer = ?MYNAME,
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_roster_version '", Username, "', '", Version, "'"]).
-endif.
+14 -2
View File
@@ -562,7 +562,13 @@ make_xhtml_output(State, Status, Headers, XHTML) ->
end, HeadersOut),
SL = [Version, integer_to_list(Status), " ",
code_to_phrase(Status), "\r\n"],
[SL, H, "\r\n", Data].
Data2 = case State#state.request_method of
'HEAD' -> "";
_ -> Data
end,
[SL, H, "\r\n", Data2].
make_text_output(State, Status, Headers, Text) when is_list(Text) ->
make_text_output(State, Status, Headers, list_to_binary(Text));
@@ -599,7 +605,13 @@ make_text_output(State, Status, Headers, Data) when is_binary(Data) ->
end, HeadersOut),
SL = [Version, integer_to_list(Status), " ",
code_to_phrase(Status), "\r\n"],
[SL, H, "\r\n", Data].
Data2 = case State#state.request_method of
'HEAD' -> "";
_ -> Data
end,
[SL, H, "\r\n", Data2].
parse_lang(Langs) ->
+20 -1
View File
@@ -1264,6 +1264,10 @@ parse_request(Data, PayloadSize, MaxStanzaSize) ->
{'EXIT', _} ->
{error, bad_request};
Rid ->
Els2 = case [E || E <- Els, E#xmlel.ns == ?NS_HTTP_BIND] of
[] -> Els;
_ -> force_ns(Data)
end,
%% I guess this is to remove XMLCDATA: Is it really needed ?
FixedEls =
lists:filter(
@@ -1275,7 +1279,7 @@ parse_request(Data, PayloadSize, MaxStanzaSize) ->
_ ->
false
end
end, Els),
end, Els2),
Sid = exmpp_xml:get_attribute_as_list(Xml, <<"sid">>, ""),
if
PayloadSize =< MaxStanzaSize ->
@@ -1290,6 +1294,21 @@ parse_request(Data, PayloadSize, MaxStanzaSize) ->
{error, bad_request}
end.
%% This BOSH stanza contains at least one XMPP stanza without NS,
%% and exmpp sets the NS of BOSH to it and its children, instead of assuming jabber:client.
%% To avoid that, we set the jabber:client NS to the BOSH stanza, parse it,
%% and the NS will be inherited to the NS-less XMPP stanza.
force_ns(Data) ->
Data2 = change_ns(Data, ""),
[#xmlel{children = Els}] = exmpp_xmlstream:parse_element(Data2),
Els.
change_ns([], Res) ->
lists:reverse(Res);
change_ns(?NS_HTTP_BIND_s ++ String, Res) ->
change_ns(String, lists:reverse(?NS_JABBER_CLIENT_s) ++ Res);
change_ns([Char | String], Res) ->
change_ns(String, [Char | Res]).
send_receiver_reply(undefined, _Reply) ->
ok;
send_receiver_reply(Receiver, Reply) ->
+9 -5
View File
@@ -64,11 +64,15 @@ get_acl_rule(["additions.js"],_) -> {"localhost", [all]};
get_acl_rule(["vhosts"],_) -> {"localhost", [all]};
%% The pages of a vhost are only accesible if the user is admin of that vhost:
get_acl_rule(["server", VHost | _RPath], 'GET') -> {VHost, [configure, webadmin_view]};
get_acl_rule(["server", VHost | _RPath], Method)
when Method=:='GET' orelse Method=:='HEAD' ->
{VHost, [configure, webadmin_view]};
get_acl_rule(["server", VHost | _RPath], 'POST') -> {VHost, [configure]};
%% Default rule: only global admins can access any other random page
get_acl_rule(_RPath, 'GET') -> {global, [configure, webadmin_view]};
get_acl_rule(_RPath, Method)
when Method=:='GET' orelse Method=:='HEAD' ->
{global, [configure, webadmin_view]};
get_acl_rule(_RPath, 'POST') -> {global, [configure]}.
is_acl_match(Host, Rules, Jid) ->
@@ -1036,7 +1040,7 @@ process_admin(global,
auth = {_, _Auth, AJID},
lang = Lang}) ->
Res = list_vhosts(Query, Lang, AJID),
make_xhtml(?H1GL(?T("ejabberd virtual hosts"), "hostnames", "Host Names") ++ Res, global, Lang, AJID);
make_xhtml(?H1GL(?T("Virtual Hosts"), "hostnames", "Host Names") ++ Res, global, Lang, AJID);
process_admin(Host,
#request{
@@ -1706,7 +1710,7 @@ list_given_users(Host, Users, Prefix, Lang, URLFunc) ->
get_offlinemsg_length(ModOffline, User, Server) ->
case ModOffline of
none -> "disabled";
_ -> pretty_string_int(ModOffline:get_queue_length(User, Server))
_ -> pretty_string_int(ModOffline:get_queue_length(list_to_binary(User), list_to_binary(Server)))
end.
get_offlinemsg_module(Server) ->
@@ -2356,7 +2360,7 @@ get_node(global, Node, ["backup"], Query, Lang) ->
ok -> [?XREST("Submitted")];
{error, Error} -> [?XRES(?T("Error") ++": " ++ io_lib:format("~p", [Error]))]
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 ++
[?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', [?XMLATTR(<<"action">>, <<>>), ?XMLATTR(<<"method">>, <<"post">>)],