Merge branch 'master' into bump-idle-timeout

This commit is contained in:
Paweł Chmielowski 2022-10-18 15:40:46 +02:00 committed by GitHub
commit a0c9eb60db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
362 changed files with 11473 additions and 2907 deletions

View File

@ -1,3 +1,46 @@
.git
.win32
.examples
*.swp
*~
\#*#
.#*
.edts
*.dump
/Makefile
/config.log
/config.status
/config/releases.exs
/configure
/aclocal.m4
/*.cache
/deps/
/.deps-update/
/ebin/
/ejabberd.init
/ejabberd.service
/ejabberdctl
/ejabberdctl.example
/rel/ejabberd/
/rel/overlays/
/src/eldap_filter_yecc.erl
/vars.config
/dialyzer/
/test/*.beam
/test/*.ctc
/logs/
/priv/bin/captcha*sh
/priv/sql
/rel/ejabberd
/_build
/database/
/.rebar
/rebar.lock
/log/
Mnesia.nonode@nohost/
# Binaries created with tools/make-{binaries,installers,packages}:
/ejabberd_*.deb
/ejabberd-*.rpm
/ejabberd-*.run
/ejabberd-*.tar.gz

119
.github/container/Dockerfile vendored Normal file
View File

@ -0,0 +1,119 @@
FROM alpine:3.15.4 AS build
ARG VERSION=master
RUN apk upgrade --update musl \
&& apk add \
autoconf \
automake \
bash \
build-base \
curl \
elixir \
erlang-odbc \
erlang-reltool \
expat-dev \
file \
gd-dev \
git \
jpeg-dev \
libpng-dev \
libwebp-dev \
linux-pam-dev \
openssl \
openssl-dev \
sqlite-dev \
yaml-dev \
zlib-dev
RUN mix local.hex --force \
&& mix local.rebar --force
COPY . ./ejabberd
WORKDIR ejabberd
RUN mv .github/container/ejabberdctl.template . \
&& ./autogen.sh \
&& ./configure --with-rebar=mix --enable-all \
&& make deps \
&& make rel
RUN cp -r _build/prod/rel/ejabberd/ /opt/ejabberd-$VERSION \
&& mkdir -p /opt/ejabberd \
&& mv /opt/ejabberd-$VERSION/conf /opt/ejabberd/conf
RUN BINPATH=$(dirname $(find /opt -name msgs))/bin/ \
&& mkdir -p $BINPATH \
&& cp tools/captcha*.sh $BINPATH
RUN [ ! -d .ejabberd-modules ] || cp -r .ejabberd-modules /opt/ejabberd/
RUN export PEM=/opt/ejabberd/conf/server.pem \
&& curl -o "/opt/ejabberd/conf/cacert.pem" 'https://curl.se/ca/cacert.pem' \
&& openssl req -x509 \
-batch \
-nodes \
-newkey rsa:4096 \
-keyout $PEM \
-out $PEM \
-days 3650 \
-subj "/CN=localhost" \
&& sed -i '/^loglevel:/a \ \
\nca_file: /opt/ejabberd/conf/cacert.pem \
\ncertfiles: \
\n - /opt/ejabberd/conf/server.pem' "/opt/ejabberd/conf/ejabberd.yml"
FROM alpine:3.15.4
ENV HOME=/opt/ejabberd
ARG VERSION=master
RUN apk upgrade --update musl \
&& apk add \
expat \
freetds \
gd \
jpeg \
libgd \
libpng \
libstdc++ \
libwebp \
linux-pam \
ncurses-libs \
openssl \
sqlite \
sqlite-libs \
unixodbc \
yaml \
zlib \
&& ln -fs /usr/lib/libtdsodbc.so.0 /usr/lib/libtdsodbc.so \
&& rm -rf /var/cache/apk/*
COPY --from=build /opt /opt
RUN echo -e \
"#!/bin/sh \
\n[ -z \$ERLANG_NODE_ARG ] && export ERLANG_NODE_ARG=ejabberd@localhost \
\nexport CONFIG_DIR=/opt/ejabberd/conf \
\nexport LOGS_DIR=/opt/ejabberd/logs \
\nexport SPOOL_DIR=/opt/ejabberd/database \
\nexec /opt/ejabberd-$VERSION/bin/ejabberdctl \"\$@\"" > /usr/local/bin/ejabberdctl \
&& chmod +x /usr/local/bin/ejabberdctl
RUN addgroup ejabberd -g 9000 \
&& adduser -s /bin/sh -D -G ejabberd ejabberd -u 9000 \
&& mkdir -p $HOME/conf $HOME/database $HOME/logs $HOME/upload \
&& chown -R ejabberd:ejabberd $HOME
HEALTHCHECK \
--interval=1m \
--timeout=5s \
--start-period=5s \
--retries=10 \
CMD /usr/local/bin/ejabberdctl status
WORKDIR $HOME
USER ejabberd
VOLUME ["$HOME/conf", "$HOME/database", "$HOME/logs", "$HOME/upload"]
EXPOSE 1883 4369-4399 5210 5222 5269 5280 5443
ENTRYPOINT ["/usr/local/bin/ejabberdctl"]
CMD ["foreground"]

View File

@ -0,0 +1,294 @@
@echo off
::
:: ejabberd container installer for Windows
:: -------------------------------------
:: v0.4
::
:: This batch script downloads an ejabberd container image
:: and setups a docker container to run ejabberd.
::
:: 1. Download and install Docker:
::
:: If you use Windows 10, download Docker Desktop from:
:: https://www.docker.com/
::
:: If you use Windows 7 or 8, download Docker Toolbox from:
:: https://github.com/docker/toolbox/releases
:: After installation, run Docker Quickstart Installer
::
::
:: 2. Edit those options:
:: Directory where your ejabberd deployment files will be installed
:: (configuration, database, logs, ...)
::
:: In Windows 10 you can configure the path:
set INSTALL_DIR_WINDOWS10=C:\ejabberd
:: In older Windows, not configurable, it will be installed in:
:: C:\Users\%USERNAME%\ejabberd
:: Please enter the desired ejabberd domain name.
:: The domain is the visible attribute that is added to the username
:: to form the Jabber Identifier (for example: user@example.net).
:: This computer must be known on the network with this address name.
:: You can later add more in conf/ejabberd.yml
set HOST=localhost
:: Please enter the administrator username for the current
:: ejabberd installation. A Jabber account with this username
:: will be created and granted administrative privileges.
:: Don't use blankspaces in the username.
set USER=admin
:: Please provide a password for that new administrator account
set PASSWORD=
:: By default this downloads 'latest' ejabberd version,
:: but you can set a specific version, for example '22.05'
:: or the bleeding edge 'master'. See available tags in
:: https://github.com/processone/ejabberd/pkgs/container/ejabberd
set VERSION=latest
:: This tells docker what ports ejabberd will use.
:: You can later configure them in conf/ejabberd.yml
set PORTS=5180 5222 5269 5443
::
:: 3. Now save this script and run it.
::
::
:: 4. When installation is completed:
::
:: If using Windows 10, open Docker Desktop and you can:
::
:: - (>) START the ejabberd container
:: - Enter WebAdmin: click the ([->]) OPEN IN BROWSER button
:: - To try ejabberdctl, click the (>_) CLI button, then: ejabberdctl
:: - ([]) STOP the ejabberd container
::
:: If using an old Windows, open Kitematic and you can:
::
:: - START the ejabberd container
:: - Open your configuration, logs, ... in Settings > Volumes
:: - Enter WebAdmin in Settings > Hostname/Ports > click on the 5180 port
:: - Try ejabberdctl in EXEC, then: ejabberdctl
:: - STOP the ejabberd container
::
:: You can delete the container and create it again running this script,
:: the configuration and database are maintained.
::
::===============================================================
:: Check Windows version
::
::===============================================================
set INSTALL_DIR_DOCKER=c/Users/%USERNAME%/ejabberd
for /f "tokens=4-5 delims=. " %%i in ('ver') do set WVERSION=%%i.%%j
if "%wversion%" == "10.0" (
echo === Preparing paths to install in Windows 10...
set INSTALL_DIR=%INSTALL_DIR_WINDOWS10%
set VC=-v %INSTALL_DIR_WINDOWS10%\conf:/opt/ejabberd/conf
set VD=-v %INSTALL_DIR_WINDOWS10%\database:/opt/ejabberd/database
set VL=-v %INSTALL_DIR_WINDOWS10%\logs:/opt/ejabberd/logs
set VM=-v %INSTALL_DIR_WINDOWS10%\ejabberd-modules:/opt/ejabberd/.ejabberd-modules
set DOCKERDOWNLOAD="First download and install Docker Desktop from https://www.docker.com/"
) else (
echo === Preparing paths to install in Windows older than 10...
set INSTALL_DIR=C:\Users\%USERNAME%\ejabberd
set VC=-v "/%INSTALL_DIR_DOCKER%/conf:/opt/ejabberd/conf"
set VD=-v "/%INSTALL_DIR_DOCKER%/database:/opt/ejabberd/database"
set VL=-v "/%INSTALL_DIR_DOCKER%/logs:/opt/ejabberd/logs"
set VM=-v "/%INSTALL_DIR_DOCKER%/ejabberd-modules:/opt/ejabberd/.ejabberd-modules"
set DOCKERDOWNLOAD="First download and install Docker Toolbox from https://github.com/docker/toolbox/releases"
)
set VOLUMES=%VC% %VD% %VL% %VM%
::===============================================================
:: Check docker is installed
::
::===============================================================
docker version >NUL
if %ERRORLEVEL% NEQ 0 (
echo.
echo === ERROR: It seems docker is not installed!!!
echo.
echo %DOCKERDOWNLOAD%
echo === Then try to run this script again.
echo.
pause
exit 1
)
::===============================================================
:: Check install options are correctly set
::
::===============================================================
if [%PASSWORD%]==[] (
echo.
echo === ERROR: PASSWORD not set!!!
echo.
echo === Please edit this script and set the PASSWORD.
echo === Then try to run this script again.
echo.
pause
exit 1
)
::===============================================================
:: Download Docker image
::
::===============================================================
set IMAGE=ghcr.io/processone/ejabberd:%VERSION%
echo.
echo === Checking if the '%IMAGE%' container image was already downloaded...
docker image history %IMAGE% >NUL
if %ERRORLEVEL% NEQ 0 (
echo === The '%IMAGE%' container image was not downloaded yet.
echo.
echo === Downloading the '%IMAGE%' container image, please wait...
docker pull %IMAGE%
) else (
echo === The '%IMAGE%' container image was already downloaded.
)
::===============================================================
:: Create preliminary container
::
::===============================================================
echo.
echo === Checking if the 'ejabberd' container already exists...
docker container logs ejabberd
if %ERRORLEVEL% EQU 0 (
echo.
echo === The 'ejabberd' container already exists.
echo === Nothing to do, so installation finishes now.
echo === You can go to Docker Desktop and start the 'ejabberd' container.
echo.
pause
exit 1
) else (
echo === The 'ejabberd' container doesn't yet exist,
echo === so let's continue the installation process.
)
echo.
if exist %INSTALL_DIR% (
echo === The INSTALL_DIR %INSTALL_DIR% already exists.
echo === No need to create the preliminary 'ejabberd-pre' image.
) else (
echo === The INSTALL_DIR %INSTALL_DIR% doesn't exist.
echo === Let's create the preliminary 'ejabberd-pre' image.
CALL :create-ejabberd-pre
)
::===============================================================
:: Create final container
::
::===============================================================
echo.
echo === Creating the final 'ejabberd' container using %IMAGE% image...
setlocal EnableDelayedExpansion
set PS=
for %%a in (%PORTS%) do (
set PS=!PS! -p %%a:%%a
)
docker create --name ejabberd --hostname localhost %PS% %VOLUMES% %IMAGE%
echo.
echo === Installation completed.
echo.
pause
EXIT /B %ERRORLEVEL%
::===============================================================
:: Function to create preliminary container
::
::===============================================================
:create-ejabberd-pre
echo.
echo === Creating a preliminary 'ejabberd-pre' container using %IMAGE% image...
docker create --name ejabberd-pre --hostname localhost %IMAGE%
echo.
echo === Now 'ejabberd-pre' will be started.
docker container start ejabberd-pre
echo.
echo === Waiting ejabberd to be running...
set /A timeout = 10
set status=4
goto :while
:statusstart
docker exec -it ejabberd-pre ejabberdctl status
goto :statusend
:while
if %status% GTR 0 (
echo.
timeout /t 1 /nobreak >NUL
set /A timeout = timeout - 1
if %timeout% EQU 0 (
set status=-1
) else (
goto :statusstart
:statusend
set status=%ERRORLEVEL%
)
goto :while
)
echo.
echo === Setting a few options...
docker exec -it ejabberd-pre sed -i "s!- localhost!- %HOST%!g" conf/ejabberd.yml
docker exec -it ejabberd-pre sed -i "s!^acl:!acl:\n admin:\n user:\n - \"%USER%@%HOST%\"!g" conf/ejabberd.yml
docker exec -it ejabberd-pre sed -i "s!5280!5180!g" conf/ejabberd.yml
docker exec -it ejabberd-pre sed -i "s!/admin!/!g" conf/ejabberd.yml
docker exec -it ejabberd-pre ejabberdctl reload_config
echo.
echo === Registering the administrator account...
docker exec -it ejabberd-pre ejabberdctl register %USER% %HOST% %PASSWORD%
docker exec -it ejabberd-pre ejabberdctl stop
echo.
echo === Copying conf, database, logs...
mkdir %INSTALL_DIR%
mkdir %INSTALL_DIR%\conf
mkdir %INSTALL_DIR%\database
mkdir %INSTALL_DIR%\logs
mkdir %INSTALL_DIR%\ejabberd-modules
docker cp ejabberd-pre:/opt/ejabberd/conf/ %INSTALL_DIR%
docker cp ejabberd-pre:/opt/ejabberd/database/ %INSTALL_DIR%
docker cp ejabberd-pre:/opt/ejabberd/logs/ %INSTALL_DIR%
echo.
echo === Deleting the preliminary 'ejabberd-pre' container...
docker stop ejabberd-pre
docker rm ejabberd-pre
EXIT /B 0

387
.github/container/ejabberdctl.template vendored Executable file
View File

@ -0,0 +1,387 @@
#!/bin/sh
# define default configuration
POLL=true
ERL_MAX_PORTS=32000
ERL_PROCESSES=250000
ERL_MAX_ETS_TABLES=1400
FIREWALL_WINDOW=""
INET_DIST_INTERFACE=""
ERLANG_NODE=ejabberd@localhost
# define default environment variables
[ -z "$SCRIPT" ] && SCRIPT=$0
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd -P)"
# shellcheck disable=SC2034
ERTS_VSN="{{erts_vsn}}"
ERL="{{erl}}"
IEX="{{bindir}}/iex"
EPMD="{{epmd}}"
[ -z "$ERLANG_COOKIE" ] && ERL_OPTIONS="-setcookie $(cat "${SCRIPT_DIR%/*}/releases/COOKIE")"
[ -n "$ERLANG_COOKIE" ] && [ ! -f "$HOME"/.erlang.cookie ] && echo "$ERLANG_COOKIE" > "$HOME"/.erlang.cookie && chmod 400 "$HOME"/.erlang.cookie
# check the proper system user is used
case $(id -un) in
"$INSTALLUSER")
EXEC_CMD="as_current_user"
;;
root)
if [ -n "$INSTALLUSER" ] ; then
EXEC_CMD="as_install_user"
else
EXEC_CMD="as_current_user"
echo "WARNING: It is not recommended to run ejabberd as root" >&2
fi
;;
*)
if [ -n "$INSTALLUSER" ] ; then
echo "ERROR: This command can only be run by root or the user $INSTALLUSER" >&2
exit 7
else
EXEC_CMD="as_current_user"
fi
;;
esac
# parse command line parameters
while [ $# -gt 0 ]; do
case $1 in
-n|--node) ERLANG_NODE_ARG=$2; shift 2;;
-s|--spool) SPOOL_DIR=$2; shift 2;;
-l|--logs) LOGS_DIR=$2; shift 2;;
-f|--config) EJABBERD_CONFIG_PATH=$2; shift 2;;
-c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift 2;;
-d|--config-dir) CONFIG_DIR=$2; shift 2;;
-t|--no-timeout) NO_TIMEOUT="--no-timeout"; shift;;
*) break;;
esac
done
# define ejabberd variables if not already defined from the command line
: "${CONFIG_DIR:="{{config_dir}}"}"
: "${LOGS_DIR:="{{logs_dir}}"}"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_CONFIG_PATH:="$CONFIG_DIR/ejabberd.yml"}"
: "${EJABBERDCTL_CONFIG_PATH:="$CONFIG_DIR/ejabberdctl.cfg"}"
# Allows passing extra Erlang command-line arguments in vm.args file
: "${VMARGS:="$CONFIG_DIR/vm.args"}"
# shellcheck source=ejabberdctl.cfg.example
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# define erl parameters
ERLANG_OPTS="+K $POLL +P $ERL_PROCESSES $ERL_OPTIONS"
if [ -n "$FIREWALL_WINDOW" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
fi
if [ -n "$INET_DIST_INTERFACE" ] ; then
INET_DIST_INTERFACE2=$("$ERL" -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
if [ -n "$INET_DIST_INTERFACE2" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
fi
fi
[ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -erl_epmd_port $ERL_DIST_PORT -start_epmd false"
# if vm.args file exists in config directory, pass it to Erlang VM
[ -f "$VMARGS" ] && ERLANG_OPTS="$ERLANG_OPTS -args_file $VMARGS"
ERL_LIBS='{{libdir}}'
ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump
ERL_INETRC="$CONFIG_DIR"/inetrc
# define ejabberd parameters
EJABBERD_OPTS="$EJABBERD_OPTS\
$(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]\{1,\}\).*/ \1/;s/:[ \t]*\(infinity\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_burst_limit_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_burst_limit_window_time/!d;s/:[ \t]*\([0-9]*[a-z]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")"
[ -n "$EJABBERD_OPTS" ] && EJABBERD_OPTS="-ejabberd $EJABBERD_OPTS"
EJABBERD_OPTS="-mnesia dir \"$SPOOL_DIR\" $MNESIA_OPTIONS $EJABBERD_OPTS -s ejabberd"
# export global variables
export EJABBERD_CONFIG_PATH
export EJABBERD_LOG_PATH
export EJABBERD_PID_PATH
export ERL_CRASH_DUMP
export ERL_EPMD_ADDRESS
export ERL_DIST_PORT
export ERL_INETRC
export ERL_MAX_PORTS
export ERL_MAX_ETS_TABLES
export CONTRIB_MODULES_PATH
export CONTRIB_MODULES_CONF_DIR
export ERL_LIBS
export SCRIPT_DIR
set_dist_client()
{
[ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -dist_listen false"
}
# run command either directly or via su $INSTALLUSER
run_cmd()
{
case $EXEC_CMD in
as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;;
as_current_user) "$@" ;;
esac
}
exec_cmd()
{
case $EXEC_CMD in
as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;;
as_current_user) exec "$@" ;;
esac
}
run_erl()
{
NODE=$1; shift
run_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@"
}
exec_erl()
{
NODE=$1; shift
exec_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@"
}
exec_iex()
{
NODE=$1; shift
exec_cmd "$IEX" -${S:--}name "$NODE" --erl "$ERLANG_OPTS" "$@"
}
# usage
debugwarning()
{
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
echo "--------------------------------------------------------------------"
echo ""
echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell"
echo "to an already running ejabberd node."
echo "If an ERROR is printed, it means the connection was not successful."
echo "You can interact with the ejabberd node if you know how to use it."
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
echo "To detach this shell from ejabberd, press:"
echo " control+c, control+c"
echo ""
echo "--------------------------------------------------------------------"
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue"
read -r _
echo ""
fi
}
livewarning()
{
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
echo "--------------------------------------------------------------------"
echo ""
echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode."
echo "All log messages will be shown in the command shell."
echo "You can interact with the ejabberd node if you know how to use it."
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
echo "To exit this LIVE mode and stop ejabberd, press:"
echo " q(). and press the Enter key"
echo ""
echo "--------------------------------------------------------------------"
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue"
read -r _
echo ""
fi
}
help()
{
echo ""
echo "Commands to start an ejabberd node:"
echo " start Start in server mode"
echo " foreground Start in server mode (attached)"
echo " foreground-quiet Start in server mode (attached), show only critical messages"
echo " live Start in interactive mode, with Erlang shell"
echo " iexlive Start in interactive mode, with Elixir shell"
echo ""
echo "Commands to interact with a running ejabberd node:"
echo " debug Attach an interactive Erlang shell to a running node"
echo " iexdebug Attach an interactive Elixir shell to a running node"
echo " etop Attach to a running node and start Erlang Top"
echo " ping Send ping to the node, returns pong or pang"
echo " started|stopped Wait for the node to fully start|stop"
echo ""
echo "Optional parameters when starting an ejabberd node:"
echo " --config-dir dir Config ejabberd: $CONFIG_DIR"
echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH"
echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH"
echo " --logs dir Directory for logs: $LOGS_DIR"
echo " --spool dir Database spool dir: $SPOOL_DIR"
echo " --node nodename ejabberd node name: $ERLANG_NODE"
echo ""
}
# dynamic node name helper
uid()
{
uuid=$(uuidgen 2>/dev/null)
random=$(awk 'BEGIN { srand(); print int(rand()*32768) }' /dev/null)
[ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid)
[ -z "$uuid" ] && uuid=$(printf "%X" "${random:-$$}$(date +%M%S)")
uuid=$(printf '%s' $uuid | sed 's/^\(...\).*$/\1/')
[ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}"
[ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}"
[ $# -eq 2 ] && echo "${uuid}-${1}@${2}"
}
# stop epmd if there is no other running node
stop_epmd()
{
[ -n "$ERL_DIST_PORT" ] && return
"$EPMD" -names 2>/dev/null | grep -q name || "$EPMD" -kill >/dev/null
}
# make sure node not already running and node name unregistered
# if all ok, ensure runtime directory exists and make it current directory
check_start()
{
[ -n "$ERL_DIST_PORT" ] && return
"$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && {
pgrep -f "$ERLANG_NODE" >/dev/null && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running."
exit 4
}
pgrep beam >/dev/null && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered,"
echo " but no related beam process has been found."
echo "Shutdown all other erlang nodes, and call 'epmd -kill'."
exit 5
}
"$EPMD" -kill >/dev/null
}
}
post_waiter_fork()
{
(FIRST_RUN=$FIRST_RUN "$0" post_waiter)&
}
post_waiter_waiting()
{
$0 started
[ -n "$FIRST_RUN" ] && [ -n "$CTL_ON_CREATE" ] && (post_waiter_loop $CTL_ON_CREATE)
[ -n "$CTL_ON_START" ] && post_waiter_loop $CTL_ON_START
}
post_waiter_loop()
{
LIST=$@
HEAD=${LIST%% ; *}
TAIL=${LIST#* ; }
echo ":> ejabberdctl $HEAD"
$0 $HEAD
[ "$HEAD" = "$TAIL" ] || post_waiter_loop $TAIL
}
# allow sync calls
wait_status()
{
# args: status try delay
# return: 0 OK, 1 KO
timeout="$2"
status=4
while [ "$status" -ne "$1" ] ; do
sleep "$3"
timeout=$((timeout - 1))
if [ $timeout -eq 0 ] ; then
status="$1"
else
run_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null
status="$?"
fi
done
[ $timeout -gt 0 ]
}
# ensure we can change current directory to SPOOL_DIR
[ -f "$SPOOL_DIR/schema.DAT" ] || FIRST_RUN=true
[ -d "$SPOOL_DIR" ] || run_cmd mkdir -p "$SPOOL_DIR"
cd "$SPOOL_DIR" || {
echo "ERROR: can not access directory $SPOOL_DIR"
exit 6
}
# main
case $1 in
start)
check_start
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached
;;
foreground)
check_start
post_waiter_fork
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput
;;
foreground-quiet)
check_start
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput -ejabberd quiet true
;;
live)
livewarning
check_start
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS
;;
debug)
debugwarning
set_dist_client
exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE"
;;
etop)
set_dist_client
exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \
-s erlang halt -output text
;;
iexdebug)
debugwarning
set_dist_client
exec_iex "$(uid debug)" --remsh "$ERLANG_NODE"
;;
iexlive)
livewarning
exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd
;;
ping)
PEER=${2:-$ERLANG_NODE}
[ "$PEER" = "${PEER%.*}" ] && PS="-s"
set_dist_client
exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \
-noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
-s erlang halt -output text
;;
started)
set_dist_client
wait_status 0 30 2 # wait 30x2s before timeout
;;
stopped)
set_dist_client
wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout
;;
post_waiter)
post_waiter_waiting
;;
*)
set_dist_client
run_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
result=$?
case $result in
2|3) help;;
*) :;;
esac
exit $result
;;
esac

229
.github/workflows/ci-19.3.yml vendored Normal file
View File

@ -0,0 +1,229 @@
name: CI (19.3)
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
pull_request:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
jobs:
tests:
name: Tests
strategy:
fail-fast: false
matrix:
otp: ['19.3']
runs-on: ubuntu-18.04
services:
redis:
image: redis
ports:
- 6379:6379
steps:
- uses: actions/checkout@v3
- name: Get specific Erlang/OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- name: Get a compatible Rebar3
run: |
rm rebar3
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
chmod +x rebar3
- name: Prepare databases
run: |
sudo systemctl start mysql.service
sudo systemctl start postgresql.service
mysql -u root -proot -e "CREATE USER 'ejabberd_test'@'localhost'
IDENTIFIED BY 'ejabberd_test';"
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
mysql -u root -proot -e "GRANT ALL ON ejabberd_test.*
TO 'ejabberd_test'@'localhost';"
mysql -u root -proot ejabberd_test < sql/mysql.sql
pg_isready
sudo -u postgres psql -c "CREATE USER ejabberd_test
WITH PASSWORD 'ejabberd_test';"
sudo -u postgres psql -c "CREATE DATABASE ejabberd_test;"
sudo -u postgres psql ejabberd_test -f sql/pg.sql
sudo -u postgres psql -c "GRANT ALL PRIVILEGES
ON DATABASE ejabberd_test TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
TABLES IN SCHEMA public
TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
SEQUENCES IN SCHEMA public
TO ejabberd_test;"
- name: Prepare libraries
run: |
sudo apt-get -qq update
sudo apt-get -y purge libgd3 nginx
sudo apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Prepare rebar
run: |
echo '{xref_ignores, [{eldap_filter_yecc, return_error, 2}
]}.' >>rebar.config
echo '{xref_checks, [deprecated_function_calls, deprecated_functions,
locals_not_used, undefined_function_calls, undefined_functions]}.
% Disabled: exports_not_used,' >>rebar.config
echo '{dialyzer, [{get_warnings, true}, {plt_extra_apps, [cache_tab,
eimp, epam, esip, ezlib, fast_tls, fast_xml, fast_yaml,
mqtree, p1_acme, p1_mysql, p1_oauth2, p1_pgsql, p1_utils, pkix,
sqlite3, stringprep, stun, xmpp, yconf]} ]}.' >>rebar.config
echo '{ct_extra_params, "-verbosity 20"}.' >>rebar.config
echo "{ct_opts, [{verbosity, 20}, {keep_logs, 20}]}." >>rebar.config
- name: Remove syntax_tools from release
run: sed -i 's|, syntax_tools||g' src/ejabberd.app.src.script
- name: Cache rebar
uses: actions/cache@v3
with:
path: |
~/.cache/rebar3/
key: ${{matrix.otp}}-${{hashFiles('rebar.config')}}
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=./rebar3 \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-elixir \
--disable-mssql \
--disable-odbc
make update
make
- run: make install -s
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- name: Check Production Release
run: |
make rel
RE=_build/prod/rel/ejabberd
$RE/bin/ejabberdctl start
$RE/bin/ejabberdctl started
$RE/bin/ejabberdctl stop
$RE/bin/ejabberdctl stopped
cat $RE/logs/ejabberd.log
grep -q "is stopped in" $RE/logs/ejabberd.log
- name: Check Development Release
run: |
make dev
RE=_build/dev/rel/ejabberd
$RE/bin/ejabberdctl start
$RE/bin/ejabberdctl started
$RE/bin/ejabberdctl stop
$RE/bin/ejabberdctl stopped
cat $RE/logs/ejabberd.log
grep -q "is stopped in" $RE/logs/ejabberd.log
- name: Run tests
id: ct
run: |
(cd priv && ln -sf ../sql)
COMMIT=`echo $GITHUB_SHA | cut -c 1-7`
DATE=`date +%s`
REF_NAME=`echo $GITHUB_REF_NAME | tr "/" "_"`
NODENAME=$DATE@$GITHUB_RUN_NUMBER-$GITHUB_ACTOR-$REF_NAME-$COMMIT
LABEL=`git show -s --format=%s | cut -c 1-30`
./rebar3 ct --name $NODENAME --label "$LABEL"
./rebar3 cover
- name: Check results
if: always() && (steps.ct.outcome != 'skipped' || steps.ct2.outcome != 'skipped')
id: ctresults
run: |
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View logs failures
if: failure() && steps.ctresults.outcome == 'failure'
run: |
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
find logs/ -name error.log -exec cat '{}' ';'
find logs/ -name exunit.log -exec cat '{}' ';'
- name: Upload test logs
if: always() && steps.ct.outcome == 'failure' && github.repository == 'processone/ejabberd'
uses: peaceiris/actions-gh-pages@v3
with:
publish_dir: _build/test
exclude_assets: '.github,lib,plugins'
external_repository: processone/ecil
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
keep_files: true
- name: View ECIL address
if: always() && steps.ct.outcome == 'failure' && github.repository == 'processone/ejabberd'
run: |
CTRUN=`ls -la _build/test/logs/last | sed 's|.*-> ||'`
echo "::notice::View CT results: https://processone.github.io/ecil/logs/$CTRUN/"
- name: Prepare new schema
run: |
[[ -d logs ]] && rm -rf logs
[[ -d _build/test/logs ]] && rm -rf _build/test/logs || true
mysql -u root -proot -e "DROP DATABASE ejabberd_test;"
sudo -u postgres psql -c "DROP DATABASE ejabberd_test;"
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
mysql -u root -proot -e "GRANT ALL ON ejabberd_test.*
TO 'ejabberd_test'@'localhost';"
mysql -u root -proot ejabberd_test < sql/mysql.new.sql
sudo -u postgres psql -c "CREATE DATABASE ejabberd_test;"
sudo -u postgres psql ejabberd_test -f sql/pg.new.sql
sudo -u postgres psql -c "GRANT ALL PRIVILEGES
ON DATABASE ejabberd_test TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
TABLES IN SCHEMA public
TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
SEQUENCES IN SCHEMA public
TO ejabberd_test;"
sed -i 's|new_schema, false|new_schema, true|g' test/suite.erl
- run: CT_BACKENDS=mysql,pgsql make test
id: ctnewschema
- name: Check results
if: always() && steps.ctnewschema.outcome != 'skipped'
run: |
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View logs failures
if: failure() && steps.ctnewschema.outcome != 'skipped'
run: |
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
find logs/ -name error.log -exec cat '{}' ';'
find logs/ -name exunit.log -exec cat '{}' ';'

View File

@ -25,15 +25,8 @@ jobs:
strategy:
fail-fast: false
matrix:
otp: ['19.3', '24.0']
include:
- otp: '19.3'
rebar: 2
os: ubuntu-18.04
- otp: '24.0'
rebar: 3
os: ubuntu-20.04
runs-on: ${{ matrix.os }}
otp: ['20.0', '21.3', '24.3', '25']
runs-on: ubuntu-20.04
services:
redis:
image: redis
@ -42,14 +35,29 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Get previous Erlang/OTP
uses: ErlGang/setup-erlang@master
if: matrix.otp != 24.0
- name: Test shell scripts
if: matrix.otp == 25
run: |
shellcheck test/ejabberd_SUITE_data/gencerts.sh
shellcheck tools/captcha.sh
shellcheck ejabberd.init.template
shellcheck -x ejabberdctl.template
- name: Get specific Erlang/OTP
if: matrix.otp != 25
uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- name: Get a compatible Rebar3
if: matrix.otp <= '21.3'
run: |
rm rebar3
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
chmod +x rebar3
- name: Prepare databases
run: |
sudo systemctl start mysql.service
@ -77,11 +85,11 @@ jobs:
- name: Prepare libraries
run: |
sudo apt-get -qq update
sudo apt-get -y purge libgd3 nginx
sudo apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Prepare rebar
id: rebar
run: |
echo '{xref_ignores, [{eldap_filter_yecc, return_error, 2}
]}.' >>rebar.config
@ -93,81 +101,103 @@ jobs:
mqtree, p1_acme, p1_mysql, p1_oauth2, p1_pgsql, p1_utils, pkix,
sqlite3, stringprep, stun, xmpp, yconf]} ]}.' >>rebar.config
echo '{ct_extra_params, "-verbosity 20"}.' >>rebar.config
echo "{ct_opts, [{verbosity, 20}, {keep_logs, 20}]}." >>rebar.config
- name: Cache rebar2
if: matrix.rebar == 2
uses: actions/cache@v2
- name: Remove syntax_tools from release
run: sed -i 's|, syntax_tools||g' src/ejabberd.app.src.script
- name: Cache rebar
uses: actions/cache@v3
with:
path: |
deps/
dialyzer/
ebin/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
~/.cache/rebar3/
key: ${{matrix.otp}}-${{hashFiles('rebar.config')}}
- name: Cache rebar3
if: matrix.rebar == 3
uses: actions/cache@v2
with:
path: ~/.cache/rebar3/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
- name: Download test logs
if: matrix.otp == 25 && github.repository == 'processone/ejabberd'
continue-on-error: true
run: |
mkdir -p _build/test
curl -sSL https://github.com/processone/ecil/tarball/gh-pages |
tar -C _build/test --strip-components=1 --wildcards -xzf -
rm -rf _build/test/logs/last/
- name: Compile
run: |
./autogen.sh
[[ ${{ matrix.rebar }} = 2 ]] && REBAR=rebar || REBAR=`which rebar3`
./configure --with-rebar=$REBAR \
./configure --with-rebar=./rebar3 \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-elixir \
--disable-mssql \
--disable-odbc
make update
make
- run: make rel
- run: make install -s
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- run: make test
- name: Check Production Release
run: |
make rel
RE=_build/prod/rel/ejabberd
$RE/bin/ejabberdctl start
$RE/bin/ejabberdctl started
$RE/bin/ejabberdctl stop
$RE/bin/ejabberdctl stopped
cat $RE/logs/ejabberd.log
grep -q "is stopped in" $RE/logs/ejabberd.log
- name: Check Development Release
run: |
make dev
RE=_build/dev/rel/ejabberd
$RE/bin/ejabberdctl start
$RE/bin/ejabberdctl started
$RE/bin/ejabberdctl stop
$RE/bin/ejabberdctl stopped
cat $RE/logs/ejabberd.log
grep -q "is stopped in" $RE/logs/ejabberd.log
- name: Run tests
id: ct
run: |
(cd priv && ln -sf ../sql)
COMMIT=`echo $GITHUB_SHA | cut -c 1-7`
DATE=`date +%s`
REF_NAME=`echo $GITHUB_REF_NAME | tr "/" "_"`
NODENAME=$DATE@$GITHUB_RUN_NUMBER-$GITHUB_ACTOR-$REF_NAME-$COMMIT
LABEL=`git show -s --format=%s | cut -c 1-30`
./rebar3 ct --name $NODENAME --label "$LABEL"
./rebar3 cover
- name: Check results
if: always()
if: always() && (steps.ct.outcome != 'skipped' || steps.ct2.outcome != 'skipped')
id: ctresults
run: |
[[ -d _build ]] && ln -s _build/test/logs/ logs \
&& ln `find _build/ -name "*dialyzer_warnings"` \
logs/dialyzer.log \
|| ln dialyzer/error.log logs/dialyzer.log
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View dialyzer report
run: cat logs/dialyzer.log
- name: View full suite.log
run: cat logs/suite.log
- name: View suite.log failures
if: failure()
run: cat logs/suite.log | awk
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
- name: View full ejabberd.log
if: failure()
run: find logs/ -name ejabberd.log -exec cat '{}' ';'
- name: View exunit.log
if: failure()
run: find logs/ -name exunit.log -exec cat '{}' ';'
- name: View logs failures
if: failure() && steps.ctresults.outcome == 'failure'
run: |
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
find logs/ -name error.log -exec cat '{}' ';'
find logs/ -name exunit.log -exec cat '{}' ';'
- name: Send to coveralls
if: matrix.otp == 24.0
if: matrix.otp == 25
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
rebar3 as test coveralls send
DIAGNOSTIC=1 ./rebar3 as test coveralls send
curl -v -k https://coveralls.io/webhook \
--header "Content-Type: application/json" \
--data '{"repo_name":"$GITHUB_REPOSITORY",
@ -175,64 +205,57 @@ jobs:
"payload":{"build_num":$GITHUB_RUN_ID,
"status":"done"}}'
binaries:
name: Binaries
needs: [tests]
strategy:
fail-fast: false
matrix:
otp: ['21.3']
include:
- otp: '21.3'
rebar: 3
os: ubuntu-20.04
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Upload test logs
if: always() && steps.ct.outcome == 'failure' && github.repository == 'processone/ejabberd'
uses: peaceiris/actions-gh-pages@v3
with:
fetch-depth: 150
- name: Get last git tag
publish_dir: _build/test
exclude_assets: '.github,lib,plugins'
external_repository: processone/ecil
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
keep_files: true
- name: View ECIL address
if: always() && steps.ct.outcome == 'failure' && github.repository == 'processone/ejabberd'
run: |
export TAGLAST=`git ls-remote --tags --refs origin 'refs/tags/2*' \
| tail -1 | awk '{print $2}'`
git fetch origin "$TAGLAST:$TAGLAST"
git describe
- name: Get previous Erlang/OTP
uses: ErlGang/setup-erlang@master
with:
otp-version: ${{ matrix.otp }}
- name: Get a compatible Rebar3
CTRUN=`ls -la _build/test/logs/last | sed 's|.*-> ||'`
echo "::notice::View CT results: https://processone.github.io/ecil/logs/$CTRUN/"
- name: Prepare new schema
run: |
wget https://github.com/erlang/rebar3/releases/download/3.15.2/rebar3 \
&& chmod +x rebar3
- name: Cache Rebar3
uses: actions/cache@v2
with:
path: ~/.cache/rebar3/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
- name: Prepare libraries
[[ -d logs ]] && rm -rf logs
[[ -d _build/test/logs ]] && rm -rf _build/test/logs || true
mysql -u root -proot -e "DROP DATABASE ejabberd_test;"
sudo -u postgres psql -c "DROP DATABASE ejabberd_test;"
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
mysql -u root -proot -e "GRANT ALL ON ejabberd_test.*
TO 'ejabberd_test'@'localhost';"
mysql -u root -proot ejabberd_test < sql/mysql.new.sql
sudo -u postgres psql -c "CREATE DATABASE ejabberd_test;"
sudo -u postgres psql ejabberd_test -f sql/pg.new.sql
sudo -u postgres psql -c "GRANT ALL PRIVILEGES
ON DATABASE ejabberd_test TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
TABLES IN SCHEMA public
TO ejabberd_test;"
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
SEQUENCES IN SCHEMA public
TO ejabberd_test;"
sed -i 's|new_schema, false|new_schema, true|g' test/suite.erl
- run: CT_BACKENDS=mysql,pgsql make test
id: ctnewschema
- name: Check results
if: always() && steps.ctnewschema.outcome != 'skipped'
run: |
sudo apt-get -qq update
sudo apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Compile
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View logs failures
if: failure() && steps.ctnewschema.outcome != 'skipped'
run: |
./autogen.sh
./configure --with-rebar=./rebar3 \
--prefix=/tmp/ejabberd \
--disable-debug \
--enable-all \
--disable-elixir
make update
make
- run: make install -s
- name: Strip binaries
run: echo 'beam_lib:strip_files(filelib:wildcard(
"/tmp/ejabberd/lib/*/ebin/*beam")), init:stop().' \
| erl -boot start_clean
- name: Upload binaries
uses: actions/upload-artifact@v2
with:
name: ejabberd-binaries
path: /tmp/ejabberd/lib
retention-days: 7
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
find logs/ -name error.log -exec cat '{}' ';'
find logs/ -name exunit.log -exec cat '{}' ';'

75
.github/workflows/container.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: Container
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
container:
name: Container
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Check out repository code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Checkout ejabberd-contrib
uses: actions/checkout@v3
with:
repository: processone/ejabberd-contrib
path: .ejabberd-modules/sources/ejabberd-contrib
- name: Log in to the Container registry
uses: docker/login-action@v1.14.1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get git describe
id: gitdescribe
run: echo "::set-output name=ver::$(git describe --tags)"
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3.8.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: |
org.opencontainers.image.revision=${{ steps.gitdescribe.outputs.ver }}
org.opencontainers.image.licenses=GPL-2.0
org.opencontainers.image.vendor=ProcessOne
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push Docker image
uses: docker/build-push-action@v2.10.0
with:
build-args: |
VERSION=${{ steps.gitdescribe.outputs.ver }}
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
file: .github/container/Dockerfile
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}

84
.github/workflows/installers.yml vendored Normal file
View File

@ -0,0 +1,84 @@
name: Installers
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
pull_request:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
jobs:
binaries:
name: Binaries
runs-on: ubuntu-latest
steps:
- name: Cache build directory
uses: actions/cache@v3
with:
path: ~/build/
key: ${{runner.os}}-ct-ng-1.25.0
- name: Install prerequisites
run: |
sudo apt-get -qq update
sudo apt-get -qq install makeself
# https://github.com/crosstool-ng/crosstool-ng/blob/master/testing/docker/ubuntu21.10/Dockerfile
sudo apt-get -qq install build-essential autoconf bison flex gawk
sudo apt-get -qq install help2man libncurses5-dev libtool libtool-bin
sudo apt-get -qq install python3-dev texinfo unzip
- name: Install FPM
run: |
gem install --no-document --user-install fpm
echo $HOME/.gem/ruby/*/bin >> $GITHUB_PATH
- name: Check out repository code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Build binary archives
run: CHECK_DEPS=false tools/make-binaries
- name: Build DEB and RPM packages
run: tools/make-packages
- name: Build installers
run: tools/make-installers
- name: Collect packages
run: |
mkdir ejabberd-packages
mv ejabberd_*.deb ejabberd-*.rpm ejabberd-*.run ejabberd-packages
- name: Upload packages
uses: actions/upload-artifact@v3
with:
name: ejabberd-packages
#
# Appending the wildcard character ("*") is a trick to make
# "ejabberd-packages" the root directory of the uploaded ZIP file:
#
# https://github.com/actions/upload-artifact#upload-using-multiple-paths-and-exclusions
#
path: ejabberd-packages*
retention-days: 14
release:
name: Release
needs: [binaries]
runs-on: ubuntu-latest
if: github.ref_type == 'tag'
steps:
- name: Download packages
uses: actions/download-artifact@v3
with:
name: ejabberd-packages
- name: Draft Release
uses: softprops/action-gh-release@v1
with:
draft: true
files: ejabberd-packages/*

202
.github/workflows/runtime.yml vendored Normal file
View File

@ -0,0 +1,202 @@
name: Runtime
on:
push:
paths:
- '*'
- '!*.md'
- '.github/workflows/runtime.yml'
- 'checkouts/**'
- 'config/**'
- 'lib/**'
- 'm4/**'
- 'plugins/**'
- 'rel/**'
pull_request:
paths:
- '*'
- '!*.md'
- '.github/workflows/runtime.yml'
- 'checkouts/**'
- 'config/**'
- 'lib/**'
- 'm4/**'
- 'plugins/**'
- 'rel/**'
jobs:
rebars:
name: Rebars
strategy:
fail-fast: false
matrix:
otp: ['19.3', '20.3', '24.3', '25']
rebar: ['rebar', 'rebar3']
runs-on: ubuntu-latest
container:
image: erlang:${{ matrix.otp }}
steps:
- uses: actions/checkout@v3
- name: Prepare libraries
run: |
apt-get -qq update
apt-get purge -y libgd3
apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=`which ${{ matrix.rebar }}` \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-elixir \
--disable-odbc
make update
make
- name: Prepare rebar
run: |
echo '{xref_ignores, [{eldap_filter_yecc, return_error, 2}
]}.' >>rebar.config
echo '{xref_checks, [deprecated_function_calls, deprecated_functions,
locals_not_used, undefined_function_calls, undefined_functions]}.
% Disabled: exports_not_used,' >>rebar.config
- run: make xref
- name: Test rel (rebar2)
if: matrix.rebar == 'rebar'
run: |
make rel
rel/ejabberd/bin/ejabberdctl start \
&& rel/ejabberd/bin/ejabberdctl started
rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass
rel/ejabberd/bin/ejabberdctl registered_users localhost
cat rel/ejabberd/logs/*
- name: Test rel
if: matrix.rebar != 'rebar'
run: |
make rel
_build/prod/rel/ejabberd/bin/ejabberdctl start \
&& _build/prod/rel/ejabberd/bin/ejabberdctl started
_build/prod/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass
_build/prod/rel/ejabberd/bin/ejabberdctl registered_users localhost
_build/prod/rel/ejabberd/bin/ejabberdctl stop \
&& _build/prod/rel/ejabberd/bin/ejabberdctl stopped
cat _build/prod/rel/ejabberd/logs/*
- name: Test dev
if: matrix.rebar != 'rebar'
run: |
make dev
_build/dev/rel/ejabberd/bin/ejabberdctl start \
&& _build/dev/rel/ejabberd/bin/ejabberdctl started
_build/dev/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass
_build/dev/rel/ejabberd/bin/ejabberdctl registered_users localhost
_build/dev/rel/ejabberd/bin/ejabberdctl stop \
&& _build/dev/rel/ejabberd/bin/ejabberdctl stopped
cat _build/dev/rel/ejabberd/logs/*
mix:
name: Mix
strategy:
fail-fast: false
matrix:
otp: ['21.3', '22.0', '25.0']
elixir: ['1.10.3', '1.11.4', '1.12.3', '1.13.0']
exclude:
- otp: '21.3'
elixir: '1.12.3'
- otp: '21.3'
elixir: '1.13.0'
- otp: '25.0'
elixir: '1.10.3'
- otp: '25.0'
elixir: '1.11.4'
- otp: '25.0'
elixir: '1.12.3'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get specific Erlang/OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- name: Prepare libraries
run: |
sudo apt-get -qq update
sudo apt-get -y purge libgd3 nginx
sudo apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Remove Elixir Matchers
run: |
echo "::remove-matcher owner=elixir-mixCompileWarning::"
echo "::remove-matcher owner=elixir-credoOutputDefault::"
echo "::remove-matcher owner=elixir-mixCompileError::"
echo "::remove-matcher owner=elixir-mixTestFailure::"
echo "::remove-matcher owner=elixir-dialyzerOutputDefault::"
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=mix \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-elixir \
--disable-odbc
mix deps.get
make
- run: make xref
- name: Run rel
run: |
make rel
_build/prod/rel/ejabberd/bin/ejabberdctl start \
&& _build/prod/rel/ejabberd/bin/ejabberdctl started
_build/prod/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass
_build/prod/rel/ejabberd/bin/ejabberdctl registered_users localhost > registered.log
_build/prod/rel/ejabberd/bin/ejabberdctl stop \
&& _build/prod/rel/ejabberd/bin/ejabberdctl stopped
- name: Run dev
run: |
make dev
_build/dev/rel/ejabberd/bin/ejabberdctl start \
&& _build/dev/rel/ejabberd/bin/ejabberdctl started
_build/dev/rel/ejabberd/bin/ejabberdctl register user2 localhost s0mePass
_build/dev/rel/ejabberd/bin/ejabberdctl registered_users localhost >> registered.log
_build/dev/rel/ejabberd/bin/ejabberdctl stop \
&& _build/dev/rel/ejabberd/bin/ejabberdctl stopped
- name: Check rel
if: always()
run: |
grep -q '^user1$' registered.log
grep -q '^user2$' registered.log
grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log
grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log
test $(find _build/prod/ -empty -name error.log)
grep -q 'is started' _build/dev/rel/ejabberd/logs/ejabberd.log
grep -q 'is stopped' _build/dev/rel/ejabberd/logs/ejabberd.log
test $(find _build/dev/ -empty -name error.log)
- name: View logs failures
if: failure()
run: |
cat _build/prod/rel/ejabberd/logs/ejabberd.log
cat _build/prod/rel/ejabberd/logs/error.log
cat _build/dev/rel/ejabberd/logs/ejabberd.log
cat _build/dev/rel/ejabberd/logs/error.log

6
.gitignore vendored
View File

@ -15,6 +15,7 @@
/*.cache
/deps/
/.deps-update/
/.ejabberd-modules/
/ebin/
/ejabberd.init
/ejabberd.service
@ -37,3 +38,8 @@
/rebar.lock
/log/
Mnesia.nonode@nohost/
# Binaries created with tools/make-{binaries,installers,packages}:
/ejabberd_*.deb
/ejabberd-*.rpm
/ejabberd-*.run
/ejabberd-*.tar.gz

4
.shellcheckrc Normal file
View File

@ -0,0 +1,4 @@
disable=SC2016,SC2086,SC2089,SC2090
external-sources=true
source=ejabberdctl.cfg.example
shell=sh

View File

@ -1,9 +1,160 @@
# Version 22.05
Core
- C2S: Don't expect that socket will be available in `c2s_terminated` hook
- Event handling process hook tracing
- Guard against `erlang:system_info(logical_processors)` not always returning a number
- `domain_balancing`: Allow for specifying `type` only, without specifying `component_number`
MQTT
- Add TLS certificate authentication for MQTT connections
- Fix login when generating client id, keep connection record (#3593)
- Pass property name as expected in mqtt_codec (fixes login using MQTT 5)
- Support MQTT subscriptions spread over the cluster (#3750)
MUC
- Attach meta field with real jid to mucsub subscription events
- Handle user removal
- Stop empty MUC rooms 30 seconds after creation
- `default_room_options`: Update options configurable
- `subscribe_room_many_max_users`: New option in `mod_muc_admin`
mod_conversejs
- Improved options to support `@HOST@` and `auto` values
- Set `auth` and `register` options based on ejabberd configuration
- `conversejs_options`: New option
- `conversejs_resources`: New option
PubSub
- `mod_pubsub`: Allow for limiting `item_expire` value
- `mod_pubsub`: Unsubscribe JID on whitelist removal
- `node_pep`: Add config-node and multi-items features (#3714)
SQL
- Improve compatibility with various db engine versions
- Sync old-to-new schema script with reality (#3790)
- Slight improvement in MSSQL testing support, but not yet complete
Other Modules
- `auth_jwt`: Checking if an user is active in SM for a JWT authenticated user (#3795)
- `mod_configure`: Implement Get List of Registered/Online Users from XEP-0133
- `mod_host_meta`: New module to serve host-meta files, see XEP-0156
- `mod_mam`: Store all mucsub notifications not only message notifications
- `mod_ping`: Delete ping timer if resource is gone after the ping has been sent
- `mod_ping`: Don't send ping if resource is gone
- `mod_push`: Fix notifications for pending sessions (XEP-0198)
- `mod_push`: Keep push session ID on session resume
- `mod_shared_roster`: Adjust special group cache size
- `mod_shared_roster`: Normalize JID on unset_presence (#3752)
- `mod_stun_disco`: Fix parsing of IPv6 listeners
Dependencies
- autoconf: Supported from 2.59 to the new 2.71
- fast_tls: Update to 1.1.14 to support OpenSSL 3
- jiffy: Update to 1.1.1 to support Erlang/OTP 25.0-rc1
- luerl: Update to 1.0.0, now available in hex.pm
- lager: This dependency is used only when Erlang is older than 22
- rebar2: Updated binary to work from Erlang/OTP 22 to 25
- rebar3: Updated binary to work from Erlang/OTP 22 to 25
- `make update`: Fix when used with rebar 3.18
Compile
- `mix release`: Copy `include/` files for ejabberd, deps and otp, in `mix.exs`
- `rebar3 release`: Fix ERTS path in `ejabberdctl`
- `configure.ac`: Set default ejabberd version number when not using git
- `mix.exs`: Move some dependencies as optional
- `mix.exs`: No need to use Distillery, Elixir has built-in support for OTP releases (#3788)
- `tools/make-binaries`: New script for building Linux binaries
- `tools/make-installers`: New script for building command line installers
Start
- New `make relive` similar to `ejabberdctl live` without installing
- `ejabberdctl`: Fix some warnings detected by ShellCheck
- `ejabberdctl`: Mention in the help: `etop`, `ping` and `started`/`stopped`
- `make rel`: Switch to paths: `conf/`, `database/`, `logs/`
- `mix.exs`: Add `-boot` and `-boot_var` in `ejabberdctl` instead of adding `vm.args`
- `tools/captcha.sh`: Fix some warnings detected by ShellCheck
Commands
- Accept more types of ejabberdctl commands arguments as JSON-encoded
- `delete_old_mam_messages_batch`: New command with rate limit
- `delete_old_messages_batch`: New command with rate limit
- `get_room_occupants_number`: Don't request the whole MUC room state (#3684, #1964)
- `get_vcard`: Add support for MUC room vCard
- `oauth_revoke_token`: Add support to work with all backends
- `room_unused_*`: Optimize commands in SQL by reusing `created_at`
- `rooms_unused_...`: Let `get_all_rooms` handle `global` argument (#3726)
- `stop|restart`: Terminate ejabberd_sm before everything else to ensure sessions closing (#3641)
- `subscribe_room_many`: New command
Translations
- Updated Catalan
- Updated French
- Updated German
- Updated Portuguese
- Updated Portuguese (Brazil)
- Updated Spanish
Workflows
- CI: Publish CT logs and Cover on failure to an external GH Pages repo
- CI: Test shell scripts using ShellCheck (#3738)
- Container: New workflow to build and publish containers
- Installers: Add job to create draft release
- Installers: New workflow to build binary packages
- Runtime: New workflow to test compilation, rel, starting and ejabberdctl
# Version 21.12
Commands
- `create_room_with_opts`: Fixed when using SQL storage
- `change_room_option`: Add missing fields from config inside `mod_muc_admin:change_options`
- piefxis: Fixed arguments of all commands
Modules
- mod_caps: Don't forget caps on XEP-0198 resumption
- mod_conversejs: New module to serve a simple page for Converse.js
- mod_http_upload_quota: Avoid `max_days` race
- mod_muc: Support MUC hats (XEP-0317, conversejs/prosody compatible)
- mod_muc: Optimize MucSub processing
- mod_muc: Fix exception in mucsub {un}subscription events multicast handler
- mod_multicast: Improve and optimize multicast routing code
- mod_offline: Allow storing non-composing x:events in offline
- mod_ping: Send ping from server, not bare user JID
- mod_push: Fix handling of MUC/Sub messages
- mod_register: New allow_modules option to restrict registration modules
- mod_register_web: Handle unknown host gracefully
- mod_register_web: Use mod_register configured restrictions
PubSub
- Add `delete_expired_pubsub_items` command
- Add `delete_old_pubsub_items` command
- Optimize publishing on large nodes (SQL)
- Support unlimited number of items
- Support `max_items=max` node configuration
- Bump default value for `max_items` limit from 10 to 1000
- Use configured `max_items` by default
- node_flat: Avoid catch-all clauses for RSM
- node_flat_sql: Avoid catch-all clauses for RSM
SQL
- Use `INSERT ... ON CONFLICT` in SQL_UPSERT for PostgreSQL >= 9.5
- mod_mam export: assign MUC entries to the MUC service
- MySQL: Fix typo when creating index
- PgSQL: Add SASL auth support, PostgreSQL 14
- PgSQL: Add missing SQL migration for table `push_session`
- PgSQL: Fix `vcard_search` definition in pgsql new schema
Other
- `captcha-ng.sh`: "sort -R" command not POSIX, added "shuf" and "cat" as fallback
- Make s2s connection table cleanup more robust
- Update export/import of scram password to XEP-0227 1.1
- Update Jose to 1.11.1 (the last in hex.pm correctly versioned)
# Version 21.07
Compilation
- Add rebar3 3.15.2 binary
- Add support for mix to: `./configure --enable-rebar=mix`
- Add workaround so rebar2 can use Elixir 1.12.0
- Improved `make rel` to work with rebar3 and mix
- Add `make dev` to build a development release with rebar3 or mix
- Hex: Add `sql/` and `vars.config` to Hex package files
@ -167,7 +318,7 @@ Translations:
- Fix problem with leaving old data when updating shared rosters
- Fix edge case that caused failure of resuming old sessions with
stream management.
- Fix crash when room that was started with loging enabled was later
- Fix crash when room that was started with logging enabled was later
changed to logging disabled
- Increase default shaper limits (this should help with delays for
clients that are using jingle)
@ -232,7 +383,7 @@ Translations:
for all backends not only SQL
- Add infrastructure for having module documentation directly
in individual module source code
- Generate man page automaticaly
- Generate man page automatically
- Implement copy feature in mod_carboncopy
* Fixes
@ -240,7 +391,7 @@ Translations:
- Fix handling of result in xmlrpc module
- Make webadmin work even when accessed through not declared domain
- Better error reporting in xmlrpc
- Limit ammount of results returned by disco queries to pubsub nodes
- Limit amount of results returned by disco queries to pubsub nodes
- Improve validation of configured JWT keys
- Fix race condition in Redis/SQL startup
- Fix loading order of third party modules
@ -341,7 +492,7 @@ Translations:
- Improve handling of unexpected iq in mod_muc_room
- Attach mod_muc_room processes to a supervisor
- Restore room when receiving message or generic iq for not started room
- Distribute routing of MUC messages accross all CPU cores
- Distribute routing of MUC messages across all CPU cores
* PubSub
- Fix pending nodes retrieval for SQL backend
@ -375,7 +526,7 @@ Translations:
- Make static hooks analyzer working again
* MUC
- Service admins are allowed to recreate room even if archiv is nonempty
- Service admins are allowed to recreate room even if archive is nonempty
- New option user_mucsub_from_muc_archive
- Avoid late arrival of get_disco_item response
- Handle get_subscribed_rooms call from mod_muc_room pid

126
COMPILE.md Normal file
View File

@ -0,0 +1,126 @@
Compile and Install ejabberd
============================
This document explains how to compile and install ejabberd
from source code.
For a more detailed explanation, please check the
ejabberd Docs: [Source Code Installation][docs-source].
[docs-source]: https://docs.ejabberd.im/admin/installation/#source-code
Requirements
------------
To compile ejabberd you need:
- GNU Make
- GCC
- Libexpat ≥ 1.95
- Libyaml ≥ 0.1.4
- Erlang/OTP ≥ 19.3
- OpenSSL ≥ 1.0.0
Other optional libraries are:
- Zlib ≥ 1.2.3, for Stream Compression support (XEP-0138)
- PAM library, for Pluggable Authentication Modules (PAM)
- ImageMagick's Convert program and Ghostscript fonts, for CAPTCHA
challenges
- Elixir ≥ 1.10.3, to support Elixir, and alternative to rebar/rebar3
If your system splits packages in libraries and development headers,
install the development packages too.
Download Source Code
--------------------
There are several ways to obtain the ejabberd source code:
- Source code archive from [ProcessOne Downloads][p1dl]
- Source code package from [ejabberd GitHub Releases][ghr]
- Latest development code from [ejabberd Git repository][gitrepo]
[p1dl]: https://www.process-one.net/en/ejabberd/downloads/
[ghr]: https://github.com/processone/ejabberd/releases
[gitrepo]: https://github.com/processone/ejabberd
Compile
-------
The general instructions to compile ejabberd are:
./configure
make
If the source code doesn't contain a `configure` script,
first of all install `autoconf` and run this to generate it:
./autogen.sh
To configure the compilation, features, install paths...
./configure --help
Install in the System
---------------------
To install ejabberd in the system, run this with system administrator rights (root user):
sudo make install
This will:
- Install the configuration files in `/etc/ejabberd/`
- Install ejabberd binary, header and runtime files in `/lib/ejabberd/`
- Install the administration script: `/sbin/ejabberdctl`
- Install ejabberd documentation in `/share/doc/ejabberd/`
- Create a spool directory: `/var/lib/ejabberd/`
- Create a directory for log files: `/var/log/ejabberd/`
Build an OTP Release
--------------------
Instead of installing ejabberd in the system, you can build an OTP release
that includes all necessary to run ejabberd in a subdirectory:
./configure --with-rebar=rebar3
make rel
Or, if you have Elixir available and plan to develop Elixir code:
./configure --with-rebar=mix
make dev
Check the full list of targets:
make help
Start ejabberd
--------------
You can use the `ejabberdctl` command line administration script to
start and stop ejabberd. Some examples, depending on your installation method:
- When installed in the system:
```
ejabberdctl start
/sbin/ejabberdctl start
```
- When built an OTP production release:
```
_build/prod/rel/ejabberd/bin/ejabberdctl start
_build/prod/rel/ejabberd/bin/ejabberdctl live
```
- Start interactively without installing or building OTP release:
```
make relive
```

313
CONTAINER.md Normal file
View File

@ -0,0 +1,313 @@
[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/processone/ejabberd?sort=semver&logo=embarcadero&label=&color=49c0c4)](https://github.com/processone/ejabberd/tags)
[![GitHub Container](https://img.shields.io/github/v/tag/processone/ejabberd?label=container&sort=semver)](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/ejabberd/ecs?label=docker)](https://hub.docker.com/r/ejabberd/ecs/)
ejabberd Container
==================
[ejabberd][home] is an open-source,
robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang],
that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service.
[home]: https://ejabberd.im/
[erlang]: https://www.erlang.org/
[xmpp]: https://xmpp.org/
[mqtt]: https://mqtt.org/
[sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol
This document explains how to use the
[ejabberd container images](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
available in the GitHub Container Registry,
built using the files in `.github/container/`.
Alternatively, there are also
[ejabberd-ecs Docker images](https://hub.docker.com/r/ejabberd/ecs/)
available in Docker Hub,
built using the
[docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs)
repository.
If you are using a Windows operating system, check the tutorials mentioned in
[ejabberd Docs > Docker Image](https://docs.ejabberd.im/admin/installation/#docker-image).
Start ejabberd
--------------
### With default configuration
Start ejabberd in a new container:
```bash
docker run --name ejabberd -d -p 5222:5222 ghcr.io/processone/ejabberd
```
That runs the container as a daemon,
using ejabberd default configuration file and XMPP domain "localhost".
Stop the running container:
```bash
docker stop ejabberd
```
Restart the stopped ejabberd container:
```bash
docker restart ejabberd
```
### Start with Erlang console attached
Start ejabberd with an Erlang console attached using the `live` command:
```bash
docker run --name ejabberd -it -p 5222:5222 ghcr.io/processone/ejabberd live
```
That uses the default configuration file and XMPP domain "localhost".
### Start with your configuration and database
Pass a configuration file as a volume
and share the local directory to store database:
```bash
mkdir database
chown ejabberd database
cp ejabberd.yml.example ejabberd.yml
docker run --name ejabberd -it \
-v $(pwd)/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml \
-v $(pwd)/database:/opt/ejabberd/database \
-p 5222:5222 ghcr.io/processone/ejabberd live
```
Notice that ejabberd runs in the container with an account named `ejabberd`,
and the volumes you mount must grant proper rights to that account.
Next steps
----------
### Register the administrator account
The default ejabberd configuration does not grant admin privileges
to any account,
you may want to register a new account in ejabberd
and grant it admin rights.
Register an account using the `ejabberdctl` script:
```bash
docker exec -it ejabberd ejabberdctl register admin localhost passw0rd
```
Then edit conf/ejabberd.yml and add the ACL as explained in
[ejabberd Docs: Administration Account](https://docs.ejabberd.im/admin/installation/#administration-account)
### Check ejabberd log files
Check the content of the log files inside the container,
even if you do not put it on a shared persistent drive:
```bash
docker exec -it ejabberd tail -f logs/ejabberd.log
```
### Inspect the container files
The container uses Alpine Linux. Start a shell inside the container:
```bash
docker exec -it ejabberd sh
```
### Open ejabberd debug console
Open an interactive debug Erlang console attached to a running ejabberd in a running container:
```bash
docker exec -it ejabberd ejabberdctl debug
```
### CAPTCHA
ejabberd includes two example CAPTCHA scripts.
If you want to use any of them, first install some additional required libraries:
```bash
docker exec --user root ejabberd apk add imagemagick ghostscript-fonts bash
```
Now update your ejabberd configuration file, for example:
```bash
docker exec -it ejabberd vi conf/ejabberd.yml
```
and add the required options:
```
captcha_cmd: /opt/ejabberd-22.04/lib/ejabberd-22.04/priv/bin/captcha.sh
captcha_url: https://localhost:5443/captcha
```
Finally, reload the configuration file or restart the container:
```bash
docker exec ejabberd ejabberdctl reload_config
```
Advanced Container Configuration
--------------------------------
### Ports
This container image exposes the ports:
- `5222`: The default port for XMPP clients.
- `5269`: For XMPP federation. Only needed if you want to communicate with users on other servers.
- `5280`: For admin interface.
- `5443`: With encryption, used for admin interface, API, CAPTCHA, OAuth, Websockets and XMPP BOSH.
- `1883`: Used for MQTT
- `4369-4399`: EPMD and Erlang connectivity, used for `ejabberdctl` and clustering
- `5210`: Erlang connectivity when `ERL_DIST_PORT` is set, alternative to EPMD
### Volumes
ejabberd produces two types of data: log files and database spool files (Mnesia).
This is the kind of data you probably want to store on a persistent or local drive (at least the database).
The volumes you may want to map:
- `/opt/ejabberd/conf/`: Directory containing configuration and certificates
- `/opt/ejabberd/database/`: Directory containing Mnesia database.
You should back up or export the content of the directory to persistent storage
(host storage, local storage, any storage plugin)
- `/opt/ejabberd/logs/`: Directory containing log files
- `/opt/ejabberd/upload/`: Directory containing uploaded files. This should also be backed up.
All these files are owned by `ejabberd` user inside the container.
It's possible to install additional ejabberd modules using volumes,
[this comment](https://github.com/processone/docker-ejabberd/issues/81#issuecomment-1036115146)
explains how to install an additional module using docker-compose.
### Commands on start
The ejabberdctl script reads the `CTL_ON_CREATE` environment variable
the first time the docker container is started,
and reads `CTL_ON_START` every time the container is started.
Those variables can contain one ejabberdctl command,
or several commands separated with the blankspace and `;` characters.
Example usage (see full example [docker-compose.yml](https://github.com/processone/docker-ejabberd/issues/64#issuecomment-887741332)):
```yaml
environment:
- CTL_ON_CREATE=register admin localhost asd
- CTL_ON_START=stats registeredusers ;
check_password admin localhost asd ;
status
```
### Clustering
When setting several containers to form a
[cluster of ejabberd nodes](https://docs.ejabberd.im/admin/guide/clustering/),
each one must have a different
[Erlang Node Name](https://docs.ejabberd.im/admin/guide/security/#erlang-node-name)
and the same
[Erlang Cookie](https://docs.ejabberd.im/admin/guide/security/#erlang-cookie).
For this you can either:
- edit `conf/ejabberdctl.cfg` and set variables `ERLANG_NODE` and `ERLANG_COOKIE`
- set the environment variables `ERLANG_NODE_ARG` and `ERLANG_COOKIE`
Example to connect a local `ejabberdctl` to a containerized ejabberd:
1. When creating the container, export port 5210, and set `ERLANG_COOKIE`:
```
docker run --name ejabberd -it \
-e ERLANG_COOKIE=`cat $HOME/.erlang.cookie` \
-p 5210:5210 -p 5222:5222 \
ghcr.io/processone/ejabberd
```
2. Set `ERL_DIST_PORT=5210` in ejabberdctl.cfg of container and local ejabberd
3. Restart the container
4. Now use `ejabberdctl` in your local ejabberd deployment
To connect using a local `ejabberd` script:
```
ERL_DIST_PORT=5210 _build/dev/rel/ejabberd/bin/ejabberd ping
```
Example using environment variables (see full example [docker-compose.yml](https://github.com/processone/docker-ejabberd/issues/64#issuecomment-887741332)):
```yaml
environment:
- ERLANG_NODE_ARG=ejabberd@node7
- ERLANG_COOKIE=dummycookie123
```
Generating a Container Image
----------------------------
This container image includes ejabberd as a standalone OTP release built using Elixir.
That OTP release is configured with:
- `mix.exs`: Customize ejabberd release
- `vars.config`: ejabberd compilation configuration options
- `config/runtime.exs`: Customize ejabberd paths
- `ejabberd.yml.template`: ejabberd default config file
Build ejabberd Community Server base image from ejabberd master on GitHub:
```bash
docker build \
-t personal/ejabberd \
-f .github/container/Dockerfile \
.
```
Build ejabberd Community Server base image for a given ejabberd version,
both for amd64 and arm64 architectures:
```bash
VERSION=22.05
git checkout $VERSION
docker buildx build \
--platform=linux/amd64,linux/arm64
-t personal/ejabberd:$VERSION \
-f .github/container/Dockerfile \
.
```
It's also possible to use podman instead of docker, just notice:
- `EXPOSE 4369-4399` port range is not supported, remove that in Dockerfile
- It mentions that `healthcheck` is not supported by the Open Container Initiative image format
- If you want to start with command `live`, add environment variable `EJABBERD_BYPASS_WARNINGS=true`
```bash
podman build \
-t ejabberd \
-f .github/container/Dockerfile \
.
podman run --name eja1 -d -p 5222:5222 localhost/ejabberd
podman exec eja1 ejabberdctl status
podman exec -it eja1 sh
podman stop eja1
```

View File

@ -10,27 +10,27 @@ exec_prefix = @exec_prefix@
DESTDIR =
# /etc/ejabberd/
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd
ETCDIR = @sysconfdir@/ejabberd
# /bin/
BINDIR = $(DESTDIR)@bindir@
BINDIR = @bindir@
# /sbin/
SBINDIR = $(DESTDIR)@sbindir@
SBINDIR = @sbindir@
# /lib/
LIBDIR = $(DESTDIR)@libdir@
LIBDIR = @libdir@
# /lib/ejabberd/
EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd
EJABBERDDIR = @libdir@/ejabberd
# /share/doc/ejabberd
PACKAGE_TARNAME = @PACKAGE_TARNAME@
datarootdir = @datarootdir@
DOCDIR = $(DESTDIR)@docdir@
DOCDIR = @docdir@
# /share/doc/man/man5
MANDIR = $(DESTDIR)@mandir@/man5
MANDIR = @mandir@/man5
# /usr/lib/ejabberd/ebin/
BEAMDIR = $(EJABBERDDIR)/ebin
@ -66,16 +66,10 @@ SQLDIR = $(PRIVDIR)/sql
LUADIR = $(PRIVDIR)/lua
# /var/lib/ejabberd/
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
# /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
SPOOLDIR = @localstatedir@/lib/ejabberd
# /var/log/ejabberd/
LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd
LOGDIR = @localstatedir@/log/ejabberd
INSTALLUSER=@INSTALLUSER@
# if no user was enabled, don't set privileges or ownership
@ -99,12 +93,14 @@ ifneq ($(INSTALLGROUP),)
endif
ifeq "$(MIX)" "mix"
IS_REBAR:=6
REBAR_VER:=6
REBAR_VER_318:=0
else
IS_REBAR:=$(shell expr `$(REBAR) --version | awk -F '[ .]' '/rebar / {print $$2}'`)
REBAR_VER:=$(shell $(REBAR) --version | awk -F '[ .]' '/rebar / {print $$2}')
REBAR_VER_318:=$(shell $(REBAR) --version | awk -F '[ .]' '/rebar / {print ($$2 == 3 && $$3 >= 18 ? 1 : 0)}')
endif
ifeq "$(IS_REBAR)" "6"
ifeq "$(REBAR_VER)" "6"
REBAR=$(MIX)
SKIPDEPS=
LISTDEPS=deps.tree
@ -113,23 +109,33 @@ ifeq "$(IS_REBAR)" "6"
DEPSBASE=_build
DEPSDIR=$(DEPSBASE)/dev/lib
GET_DEPS= deps.get
CONFIGURE_DEPS=
CONFIGURE_DEPS=(cd deps/eimp; ./configure)
EBINDIR=$(DEPSDIR)/ejabberd/ebin
XREFOPTIONS=graph
CLEANARG=--deps
REBARREL=MIX_ENV=prod $(REBAR) release --overwrite
REBARDEV=MIX_ENV=dev $(REBAR) release --overwrite
RELIVECMD=escript rel/relive.escript && MIX_ENV=dev RELIVE=true iex --name ejabberd@localhost -S mix run
else
ifeq "$(IS_REBAR)" "3"
ifeq "$(REBAR_VER)" "3"
SKIPDEPS=
LISTDEPS=tree
ifeq "$(REBAR_VER_318)" "1"
UPDATEDEPS=upgrade --all
else
UPDATEDEPS=upgrade
endif
DEPSPATTERN="s/ (.*//; /^ / s/.* \([a-z0-9_]*\).*/\1/p;"
DEPSBASE=_build
DEPSDIR=$(DEPSBASE)/default/lib
GET_DEPS= get-deps
CONFIGURE_DEPS=$(REBAR) configure-deps
EBINDIR=$(DEPSDIR)/ejabberd/ebin
XREFOPTIONS=
CLEANARG=--all
REBARREL=$(REBAR) as prod tar
REBARDEV=REBAR_PROFILE=dev $(REBAR) release
RELIVECMD=$(REBAR) relive
else
SKIPDEPS=skip_deps=true
LISTDEPS=-q list-deps
@ -140,12 +146,16 @@ else
GET_DEPS= get-deps
CONFIGURE_DEPS=$(REBAR) configure-deps
EBINDIR=ebin
XREFOPTIONS=
CLEANARG=
REBARREL=$(REBAR) generate
REBARDEV=
RELIVECMD=@echo "Rebar2 detected... relive not supported.\
\nTry: ./configure --with-rebar=./rebar3 ; make relive"
endif
endif
all: deps src
all: scripts deps src
deps: $(DEPSDIR)/.got
@ -154,9 +164,9 @@ $(DEPSDIR)/.got:
rm -rf $(DEPSDIR)/.built
mkdir -p $(DEPSDIR)
$(REBAR) $(GET_DEPS) && :> $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
$(DEPSDIR)/.built: $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
$(REBAR) compile && :> $(DEPSDIR)/.built
src: $(DEPSDIR)/.built
@ -166,9 +176,10 @@ update:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
$(REBAR) $(UPDATEDEPS) && :> $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
xref: all
$(REBAR) $(SKIPDEPS) xref
$(REBAR) $(SKIPDEPS) xref $(XREFOPTIONS)
hooks: all
tools/hook_deps.sh $(EBINDIR)
@ -194,7 +205,7 @@ ELIXIR_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 5,1000,
DEPS_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 3,1000,$(1))
MAIN_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,ejabberd) $(1)
TO_DEST_SINGLE=$(if $(subst X$(DEPSBASE)X,,X$(word 1,$(1))X),$(call MAIN_TO_DEST,$(1)),$(if $(subst XlibX,,X$(word $(LIBIX),$(1))X),$(call DEPS_TO_DEST,$(wordlist $(DEPIX),1000,$(1))),$(call ELIXIR_TO_DEST,$(wordlist $(DEPIX),1000,$(1)))))
TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(call TO_DEST_SINGLE,$(subst /, ,$(path)))))
TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(DESTDIR)$(call TO_DEST_SINGLE,$(subst /, ,$(path)))))
FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path)))
FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w))))
@ -235,7 +246,7 @@ $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,
$(foreach file,$(BINARIES),$(eval $(call COPY_BINARY_template,$(file))))
$(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))):
$(INSTALL) -d $@
$(INSTALL) -d $@
$(call TO_DEST,priv/sql/lite.sql): sql/lite.sql $(call TO_DEST,priv/sql)
$(INSTALL) -m 644 $< $@
@ -249,7 +260,15 @@ $(call TO_DEST,priv/bin/captcha.sh): tools/captcha.sh $(call TO_DEST,priv/bin)
$(call TO_DEST,priv/lua/redis_sm.lua): priv/lua/redis_sm.lua $(call TO_DEST,priv/lua)
$(INSTALL) -m 644 $< $@
copy-files-sub2: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES) priv/bin/captcha.sh priv/sql/lite.sql priv/sql/lite.new.sql priv/lua/redis_sm.lua)
ifeq (@sqlite@,true)
SQLITE_FILES = priv/sql/lite.sql priv/sql/lite.new.sql
endif
ifeq (@redis@,true)
REDIS_FILES = priv/lua/redis_sm.lua
endif
copy-files-sub2: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES) priv/bin/captcha.sh $(SQLITE_FILES) $(REDIS_FILES))
.PHONY: $(call TO_DEST,$(DEPS_FILES) $(MAIN_DIRS) $(DEPS_DIRS))
@ -260,135 +279,155 @@ copy-files:
copy-files-sub: copy-files-sub2
install: copy-files
#
# Configuration files
$(INSTALL) -d -m 750 $(G_USER) $(ETCDIR)
[ -f $(ETCDIR)/ejabberd.yml ] \
&& $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml-new \
|| $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml
$(SED) -e "s*{{rootdir}}*@prefix@*g" \
-e "s*{{installuser}}*@INSTALLUSER@*g" \
relive:
$(RELIVECMD)
relivelibdir=$(shell pwd)/$(DEPSDIR)
relivedir=$(shell pwd)/_build/relive
iexpath=$(shell which iex)
CONFIG_DIR = ${relivedir}/conf
SPOOL_DIR = ${relivedir}/database
LOGS_DIR = ${relivedir}/logs
ejabberdctl.relive:
$(SED) -e "s*{{installuser}}*@INSTALLUSER@*g" \
-e "s*{{config_dir}}*${CONFIG_DIR}*g" \
-e "s*{{logs_dir}}*${LOGS_DIR}*g" \
-e "s*{{spool_dir}}*${SPOOL_DIR}*g" \
-e "s*{{bindir}}/iex*$(iexpath)*g" \
-e "s*{{bindir}}*@bindir@*g" \
-e "s*{{libdir}}*@libdir@*g" \
-e "s*{{sysconfdir}}*@sysconfdir@*g" \
-e "s*{{localstatedir}}*@localstatedir@*g" \
-e "s*{{docdir}}*@docdir@*g" \
-e "s*{{libdir}}*${relivelibdir}*g" \
-e "s*{{erl}}*@ERL@*g" \
-e "s*{{epmd}}*@EPMD@*g" ejabberdctl.template \
> ejabberdctl.example
[ -f $(ETCDIR)/ejabberdctl.cfg ] \
&& $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg-new \
|| $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg
$(INSTALL) -b -m 644 $(G_USER) inetrc $(ETCDIR)/inetrc
#
# Administration script
[ -d $(SBINDIR) ] || $(INSTALL) -d -m 755 $(SBINDIR)
$(INSTALL) -m 550 $(G_USER) ejabberdctl.example $(SBINDIR)/ejabberdctl
# Elixir binaries
[ -d $(BINDIR) ] || $(INSTALL) -d -m 755 $(BINDIR)
[ -f $(DEPSDIR)/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/iex $(BINDIR)/iex || true
[ -f $(DEPSDIR)/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/elixir $(BINDIR)/elixir || true
[ -f $(DEPSDIR)/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/mix $(BINDIR)/mix || true
#
# Init script
> ejabberdctl.relive
ejabberd.init:
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" \
-e "s*@installuser@*$(INIT_USER)*g" ejabberd.init.template \
> ejabberd.init
chmod 755 ejabberd.init
#
# Service script
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" ejabberd.service.template \
ejabberd.service:
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" \
-e "s*@installuser@*$(INIT_USER)*g" ejabberd.service.template \
> ejabberd.service
chmod 644 ejabberd.service
ejabberdctl.example: vars.config
$(SED) -e "s*{{installuser}}*@INSTALLUSER@*g" \
-e "s*{{config_dir}}*${ETCDIR}*g" \
-e "s*{{logs_dir}}*${LOGDIR}*g" \
-e "s*{{spool_dir}}*${SPOOLDIR}*g" \
-e "s*{{bindir}}*@bindir@*g" \
-e "s*{{libdir}}*@libdir@*g" \
-e "s*{{erl}}*@ERL@*g" \
-e "s*{{epmd}}*@EPMD@*g" ejabberdctl.template \
> ejabberdctl.example
scripts: ejabberd.init ejabberd.service ejabberdctl.example
install: copy-files
#
# Configuration files
$(INSTALL) -d -m 750 $(G_USER) $(DESTDIR)$(ETCDIR)
[ -f $(DESTDIR)$(ETCDIR)/ejabberd.yml ] \
&& $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(DESTDIR)$(ETCDIR)/ejabberd.yml-new \
|| $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(DESTDIR)$(ETCDIR)/ejabberd.yml
[ -f $(DESTDIR)$(ETCDIR)/ejabberdctl.cfg ] \
&& $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(DESTDIR)$(ETCDIR)/ejabberdctl.cfg-new \
|| $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(DESTDIR)$(ETCDIR)/ejabberdctl.cfg
$(INSTALL) -b -m 644 $(G_USER) inetrc $(DESTDIR)$(ETCDIR)/inetrc
#
# Administration script
[ -d $(DESTDIR)$(SBINDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(SBINDIR)
$(INSTALL) -m 550 $(G_USER) ejabberdctl.example $(DESTDIR)$(SBINDIR)/ejabberdctl
# Elixir binaries
[ -d $(DESTDIR)$(BINDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)
[ -f $(DEPSDIR)/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/iex $(DESTDIR)$(BINDIR)/iex || true
[ -f $(DEPSDIR)/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/elixir $(DESTDIR)$(BINDIR)/elixir || true
[ -f $(DEPSDIR)/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/mix $(DESTDIR)$(BINDIR)/mix || true
#
# Spool directory
$(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(SPOOLDIR)
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
#
# ejabberdctl lock directory
$(INSTALL) -d -m 750 $(O_USER) $(CTLLOCKDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(CTLLOCKDIR)
$(INSTALL) -d -m 750 $(O_USER) $(DESTDIR)$(SPOOLDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(DESTDIR)$(SPOOLDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(DESTDIR)$(SPOOLDIR)
#
# Log directory
$(INSTALL) -d -m 750 $(O_USER) $(LOGDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(LOGDIR)
$(INSTALL) -d -m 750 $(O_USER) $(DESTDIR)$(LOGDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(DESTDIR)$(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(DESTDIR)$(LOGDIR)
#
# Documentation
$(INSTALL) -d $(MANDIR)
$(INSTALL) -d $(DOCDIR)
$(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL) -d $(DESTDIR)$(DOCDIR)
[ -f man/ejabberd.yml.5 ] \
&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(MANDIR) \
&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(DESTDIR)$(MANDIR) \
|| echo "Man page not included in sources"
$(INSTALL) -m 644 COPYING $(DOCDIR)
$(INSTALL) -m 644 COPYING $(DESTDIR)$(DOCDIR)
uninstall: uninstall-binary
uninstall-binary:
rm -f $(SBINDIR)/ejabberdctl
rm -f $(BINDIR)/iex
rm -f $(BINDIR)/elixir
rm -f $(BINDIR)/mix
rm -fr $(DOCDIR)
rm -f $(BEAMDIR)/*.beam
rm -f $(BEAMDIR)/*.app
rm -fr $(BEAMDIR)
rm -f $(INCLUDEDIR)/*.hrl
rm -fr $(INCLUDEDIR)
rm -fr $(PBINDIR)
rm -f $(SODIR)/*.so
rm -fr $(SODIR)
rm -f $(MSGSDIR)/*.msg
rm -fr $(MSGSDIR)
rm -f $(CSSDIR)/*.css
rm -fr $(CSSDIR)
rm -f $(IMGDIR)/*.png
rm -fr $(IMGDIR)
rm -f $(JSDIR)/*.js
rm -fr $(JSDIR)
rm -f $(SQLDIR)/*.sql
rm -fr $(SQLDIR)
rm -fr $(LUADIR)/*.lua
rm -fr $(LUADIR)
rm -fr $(PRIVDIR)
rm -fr $(EJABBERDDIR)
rm -f $(DESTDIR)$(SBINDIR)/ejabberdctl
rm -f $(DESTDIR)$(BINDIR)/iex
rm -f $(DESTDIR)$(BINDIR)/elixir
rm -f $(DESTDIR)$(BINDIR)/mix
rm -fr $(DESTDIR)$(DOCDIR)
rm -f $(DESTDIR)$(BEAMDIR)/*.beam
rm -f $(DESTDIR)$(BEAMDIR)/*.app
rm -fr $(DESTDIR)$(BEAMDIR)
rm -f $(DESTDIR)$(INCLUDEDIR)/*.hrl
rm -fr $(DESTDIR)$(INCLUDEDIR)
rm -fr $(DESTDIR)$(PBINDIR)
rm -f $(DESTDIR)$(SODIR)/*.so
rm -fr $(DESTDIR)$(SODIR)
rm -f $(DESTDIR)$(MSGSDIR)/*.msg
rm -fr $(DESTDIR)$(MSGSDIR)
rm -f $(DESTDIR)$(CSSDIR)/*.css
rm -fr $(DESTDIR)$(CSSDIR)
rm -f $(DESTDIR)$(IMGDIR)/*.png
rm -fr $(DESTDIR)$(IMGDIR)
rm -f $(DESTDIR)$(JSDIR)/*.js
rm -fr $(DESTDIR)$(JSDIR)
rm -f $(DESTDIR)$(SQLDIR)/*.sql
rm -fr $(DESTDIR)$(SQLDIR)
rm -fr $(DESTDIR)$(LUADIR)/*.lua
rm -fr $(DESTDIR)$(LUADIR)
rm -fr $(DESTDIR)$(PRIVDIR)
rm -fr $(DESTDIR)$(EJABBERDDIR)
uninstall-all: uninstall-binary
rm -rf $(ETCDIR)
rm -rf $(EJABBERDDIR)
rm -rf $(SPOOLDIR)
rm -rf $(CTLLOCKDIR)
rm -rf $(LOGDIR)
rm -rf $(DESTDIR)$(ETCDIR)
rm -rf $(DESTDIR)$(EJABBERDDIR)
rm -rf $(DESTDIR)$(SPOOLDIR)
rm -rf $(DESTDIR)$(LOGDIR)
clean:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
rm -rf test/*.beam
$(REBAR) clean
rm -f rebar.lock
rm -f ejabberdctl.example ejabberd.init ejabberd.service
$(REBAR) clean $(CLEANARG)
clean-rel:
rm -rf rel/ejabberd
distclean: clean clean-rel
rm -f aclocal.m4
rm -f config.status
rm -f config.log
rm -rf autom4te.cache
rm -rf $(EBINDIR)
rm -rf $(DEPSBASE)
rm -rf deps
rm -f Makefile
rm -f vars.config
rm -f src/ejabberd.app.src
rm -f ejabberdctl.example ejabberd.init ejabberd.service
[ ! -f ../ChangeLog ] || rm -f ../ChangeLog
rel:
$(REBARREL)
DEV_CONFIG = _build/dev/rel/ejabberd/etc/ejabberd/ejabberd.yml
DEV_CONFIG = _build/dev/rel/ejabberd/conf/ejabberd.yml
dev $(DEV_CONFIG):
$(REBARDEV)
@ -398,7 +437,7 @@ TAGS:
Makefile: Makefile.in
ifeq "$(IS_REBAR)" "3"
ifeq "$(REBAR_VER)" "3"
dialyzer:
$(REBAR) dialyzer
else
@ -455,9 +494,10 @@ test:
help:
@echo ""
@echo " [all] Compile dependencies and ejabberd"
@echo " src Compile ejabberd"
@echo " deps Get dependencies"
@echo " [all] "
@echo " scripts Prepare ejabberd start scripts"
@echo " deps Get and configure dependencies"
@echo " src Compile dependencies and ejabberd"
@echo " update Update dependencies' source code"
@echo " clean Clean binary files"
@echo " distclean Clean completely the development files"
@ -468,6 +508,7 @@ help:
@echo ""
@echo " rel Build a production release"
@echo " dev Build a development release"
@echo " relive Start a live ejabberd in _build/relive/"
@echo ""
@echo " edoc Generate edoc documentation (unused)"
@echo " options Generate ejabberd_option.erl"

282
README.md
View File

@ -1,208 +1,126 @@
ejabberd Community Edition
==========================
[![CI](https://github.com/processone/ejabberd/actions/workflows/ci.yml/badge.svg)](https://github.com/processone/ejabberd/actions/workflows/ci.yml)
[![Coverage Status](https://coveralls.io/repos/github/processone/ejabberd/badge.svg?branch=master "Coverage in coveralls.io")](https://coveralls.io/github/processone/ejabberd?branch=master)
[![Translation status](https://hosted.weblate.org/widgets/ejabberd/-/ejabberd-po/svg-badge.svg "Translation status in Weblate")](https://hosted.weblate.org/projects/ejabberd/ejabberd-po/)
[![Hex version](https://img.shields.io/hexpm/v/ejabberd.svg "Hex version")](https://hex.pm/packages/ejabberd)
ejabberd is a distributed, fault-tolerant technology that allows the creation
of large-scale instant messaging applications. The server can reliably support
thousands of simultaneous users on a single node and has been designed to
provide exceptional standards of fault tolerance. As an open source
technology, based on industry-standards, ejabberd can be used to build bespoke
solutions very cost effectively.
<p align="center">
<img src="https://www.process-one.net/wp-content/uploads/2022/05/ejabberd-logo-rounded-index.png"
height="216">
</p>
<p align="center">
<a href="https://github.com/processone/ejabberd/tags" alt="GitHub tag (latest SemVer)">
<img src="https://img.shields.io/github/v/tag/processone/ejabberd?sort=semver&logo=embarcadero&label=&color=3fb0d2&logoWidth=20" /></a>
<a href="https://hex.pm/packages/ejabberd" alt="Hex version">
<img src="https://img.shields.io/hexpm/v/ejabberd.svg" /></a>
<a href="https://github.com/processone/ejabberd/pkgs/container/ejabberd" alt="GitHub Container">
<img src="https://img.shields.io/github/v/tag/processone/ejabberd?label=container&sort=semver" /></a>
<a href="https://hub.docker.com/r/ejabberd/ecs/" alt="Docker Image Version (latest semver)">
<img src="https://img.shields.io/docker/v/ejabberd/ecs?label=docker" /></a>
<a href="https://formulae.brew.sh/formula/ejabberd" alt="homebrew version">
<img src="https://img.shields.io/homebrew/v/ejabberd" /></a>
<br />
<a href="https://github.com/processone/ejabberd/actions/workflows/ci.yml" alt="CI">
<img src="https://github.com/processone/ejabberd/actions/workflows/ci.yml/badge.svg" /></a>
<a href="https://coveralls.io/github/processone/ejabberd?branch=master" alt="Coverage Status">
<img src="https://coveralls.io/repos/github/processone/ejabberd/badge.svg?branch=master "Coverage in coveralls.io"" /></a>
<a href="https://hosted.weblate.org/projects/ejabberd/ejabberd-po/" alt="Translation status">
<img src="https://hosted.weblate.org/widgets/ejabberd/-/ejabberd-po/svg-badge.svg"" /></a>
</p>
Key Features
[ejabberd][im] is an open-source,
robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang],
that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service.
Check the features in [ejabberd.im][im], [ejabberd Docs][features],
[ejabberd at ProcessOne][p1home], and a list of [supported protocols and XEPs][xeps].
Installation
------------
- **Cross-platform**
ejabberd runs under Microsoft Windows and Unix-derived systems such as
Linux, FreeBSD and NetBSD.
There are several ways to install ejabberd:
- **Distributed**
You can run ejabberd on a cluster of machines and all of them will serve the
same XMPP domain(s). When you need more capacity you can simply add a new
cheap node to your cluster. Accordingly, you do not need to buy an expensive
high-end machine to support tens of thousands concurrent users.
- **Fault-tolerant**
You can deploy an ejabberd cluster so that all the information required for
a properly working service will be replicated permanently on all nodes. This
means that if one of the nodes crashes, the others will continue working
without disruption. In addition, nodes also can be added or replaced on
the fly.
- **Administrator-friendly**
ejabberd is built on top of the Open Source Erlang. As a result you do not
need to install an external database, an external web server, amongst others
because everything is already included, and ready to run out of the box.
Other administrator benefits include:
- Comprehensive documentation.
- Straightforward installers for Linux.
- Docker packaging to help with deploy / development on Linux, Windows or MacOS.
- Deb and RPM packaging to support most Linux distributions.
- Web administration.
- Shared roster groups.
- Command line administration tool.
- Can integrate with existing authentication mechanisms.
- Capability to send announce messages.
- **Internationalized**
ejabberd leads in internationalization. Hence it is very well suited in a
globalized world. Related features are:
- Translated to 25 languages.
- Support for IDNA.
- **Open Standards**
ejabberd is the first Open Source XMPP server claiming to fully comply to
the XMPP standard.
- Fully XMPP-compliant.
- XML-based protocol.
- Many protocols supported.
- Source code: compile yourself, see [COMPILE](COMPILE.md)
- Installers from [ejabberd GitHub Releases][releases] (run/deb/rpm for x64 and arm64)
- Container image from [ejabberd Docker Hub][hubecs], see [ecs README][docker-ecs-readme] (for x64)
- Container image from [ejabberd Github Packages][packages], see [CONTAINER](CONTAINER.md) (for x64 and arm64)
- Using your [Operating System package][osp]
- Using the [Homebrew][homebrew] package manager
Additional Features
-------------------
Documentation
-------------
Moreover, ejabberd comes with a wide range of other state-of-the-art features:
Please check the [ejabberd Docs][docs] website.
- **Modularity**
- Load only the modules you want.
- Extend ejabberd with your own custom modules.
- **Security**
- SASL and STARTTLS for c2s and s2s connections.
- STARTTLS and Dialback s2s connections.
- Web Admin accessible via HTTPS secure access.
- **Databases**
- Internal database for fast deployment (Mnesia).
- Native MySQL support.
- Native PostgreSQL support.
- ODBC data storage support.
- Microsoft SQL Server support.
- **Authentication**
- Internal authentication.
- PAM, LDAP and ODBC.
- External authentication script.
- **Others**
- Support for virtual hosting.
- Compressing XML streams with Stream Compression (XEP-0138).
- Statistics via Statistics Gathering (XEP-0039).
- IPv6 support both for c2s and s2s connections.
- Multi-User Chat module with support for clustering and HTML logging.
- Users Directory based on users vCards.
- Publish-Subscribe component with support for Personal Eventing.
- Support for web clients: HTTP Polling and HTTP Binding (BOSH).
- Component support: interface with networks such as AIM, ICQ and MSN.
Quickstart guide
----------------
### 0. Requirements
To compile ejabberd you need:
- GNU Make.
- GCC.
- Libexpat ≥ 1.95.
- Libyaml ≥ 0.1.4.
- Erlang/OTP ≥ 19.3.
- OpenSSL ≥ 1.0.0.
- Zlib ≥ 1.2.3, for Stream Compression support (XEP-0138). Optional.
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
- ImageMagick's Convert program and Ghostscript fonts. Optional. For CAPTCHA
challenges.
- Elixir ≥ 1.10.3. Optional. Alternative to build ejabberd
If your system splits packages in libraries and development headers, you must
install the development packages also.
### 1. Compile and install on *nix systems
To compile ejabberd, execute the following commands. The first one is only
necessary if your source tree didn't come with a `configure` script (In this
case you need autoconf installed).
./autogen.sh
./configure
make
To install ejabberd, run this command with system administrator rights (root
user):
sudo make install
These commands will:
- Install the configuration files in `/etc/ejabberd/`
- Install ejabberd binary, header and runtime files in `/lib/ejabberd/`
- Install the administration script: `/sbin/ejabberdctl`
- Install ejabberd documentation in `/share/doc/ejabberd/`
- Create a spool directory: `/var/lib/ejabberd/`
- Create a directory for log files: `/var/log/ejabberd/`
### 2. Start ejabberd
You can use the `ejabberdctl` command line administration script to
start and stop ejabberd. For example:
ejabberdctl start
For detailed information please refer to the
[ejabberd Documentation](https://docs.ejabberd.im)
### 3. Use ejabberd locally
Alternatively, you can setup ejabberd without installing in your system:
./configure --with-rebar=rebar3
make dev
Or, if you have Elixir available and plan to develop Elixir code:
./configure --with-rebar=mix
make dev
Check the full list of targets:
When compiling from source code, you can get some help with:
./configure --help
make help
Once ejabberd is installed, try:
ejabberdctl help
man ejabberd.yml
Development
-----------
In order to assist in the development of ejabberd, and particularly the
execution of the test suite, a Vagrant environment is available at
https://github.com/processone/ejabberd-vagrant-dev.
Bug reports and features are tracked using [GitHub Issues][issues],
please check [CONTRIBUTING](CONTRIBUTING.md) for details.
To start ejabberd in development mode from the repository directory, you can
type a command like:
Translations can be improved online [using Weblate][weblate]
or in your local machine as explained in [Localization][localization].
EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -pa deps/elixir/lib/*/ebin/ -s ejabberd
Documentation for developers is available in [ejabberd docs: Developers][docs-dev].
Security reports or concerns should preferably be reported privately,
please send an email to the address: contact [at] process-one [dot] net
or some other method from [ProcessOne Contact][p1contact].
For commercial offering and support, including [ejabberd Business Edition][p1home]
and [Fluux (ejabberd in the Cloud)][fluux], please check [ProcessOne ejabberd page][p1home].
Translation
-----------
Community
---------
Using any gettext editor, you can improve the translation files found in
`priv/msgs/*.po`, and then submit your changes.
There are several places to get in touch with other ejabberd developers and administrators:
Alternatively, a simple way to improve translations is using our Weblate project:
https://hosted.weblate.org/projects/ejabberd/ejabberd-po/
- [ejabberd XMPP chatroom][muc]: ejabberd@conference.process-one.net
- [Mailing list][list]
- [GitHub Discussions][discussions]
- [Stack Overflow][stackoverflow]
Links
-----
License
-------
- Documentation: https://docs.ejabberd.im
- Community site: https://www.ejabberd.im
- ejabberd commercial offering and support: https://www.process-one.net/en/ejabberd
ejabberd is released under the GNU General Public License v2 (see [COPYING](COPYING.md)),
and [ejabberd translations](https://github.com/processone/ejabberd-po/) under MIT License.
[discussions]: https://github.com/processone/ejabberd/discussions
[docker-ecs-readme]: https://github.com/processone/docker-ejabberd/tree/master/ecs#readme
[docs-dev]: https://docs.ejabberd.im/developer/
[docs]: https://docs.ejabberd.im
[erlang]: https://www.erlang.org/
[features]: https://docs.ejabberd.im/admin/introduction/
[fluux]: https://fluux.io/
[github]: https://github.com/processone/ejabberd
[homebrew]: https://docs.ejabberd.im/admin/installation/#homebrew
[hubecs]: https://hub.docker.com/r/ejabberd/ecs/
[im]: https://ejabberd.im/
[issues]: https://github.com/processone/ejabberd/issues
[list]: https://lists.jabber.ru/mailman/listinfo/ejabberd
[localization]: https://docs.ejabberd.im/developer/extending-ejabberd/localization/
[mqtt]: https://mqtt.org/
[muc]: xmpp:ejabberd@conference.process-one.net
[osp]: https://docs.ejabberd.im/admin/installation/#operating-system-packages
[p1contact]: https://www.process-one.net/en/company/contact/
[p1home]: https://www.process-one.net/en/ejabberd/
[packages]: https://github.com/processone/ejabberd/pkgs/container/ejabberd
[releases]: https://github.com/processone/ejabberd/releases
[sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol
[stackoverflow]: https://stackoverflow.com/questions/tagged/ejabberd?sort=newest
[weblate]: https://hosted.weblate.org/projects/ejabberd/ejabberd-po/
[xeps]: https://www.process-one.net/en/ejabberd/protocols/
[xmpp]: https://xmpp.org/

View File

@ -19,7 +19,7 @@ init(State) ->
{example, "rebar3 configure-deps"}, % How to use the plugin
{opts, []}, % list of options understood by the plugin
{short_desc, "Explicitly run ./configure for dependencies"},
{desc, "A rebar plugin to allow explicitly running ./configure on depdendencies. Useful if dependencies might change prior to compilation when configure is run."}
{desc, "A rebar plugin to allow explicitly running ./configure on dependencies. Useful if dependencies might change prior to compilation when configure is run."}
]),
{ok, rebar_state:add_provider(State, Provider)}.

View File

@ -1,12 +1,13 @@
import Config
rootpath = System.get_env("RELEASE_ROOT", "")
rootdefault = case System.get_env("RELIVE", "false") do
"true" -> "_build/relive"
"false" -> ""
end
# This is standard path in the context of ejabberd release
rootpath = System.get_env("RELEASE_ROOT", rootdefault)
config :ejabberd,
file: Path.join(rootpath, "etc/ejabberd/ejabberd.yml"),
log_path: Path.join(rootpath, 'var/log/ejabberd/ejabberd.log')
# Customize Mnesia directory:
file: Path.join(rootpath, "conf/ejabberd.yml"),
log_path: Path.join(rootpath, 'logs/ejabberd.log')
config :mnesia,
dir: Path.join(rootpath, 'var/lib/ejabberd/')
dir: Path.join(rootpath, 'database/')

View File

@ -1,8 +1,8 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.53)
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
AC_PREREQ(2.59)
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 22.05` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
REQUIRE_ERLANG_MIN="8.3 (Erlang/OTP 19.3)"
REQUIRE_ERLANG_MAX="100.0.0 (No Max)"
@ -19,8 +19,7 @@ fi
# Checks Erlang runtime and compiler
AC_ARG_WITH(erlang,
AC_HELP_STRING([--with-erlang=dir],
[search for erlang in dir]),
AS_HELP_STRING([--with-erlang=dir],[search for erlang in dir]),
[if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_erlang" = "X"; then
extra_erl_path=""
else
@ -29,8 +28,7 @@ fi
])
AC_ARG_WITH(rebar,
AC_HELP_STRING([--with-rebar=bin],
[use the rebar/rebar3/mix binary specified]),
AS_HELP_STRING([--with-rebar=bin],[use the rebar/rebar3/mix binary specified]),
[if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_rebar" = "X"; then
rebar="rebar"
else
@ -70,15 +68,15 @@ AC_CONFIG_FILES([Makefile
vars.config])
AC_ARG_ENABLE(all,
[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-redis --enable-elixir --enable-stun --enable-sip --enable-debug --enable-lua --enable-tools (useful for Dialyzer checks, default: no)])],
[AS_HELP_STRING([--enable-all],[same as --enable-odbc --enable-mssql --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-redis --enable-elixir --enable-stun --enable-sip --enable-debug --enable-lua --enable-tools (useful for Dialyzer checks, default: no)])],
[case "${enableval}" in
yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true redis=true elixir=true stun=true sip=true debug=true lua=true tools=true ;;
no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false redis=false elixir=false stun=false sip=false debug=false lua=false tools=false ;;
yes) odbc=true mssql=true mysql=true pgsql=true sqlite=true pam=true zlib=true redis=true elixir=true stun=true sip=true debug=true lua=true tools=true ;;
no) odbc=false mssql=false mysql=false pgsql=false sqlite=false pam=false zlib=false redis=false elixir=false stun=false sip=false debug=false lua=false tools=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
esac],[])
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
[AS_HELP_STRING([--enable-debug],[enable debug information (default: yes)])],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
@ -86,7 +84,7 @@ AC_ARG_ENABLE(debug,
esac],[if test "x$debug" = "x"; then debug=true; fi])
AC_ARG_ENABLE(elixir,
[AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])],
[AS_HELP_STRING([--enable-elixir],[enable Elixir support (default: no)])],
[case "${enableval}" in
yes) elixir=true ;;
no) elixir=false ;;
@ -94,8 +92,7 @@ AC_ARG_ENABLE(elixir,
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
AC_ARG_ENABLE(erlang-version-check,
[AC_HELP_STRING([--enable-erlang-version-check],
[Check Erlang/OTP version (default: yes)])])
[AS_HELP_STRING([--enable-erlang-version-check],[Check Erlang/OTP version (default: yes)])])
case "$enable_erlang_version_check" in
yes|'')
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX])
@ -106,7 +103,7 @@ case "$enable_erlang_version_check" in
esac
AC_ARG_ENABLE(full_xml,
[AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
[AS_HELP_STRING([--enable-full-xml],[use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
[case "${enableval}" in
yes) full_xml=true ;;
no) full_xml=false ;;
@ -128,7 +125,7 @@ if test "$ENABLEGROUP" != ""; then
fi
AC_ARG_ENABLE(latest_deps,
[AC_HELP_STRING([--enable-latest-deps], [makes rebar use latest commits for dependencies instead of tagged versions (default: no)])],
[AS_HELP_STRING([--enable-latest-deps],[makes rebar use latest commits for dependencies instead of tagged versions (default: no)])],
[case "${enableval}" in
yes) latest_deps=true ;;
no) latest_deps=false ;;
@ -136,7 +133,7 @@ AC_ARG_ENABLE(latest_deps,
esac],[if test "x$latest_deps" = "x"; then latest_deps=false; fi])
AC_ARG_ENABLE(lua,
[AC_HELP_STRING([--enable-lua], [enable Lua support, to import from Prosody (default: no)])],
[AS_HELP_STRING([--enable-lua],[enable Lua support, to import from Prosody (default: no)])],
[case "${enableval}" in
yes) lua=true ;;
no) lua=false ;;
@ -144,15 +141,15 @@ AC_ARG_ENABLE(lua,
esac],[if test "x$lua" = "x"; then lua=false; fi])
AC_ARG_ENABLE(mssql,
[AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
[AS_HELP_STRING([--enable-mssql],[use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
[case "${enableval}" in
yes) db_type=mssql; mssql=true ;;
no) db_type=generic; mssql=false ;;
yes) mssql=true ;;
no) mssql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[db_type=generic])
esac],[if test "x$mssql" = "x"; then mssql=false; fi])
AC_ARG_ENABLE(mysql,
[AC_HELP_STRING([--enable-mysql], [enable MySQL support (default: no)])],
[AS_HELP_STRING([--enable-mysql],[enable MySQL support (default: no)])],
[case "${enableval}" in
yes) mysql=true ;;
no) mysql=false ;;
@ -160,7 +157,7 @@ AC_ARG_ENABLE(mysql,
esac],[if test "x$mysql" = "x"; then mysql=false; fi])
AC_ARG_ENABLE(new_sql_schema,
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
[AS_HELP_STRING([--enable-new-sql-schema],[use new SQL schema by default (default: no)])],
[case "${enableval}" in
yes) new_sql_schema=true ;;
no) new_sql_schema=false ;;
@ -168,7 +165,7 @@ AC_ARG_ENABLE(new_sql_schema,
esac],[new_sql_schema=false])
AC_ARG_ENABLE(odbc,
[AC_HELP_STRING([--enable-odbc], [enable pure ODBC support (default: no)])],
[AS_HELP_STRING([--enable-odbc],[enable pure ODBC support (default: no)])],
[case "${enableval}" in
yes) odbc=true ;;
no) odbc=false ;;
@ -176,7 +173,7 @@ AC_ARG_ENABLE(odbc,
esac],[if test "x$odbc" = "x"; then odbc=false; fi])
AC_ARG_ENABLE(pam,
[AC_HELP_STRING([--enable-pam], [enable PAM support (default: no)])],
[AS_HELP_STRING([--enable-pam],[enable PAM support (default: no)])],
[case "${enableval}" in
yes) pam=true ;;
no) pam=false ;;
@ -184,7 +181,7 @@ AC_ARG_ENABLE(pam,
esac],[if test "x$pam" = "x"; then pam=false; fi])
AC_ARG_ENABLE(pgsql,
[AC_HELP_STRING([--enable-pgsql], [enable PostgreSQL support (default: no)])],
[AS_HELP_STRING([--enable-pgsql],[enable PostgreSQL support (default: no)])],
[case "${enableval}" in
yes) pgsql=true ;;
no) pgsql=false ;;
@ -192,7 +189,7 @@ AC_ARG_ENABLE(pgsql,
esac],[if test "x$pgsql" = "x"; then pgsql=false; fi])
AC_ARG_ENABLE(redis,
[AC_HELP_STRING([--enable-redis], [enable Redis support (default: no)])],
[AS_HELP_STRING([--enable-redis],[enable Redis support (default: no)])],
[case "${enableval}" in
yes) redis=true ;;
no) redis=false ;;
@ -200,7 +197,7 @@ AC_ARG_ENABLE(redis,
esac],[if test "x$redis" = "x"; then redis=false; fi])
AC_ARG_ENABLE(roster_gateway_workaround,
[AC_HELP_STRING([--enable-roster-gateway-workaround], [turn on workaround for processing gateway subscriptions (default: no)])],
[AS_HELP_STRING([--enable-roster-gateway-workaround],[turn on workaround for processing gateway subscriptions (default: no)])],
[case "${enableval}" in
yes) roster_gateway_workaround=true ;;
no) roster_gateway_workaround=false ;;
@ -208,7 +205,7 @@ AC_ARG_ENABLE(roster_gateway_workaround,
esac],[roster_gateway_workaround=false])
AC_ARG_ENABLE(sip,
[AC_HELP_STRING([--enable-sip], [enable SIP support (default: no)])],
[AS_HELP_STRING([--enable-sip],[enable SIP support (default: no)])],
[case "${enableval}" in
yes) sip=true ;;
no) sip=false ;;
@ -216,7 +213,7 @@ AC_ARG_ENABLE(sip,
esac],[if test "x$sip" = "x"; then sip=false; fi])
AC_ARG_ENABLE(sqlite,
[AC_HELP_STRING([--enable-sqlite], [enable SQLite support (default: no)])],
[AS_HELP_STRING([--enable-sqlite],[enable SQLite support (default: no)])],
[case "${enableval}" in
yes) sqlite=true ;;
no) sqlite=false ;;
@ -224,7 +221,7 @@ AC_ARG_ENABLE(sqlite,
esac],[if test "x$sqlite" = "x"; then sqlite=false; fi])
AC_ARG_ENABLE(stun,
[AC_HELP_STRING([--enable-stun], [enable STUN/TURN support (default: yes)])],
[AS_HELP_STRING([--enable-stun],[enable STUN/TURN support (default: yes)])],
[case "${enableval}" in
yes) stun=true ;;
no) stun=false ;;
@ -232,7 +229,7 @@ AC_ARG_ENABLE(stun,
esac],[if test "x$stun" = "x"; then stun=true; fi])
AC_ARG_ENABLE(system_deps,
[AC_HELP_STRING([--enable-system-deps], [makes rebar use locally installed dependencies instead of downloading them (default: no)])],
[AS_HELP_STRING([--enable-system-deps],[makes rebar use locally installed dependencies instead of downloading them (default: no)])],
[case "${enableval}" in
yes) system_deps=true ;;
no) system_deps=false ;;
@ -240,7 +237,7 @@ AC_ARG_ENABLE(system_deps,
esac],[if test "x$system_deps" = "x"; then system_deps=false; fi])
AC_ARG_ENABLE(tools,
[AC_HELP_STRING([--enable-tools], [build development tools (default: no)])],
[AS_HELP_STRING([--enable-tools],[build development tools (default: no)])],
[case "${enableval}" in
yes) tools=true ;;
no) tools=false ;;
@ -262,7 +259,7 @@ if test "$ENABLEUSER" != ""; then
fi
AC_ARG_ENABLE(zlib,
[AC_HELP_STRING([--enable-zlib], [enable Stream Compression (XEP-0138) using zlib (default: yes)])],
[AS_HELP_STRING([--enable-zlib],[enable Stream Compression (XEP-0138) using zlib (default: yes)])],
[case "${enableval}" in
yes) zlib=true ;;
no) zlib=false ;;
@ -286,8 +283,8 @@ esac
AC_SUBST(roster_gateway_workaround)
AC_SUBST(new_sql_schema)
AC_SUBST(full_xml)
AC_SUBST(db_type)
AC_SUBST(odbc)
AC_SUBST(mssql)
AC_SUBST(mysql)
AC_SUBST(pgsql)
AC_SUBST(sqlite)

View File

@ -4,8 +4,8 @@ After=network.target
[Service]
Type=notify
User=ejabberd
Group=ejabberd
User=@installuser@
Group=@installuser@
LimitNOFILE=65536
Restart=on-failure
RestartSec=5

View File

@ -47,10 +47,28 @@
#INET_DIST_INTERFACE=127.0.0.1
#.
#' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections
#' ERL_DIST_PORT: Port number for Erlang distribution
#
# For Erlang distribution, clustering and ejabberdctl usage, the
# Erlang VM listens in a random TCP port number, and the Erlang Port
# Mapper Daemon (EPMD) is spawned and used to determine this port
# number.
#
# ERL_DIST_PORT can define this port number. In that case, EPMD is
# not spawned during ejabberd startup, and ERL_EPMD_ADDRESS is
# ignored. ERL_DIST_PORT must be set to the same port number during
# ejabberd startup and when calling ejabberdctl. This feature
# requires at least Erlang/OTP 23.1.
#
# Default: not defined
#
#ERL_DIST_PORT=5210
#.
#' ERL_EPMD_ADDRESS: IP addresses where EPMD listens for connections
#
# This environment variable may be set to a comma-separated
# list of IP addresses, in which case the epmd daemon
# 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

View File

@ -12,6 +12,8 @@ ERLANG_NODE=ejabberd@localhost
# define default environment variables
[ -z "$SCRIPT" ] && SCRIPT=$0
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd -P)"
# shellcheck disable=SC2034
ERTS_VSN="{{erts_vsn}}"
ERL="{{erl}}"
IEX="{{bindir}}/iex"
EPMD="{{epmd}}"
@ -48,24 +50,24 @@ while [ $# -gt 0 ]; do
-l|--logs) LOGS_DIR=$2; shift 2;;
-f|--config) EJABBERD_CONFIG_PATH=$2; shift 2;;
-c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift 2;;
-d|--config-dir) ETC_DIR=$2; shift 2;;
-d|--config-dir) CONFIG_DIR=$2; shift 2;;
-t|--no-timeout) NO_TIMEOUT="--no-timeout"; shift;;
*) break;;
esac
done
# define ejabberd variables if not already defined from the command line
: "${ETC_DIR:="{{sysconfdir}}/ejabberd"}"
: "${LOGS_DIR:="{{localstatedir}}/log/ejabberd"}"
: "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}"
: "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}"
: "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}"
: "${CONFIG_DIR:="{{config_dir}}"}"
: "${LOGS_DIR:="{{logs_dir}}"}"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_CONFIG_PATH:="$CONFIG_DIR/ejabberd.yml"}"
: "${EJABBERDCTL_CONFIG_PATH:="$CONFIG_DIR/ejabberdctl.cfg"}"
# Allows passing extra Erlang command-line arguments in vm.args file
: "${VMARGS:="$ETC_DIR/vm.args"}"
: "${VMARGS:="$CONFIG_DIR/vm.args"}"
# shellcheck source=ejabberdctl.cfg.example
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${EJABBERD_DOC_PATH:="{{docdir}}"}"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# define erl parameters
@ -79,32 +81,41 @@ if [ -n "$INET_DIST_INTERFACE" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
fi
fi
[ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -erl_epmd_port $ERL_DIST_PORT -start_epmd false"
# if vm.args file exists in config directory, pass it to Erlang VM
[ -f "$VMARGS" ] && ERLANG_OPTS="$ERLANG_OPTS -args_file $VMARGS"
ERL_LIBS={{libdir}}
ERL_LIBS='{{libdir}}'
ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump
ERL_INETRC="$ETC_DIR"/inetrc
ERL_INETRC="$CONFIG_DIR"/inetrc
# define ejabberd parameters
EJABBERD_OPTS="$EJABBERD_OPTS\
$(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]\{1,\}\).*/ \1/;s/:[ \t]*\(infinity\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")"
$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_burst_limit_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
$(sed '/^log_burst_limit_window_time/!d;s/:[ \t]*\([0-9]*[a-z]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")"
[ -n "$EJABBERD_OPTS" ] && EJABBERD_OPTS="-ejabberd $EJABBERD_OPTS"
EJABBERD_OPTS="-mnesia dir \"$SPOOL_DIR\" $MNESIA_OPTIONS $EJABBERD_OPTS -s ejabberd"
# export global variables
export EJABBERD_CONFIG_PATH
export EJABBERD_LOG_PATH
export EJABBERD_DOC_PATH
export EJABBERD_PID_PATH
export ERL_CRASH_DUMP
export ERL_EPMD_ADDRESS
export ERL_DIST_PORT
export ERL_INETRC
export ERL_MAX_PORTS
export ERL_MAX_ETS_TABLES
export CONTRIB_MODULES_PATH
export CONTRIB_MODULES_CONF_DIR
export ERL_LIBS
export SCRIPT_DIR
set_dist_client()
{
[ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -dist_listen false"
}
# run command either directly or via su $INSTALLUSER
exec_cmd()
@ -128,14 +139,6 @@ exec_iex()
# usage
debugwarning()
{
if [ "$OSTYPE" != "cygwin" ] && [ "$OSTYPE" != "win32" ] ; then
if [ "a$TERM" = "a" ] || [ "$TERM" = "dumb" ] ; then
echo "Terminal type not supported."
echo "You may have to set the TERM environment variable to fix this."
exit 8
fi
fi
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
echo "--------------------------------------------------------------------"
echo ""
@ -153,7 +156,7 @@ debugwarning()
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue"
read -r input
read -r _
echo ""
fi
}
@ -176,7 +179,7 @@ livewarning()
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue"
read -r input
read -r _
echo ""
fi
}
@ -185,15 +188,21 @@ help()
{
echo ""
echo "Commands to start an ejabberd node:"
echo " start Start an ejabberd node in server mode"
echo " debug Attach an interactive Erlang shell to a running ejabberd node"
echo " iexdebug Attach an interactive Elixir shell to a running ejabberd node"
echo " live Start an ejabberd node in live (interactive) mode"
echo " iexlive Start an ejabberd node in live (interactive) mode, within an Elixir shell"
echo " foreground Start an ejabberd node in server mode (attached)"
echo " start Start in server mode"
echo " foreground Start in server mode (attached)"
echo " foreground-quiet Start in server mode (attached), show only critical messages"
echo " live Start in interactive mode, with Erlang shell"
echo " iexlive Start in interactive mode, with Elixir shell"
echo ""
echo "Commands to interact with a running ejabberd node:"
echo " debug Attach an interactive Erlang shell to a running node"
echo " iexdebug Attach an interactive Elixir shell to a running node"
echo " etop Attach to a running node and start Erlang Top"
echo " ping Send ping to the node, returns pong or pang"
echo " started|stopped Wait for the node to fully start|stop"
echo ""
echo "Optional parameters when starting an ejabberd node:"
echo " --config-dir dir Config ejabberd: $ETC_DIR"
echo " --config-dir dir Config ejabberd: $CONFIG_DIR"
echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH"
echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH"
echo " --logs dir Directory for logs: $LOGS_DIR"
@ -206,8 +215,9 @@ help()
uid()
{
uuid=$(uuidgen 2>/dev/null)
random=$(awk 'BEGIN { srand(); print int(rand()*32768) }' /dev/null)
[ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid)
[ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)")
[ -z "$uuid" ] && uuid=$(printf "%X" "${random:-$$}$(date +%M%S)")
uuid=$(printf '%s' $uuid | sed 's/^\(...\).*$/\1/')
[ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}"
[ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}"
@ -217,6 +227,7 @@ uid()
# stop epmd if there is no other running node
stop_epmd()
{
[ -n "$ERL_DIST_PORT" ] && return
"$EPMD" -names 2>/dev/null | grep -q name || "$EPMD" -kill >/dev/null
}
@ -224,6 +235,7 @@ stop_epmd()
# if all ok, ensure runtime directory exists and make it current directory
check_start()
{
[ -n "$ERL_DIST_PORT" ] && return
"$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && {
pgrep -f "$ERLANG_NODE" >/dev/null && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running."
@ -288,14 +300,17 @@ case $1 in
;;
debug)
debugwarning
set_dist_client
exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE"
;;
etop)
set_dist_client
exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \
-s erlang halt -output text
;;
iexdebug)
debugwarning
set_dist_client
exec_iex "$(uid debug)" --remsh "$ERLANG_NODE"
;;
iexlive)
@ -305,17 +320,21 @@ case $1 in
ping)
PEER=${2:-$ERLANG_NODE}
[ "$PEER" = "${PEER%.*}" ] && PS="-s"
set_dist_client
exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \
-noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
-s erlang halt -output text
;;
started)
set_dist_client
wait_status 0 30 2 # wait 30x2s before timeout
;;
stopped)
set_dist_client
wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout
;;
*)
set_dist_client
exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
result=$?

View File

@ -1,44 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 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.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-record(adhoc_request,
{
lang = <<"">> :: binary(),
node = <<"">> :: binary(),
sessionid = <<"">> :: binary(),
action = <<"">> :: binary(),
xdata = false :: false | xmlel(),
others = [] :: [xmlel()]
}).
-record(adhoc_response,
{
lang = <<"">> :: binary(),
node = <<"">> :: binary(),
sessionid = <<"">> :: binary(),
status :: atom(),
defaultaction = <<"">> :: binary(),
actions = [] :: [binary()],
notes = [] :: [{binary(), binary()}],
elements = [] :: [xmlel()]
}).
-type adhoc_request() :: #adhoc_request{}.
-type adhoc_response() :: #adhoc_response{}.

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@ -59,6 +59,7 @@
policy = restricted :: open | restricted | admin | user,
%% access is: [accessRuleName] or [{Module, AccessOption, DefaultAccessRuleName}]
access = [] :: [{atom(),atom(),atom()}|atom()],
definer = unknown :: atom(),
result = {res, rescode} :: rterm() | '_' | '$2',
args_rename = [] :: [{atom(),atom()}],
args_desc = none :: none | [string()] | '_',

View File

@ -1,30 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 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.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-record(local_config, {key :: any(), value :: any()}).
-type local_config() :: #local_config{}.
-record(state,
{opts = [] :: [acl:acl() | local_config()],
hosts = [] :: [binary()],
override_local = false :: boolean(),
override_global = false :: boolean(),
override_acls = false :: boolean()}).

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@ -65,6 +65,7 @@
captcha_whitelist = (?SETS):empty() :: gb_sets:set(),
mam = false :: boolean(),
pubsub = <<"">> :: binary(),
enable_hats = false :: boolean(),
lang = ejabberd_option:language() :: binary()
}).
@ -87,6 +88,16 @@
nick = <<>> :: binary(),
nodes = [] :: [binary()]}).
-record(muc_subscribers,
{subscribers = #{} :: subscribers(),
subscriber_nicks = #{} :: subscriber_nicks(),
subscriber_nodes = #{} :: subscriber_nodes()
}).
-type subscribers() :: #{ljid() => #subscriber{}}.
-type subscriber_nicks() :: #{binary() => [ljid()]}.
-type subscriber_nodes() :: #{binary() => subscribers()}.
-record(activity,
{
message_time = 0 :: integer(),
@ -106,15 +117,16 @@
jid = #jid{} :: jid(),
config = #config{} :: config(),
users = #{} :: users(),
subscribers = #{} :: subscribers(),
subscriber_nicks = #{} :: subscriber_nicks(),
muc_subscribers = #muc_subscribers{} :: #muc_subscribers{},
last_voice_request_time = treap:empty() :: treap:treap(),
robots = #{} :: robots(),
nicks = #{} :: nicks(),
affiliations = #{} :: affiliations(),
roles = #{} :: roles(),
history = #lqueue{} :: lqueue(),
subject = [] :: [text()],
subject_author = <<"">> :: binary(),
hats_users = #{} :: map(), % FIXME on OTP 21+: #{ljid() => #{binary() => binary()}},
just_created = erlang:system_time(microsecond) :: true | integer(),
activity = treap:empty() :: treap:treap(),
room_shaper = none :: ejabberd_shaper:shaper(),
@ -126,5 +138,4 @@
-type robots() :: #{jid() => {binary(), stanza()}}.
-type nicks() :: #{binary() => [ljid()]}.
-type affiliations() :: #{ljid() => affiliation() | {affiliation(), binary()}}.
-type subscribers() :: #{ljid() => #subscriber{}}.
-type subscriber_nicks() :: #{binary() => [ljid()]}.
-type roles() :: #{ljid() => role() | {role(), binary()}}.

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -2,7 +2,7 @@
%%% RFC 1928 constants.
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,5 +1,5 @@
%%%----------------------------------------------------------------------
%%% ejabberd, Copyright (C) 2017-2021 ProcessOne
%%% ejabberd, Copyright (C) 2017-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as

View File

@ -1,22 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 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.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-record(vcard_xupdate, {us = {<<>>, <<>>} :: {binary(), binary()},
hash = <<>> :: binary()}).

View File

@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2002-2021 ProcessOne, SARL. All Rights Reserved.
%%% @copyright (C) 2002-2022 ProcessOne, SARL. All Rights Reserved.
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@ -23,7 +23,7 @@
-define(ERR_EXTENDED(E, C), mod_pubsub:extended_error(E, C)).
%% The actual limit can be configured with mod_pubsub's option max_items_node
-define(MAXITEMS, 10).
-define(MAXITEMS, 1000).
%% this is currently a hard limit.
%% Would be nice to have it configurable.

File diff suppressed because it is too large Load Diff

141
mix.exs
View File

@ -5,7 +5,7 @@ defmodule Ejabberd.MixProject do
[app: :ejabberd,
version: version(),
description: description(),
elixir: "~> 1.4",
elixir: elixir_required_version(),
elixirc_paths: ["lib"],
compile_path: ".",
compilers: [:asn1] ++ Mix.compilers,
@ -24,10 +24,11 @@ defmodule Ejabberd.MixProject do
case config(:vsn) do
:false -> "0.0.0" # ./configure wasn't run: vars.config not created
'0.0' -> "0.0.0" # the full git repository wasn't downloaded
'latest.0' -> "0.0.0" # running 'docker-ejabberd/ecs/build.sh latest'
[_, _, ?., _, _] = x ->
head = String.replace(:erlang.list_to_binary(x), ~r/0+([0-9])/, "\\1")
head = String.replace(:erlang.list_to_binary(x), ~r/\.0+([0-9])/, ".\\1")
<<head::binary, ".0">>
vsn -> String.replace(:erlang.list_to_binary(vsn), ~r/0+([0-9])/, "\\1")
vsn -> String.replace(:erlang.list_to_binary(vsn), ~r/\.0+([0-9])/, ".\\1")
end
end
@ -42,22 +43,13 @@ defmodule Ejabberd.MixProject do
extra_applications: [:mix],
applications: [:idna, :inets, :kernel, :sasl, :ssl, :stdlib,
:base64url, :fast_tls, :fast_xml, :fast_yaml, :jiffy, :jose,
:p1_utils, :stringprep, :stun, :yconf],
included_applications: [:lager, :mnesia, :os_mon,
:cache_tab, :eimp, :esip, :mqtree, :p1_acme,
:p1_utils, :stringprep, :syntax_tools, :yconf],
included_applications: [:mnesia, :os_mon,
:cache_tab, :eimp, :mqtree, :p1_acme,
:p1_oauth2, :pkix, :xmpp]
++ cond_apps()]
end
defp if_function_exported(mod, fun, arity, okResult) do
:code.ensure_loaded(mod)
if :erlang.function_exported(mod, fun, arity) do
okResult
else
[]
end
end
defp if_version_above(ver, okResult) do
if :erlang.system_info(:otp_release) > ver do
okResult
@ -77,17 +69,19 @@ defmodule Ejabberd.MixProject do
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"])
result = [:debug_info, {:d, :ELIXIR_ENABLED}] ++
result = [{:d, :ELIXIR_ENABLED}] ++
cond_options() ++
Enum.map(includes, fn (path) -> {:i, path} end) ++
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_above('20', [{:d, :HAVE_URI_STRING}]) ++
if_version_above('20', [{:d, :HAVE_ERL_ERROR}]) ++
if_version_below('21', [{:d, :USE_OLD_HTTP_URI}]) ++
if_version_below('22', [{:d, :LAGER}]) ++
if_version_below('21', [{:d, :NO_CUSTOMIZE_HOSTNAME_CHECK}]) ++
if_version_below('23', [{:d, :USE_OLD_CRYPTO_HMAC}]) ++
if_version_below('23', [{:d, :USE_OLD_PG2}]) ++
if_version_below('24', [{:d, :COMPILER_REPORTS_ONLY_LINES}]) ++
if_version_below('24', [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) ++
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
if_version_below('24', [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end
@ -95,36 +89,32 @@ defmodule Ejabberd.MixProject do
defp cond_options do
for {:true, option} <- [{config(:sip), {:d, :SIP}},
{config(:stun), {:d, :STUN}},
{config(:roster_gateway_workaround), {:d, :ROSTER_GATWAY_WORKAROUND}},
{config(:debug), :debug_info},
{not config(:debug), {:debug_info, false}},
{config(:roster_gateway_workaround), {:d, :ROSTER_GATEWAY_WORKAROUND}},
{config(:new_sql_schema), {:d, :NEW_SQL_SCHEMA}}
], do:
option
end
defp deps do
[{:base64url, "~> 0.0.1"},
[{:base64url, "~> 1.0"},
{:cache_tab, "~> 1.0"},
{:distillery, "~> 2.0"},
{:eimp, "~> 1.0"},
{:esip, "~> 1.0"},
{:ex_doc, ">= 0.0.0", only: :dev},
{:fast_tls, "~> 1.1"},
{:fast_xml, "~> 1.1"},
{:fast_yaml, "~> 1.0"},
{:idna, "~> 6.0"},
{:jiffy, "~> 1.0.5"},
{:jose, "~> 1.8"},
{:lager, "~> 3.9.1"},
{:jiffy, "~> 1.1.1"},
{:jose, "~> 1.11.1"},
{:mqtree, "~> 1.0"},
{:p1_acme, "~> 1.0"},
{:p1_mysql, "~> 1.0"},
{:p1_oauth2, "~> 0.6"},
{:p1_pgsql, "~> 1.1"},
{:p1_utils, "~> 1.0"},
{:pkix, "~> 1.0"},
{:stringprep, ">= 1.0.26"},
{:stun, "~> 1.0"},
{:xmpp, "~> 1.5"},
{:xmpp, ">= 1.6.0"},
{:yconf, "~> 1.0"}]
++ cond_deps()
end
@ -144,15 +134,24 @@ defmodule Ejabberd.MixProject do
defp cond_deps do
for {:true, dep} <- [{config(:pam), {:epam, "~> 1.0"}},
{config(:redis), {:eredis, "~> 1.2.0"}},
{config(:sip), {:esip, "~> 1.0"}},
{config(:zlib), {:ezlib, "~> 1.0"}},
{config(:lua), {:luerl, "~> 0.3.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}}], do:
{if_version_below('22', true), {:lager, "~> 3.9.1"}},
{config(:lua), {:luerl, "~> 1.0"}},
{config(:mysql), {:p1_mysql, "~> 1.0.20"}},
{config(:pgsql), {:p1_pgsql, "~> 1.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}},
{config(:stun), {:stun, "~> 1.0"}}], do:
dep
end
defp cond_apps do
for {:true, app} <- [{config(:redis), :eredis},
for {:true, app} <- [{config(:pam), :epam},
{config(:lua), :luerl},
{config(:redis), :eredis},
{if_version_below('22', true), :lager},
{config(:mysql), :p1_mysql},
{config(:sip), :esip},
{config(:odbc), :odbc},
{config(:pgsql), :p1_pgsql},
{config(:sqlite), :sqlite3}], do:
@ -165,7 +164,7 @@ defmodule Ejabberd.MixProject do
"COPYING", "README.md",
"mix.exs", "rebar.config", "rebar.config.script", "vars.config"],
maintainers: ["ProcessOne"],
licenses: ["GPLv2"],
licenses: ["GPL-2.0-or-later"],
links: %{"Site" => "https://www.ejabberd.im",
"Documentation" => "http://docs.ejabberd.im",
"Source" => "https://github.com/processone/ejabberd",
@ -186,6 +185,35 @@ defmodule Ejabberd.MixProject do
end
end
defp elixir_required_version do
case {Map.get(System.get_env(), "RELIVE", "false"),
MapSet.member?(MapSet.new(System.argv()), "release")}
do
{"true", _} ->
case Version.match?(System.version(), "~> 1.11") do
false ->
IO.puts("ERROR: To use 'make relive', Elixir 1.11.0 or higher is required.")
_ -> :ok
end
"~> 1.11"
{_, true} ->
case Version.match?(System.version(), "~> 1.10") do
false ->
IO.puts("ERROR: To build releases, Elixir 1.10.0 or higher is required.")
_ -> :ok
end
case Version.match?(System.version(), "< 1.11.4")
and :erlang.system_info(:otp_release) > '23' do
true ->
IO.puts("ERROR: To build releases with Elixir lower than 1.11.4, Erlang/OTP lower than 24 is required.")
_ -> :ok
end
"~> 1.10"
_ ->
"~> 1.4"
end
end
defp releases do
maybe_tar = case Mix.env() do
:prod -> [:tar]
@ -208,11 +236,14 @@ defmodule Ejabberd.MixProject do
libdir: config(:libdir),
sysconfdir: config(:sysconfdir),
localstatedir: config(:localstatedir),
docdir: config(:docdir),
config_dir: config(:config_dir),
logs_dir: config(:logs_dir),
spool_dir: config(:spool_dir),
erl: config(:erl),
epmd: config(:epmd),
bindir: Path.join([config(:release_dir), "releases", version()]),
release_dir: config(:release_dir),
erts_dir: config(:erts_dir),
erts_vsn: "erts-#{release.erts_version}"
]
ro = "rel/overlays"
@ -229,7 +260,7 @@ defmodule Ejabberd.MixProject do
end
# Mix/Elixir lower than 1.11.0 use config/releases.exs instead of runtime.exs
case Version.match?(System.version, ">= 1.11.0") do
case Version.match?(System.version, "~> 1.11") do
true ->
:ok
false ->
@ -238,37 +269,55 @@ defmodule Ejabberd.MixProject do
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.template > ejabberdctl.example1")
Mix.Generator.copy_template("ejabberdctl.example1", "ejabberdctl.example2", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2 > ejabberdctl.example3")
execute.("sed -e 's|ERLANG_NODE=ejabberd@localhost|ERLANG_NODE=ejabberd|g' ejabberdctl.example3 > ejabberdctl.example4")
execute.("sed -e 's|INSTALLUSER=|ERL_OPTIONS=\"-setcookie \\$\\(cat \"\\${SCRIPT_DIR%/*}/releases/COOKIE\")\"\\nINSTALLUSER=|g' ejabberdctl.example4 > ejabberdctl.example5")
Mix.Generator.copy_template("ejabberdctl.example5", "#{ro}/bin/ejabberdctl", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2> ejabberdctl.example2a")
Mix.Generator.copy_template("ejabberdctl.example2a", "ejabberdctl.example2b", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2b > ejabberdctl.example3")
execute.("sed -e 's|^ERLANG_NODE=ejabberd@localhost|ERLANG_NODE=ejabberd|g' ejabberdctl.example3 > ejabberdctl.example4")
execute.("sed -e 's|^ERLANG_OPTS=\"|ERLANG_OPTS=\"-boot ../releases/#{release.version}/start_clean -boot_var RELEASE_LIB ../lib |' ejabberdctl.example4 > ejabberdctl.example5")
execute.("sed -e 's|^INSTALLUSER=|ERL_OPTIONS=\"-setcookie \\$\\(cat \"\\${SCRIPT_DIR%/*}/releases/COOKIE\")\"\\nINSTALLUSER=|g' ejabberdctl.example5 > ejabberdctl.example6")
Mix.Generator.copy_template("ejabberdctl.example6", "#{ro}/bin/ejabberdctl", assigns)
File.chmod("#{ro}/bin/ejabberdctl", 0o755)
File.rm("ejabberdctl.example1")
File.rm("ejabberdctl.example2")
File.rm("ejabberdctl.example2a")
File.rm("ejabberdctl.example2b")
File.rm("ejabberdctl.example3")
File.rm("ejabberdctl.example4")
File.rm("ejabberdctl.example5")
File.rm("ejabberdctl.example6")
suffix = case Mix.env() do
:dev ->
Mix.Generator.copy_file("test/ejabberd_SUITE_data/ca.pem", "#{ro}/etc/ejabberd/ca.pem")
Mix.Generator.copy_file("test/ejabberd_SUITE_data/cert.pem", "#{ro}/etc/ejabberd/cert.pem")
Mix.Generator.copy_file("test/ejabberd_SUITE_data/ca.pem", "#{ro}/conf/ca.pem")
Mix.Generator.copy_file("test/ejabberd_SUITE_data/cert.pem", "#{ro}/conf/cert.pem")
".example"
_ -> ""
end
Mix.Generator.copy_file("ejabberd.yml.example", "#{ro}/etc/ejabberd/ejabberd.yml#{suffix}")
Mix.Generator.copy_file("ejabberdctl.cfg.example", "#{ro}/etc/ejabberd/ejabberdctl.cfg#{suffix}")
Mix.Generator.copy_file("inetrc", "#{ro}/etc/ejabberd/inetrc")
Mix.Generator.copy_template("rel/vm.args.mix", "#{ro}/etc/ejabberd/vm.args", assigns)
Mix.Generator.copy_file("ejabberd.yml.example", "#{ro}/conf/ejabberd.yml#{suffix}")
Mix.Generator.copy_file("ejabberdctl.cfg.example", "#{ro}/conf/ejabberdctl.cfg#{suffix}")
Mix.Generator.copy_file("inetrc", "#{ro}/conf/inetrc")
Enum.each(File.ls!("sql"),
fn x ->
Mix.Generator.copy_file("sql/#{x}", "#{ro}/lib/ejabberd-#{release.version}/priv/sql/#{x}")
end)
Mix.Generator.create_directory("#{ro}/var/lib/ejabberd")
File.cp_r!("include", "#{ro}/lib/ejabberd-#{release.version}/include")
for {name, details} <- Map.to_list(release.applications) do
{_, is_otp_app} = List.keyfind(details, :otp_app?, 0)
{_, vsn} = List.keyfind(details, :vsn, 0)
{_, path} = List.keyfind(details, :path, 0)
source_dir = case is_otp_app do
:true -> "#{path}/include"
:false -> "deps/#{name}/include"
end
target_dir = "#{ro}/lib/#{name}-#{vsn}/include"
File.exists?(source_dir)
&& File.mkdir_p(target_dir)
&& File.cp_r!(source_dir, target_dir)
end
case Mix.env() do
:dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh")

View File

@ -1,36 +1,35 @@
%{
"artificery": {:hex, :artificery, "0.4.3", "0bc4260f988dcb9dda4b23f9fc3c6c8b99a6220a331534fdf5bf2fd0d4333b02", [:mix], [], "hexpm", "12e95333a30e20884e937abdbefa3e7f5e05609c2ba8cf37b33f000b9ffc0504"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
"cache_tab": {:hex, :cache_tab, "1.0.29", "6c161988620b788d8df28c8f6af557571609c8e4b671dbadab295a4722cd501b", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "a02a638021cce91ed1a8628dcbb4795bf5c01c9d11db8c613065923142824ce9"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
"earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"},
"eimp": {:hex, :eimp, "1.0.21", "2e918a5dc9a1959ef8713a2360499e3baeee64cfd7881bd9d1f361ca9ddf07e8", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "998f58538f58aa0cff103414994d7ce56dc253e6576cd6fb40c1ead64aa73a28"},
"base64url": {:hex, :base64url, "1.0.1", "f8c7f2da04ca9a5d0f5f50258f055e1d699f0e8bf4cfdb30b750865368403cf6", [:rebar3], [], "hexpm", "f9b3add4731a02a9b0410398b475b33e7566a695365237a6bdee1bb447719f5c"},
"cache_tab": {:hex, :cache_tab, "1.0.30", "6d35eecfb65fbe5fc85988503a27338d32de01243f3fc8ea3ee7161af08725a4", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "6d8a5e00d8f84c42627706a6dbedb02e34d58495f3ed61935c8475ca0531cda0"},
"earmark_parser": {:hex, :earmark_parser, "1.4.25", "2024618731c55ebfcc5439d756852ec4e85978a39d0d58593763924d9a15916f", [:mix], [], "hexpm", "56749c5e1c59447f7b7a23ddb235e4b3defe276afc220a6227237f3efe83f51e"},
"eimp": {:hex, :eimp, "1.0.22", "fa9b376ef0b50e8455db15c7c11dea4522c6902e04412288aab436d26335f6eb", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "b3b9ffb1d9a5f4a2ba88ac418a819164932d9a9d3a2fc3d32ca338ce855c4392"},
"epam": {:hex, :epam, "1.0.12", "2a5625d4133bca4b3943791a3f723ba764455a461ae9b6ba5debb262efcf4b40", [:rebar3], [], "hexpm", "54c166c4459cef72f2990a3d89a8f0be27180fe0ab0f24b28ddcc3b815f49f7f"},
"esip": {:hex, :esip, "1.0.43", "1cbdc073073f80b9b50e2759f66ca13a353eb4f874bcf92501bd4cd767e34d46", [:rebar3], [{:fast_tls, "1.1.13", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.44", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "b2c758ae52c4588e0399c0b4ce550bfa56551a5a2f828a28389f2614797e4f4b"},
"ex_doc": {:hex, :ex_doc, "0.25.0", "4070a254664ee5495c2f7cce87c2f43064a8752f7976f2de4937b65871b05223", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2d90883bd4f3d826af0bde7fea733a4c20adba1c79158e2330f7465821c8949b"},
"ezlib": {:hex, :ezlib, "1.0.10", "c1c24eb18944cfde55f0574e9922d5b0392fa864282f769f82b2ea15e54f6003", [:rebar3], [], "hexpm", "1d317f1d85373686199eb3b4164d3477e95033ac68e45a95ba18e7b7a8c23241"},
"fast_tls": {:hex, :fast_tls, "1.1.13", "828cdc75e1e8fce8158846d2b971d8b4fe2b2ddcc75b759e88d751079bf78afd", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "d1f422af40c7777fe534496f508ee86515cb929ad10f7d1d56aa94ce899b44a0"},
"fast_xml": {:hex, :fast_xml, "1.1.47", "bd1d6c081b69c7bce0d2f22b013c1b864ed2588d48f34e2156d9428f8f772c66", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "dd014c45247498effb9a28cf98cb716db79be635ad1e98c951240763119f24c7"},
"fast_yaml": {:hex, :fast_yaml, "1.0.32", "43f53a2c8572f2e4d66cd4e787fc6761b1c65b9132e42c511d8b9540b0989d65", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "7258e322739ff0824237ebe44cd158e0bf52cd27a15fe731cf92f4b4c70b913e"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"},
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm", "d9b5abef2c2c8aba8f32aa018203e0b3dc8b1157773b254ab1d4c2002317f1e1"},
"esip": {:hex, :esip, "1.0.48", "3b3b3afc798be9458517d4fd2730674322368e54c2c1211aa630327354946d1b", [:rebar3], [{:fast_tls, "1.1.16", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.2.6", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "02b9fc6e071415cbc62105f5115aeb68d11184bdad3960da7b62ea3e99e7fccf"},
"ex_doc": {:hex, :ex_doc, "0.28.4", "001a0ea6beac2f810f1abc3dbf4b123e9593eaa5f00dd13ded024eae7c523298", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bf85d003dd34911d89c8ddb8bda1a958af3471a274a4c2150a9c01c78ac3f8ed"},
"ezlib": {:hex, :ezlib, "1.0.12", "ffe906ba10d03aaee7977e1e0e81d9ffc3bb8b47fb9cd8e2e453507a2e56221f", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "30e94355fb42260aab6e12582cb0c56bf233515e655c8aeaf48760e7561e4ebb"},
"fast_tls": {:hex, :fast_tls, "1.1.16", "85fa7f3112ea4ff5ccb4f3abadc130a8c855ad74eb00869487399cb0c322d208", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "aa08cca89b4044e74f1f12e399817d8beaeae3ee006c98a893c0bfb1d81fba51"},
"fast_xml": {:hex, :fast_xml, "1.1.49", "67d9bfcadd04efd930e0ee1412b5ea09d3e791f1fdbd4d3e9a8c8f29f8bfed8c", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "01da064d2f740818956961036637fee2475c17bf8aab9442217f90dc77883593"},
"fast_yaml": {:hex, :fast_yaml, "1.0.34", "3be1ed8a37fe87a53f7f2ad1ee9586dcc257103d0b1d1f0ee6306cad9d54c29a", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "926dc1798399418d3983bd53356f3395b01c07a550f6b8d1dd5d6cc07c22c1c9"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
"jiffy": {:hex, :jiffy, "1.0.5", "a69b58faf7123534c20e1b0b7ae97ac52079ca02ed4b6989b4b380179cd63a54", [:rebar3], [], "hexpm", "b617a53f46ae84f20d0c38951367dc947a2cf8cff922aa5c6ac6b64b8b052289"},
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm", "6429c4fee52b2dda7861ee19a4f09c8c1ffa213bee3a1ec187828fde95d447ed"},
"lager": {:hex, :lager, "3.9.2", "4cab289120eb24964e3886bd22323cb5fefe4510c076992a23ad18cf85413d8c", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "7f904d9e87a8cb7e66156ed31768d1c8e26eba1d54f4bc85b1aa4ac1f6340c28"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
"jiffy": {:hex, :jiffy, "1.1.1", "aca10f47aa91697bf24ab9582c74e00e8e95474c7ef9f76d4f1a338d0f5de21b", [:rebar3], [], "hexpm", "62e1f0581c3c19c33a725c781dfa88410d8bff1bbafc3885a2552286b4785c4c"},
"jose": {:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb", [:mix, :rebar3], [], "hexpm", "078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
"luerl": {:hex, :luerl, "1.0.0", "1b68c30649323590d5339b967b419260500ffe520cd3abc1987482a82d3b5a6c", [:rebar3], [], "hexpm", "c17bc45cb4b0845ec975387f9a5d8c81ab60456698527a29c96f78992af86bd1"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"mqtree": {:hex, :mqtree, "1.0.14", "d201a79b51a9232b80e764b4b77a866f7c30a90c7ac6205d71f391eb3ea7eb31", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "8626dac5e862b575eaf4836f0fc1be5a7c8435c378c5a309e34ee012d48b6f6e"},
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"p1_acme": {:hex, :p1_acme, "1.0.13", "fec71df416004ce49e295f4846fe5ba3478b41fbe4f73a06b4a8fbc967d6e659", [:rebar3], [{:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "1.0.5", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "1.0.12", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "a2ce9d4904304df020c8e92e8577e0fc88f32623540656317c7e25440b4ac8d2"},
"p1_mysql": {:hex, :p1_mysql, "1.0.19", "22f1be58397780a7d580a954e7af66cde32a29dee1a24ab2aa196272fc654a4a", [:rebar3], [], "hexpm", "88f6cdb510e8959c14b6ae84ccda04967e3de239228f859d8341da67949622b1"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.10", "09ba1fbd447b1f480b223903e36d0415f21be592a1b00db964eea01285749028", [:rebar3], [], "hexpm", "c79cb61ababee4a8c85409b7f4932035797c093aeef1f9f53985e512b26f2a64"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.12", "10ae79eeb35ea98c0424a8b6420542fef9e4469eb12ccf41475d10840c291e68", [:rebar3], [], "hexpm", "32203f779e01cf0353270df24833a1d831ad7cb3e3e8e35a7556dfa1f40948d5"},
"p1_utils": {:hex, :p1_utils, "1.0.23", "7f94466ada69bd982ea7bb80fbca18e7053e7d0b82c9d9e37621fa508587069b", [:rebar3], [], "hexpm", "47f21618694eeee5006af1c88731ad86b757161e7823c29b6f73921b571c8502"},
"pkix": {:hex, :pkix, "1.0.8", "98ea05243847fd4504f7c7a0cd82cecd1010ac327a082e1c674c5384006eae75", [:rebar3], [], "hexpm", "399508819501fab9d2e586dfa601b5ee3ef22b5612d3db58204dd2d089ef45d7"},
"stringprep": {:hex, :stringprep, "1.0.27", "02808c7024bc6285ca6a8a67e7addfc16f35dda55551a582c5181d8ea960e890", [:rebar3], [{:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "a5967b1144ca8002a58a03d16dd109fbd0bcdb82616cead2f983944314af6a00"},
"stun": {:hex, :stun, "1.0.44", "30b6b774864b24b05ba901291abe583bff19081e7c4efb3361df50b781ec9d3b", [:rebar3], [{:fast_tls, "1.1.13", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "e45bba816cbefff01d820e49e66814f450df25a7a468a70d68d1e64218d46520"},
"mqtree": {:hex, :mqtree, "1.0.15", "bc54d8b88698fdaebc1e27a9ac43688b927e3dbc05bd5cee4057e69a89a8cf17", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "294ac43c9b3d372e24eeea56c259e19c655522dcff64a55c401a639663b9d829"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"p1_acme": {:hex, :p1_acme, "1.0.20", "c976cbca2dd1bdcf71a6e17fb512e30451b5f258694157f7b63963767ee26560", [:rebar3], [{:base64url, "1.0.1", [hex: :base64url, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "1.1.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "1.11.1", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "1.0.14", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "70e0ecf8c8729dfc01f6a15279ef9fa4003c3b5af47b6732d9312296a8ba4f5c"},
"p1_mysql": {:hex, :p1_mysql, "1.0.20", "08aeade83a24902a5fca2dbf78fa674eef25ca4e66250b4be8bd3580f35880e7", [:rebar3], [], "hexpm", "12152e8feadcf8ce586334314ca27cb088f12e0a5c850c496a8df69859390877"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.11", "96b4e85c08355720523c2f892011a81a07994d15c179ce4dd82d704fecad15b2", [:rebar3], [], "hexpm", "9c3c6ae59382b9525473bb02a32949889808f33f95f6db10594fd92acd1f63db"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.19", "dc615844fd22a2e45182018d5bcc6b757ac19f576fab3fe6d69e1c0ff25cee2b", [:rebar3], [{:xmpp, "1.6.0", [hex: :xmpp, repo: "hexpm", optional: false]}], "hexpm", "4b0c6d30bbf881feb01171d13f444a6e05e1d19b6926e3f56f4028823d02730b"},
"p1_utils": {:hex, :p1_utils, "1.0.25", "2d39b5015a567bbd2cc7033eeb93a7c60d8c84efe1ef69a3473faa07fa268187", [:rebar3], [], "hexpm", "9219214428f2c6e5d3187ff8eb9a8783695c2427420be9a259840e07ada32847"},
"pkix": {:hex, :pkix, "1.0.9", "eb20b2715d71a23b4fe7e754dae9281a964b51113d0bba8adf9da72bf9d65ac2", [:rebar3], [], "hexpm", "daab2c09cdd4eda05c9b45a5c00e994a1a5f27634929e1377e2e59b707103e3a"},
"sqlite3": {:hex, :sqlite3, "1.1.13", "94a6e0508936514e1493efeb9b939a9bbfa861f4b8dc93ef174ae88a1d9381d3", [:rebar3], [], "hexpm", "b77fad096d1ae9553ad8551ea75bd0d64a2f5b09923a7ca48b14215564dbfc48"},
"stringprep": {:hex, :stringprep, "1.0.29", "02f23e8c3a219a3dfe40a22e908bece3a2f68af0ff599ea8a7b714ecb21e62ee", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "928eba304c3006eb1512110ebd7b87db163b00859a09375a1e4466152c6c462a"},
"stun": {:hex, :stun, "1.2.6", "5d1978d340ea20efb28bc1e58779a3a1d64568c66168db4d20692e76ce813d5e", [:rebar3], [{:fast_tls, "1.1.16", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "21aed098457e5099e925129459590592e001c470cf7503e5614a7a6b688ff146"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
"xmpp": {:hex, :xmpp, "1.5.4", "6cd8144b3fe04745dc2cb3e746d6f2a963bb283db48a61f159b49cbe3fab8623", [:rebar3], [{:ezlib, "1.0.10", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.13", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.47", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.23", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.27", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "3bc2b5cb24e52964fb11641422ce2b7ba7c261dd50080689a1cbe3d952a9db35"},
"yconf": {:hex, :yconf, "1.0.12", "78c119d39bb805207fcb7671cb884805d75ee89c9ec98632b678f90a597dee2c", [:rebar3], [{:fast_yaml, "1.0.32", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "12faa51c281e95bcb6abf185fd034a242209621a7bb04b6cc411c867b192e207"},
"xmpp": {:hex, :xmpp, "1.6.0", "2ca2180eac1a97e929d1cfa1e4faabef4f32a719331c7f56e47d305c0ec8e438", [:rebar3], [{:ezlib, "1.0.12", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.16", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.49", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.29", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "5fd723c95bce79600a8f44ba79cf5d3b1dac80af65493a4a414e39791f7dd7e9"},
"yconf": {:hex, :yconf, "1.0.14", "b216f385f729b338385b25176f6e4fe8cabfdf7ede9c40a35b2e77fc93e98fc8", [:rebar3], [{:fast_yaml, "1.0.34", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "a8a9262553c11ed4cd13cc8e656e53acb00f9385f0a50cd235af7d02e9204bce"},
}

11
priv/msgs/ar.msg Normal file
View File

@ -0,0 +1,11 @@
%% Generated automatically
%% DO NOT EDIT: run `make translations` instead
%% To improve translations please read:
%% https://docs.ejabberd.im/developer/extending-ejabberd/localization/
{" (Add * to the end of field to match substring)"," (أضف * في نهاية الحقل لمطابقة السلسلة الفرعية)"}.
{" has set the subject to: "," حدد الموضوع إلى: "}.
{"# participants","# المشاركين"}.
{"A description of the node","وصف العقدة"}.
{"A Web Page","موقع الكتروني"}.
{"'Displayed groups' not added (they do not exist!): ","لم تتم إضافة \"المجموعات المعروضة\" (فهي غير موجودة!): "}.

View File

@ -20,6 +20,7 @@
{"Access model","Model d'Accés"}.
{"Account doesn't exist","El compte no existeix"}.
{"Action on user","Acció en l'usuari"}.
{"Add a hat to a user","Afegir un barret a un usuari"}.
{"Add Jabber ID","Afegir Jabber ID"}.
{"Add New","Afegir nou"}.
{"Add User","Afegir usuari"}.
@ -78,6 +79,7 @@
{"Changing role/affiliation is not allowed","No està permès canviar el rol/afiliació"}.
{"Channel already exists","El canal ja existeix"}.
{"Channel does not exist","El canal no existeix"}.
{"Channel JID","JID del Canal"}.
{"Channels","Canals"}.
{"Characters not allowed:","Caràcters no permesos:"}.
{"Chatroom configuration modified","Configuració de la sala de xat modificada"}.
@ -97,6 +99,7 @@
{"Configuration","Configuració"}.
{"Connected Resources:","Recursos connectats:"}.
{"Contact Addresses (normally, room owner or owners)","Adreces de contacte (normalment, propietaris de la sala)"}.
{"Contrib Modules","Mòduls Contrib"}.
{"Country","Pais"}.
{"CPU Time:","Temps de CPU:"}.
{"Current Discussion Topic","Assumpte de discussió actual"}.
@ -136,6 +139,7 @@
{"Elements","Elements"}.
{"Email Address","Adreça de correu"}.
{"Email","Correu"}.
{"Enable hats","Activar barrets"}.
{"Enable logging","Habilitar el registre de la conversa"}.
{"Enable message archiving","Activar l'emmagatzematge de missatges"}.
{"Enabling push without 'node' attribute is not supported","No està suportat activar Push sense l'atribut 'node'"}.
@ -170,6 +174,8 @@
{"Full List of Room Admins","Llista completa de administradors de la sala"}.
{"Full List of Room Owners","Llista completa de propietaris de la sala"}.
{"Full Name","Nom complet"}.
{"Get List of Online Users","Obté la llista d'usuaris en línia"}.
{"Get List of Registered Users","Obté la llista d'usuaris registrats"}.
{"Get Number of Online Users","Obtenir Número d'Usuaris Connectats"}.
{"Get Number of Registered Users","Obtenir Número d'Usuaris Registrats"}.
{"Get Pending","Obtenir Pendents"}.
@ -186,6 +192,9 @@
{"has been kicked because of an affiliation change","ha sigut expulsat a causa d'un canvi d'afiliació"}.
{"has been kicked because the room has been changed to members-only","ha sigut expulsat perquè la sala ara és només per a membres"}.
{"has been kicked","ha sigut expulsat"}.
{"Hat title","Títol del barret"}.
{"Hat URI","URI del barret"}.
{"Hats limit exceeded","El límit de tràfic ha sigut sobrepassat"}.
{"Host unknown","Host desconegut"}.
{"Host","Host"}.
{"HTTP File Upload","HTTP File Upload"}.
@ -208,6 +217,8 @@
{"Incorrect value of 'action' attribute","Valor incorrecte del atribut 'action'"}.
{"Incorrect value of 'action' in data form","Valor incorrecte de 'action' al formulari de dades"}.
{"Incorrect value of 'path' in data form","Valor incorrecte de 'path' al formulari de dades"}.
{"Installed Modules:","Mòduls instal·lats:"}.
{"Install","Instal·lar"}.
{"Insufficient privilege","Privilegi insuficient"}.
{"Internal server error","Error intern del servidor"}.
{"Invalid 'from' attribute in forwarded message","Atribut 'from' invàlid al missatge reenviat"}.
@ -224,6 +235,8 @@
{"January","Gener"}.
{"JID normalization denied by service policy","S'ha denegat la normalització del JID per política del servei"}.
{"JID normalization failed","Ha fallat la normalització del JID"}.
{"Joined MIX channels of ~ts","Canals MIX units de ~ts"}.
{"Joined MIX channels:","Canals MIX units:"}.
{"joins the room","entra a la sala"}.
{"July","Juliol"}.
{"June","Juny"}.
@ -237,6 +250,8 @@
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","Els bits menys significants del hash SHA-256 del text deurien ser iguals a l'etiqueta hexadecimal"}.
{"leaves the room","surt de la sala"}.
{"List of rooms","Llista de sales"}.
{"List of users with hats","Llista d'usuaris amb barrets"}.
{"List users with hats","Llista d'usuaris amb barrets"}.
{"Logging","Registre"}.
{"Low level update script","Script d'actualització de baix nivell"}.
{"Make participants list public","Crear una llista de participants pública"}.
@ -249,7 +264,7 @@
{"Malformed username","Nom d'usuari mal format"}.
{"MAM preference modification denied by service policy","Se t'ha denegat la modificació de la preferència de MAM per política del servei"}.
{"March","Març"}.
{"Max # of items to persist","Màxim # d'elements que persistixen"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","Màxim # d'elements a persistir, o `max` per a no tindre altre límit més que el màxim imposat pel servidor"}.
{"Max payload size in bytes","Màxim tamany del payload en bytes"}.
{"Maximum file size","Mida màxima de fitxer"}.
{"Maximum Number of History Messages Returned by Room","Numero màxim de missatges de l'historia que retorna la sala"}.
@ -324,6 +339,7 @@
{"Node index not found","Index de node no trobat"}.
{"Node not found","Node no trobat"}.
{"Node ~p","Node ~p"}.
{"Node","Node"}.
{"Nodeprep has failed","Ha fallat Nodeprep"}.
{"Nodes","Nodes"}.
{"None","Cap"}.
@ -339,8 +355,9 @@
{"Number of Offline Messages","Número de missatges offline"}.
{"Number of online users","Número d'usuaris connectats"}.
{"Number of registered users","Número d'Usuaris Registrats"}.
{"Number of seconds after which to automatically purge items","Número de segons després dels quals es purgaran automàticament elements"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","Número de segons després dels quals es purgaran automàticament elements, o `max` per a no tindre altre límit més que el màxim imposat pel servidor"}.
{"Occupants are allowed to invite others","Els ocupants poden invitar a altres"}.
{"Occupants are allowed to query others","Els ocupants poden enviar peticions a altres"}.
{"Occupants May Change the Subject","Els ocupants poden canviar el Tema"}.
{"October","Octubre"}.
{"Offline Messages:","Missatges fora de línia:"}.
@ -367,11 +384,13 @@
{"Only those on a whitelist may subscribe and retrieve items","Només qui estiga a una llista blanca pot subscriure's i recuperar elements"}.
{"Organization Name","Nom de la organizació"}.
{"Organization Unit","Unitat de la organizació"}.
{"Other Modules Available:","Altres mòduls disponibles:"}.
{"Outgoing s2s Connections:","Connexions d'eixida s2s:"}.
{"Outgoing s2s Connections","Connexions s2s d'eixida"}.
{"Owner privileges required","Es requerixen privilegis de propietari de la sala"}.
{"Packet relay is denied by service policy","S'ha denegat el reenviament del paquet per política del servei"}.
{"Packet","Paquet"}.
{"Participant ID","ID del Participant"}.
{"Participant","Participant"}.
{"Password Verification","Verificació de la Contrasenya"}.
{"Password Verification:","Verificació de la Contrasenya:"}.
@ -418,6 +437,7 @@
{"Registered Users:","Usuaris registrats:"}.
{"Register","Registrar"}.
{"Remote copy","Còpia remota"}.
{"Remove a hat from a user","Eliminar un barret d'un usuari"}.
{"Remove All Offline Messages","Eliminar tots els missatges offline"}.
{"Remove User","Eliminar usuari"}.
{"Remove","Borrar"}.
@ -473,6 +493,7 @@
{"Shut Down Service","Apager el Servei"}.
{"SOCKS5 Bytestreams","SOCKS5 Bytestreams"}.
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clients XMPP poden emmagatzemar la teva contrasenya al ordinador, però només hauries de fer això al teu ordinador personal, per raons de seguretat."}.
{"Sources Specs:","Especificacions de Codi Font:"}.
{"Specify the access model","Especificar el model d'accés"}.
{"Specify the event message type","Especifica el tipus de missatge d'event"}.
{"Specify the publisher model","Especificar el model del publicant"}.
@ -518,8 +539,10 @@
{"The JIDs of those to contact with questions","Els JIDs a qui contactar amb preguntes"}.
{"The JIDs of those with an affiliation of owner","Els JIDs de qui tenen una afiliació de propietaris"}.
{"The JIDs of those with an affiliation of publisher","Els JIDs de qui tenen una afiliació de publicadors"}.
{"The list of all online users","La llista de tots els usuaris en línia"}.
{"The list of all users","La llista de tots els usuaris"}.
{"The list of JIDs that may associate leaf nodes with a collection","La llista de JIDs que poden associar nodes fulla amb una col·lecció"}.
{"The maximum number of child nodes that can be associated with a collection","El màxim número de nodes fills que poden associar-se amb una col·lecció"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","El màxim número de nodes fills que poden associar-se amb una col·lecció, o `max` per a no tindre altre límit més que el màxim imposat pel servidor"}.
{"The minimum number of milliseconds between sending any two notification digests","El número mínim de mil·lisegons entre l'enviament de dos resums de notificacions"}.
{"The name of the node","El nom del node"}.
{"The node is a collection node","El node es una col·lecció"}.
@ -544,7 +567,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","El tipus de dades al node, usualment especificat pel namespace del payload (si n'hi ha)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","La URL de uns transformació XSL que pot ser aplicada als payloads per a generar un element apropiat de contingut de missatge."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","La URL de una transformació XSL que pot ser aplicada al format de payload per a generar un resultat valid de Data Forms, que el client puga mostrar usant un métode generic de Data Forms"}.
{"The username is not valid","El nom d'usuari no es vàlid"}.
{"There was an error changing the password: ","Hi ha hagut un error canviant la contrasenya: "}.
{"There was an error creating the account: ","Hi ha hagut un error creant el compte: "}.
{"There was an error deleting the account: ","Hi ha hagut un error esborrant el compte: "}.
@ -571,7 +593,7 @@
{"Too many users in this conference","N'hi ha massa usuaris en esta sala de conferència"}.
{"To","Per a"}.
{"Total rooms","Sales totals"}.
{"Traffic rate limit is exceeded","El llímit de tràfic ha sigut sobrepassat"}.
{"Traffic rate limit is exceeded","El límit de tràfic ha sigut sobrepassat"}.
{"Transactions Aborted:","Transaccions Avortades:"}.
{"Transactions Committed:","Transaccions Realitzades:"}.
{"Transactions Logged:","Transaccions registrades:"}.
@ -583,6 +605,7 @@
{"Unauthorized","No autoritzat"}.
{"Unexpected action","Acció inesperada"}.
{"Unexpected error condition: ~p","Condició d'error inesperada: ~p"}.
{"Uninstall","Desinstal·lar"}.
{"Unregister an XMPP account","Anul·lar el registre d'un compte XMPP"}.
{"Unregister","Anul·lar el registre"}.
{"Unselect All","Deseleccionar tots"}.
@ -593,7 +616,10 @@
{"Update ~p","Actualitzar ~p"}.
{"Update plan","Pla d'actualització"}.
{"Update script","Script d'actualització"}.
{"Update specs to get modules source, then install desired ones.","Actualitza les especificacions per obtindre el codi font dels mòduls, després instal·la els que vulgues."}.
{"Update Specs","Actualitzar Especificacions"}.
{"Update","Actualitzar"}.
{"Upgrade","Actualitza"}.
{"Uptime:","Temps en marxa:"}.
{"URL for Archived Discussion Logs","URL dels Arxius de Discussions"}.
{"User already exists","El usuari ja existeix"}.
@ -616,6 +642,7 @@
{"Value of '~s' should be integer","El valor de '~s' deuria ser un numero enter"}.
{"Value 'set' of 'type' attribute is not allowed","El valor 'set' a l'atribut 'type' no és permès"}.
{"vCard User Search","vCard recerca d'usuari"}.
{"View joined MIX channels","Vore els canals MIX units"}.
{"View Queue","Vore Cua"}.
{"View Roster","Vore Llista de contactes"}.
{"Virtual Hosts","Hosts virtuals"}.

View File

@ -181,7 +181,6 @@
{"Make room public searchable","Nastavit místnost jako veřejnou"}.
{"Malformed username","Chybně formátováné jméno uživatele"}.
{"March",". března"}.
{"Max # of items to persist","Maximální počet položek, které je možné natrvalo uložit"}.
{"Max payload size in bytes","Maximální náklad v bajtech"}.
{"Maximum Number of Occupants","Počet účastníků"}.
{"May",". května"}.

View File

@ -20,6 +20,7 @@
{"Access model","Zugriffsmodell"}.
{"Account doesn't exist","Konto existiert nicht"}.
{"Action on user","Aktion auf Benutzer"}.
{"Add a hat to a user","Funktion zu einem Benutzer hinzufügen"}.
{"Add Jabber ID","Jabber-ID hinzufügen"}.
{"Add New","Neue(n) hinzufügen"}.
{"Add User","Benutzer hinzufügen"}.
@ -136,6 +137,7 @@
{"Elements","Elemente"}.
{"Email Address","E-Mail-Adresse"}.
{"Email","E-Mail"}.
{"Enable hats","Funktion einschalten"}.
{"Enable logging","Protokollierung aktivieren"}.
{"Enable message archiving","Nachrichtenarchivierung aktivieren"}.
{"Enabling push without 'node' attribute is not supported","push ohne 'node'-Attribut zu aktivieren wird nicht unterstützt"}.
@ -170,6 +172,8 @@
{"Full List of Room Admins","Vollständige Liste der Raumadmins"}.
{"Full List of Room Owners","Vollständige Liste der Raumbesitzer"}.
{"Full Name","Vollständiger Name"}.
{"Get List of Online Users","Liste der angemeldeten Benutzer abrufen"}.
{"Get List of Registered Users","Liste der registrierten Benutzer abrufen"}.
{"Get Number of Online Users","Anzahl der angemeldeten Benutzer abrufen"}.
{"Get Number of Registered Users","Anzahl der registrierten Benutzer abrufen"}.
{"Get Pending","Ausstehende abrufen"}.
@ -186,6 +190,9 @@
{"has been kicked because of an affiliation change","wurde wegen einer Änderung der Zugehörigkeit hinausgeworfen"}.
{"has been kicked because the room has been changed to members-only","wurde hinausgeworfen weil der Raum zu Nur-Mitglieder geändert wurde"}.
{"has been kicked","wurde hinausgeworfen"}.
{"Hat title","Funktionstitel"}.
{"Hat URI","Funktions-URI"}.
{"Hats limit exceeded","Funktionslimit wurde überschritten"}.
{"Host unknown","Host unbekannt"}.
{"Host","Host"}.
{"HTTP File Upload","HTTP-Dateiupload"}.
@ -237,6 +244,8 @@
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","Niederwertigstes Bit des SHA-256-Hashes des Textes sollte hexadezimalem Label gleichen"}.
{"leaves the room","verlässt den Raum"}.
{"List of rooms","Liste von Räumen"}.
{"List of users with hats","Liste der Benutzer mit Funktionen"}.
{"List users with hats","Benutzer mit Funktionen auflisten"}.
{"Logging","Protokollierung"}.
{"Low level update script","Low-Level-Aktualisierungsscript"}.
{"Make participants list public","Teilnehmerliste öffentlich machen"}.
@ -249,7 +258,7 @@
{"Malformed username","Ungültiger Benutzername"}.
{"MAM preference modification denied by service policy","Modifikation der MAM-Präferenzen aufgrund der Dienstrichtlinien verweigert"}.
{"March","März"}.
{"Max # of items to persist","Maximale Anzahl persistenter Items"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","Maximale Anzahl der aufzubewahrenden Elemente oder `max`, wenn es keine spezifische Begrenzung gibt, außer einer vom Server festgelegten Höchstzahl"}.
{"Max payload size in bytes","Maximale Nutzdatengröße in Bytes"}.
{"Maximum file size","Maximale Dateigröße"}.
{"Maximum Number of History Messages Returned by Room","Maximale Anzahl der vom Raum zurückgegebenen History-Nachrichten"}.
@ -340,7 +349,7 @@
{"Number of Offline Messages","Anzahl der Offline-Nachrichten"}.
{"Number of online users","Anzahl der angemeldeten Benutzer"}.
{"Number of registered users","Anzahl der registrierten Benutzer"}.
{"Number of seconds after which to automatically purge items","Anzahl der Sekunden, nach der Items automatisch gelöscht werden"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","Anzahl der Sekunden, nach denen Elemente automatisch gelöscht werden sollen, oder `max`, wenn es keine spezifische Grenze gibt, außer einer vom Server festgelegten Höchstgrenze"}.
{"Occupants are allowed to invite others","Teilnehmer dürfen andere einladen"}.
{"Occupants May Change the Subject","Teilnehmer dürfen das Thema ändern"}.
{"October","Oktober"}.
@ -419,6 +428,7 @@
{"Registered Users","Registrierte Benutzer"}.
{"Registered Users:","Registrierte Benutzer:"}.
{"Remote copy","Fernkopie"}.
{"Remove a hat from a user","Eine Funktion bei einem Benutzer entfernen"}.
{"Remove All Offline Messages","Alle Offline-Nachrichten löschen"}.
{"Remove User","Benutzer löschen"}.
{"Remove","Entfernen"}.
@ -437,7 +447,7 @@
{"Roles and Affiliations that May Retrieve Member List","Rollen und Zugehörigkeiten die Mitgliederliste abrufen dürfen"}.
{"Roles for which Presence is Broadcasted","Rollen für welche die Präsenz übertragen wird"}.
{"Roles that May Send Private Messages","Rollen die Privatnachrichten senden dürfen"}.
{"Room Configuration","Raum-Konfiguration"}.
{"Room Configuration","Raumkonfiguration"}.
{"Room creation is denied by service policy","Anlegen des Raumes aufgrund der Dienstrichtlinien verweigert"}.
{"Room description","Raumbeschreibung"}.
{"Room Occupants","Raumteilnehmer"}.
@ -519,8 +529,10 @@
{"The JIDs of those to contact with questions","Die JIDs jener, die bei Fragen zu kontaktieren sind"}.
{"The JIDs of those with an affiliation of owner","Die JIDs jener mit einer Zugehörigkeit von Besitzer"}.
{"The JIDs of those with an affiliation of publisher","Die JIDs jener mit einer Zugehörigkeit von Veröffentlicher"}.
{"The list of all online users","Die Liste aller angemeldeter Benutzer"}.
{"The list of all users","Die Liste aller Benutzer"}.
{"The list of JIDs that may associate leaf nodes with a collection","Die Liste der JIDs die Blattknoten mit einer Sammlung verknüpfen dürfen"}.
{"The maximum number of child nodes that can be associated with a collection","Die maximale Anzahl der Kindknoten die mit einer Sammlung verknüpft werden können"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","Die Höchstzahl der untergeordneten Knoten, die einer Sammlung zugeordnet werden können, oder `max`, wenn es keine spezifische Begrenzung gibt, sondern nur eine vom Server festgelegte Höchstzahl"}.
{"The minimum number of milliseconds between sending any two notification digests","Die minimale Anzahl an Millisekunden zwischen dem Senden von zwei Benachrichtigungs-Übersichten"}.
{"The name of the node","Der Name des Knotens"}.
{"The node is a collection node","Der Knoten ist ein Sammlungsknoten"}.
@ -545,7 +557,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","Die Art der Knotendaten, üblicherweise vom Namensraum der Nutzdaten angegeben (gegebenenfalls)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","Die URL einer XSL-Transformation welche auf Nutzdaten angewendet werden kann, um ein geeignetes Nachrichtenkörper-Element zu generieren."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","Die URL einer XSL-Transformation welche auf das Nutzdaten-Format angewendet werden kann, um ein gültiges Data Forms-Ergebnis zu generieren das der Client mit Hilfe einer generischen Data Forms-Rendering-Engine anzeigen könnte"}.
{"The username is not valid","Der Benutzername ist nicht gültig"}.
{"There was an error changing the password: ","Es trat ein Fehler beim Ändern des Passwortes auf: "}.
{"There was an error creating the account: ","Es trat ein Fehler beim Erstellen des Kontos auf: "}.
{"There was an error deleting the account: ","Es trat ein Fehler beim Löschen des Kontos auf: "}.

View File

@ -249,7 +249,6 @@
{"Malformed username","Λανθασμένη μορφή ονόματος χρήστη"}.
{"MAM preference modification denied by service policy","Άρνηση αλλαγής προτιμήσεων MAM, λόγω της τακτικής Παροχής Υπηρεσιών"}.
{"March","Μάρτιος"}.
{"Max # of items to persist","Μέγιστος αριθμός μόνιμων στοιχείων"}.
{"Max payload size in bytes","Μέγιστο μέγεθος φορτίου σε bytes"}.
{"Maximum file size","Μέγιστο μέγεθος αρχείου"}.
{"Maximum Number of History Messages Returned by Room","Μέγιστος αριθμός μηνυμάτων Ιστορικού που επιστρέφονται από την Αίθουσα"}.
@ -339,7 +338,6 @@
{"Number of Offline Messages","Πλήθος μηνυμάτων Χωρίς Σύνδεση"}.
{"Number of online users","Αριθμός συνδεδεμένων χρηστών"}.
{"Number of registered users","Αριθμός εγγεγραμμένων χρηστών"}.
{"Number of seconds after which to automatically purge items","Πλήθος δευτερολέπτων μετά τα οποία αυτομάτως εκκαθαρίζονται αντικείμενα"}.
{"Occupants are allowed to invite others","Οι συμμετέχοντες μπορούν να προσκαλέσουν και άλλους"}.
{"Occupants May Change the Subject","Επιτρέψτε στους χρήστες να αλλάζουν το Θέμα"}.
{"October","Οκτώβριος"}.
@ -519,7 +517,6 @@
{"The JIDs of those with an affiliation of owner","Το JID αυτών που σχετίζονται με τον ιδιοκτήτη"}.
{"The JIDs of those with an affiliation of publisher","Το JID αυτών που σχετίζονται με τον εκδότη"}.
{"The list of JIDs that may associate leaf nodes with a collection","Λίστα των JIDs που μπορούν να σχετίζουν leaf κόμβους με μια Συλλογή"}.
{"The maximum number of child nodes that can be associated with a collection","Το μέγιστο πλήθος θυγατρικών κόμβων που μπορούν να συσχετιστούν με μία Συλλογή"}.
{"The minimum number of milliseconds between sending any two notification digests","Το ελάχιστο πλήθος χιλιοστών του δευτερολέπτου μεταξύ της αποστολής δύο συγχωνεύσεων ειδοποιήσεων"}.
{"The name of the node","Το όνομα του κόμβου"}.
{"The node is a collection node","Ο κόμβος είναι κόμβος Συλλογής"}.
@ -544,7 +541,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","Ο τύπος των δεδομένων του κόμβου συνήθως προσδιορίζεται από το namespace του φόρτου εργασιών (αν υπάρχουν)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","Το URL ενός μετασχηματισμού XSL το οποίο μπορεί να εφαρμοστεί σε φόρτους εργασίας για να παραχθεί το κατάλληλο στοιχείο του σώματος του μηνύματος."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","Το URL ενός μετασχηματισμού XSL, το οποίο μπορεί να εφαρμοστεί στους τύπους φόρτου εργασίας για να παραχθεί έγκυρο αποτέλεσμα Data Forms, τέτοιο που ο πελάτης μπορεί να εμφανίσει, χρησιμοποιώντας μια ευρείας χρήσης μηχανή επεξεργασίας Data Forms"}.
{"The username is not valid","Το όνομα Χρήστη δεν είναι έγκυρο"}.
{"There was an error changing the password: ","Παρουσιάστηκε σφάλμα κατά την αλλαγή του κωδικού πρόσβασης: "}.
{"There was an error creating the account: ","Υπήρξε ένα σφάλμα κατά τη δημιουργία του λογαριασμού: "}.
{"There was an error deleting the account: ","Υπήρξε ένα σφάλμα κατά τη διαγραφή του λογαριασμού: "}.

View File

@ -186,7 +186,6 @@
{"Make room persistent","Farigu babilejon daŭra"}.
{"Make room public searchable","Farigu babilejon publike trovebla"}.
{"March","Marĉo"}.
{"Max # of items to persist","Maksimuma kiomo de eroj en konservado"}.
{"Max payload size in bytes","Maksimuma aĵo-grando je bajtoj"}.
{"Maximum file size","Maksimuma grando de dosiero"}.
{"Maximum Number of Occupants","Limigo de nombro de partoprenantoj"}.

View File

@ -20,6 +20,7 @@
{"Access model","Modelo de Acceso"}.
{"Account doesn't exist","La cuenta no existe"}.
{"Action on user","Acción en el usuario"}.
{"Add a hat to a user","Añade un sombrero a un usuario"}.
{"Add Jabber ID","Añadir Jabber ID"}.
{"Add New","Añadir nuevo"}.
{"Add User","Añadir usuario"}.
@ -78,6 +79,7 @@
{"Changing role/affiliation is not allowed","No está permitido cambiar el rol/afiliación"}.
{"Channel already exists","El canal ya existe"}.
{"Channel does not exist","El canal no existe"}.
{"Channel JID","JID del Canal"}.
{"Channels","Canales"}.
{"Characters not allowed:","Caracteres no permitidos:"}.
{"Chatroom configuration modified","Configuración de la sala modificada"}.
@ -97,6 +99,7 @@
{"Configuration","Configuración"}.
{"Connected Resources:","Recursos conectados:"}.
{"Contact Addresses (normally, room owner or owners)","Direcciones de contacto (normalmente la del dueño o dueños de la sala)"}.
{"Contrib Modules","Módulos Contrib"}.
{"Country","País"}.
{"CPU Time:","Tiempo consumido de CPU:"}.
{"Current Discussion Topic","Tema de discusión actual"}.
@ -136,6 +139,7 @@
{"Elements","Elementos"}.
{"Email Address","Dirección de correo electrónico"}.
{"Email","Correo electrónico"}.
{"Enable hats","Activar sombreros"}.
{"Enable logging","Guardar históricos"}.
{"Enable message archiving","Activar el almacenamiento de mensajes"}.
{"Enabling push without 'node' attribute is not supported","No está soportado activar Push sin el atributo 'node'"}.
@ -170,6 +174,8 @@
{"Full List of Room Admins","Lista completa de administradores de la sala"}.
{"Full List of Room Owners","Lista completa de dueños de la sala"}.
{"Full Name","Nombre completo"}.
{"Get List of Online Users","Ver lista de usuarios conectados"}.
{"Get List of Registered Users","Ver lista de usuarios registrados"}.
{"Get Number of Online Users","Ver número de usuarios conectados"}.
{"Get Number of Registered Users","Ver número de usuarios registrados"}.
{"Get Pending","Obtener pendientes"}.
@ -186,6 +192,9 @@
{"has been kicked because of an affiliation change","ha sido expulsado por un cambio de su afiliación"}.
{"has been kicked because the room has been changed to members-only","ha sido expulsado porque la sala es ahora solo para miembros"}.
{"has been kicked","ha sido expulsado"}.
{"Hat title","Título del sombrero"}.
{"Hat URI","Dirección del sombrero"}.
{"Hats limit exceeded","Se ha excedido el límite de sombreros"}.
{"Host unknown","Dominio desconocido"}.
{"Host","Dominio"}.
{"HTTP File Upload","Subir fichero por HTTP"}.
@ -208,6 +217,8 @@
{"Incorrect value of 'action' attribute","Valor incorrecto del atributo 'action'"}.
{"Incorrect value of 'action' in data form","Valor incorrecto de 'action' en el formulario de datos"}.
{"Incorrect value of 'path' in data form","Valor incorrecto de 'path' en el formulario de datos"}.
{"Installed Modules:","Módulos Instalados:"}.
{"Install","Instalar"}.
{"Insufficient privilege","Privilegio insuficiente"}.
{"Internal server error","Error interno en el servidor"}.
{"Invalid 'from' attribute in forwarded message","Atributo 'from' no válido en el mensaje reenviado"}.
@ -224,6 +235,8 @@
{"January","Enero"}.
{"JID normalization denied by service policy","Se ha denegado la normalización del JID por política del servicio"}.
{"JID normalization failed","Ha fallado la normalización del JID"}.
{"Joined MIX channels of ~ts","Canales MIX unidos de ~ts"}.
{"Joined MIX channels:","Canales MIX unidos:"}.
{"joins the room","entra en la sala"}.
{"July","Julio"}.
{"June","Junio"}.
@ -237,6 +250,8 @@
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","Los bits menos significativos del hash SHA-256 del texto deberían ser iguales a la etiqueta hexadecimal"}.
{"leaves the room","sale de la sala"}.
{"List of rooms","Lista de salas"}.
{"List of users with hats","Lista de usuarios con sombreros"}.
{"List users with hats","Listar usuarios con sombreros"}.
{"Logging","Histórico de mensajes"}.
{"Low level update script","Script de actualización a bajo nivel"}.
{"Make participants list public","La lista de participantes es pública"}.
@ -249,7 +264,7 @@
{"Malformed username","Nombre de usuario mal formado"}.
{"MAM preference modification denied by service policy","Se ha denegado modificar la preferencia MAM por política del servicio"}.
{"March","Marzo"}.
{"Max # of items to persist","Máximo # de elementos que persisten"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","Máximo # de elementos a persistir, o `max` para no especificar un límite, más que el máximo impuesto por el servidor"}.
{"Max payload size in bytes","Máximo tamaño del contenido en bytes"}.
{"Maximum file size","Tamaño máximo de fichero"}.
{"Maximum Number of History Messages Returned by Room","Máximo número de mensajes del historial devueltos por la sala"}.
@ -324,6 +339,7 @@
{"Node index not found","No se ha encontrado índice de nodo"}.
{"Node not found","Nodo no encontrado"}.
{"Node ~p","Nodo ~p"}.
{"Node","Nodo"}.
{"Nodeprep has failed","Ha fallado el procesado del nombre de nodo (nodeprep)"}.
{"Nodes","Nodos"}.
{"None","Ninguno"}.
@ -339,8 +355,9 @@
{"Number of Offline Messages","Número de mensajes diferidos"}.
{"Number of online users","Número de usuarios conectados"}.
{"Number of registered users","Número de usuarios registrados"}.
{"Number of seconds after which to automatically purge items","Número de segundos después de los cuales se purgarán elementos automáticamente"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","Número de segundos después de los cuales se purgarán elementos automáticamente, o `max` para no especificar un límite, más que el máximo impuesto por el servidor"}.
{"Occupants are allowed to invite others","Los ocupantes pueden invitar a otras personas"}.
{"Occupants are allowed to query others","Los ocupantes pueden enviar peticiones a otros"}.
{"Occupants May Change the Subject","Los ocupantes pueden cambiar el Asunto"}.
{"October","Octubre"}.
{"Offline Messages","Mensajes diferidos"}.
@ -367,11 +384,13 @@
{"Only those on a whitelist may subscribe and retrieve items","Solo quienes están en una lista blanca pueden suscribirse y recibir elementos"}.
{"Organization Name","Nombre de la organización"}.
{"Organization Unit","Unidad de la organización"}.
{"Other Modules Available:","Otros módulos disponibles:"}.
{"Outgoing s2s Connections","Conexiones S2S salientes"}.
{"Outgoing s2s Connections:","Conexiones S2S salientes:"}.
{"Owner privileges required","Se requieren privilegios de propietario de la sala"}.
{"Packet relay is denied by service policy","Se ha denegado el reenvío del paquete por política del servicio"}.
{"Packet","Paquete"}.
{"Participant ID","ID del Participante"}.
{"Participant","Participante"}.
{"Password Verification","Verificación de la contraseña"}.
{"Password Verification:","Verificación de la contraseña:"}.
@ -418,6 +437,7 @@
{"Registered Users:","Usuarios registrados:"}.
{"Register","Registrar"}.
{"Remote copy","Copia remota"}.
{"Remove a hat from a user","Quitarle un sombrero a un usuario"}.
{"Remove All Offline Messages","Borrar todos los mensajes diferidos"}.
{"Remove User","Eliminar usuario"}.
{"Remove","Borrar"}.
@ -473,6 +493,7 @@
{"Shut Down Service","Detener el servicio"}.
{"SOCKS5 Bytestreams","SOCKS5 Bytestreams"}.
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Algunos clientes XMPP pueden guardar tu contraseña en la máquina, pero solo deberías hacer esto en tu propia máquina personal, por razones de seguridad."}.
{"Sources Specs:","Especificaciones de Códigos Fuente:"}.
{"Specify the access model","Especifica el modelo de acceso"}.
{"Specify the event message type","Especifica el tipo del mensaje de evento"}.
{"Specify the publisher model","Especificar el modelo del publicante"}.
@ -518,8 +539,10 @@
{"The JIDs of those to contact with questions","Los JIDs a quienes contactar con preguntas"}.
{"The JIDs of those with an affiliation of owner","Los JIDs de quienes tienen una afiliación de dueños"}.
{"The JIDs of those with an affiliation of publisher","Los JIDs de quienes tienen una afiliación de publicadores"}.
{"The list of all online users","La lista de todos los usuarios conectados"}.
{"The list of all users","La lista de todos los usuarios"}.
{"The list of JIDs that may associate leaf nodes with a collection","La lista de JIDs que pueden asociar nodos hijo con una colección"}.
{"The maximum number of child nodes that can be associated with a collection","El número máximo de nodos hijo que pueden asociarse a una colección"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","El número máximo de nodos hijo que pueden asociarse a una colección, o `max` para no especificar un límite, más que el máximo impuesto por el servidor"}.
{"The minimum number of milliseconds between sending any two notification digests","El número mínimo de milisegundos entre dos envíos de resumen de notificaciones"}.
{"The name of the node","El nombre del nodo"}.
{"The node is a collection node","El nodo es una colección"}.
@ -544,7 +567,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","El tipo de datos del nodo, usualmente especificado por el namespace del payload (en caso de haberlo)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","La URL de una transformación XSL que puede aplicarse a payloads para generar un elemento de contenido del mensaje apropiado."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","La URL de una transformación XSL que puede aplicarse al formato de payload para generar un resultado de Formulario de Datos válido, que el cliente pueda mostrar usando un mecanismo de dibujado genérico de Formulario de Datos"}.
{"The username is not valid","El nombre de usuario no es válido"}.
{"There was an error changing the password: ","Hubo uno error al cambiar la contaseña: "}.
{"There was an error creating the account: ","Hubo uno error al crear la cuenta: "}.
{"There was an error deleting the account: ","Hubo un error borrando la cuenta: "}.
@ -571,7 +593,7 @@
{"Too many users in this conference","Demasiados usuarios en esta sala"}.
{"To","Para"}.
{"Total rooms","Salas totales"}.
{"Traffic rate limit is exceeded","Se ha exedido el límite de tráfico"}.
{"Traffic rate limit is exceeded","Se ha excedido el límite de tráfico"}.
{"Transactions Aborted:","Transacciones abortadas:"}.
{"Transactions Committed:","Transacciones finalizadas:"}.
{"Transactions Logged:","Transacciones registradas:"}.
@ -583,6 +605,7 @@
{"Unauthorized","No autorizado"}.
{"Unexpected action","Acción inesperada"}.
{"Unexpected error condition: ~p","Condición de error inesperada: ~p"}.
{"Uninstall","Desinstalar"}.
{"Unregister an XMPP account","Borrar una cuenta XMPP"}.
{"Unregister","Borrar"}.
{"Unselect All","Deseleccionar todo"}.
@ -593,7 +616,10 @@
{"Update ~p","Actualizar ~p"}.
{"Update plan","Plan de actualización"}.
{"Update script","Script de actualización"}.
{"Update specs to get modules source, then install desired ones.","Actualizar Especificaciones para conseguir el código fuente de los módulos, luego instala los que quieras."}.
{"Update Specs","Actualizar Especificaciones"}.
{"Update","Actualizar"}.
{"Upgrade","Actualizar"}.
{"Uptime:","Tiempo desde el inicio:"}.
{"URL for Archived Discussion Logs","URL del registro de discusiones archivadas"}.
{"User already exists","El usuario ya existe"}.
@ -616,6 +642,7 @@
{"Value of '~s' should be integer","El valor de '~s' debería ser un entero"}.
{"Value 'set' of 'type' attribute is not allowed","El valor 'set' del atributo 'type' no está permitido"}.
{"vCard User Search","Búsqueda de vCard de usuarios"}.
{"View joined MIX channels","Ver los canales MIX unidos"}.
{"View Queue","Ver Cola"}.
{"View Roster","Ver Lista de contactos"}.
{"Virtual Hosts","Dominios Virtuales"}.

View File

@ -5,11 +5,20 @@
{" (Add * to the end of field to match substring)"," (Ajouter * à la fin du champ pour correspondre à la sous-chaîne)"}.
{" has set the subject to: "," a défini le sujet sur : "}.
{"# participants","# participants"}.
{"A description of the node","Une description du nœud"}.
{"A friendly name for the node","Un nom convivial pour le nœud"}.
{"A password is required to enter this room","Un mot de passe est nécessaire pour accéder à ce salon"}.
{"A Web Page","Une page Web"}.
{"Accept","Accepter"}.
{"Access denied by service policy","L'accès au service est refusé"}.
{"Access model of authorize","Modèle daccès de «autoriser»"}.
{"Access model of open","Modèle daccès de «ouvrir»"}.
{"Access model of presence","Modèle daccès de «présence»"}.
{"Access model of roster","Modèle daccès de «liste»"}.
{"Access model of whitelist","Modèle daccès de «liste blanche»"}.
{"Access model","Modèle daccès"}.
{"Account doesn't exist","Le compte nexiste pas"}.
{"Action on user","Action sur l'utilisateur"}.
{"Add Jabber ID","Ajouter un Jabber ID"}.
{"Add New","Ajouter"}.
@ -19,7 +28,9 @@
{"Administrator privileges required","Les droits d'administrateur sont nécessaires"}.
{"All activity","Toute activité"}.
{"All Users","Tous les utilisateurs"}.
{"Allow subscription","Autoriser labonnement"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","Autoriser ce Jabber ID à s'abonner à ce nœud PubSub ?"}.
{"Allow this person to register with the room?","Autoriser cette personne à enregistrer ce salon?"}.
{"Allow users to change the subject","Autoriser les utilisateurs à changer le sujet"}.
{"Allow users to query other users","Autoriser les utilisateurs à envoyer des requêtes aux autres utilisateurs"}.
{"Allow users to send invites","Autoriser les utilisateurs à envoyer des invitations"}.
@ -28,8 +39,25 @@
{"Allow visitors to send private messages to","Autoriser les visiteurs à envoyer des messages privés"}.
{"Allow visitors to send status text in presence updates","Autoriser les visiteurs à envoyer un message d'état avec leur présence"}.
{"Allow visitors to send voice requests","Permettre aux visiteurs d'envoyer des demandes de 'voice'"}.
{"An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.","Un groupe LDAP associé qui définit ladhésion à un salon; cela devrait être un nom distingué LDAP selon la définition spécifique à limplémentation ou au déploiement dun groupe."}.
{"Announcements","Annonces"}.
{"Answer associated with a picture","Réponse associée à une image"}.
{"Answer associated with a video","Réponse associée à une vidéo"}.
{"Answer associated with speech","Réponse associée à un discours"}.
{"Answer to a question","Réponse à une question"}.
{"Anyone in the specified roster group(s) may subscribe and retrieve items","Nimporte qui dans le groupe de la liste spécifiée peut sabonner et récupérer les items"}.
{"Anyone may associate leaf nodes with the collection","Nimporte qui peut associer les feuilles avec la collection"}.
{"Anyone may publish","Nimporte qui peut publier"}.
{"Anyone may subscribe and retrieve items","Nimporte qui peut sabonner et récupérer les items"}.
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Nimporte qui avec un abonnement de présence peut sabonner et récupérer les items"}.
{"Anyone with Voice","Nimporte qui avec Voice"}.
{"Anyone","Nimporte qui"}.
{"April","Avril"}.
{"Attribute 'channel' is required for this request","Lattribut «channel» est requis pour la requête"}.
{"Attribute 'id' is mandatory for MIX messages","Lattribut «id» est obligatoire pour les messages MIX"}.
{"Attribute 'jid' is not allowed here","Lattribut «jid» nest pas autorisé ici"}.
{"Attribute 'node' is not allowed here","Lattribut «node» nest pas autorisé ici"}.
{"Attribute 'to' of stanza that triggered challenge","Lattribut «to» de la strophe qui a déclenché le défi"}.
{"August","Août"}.
{"Automatic node creation is not enabled","La creation implicite de nœud n'est pas disponible"}.
{"Backup Management","Gestion des sauvegardes"}.
@ -43,10 +71,14 @@
{"Cannot remove active list","La liste active ne peut être supprimée"}.
{"Cannot remove default list","La liste par défaut ne peut être supprimée"}.
{"CAPTCHA web page","Page web de CAPTCHA"}.
{"Challenge ID","Identifiant du défi"}.
{"Change Password","Modifier le mot de passe"}.
{"Change User Password","Changer le mot de passe de l'utilisateur"}.
{"Changing password is not allowed","La modification du mot de passe n'est pas autorisée"}.
{"Changing role/affiliation is not allowed","La modification role/affiliation n'est pas autorisée"}.
{"Channel already exists","Ce canal existe déjà"}.
{"Channel does not exist","Le canal nexiste pas"}.
{"Channels","Canaux"}.
{"Characters not allowed:","Caractères non autorisés :"}.
{"Chatroom configuration modified","Configuration du salon modifiée"}.
{"Chatroom is created","Le salon de discussion est créé"}.
@ -58,30 +90,39 @@
{"Choose storage type of tables","Choisissez un type de stockage pour les tables"}.
{"Choose whether to approve this entity's subscription.","Choisissez d'approuver ou non l'abonnement de cette entité."}.
{"City","Ville"}.
{"Client acknowledged more stanzas than sent by server","Le client accuse réception de plus de strophes que ce qui est envoyé par le serveur"}.
{"Commands","Commandes"}.
{"Conference room does not exist","Le salon de discussion n'existe pas"}.
{"Configuration of room ~s","Configuration pour le salon ~s"}.
{"Configuration","Configuration"}.
{"Connected Resources:","Ressources connectées :"}.
{"Contact Addresses (normally, room owner or owners)","Adresses de contact (normalement les administrateurs du salon)"}.
{"Country","Pays"}.
{"CPU Time:","Temps CPU :"}.
{"Current Discussion Topic","Sujet de discussion courant"}.
{"Database failure","Échec sur la base de données"}.
{"Database Tables at ~p","Tables de base de données sur ~p"}.
{"Database Tables Configuration at ","Configuration des tables de base de données sur "}.
{"Database","Base de données"}.
{"December","Décembre"}.
{"Default users as participants","Les utilisateurs sont participant par défaut"}.
{"Delete content","Supprimer le contenu"}.
{"Delete message of the day on all hosts","Supprimer le message du jour sur tous les domaines"}.
{"Delete message of the day","Supprimer le message du jour"}.
{"Delete Selected","Suppression des éléments sélectionnés"}.
{"Delete table","Supprimer la table"}.
{"Delete User","Supprimer l'utilisateur"}.
{"Deliver event notifications","Envoyer les notifications d'événement"}.
{"Deliver payloads with event notifications","Inclure le contenu du message avec la notification"}.
{"Description:","Description :"}.
{"Disc only copy","Copie sur disque uniquement"}.
{"'Displayed groups' not added (they do not exist!): ","«Groupes affichés» non ajoutés (ils nexistent pas!) : "}.
{"Displayed:","Affichés :"}.
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","Ne révélez votre mot de passe à personne, pas même aux administrateurs du serveur XMPP."}.
{"Dump Backup to Text File at ","Enregistrer la sauvegarde dans un fichier texte sur "}.
{"Dump to Text File","Sauvegarder dans un fichier texte"}.
{"Duplicated groups are not allowed by RFC6121","Les groupes dupliqués ne sont pas autorisés par la RFC6121"}.
{"Dynamically specify a replyto of the item publisher","Spécifie dynamiquement un «réponse à » de litem de léditeur"}.
{"Edit Properties","Modifier les propriétés"}.
{"Either approve or decline the voice request.","Accepter ou refuser la demande de voix."}.
{"ejabberd MUC module","Module MUC ejabberd"}.
@ -90,6 +131,7 @@
{"ejabberd SOCKS5 Bytestreams module","Module SOCKS5 Bytestreams per ejabberd"}.
{"ejabberd vCard module","Module vCard ejabberd"}.
{"ejabberd Web Admin","Console Web d'administration de ejabberd"}.
{"ejabberd","ejabberd"}.
{"Elements","Éléments"}.
{"Email Address","Adresse courriel"}.
{"Email","Courriel"}.
@ -103,6 +145,7 @@
{"Enter path to jabberd14 spool file","Entrez le chemin vers le fichier spool de Jabberd 1.4"}.
{"Enter path to text file","Entrez le chemin vers le fichier texte"}.
{"Enter the text you see","Tapez le texte que vous voyez"}.
{"Erlang XMPP Server","Serveur XMPP Erlang"}.
{"Error","Erreur"}.
{"Exclude Jabber IDs from CAPTCHA challenge","Exempter des Jabberd IDs du test CAPTCHA"}.
{"Export all tables as SQL queries to a file:","Exporter toutes les tables vers un fichier SQL :"}.
@ -116,12 +159,18 @@
{"Failed to parse HTTP response","Échec de lecture de la réponse HTTP"}.
{"Failed to process option '~s'","Échec de traitement de l'option '~s'"}.
{"Family Name","Nom de famille"}.
{"FAQ Entry","Entrée FAQ"}.
{"February","Février"}.
{"File larger than ~w bytes","Taille de fichier suppérieur à ~w octets"}.
{"Fill in the form to search for any matching XMPP User","Complétez le formulaire pour rechercher un utilisateur XMPP correspondant"}.
{"Friday","Vendredi"}.
{"From ~ts","De ~ts"}.
{"From","De"}.
{"Full List of Room Admins","Liste complète des administrateurs des salons"}.
{"Full List of Room Owners","Liste complète des propriétaires des salons"}.
{"Full Name","Nom complet"}.
{"Get List of Online Users","Récupérer les utilisateurs en ligne"}.
{"Get List of Registered Users","Récupérer les utilisateurs enregistrés"}.
{"Get Number of Online Users","Récupérer le nombre d'utilisateurs en ligne"}.
{"Get Number of Registered Users","Récupérer le nombre d'utilisateurs enregistrés"}.
{"Get User Last Login Time","Récupérer la dernière date de connexion de l'utilisateur"}.
@ -137,9 +186,11 @@
{"has been kicked because of an affiliation change","a été éjecté à cause d'un changement d'autorisation"}.
{"has been kicked because the room has been changed to members-only","a été éjecté car la salle est désormais réservée aux membres"}.
{"has been kicked","a été expulsé"}.
{"Hats limit exceeded","La limite a été dépassée"}.
{"Host unknown","Serveur inconnu"}.
{"Host","Serveur"}.
{"HTTP File Upload","Téléversement de fichier HTTP"}.
{"Idle connection","Connexion inactive"}.
{"If you don't see the CAPTCHA image here, visit the web page.","SI vous ne voyez pas l'image CAPTCHA ici, visitez la page web."}.
{"Import Directory","Importer un répertoire"}.
{"Import File","Importer un fichier"}.
@ -176,8 +227,10 @@
{"July","Juillet"}.
{"June","Juin"}.
{"Just created","Vient d'être créé"}.
{"Label:","Étiquette :"}.
{"Last Activity","Dernière activité"}.
{"Last login","Dernière connexion"}.
{"Last message","Dernier message"}.
{"Last month","Dernier mois"}.
{"Last year","Dernière année"}.
{"leaves the room","quitte le salon"}.
@ -192,7 +245,6 @@
{"Make room public searchable","Rendre le salon public"}.
{"Malformed username","Nom d'utilisateur invalide"}.
{"March","Mars"}.
{"Max # of items to persist","Nombre maximum d'éléments à stocker"}.
{"Max payload size in bytes","Taille maximum pour le contenu du message en octet"}.
{"Maximum file size","Taille maximale du fichier"}.
{"Maximum Number of History Messages Returned by Room","Nombre maximal de messages d'historique renvoyés par salle"}.
@ -201,6 +253,7 @@
{"May","Mai"}.
{"Membership is required to enter this room","Vous devez être membre pour accèder à ce salon"}.
{"Members:","Membres :"}.
{"Memorize your password, or write it in a paper placed in a safe place. In XMPP there isn't an automated way to recover your password if you forget it.","Mémorisez votre mot de passe, ou écrivez-le sur un papier conservé dans un endroit secret. Dans XMPP il n'y a pas de mécanisme pour retrouver votre mot de passe si vous l'avez oublié."}.
{"Memory","Mémoire"}.
{"Message body","Corps du message"}.
{"Message not found in forwarded payload","Message non trouvé dans l'enveloppe transférée"}.
@ -210,10 +263,13 @@
{"Middle Name","Autre nom"}.
{"Minimum interval between voice requests (in seconds)","Intervalle minimum entre les demandes de 'voice' (en secondes)"}.
{"Moderator privileges required","Les droits de modérateur sont nécessaires"}.
{"Moderator","Modérateur"}.
{"Moderators Only","Modérateurs uniquement"}.
{"Modified modules","Modules mis à jour"}.
{"Module failed to handle the query","Échec de traitement de la demande"}.
{"Monday","Lundi"}.
{"Multicast","Multidiffusion"}.
{"Multiple <item/> elements are not allowed by RFC6121","Les multiples éléments <item/> ne sont pas autorisés avec RFC6121"}.
{"Multi-User Chat","Discussion de groupe"}.
{"Name","Nom"}.
{"Name:","Nom :"}.
@ -223,15 +279,20 @@
{"Neither 'role' nor 'affiliation' attribute found","Attribut 'role' ou 'affiliation' absent"}.
{"Never","Jamais"}.
{"New Password:","Nouveau mot de passe :"}.
{"Nickname can't be empty","Le pseudonyme ne peut être laissé vide"}.
{"Nickname Registration at ","Enregistrement d'un pseudo sur "}.
{"Nickname ~s does not exist in the room","Le pseudo ~s n'existe pas dans ce salon"}.
{"Nickname","Pseudo"}.
{"No address elements found","Aucun élément d'adresse trouvé"}.
{"No addresses element found","Aucun élément d'adresses trouvé"}.
{"No 'affiliation' attribute found","Attribut 'affiliation' absent"}.
{"No available resource found","Aucune ressource disponible"}.
{"No body provided for announce message","Pas de corps de message pour l'annonce"}.
{"No child elements found","Aucun élément enfant trouvé"}.
{"No data form found","Formulaire non trouvé"}.
{"No Data","Aucune information disponible"}.
{"No features available","Aucune fonctionalité disponible"}.
{"No <forwarded/> element found","Aucun élément <forwarded/> trouvé"}.
{"No hook has processed this command","Aucun gestionnaire n'a pris en charge cette commande"}.
{"No info about last activity found","Aucune activité précédente trouvée"}.
{"No 'item' element found","Aucun élément 'item' trouvé"}.
@ -249,23 +310,30 @@
{"No services available","Aucun service disponible"}.
{"No statistics found for this item","Pas de statistiques"}.
{"No 'to' attribute found in the invitation","L'élément 'to' est absent de l'invitation"}.
{"Nobody","Personne"}.
{"Node already exists","Ce nœud existe déjà"}.
{"Node ID","Identifiant du nœud"}.
{"Node index not found","Index de nœud non trouvé"}.
{"Node not found","Nœud non trouvé"}.
{"Node ~p","Nœud ~p"}.
{"Node","Nœud"}.
{"Nodeprep has failed","Échec de formattage"}.
{"Nodes","Nœuds"}.
{"None","Aucun"}.
{"Not allowed","Non autorisé"}.
{"Not Found","Nœud non trouvé"}.
{"Not subscribed","Pas abonné"}.
{"Notify subscribers when items are removed from the node","Avertir les abonnés lorsque des éléments sont supprimés sur le nœud"}.
{"Notify subscribers when the node configuration changes","Avertir les abonnés lorsque la configuration du nœud change"}.
{"Notify subscribers when the node is deleted","Avertir les abonnés lorsque le nœud est supprimé"}.
{"November","Novembre"}.
{"Number of answers required","Nombre de réponses requises"}.
{"Number of occupants","Nombre d'occupants"}.
{"Number of Offline Messages","Nombre de messages hors ligne"}.
{"Number of online users","Nombre d'utilisateurs en ligne"}.
{"Number of registered users","Nombre d'utilisateurs enregistrés"}.
{"Occupants are allowed to invite others","Les occupants sont autorisés à inviter dautres personnes"}.
{"Occupants May Change the Subject","Les occupants peuvent changer le sujet"}.
{"October","Octobre"}.
{"Offline Messages","Messages en attente"}.
{"Offline Messages:","Messages hors ligne :"}.
@ -274,6 +342,7 @@
{"Online Users:","Utilisateurs connectés :"}.
{"Online Users","Utilisateurs en ligne"}.
{"Online","En ligne"}.
{"Only admins can see this","Seuls les administrateurs peuvent voir cela"}.
{"Only deliver notifications to available users","Envoyer les notifications uniquement aux utilisateurs disponibles"}.
{"Only <enable/> or <disable/> tags are allowed","Seul le tag <enable/> ou <disable/> est autorisé"}.
{"Only <list/> element is allowed in this query","Seul l'élément <list/> est autorisé dans cette requête"}.
@ -283,6 +352,7 @@
{"Only moderators can approve voice requests","Seuls les modérateurs peuvent accépter les requêtes voix"}.
{"Only occupants are allowed to send messages to the conference","Seuls les occupants peuvent envoyer des messages à la conférence"}.
{"Only occupants are allowed to send queries to the conference","Seuls les occupants sont autorisés à envoyer des requêtes à la conférence"}.
{"Only publishers may publish","Seuls les éditeurs peuvent publier"}.
{"Only service administrators are allowed to send service messages","Seuls les administrateurs du service sont autoriser à envoyer des messages de service"}.
{"Organization Name","Nom de l'organisation"}.
{"Organization Unit","Unité de l'organisation"}.
@ -290,6 +360,7 @@
{"Outgoing s2s Connections:","Connexions s2s sortantes :"}.
{"Owner privileges required","Les droits de propriétaire sont nécessaires"}.
{"Packet","Paquet"}.
{"Participant","Participant"}.
{"Password Verification","Vérification du mot de passe"}.
{"Password Verification:","Vérification du mot de passe :"}.
{"Password","Mot de passe"}.
@ -299,13 +370,21 @@
{"Pending","En suspens"}.
{"Period: ","Période : "}.
{"Persist items to storage","Stockage persistant des éléments"}.
{"Persistent","Persistant"}.
{"Ping query is incorrect","Requête ping incorrecte"}.
{"Ping","Ping"}.
{"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.","Ces options sauvegardent uniquement la base de données interne Mnesia. Si vous utilisez le module ODBC vous devez sauvegarde votre base SQL séparément."}.
{"Please, wait for a while before sending new voice request","Attendez un moment avant de re-lancer une requête de voix"}.
{"Pong","Pong"}.
{"Possessing 'ask' attribute is not allowed by RFC6121","L'appartenance de l'attribut 'ask' n'est pas autorisé avec RFC6121"}.
{"Present real Jabber IDs to","Rendre le Jabber ID réel visible pour"}.
{"private, ","privé"}.
{"Previous session not found","Session précédente introuvable"}.
{"Previous session PID has been killed","Le précédent PID de session a été tuée"}.
{"Previous session PID has exited","Le précédent PID de session a quitté"}.
{"Previous session PID is dead","Le précédent PID de session est mort"}.
{"Previous session timed out","La session précédente a expiré"}.
{"private, ","privé, "}.
{"Public","Public"}.
{"Publish-Subscribe","Publication-Abonnement"}.
{"PubSub subscriber request","Demande d'abonnement PubSub"}.
{"Purge all items when the relevant publisher goes offline","Purger tous les items lorsque publieur est hors-ligne"}.
@ -314,7 +393,12 @@
{"RAM and disc copy","Copie en mémoire vive (RAM) et sur disque"}.
{"RAM copy","Copie en mémoire vive (RAM)"}.
{"Really delete message of the day?","Confirmer la suppression du message du jour ?"}.
{"Receive notification from all descendent nodes","Recevoir les notifications de tous les nœuds descendants"}.
{"Receive notification from direct child nodes only","Recevoir les notifications des nœuds enfants seulement"}.
{"Receive notification of new items only","Recevoir les notifications des nouveaux éléments uniquement"}.
{"Receive notification of new nodes only","Recevoir les notifications de tous les nouveaux nœuds descendants"}.
{"Recipient is not in the conference room","Le destinataire n'est pas dans la conférence"}.
{"Register an XMPP account","Inscrire un compte XMPP"}.
{"Registered Users","Utilisateurs enregistrés"}.
{"Registered Users:","Utilisateurs enregistrés :"}.
{"Register","Enregistrer"}.
@ -323,6 +407,9 @@
{"Remove User","Supprimer l'utilisateur"}.
{"Remove","Supprimer"}.
{"Replaced by new connection","Remplacé par une nouvelle connexion"}.
{"Request has timed out","La demande a expiré"}.
{"Request is ignored","La demande est ignorée"}.
{"Requested role","Rôle demandé"}.
{"Resources","Ressources"}.
{"Restart Service","Redémarrer le service"}.
{"Restart","Redémarrer"}.
@ -337,28 +424,38 @@
{"Room Occupants","Occupants du salon"}.
{"Room title","Titre du salon"}.
{"Roster groups allowed to subscribe","Groupes de liste de contact autorisés à s'abonner"}.
{"Roster of ~ts","Liste de contacts de ~ts"}.
{"Roster size","Taille de la liste de contacts"}.
{"Roster:","Liste de contacts :"}.
{"RPC Call Error","Erreur d'appel RPC"}.
{"Running Nodes","Nœuds actifs"}.
{"~s invites you to the room ~s","~s vous invite dans la salle de discussion ~s"}.
{"Saturday","Samedi"}.
{"Script check","Validation du script"}.
{"Search Results for ","Résultats de recherche pour "}.
{"Search the text","Recherche le texte"}.
{"Search until the date","Rechercher jusquà la date"}.
{"Search users in ","Rechercher des utilisateurs "}.
{"Select All","Tout sélectionner"}.
{"Send announcement to all online users on all hosts","Envoyer l'annonce à tous les utilisateurs en ligne sur tous les serveurs"}.
{"Send announcement to all online users","Envoyer l'annonce à tous les utilisateurs en ligne"}.
{"Send announcement to all users on all hosts","Envoyer une annonce à tous les utilisateurs de tous les domaines"}.
{"Send announcement to all users","Envoyer l'annonce à tous les utilisateurs"}.
{"September","Septembre"}.
{"Server:","Serveur :"}.
{"Service list retrieval timed out","La récupération de la liste des services a expiré"}.
{"Set message of the day and send to online users","Définir le message du jour et l'envoyer aux utilisateurs en ligne"}.
{"Set message of the day on all hosts and send to online users","Définir le message du jour pour tous domaines et l'envoyer aux utilisateurs en ligne"}.
{"Shared Roster Groups","Groupes de liste de contacts partagée"}.
{"Show Integral Table","Montrer la table intégralement"}.
{"Show Ordinary Table","Montrer la table ordinaire"}.
{"Shut Down Service","Arrêter le service"}.
{"SOCKS5 Bytestreams","SOCKS5 Bytestreams"}.
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Certains clients XMPP peuvent stocker votre mot de passe sur votre ordinateur. N'utilisez cette fonctionnalité que si vous avez confiance en la sécurité de votre ordinateur."}.
{"Specify the access model","Définir le modèle d'accès"}.
{"Specify the event message type","Définir le type de message d'événement"}.
{"Specify the publisher model","Définir le modèle de publication"}.
{"Stanza ID","Identifiant Stanza"}.
{"Statistics of ~p","Statistiques de ~p"}.
{"Statistics","Statistiques"}.
{"Stop","Arrêter"}.
@ -366,33 +463,64 @@
{"Storage Type","Type de stockage"}.
{"Store binary backup:","Sauvegarde binaire :"}.
{"Store plain text backup:","Sauvegarde texte :"}.
{"Stream management is already enabled","La gestion des flux est déjà activée"}.
{"Subject","Sujet"}.
{"Submit","Soumettre"}.
{"Submitted","Soumis"}.
{"Subscriber Address","Adresse de l'abonné"}.
{"Subscribers may publish","Les souscripteurs peuvent publier"}.
{"Subscription","Abonnement"}.
{"Subscriptions are not allowed","Les abonnement ne sont pas autorisés"}.
{"Sunday","Dimanche"}.
{"Text associated with a picture","Texte associé à une image"}.
{"Text associated with a sound","Texte associé à un son"}.
{"Text associated with a video","Texte associé à une vidéo"}.
{"Text associated with speech","Texte associé au discours"}.
{"That nickname is already in use by another occupant","Le pseudo est déjà utilisé par un autre occupant"}.
{"That nickname is registered by another person","Le pseudo est enregistré par une autre personne"}.
{"The CAPTCHA is valid.","Le CAPTCHA est valide"}.
{"The account already exists","Le compte existe déjà"}.
{"The account was not unregistered","Le compte na pas été désinscrit"}.
{"The body text of the last received message","Le corps du texte du dernier message reçu"}.
{"The CAPTCHA is valid.","Le CAPTCHA est valide."}.
{"The CAPTCHA verification has failed","La vérification du CAPTCHA a échoué"}.
{"The captcha you entered is wrong","Le captcha que vous avez saisi est erroné"}.
{"The collections with which a node is affiliated","Les collections avec lesquelle un nœud est affilié"}.
{"The datetime when the node was created","La date à laquelle le nœud a été créé"}.
{"The default language of the node","La langue par défaut du nœud"}.
{"The feature requested is not supported by the conference","La demande de fonctionalité n'est pas supportée par la conférence"}.
{"The JID of the node creator","Le JID du créateur du nœud"}.
{"The list of all online users","Les utilisateurs en ligne"}.
{"The list of all users","La liste de tous les utilisateurs"}.
{"The name of the node","Le nom du nœud"}.
{"The node is a collection node","Le nœud est un nœud de collecte"}.
{"The node is a leaf node (default)","Ce nœud est un nœud feuille (défaut)"}.
{"The number of subscribers to the node","Le nombre denregistrés au nœud"}.
{"The number of unread or undelivered messages","Le nombre de messages non lus ou non remis"}.
{"The password contains unacceptable characters","Le mot de passe contient des caractères non-acceptables"}.
{"The password is too weak","Le mot de passe est trop faible"}.
{"the password is","le mot de passe est"}.
{"The password of your XMPP account was successfully changed.","Le mot de passe de votre compte XMPP a été modifié avec succès."}.
{"The password was not changed","Le mot de passe na pas été modifié"}.
{"The passwords are different","Les mots de passe sont différents"}.
{"The query is only allowed from local users","La requête n'est autorisé qu'aux utilisateurs locaux"}.
{"The query must not contain <item/> elements","La requête ne doit pas contenir d'élément <item/>"}.
{"The room subject can be modified by participants","Le sujet du salon peut être modifié par les participants"}.
{"The sender of the last received message","Lexpéditeur du dernier message reçu"}.
{"The subscription identifier associated with the subscription request","Lidentificateur dabonnement associé à la demande dabonnement"}.
{"There was an error changing the password: ","Une erreur sest produite lors de la modification du mot de passe : "}.
{"There was an error creating the account: ","Il y a eu une erreur en créant le compte : "}.
{"There was an error deleting the account: ","Il y a eu une erreur en effaçant le compte : "}.
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","C'est insensible à la casse : macbeth est identique à MacBeth et Macbeth."}.
{"This page allows to register an XMPP account in this XMPP server. Your JID (Jabber ID) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Cette page permet de créer un compte XMPP sur ce serveur XMPP. Votre JID (Jabber IDentifier, identifiant Jabber) sera de la forme : nom@serveur. Prière de lire avec attention les instructions pour remplir correctement ces champs."}.
{"This page allows to unregister an XMPP account in this XMPP server.","Cette page permet de désenregistrer un compte XMPP sur ce serveur XMPP."}.
{"This room is not anonymous","Ce salon n'est pas anonyme"}.
{"This service can not process the address: ~s","Ce service ne peut pas traiter ladresse: ~s"}.
{"Thursday","Jeudi"}.
{"Time delay","Délais"}.
{"Timed out waiting for stream resumption","Expiration du délai dattente pour la reprise du flux"}.
{"Time","Heure"}.
{"To register, visit ~s","Pour vous enregistrer, visitez ~s"}.
{"To ~ts","À ~ts"}.
{"To","A"}.
{"Token TTL","Jeton TTL"}.
{"Too many active bytestreams","Trop de flux SOCKS5 actifs"}.
@ -400,6 +528,7 @@
{"Too many <item/> elements","Trop d'éléments <item/>"}.
{"Too many <list/> elements","Trop d'éléments <list/>"}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Trop (~p) d'authentification ont échoué pour cette adresse IP (~s). L'adresse sera débloquée à ~s UTC"}.
{"Too many receiver fields were specified","Trop de champs de récepteurs ont été spécifiés"}.
{"Too many unacked stanzas","Trop de stanzas sans accusé de réception (ack)"}.
{"Too many users in this conference","Trop d'utilisateurs dans cette conférence"}.
{"Total rooms","Nombre de salons"}.
@ -413,8 +542,12 @@
{"Unable to register route on existing local domain","Impossible d'enregistrer la route sur un domaine locale existant"}.
{"Unauthorized","Non autorisé"}.
{"Unexpected action","Action inattendu"}.
{"Unexpected error condition: ~p","Condition derreur inattendue : ~p"}.
{"Unregister an XMPP account","Annuler lenregistrement dun compte XMPP"}.
{"Unregister","Désinscrire"}.
{"Unselect All","Tout désélectionner"}.
{"Unsupported <index/> element","Elément <index/> non supporté"}.
{"Unsupported version","Version non prise en charge"}.
{"Update message of the day (don't send)","Mise à jour du message du jour (pas d'envoi)"}.
{"Update message of the day on all hosts (don't send)","Mettre à jour le message du jour sur tous les domaines (ne pas envoyer)"}.
{"Update plan","Plan de mise à jour"}.
@ -422,12 +555,15 @@
{"Update script","Script de mise à jour"}.
{"Update","Mettre à jour"}.
{"Uptime:","Temps depuis le démarrage :"}.
{"URL for Archived Discussion Logs","URL des journaux de discussion archivés"}.
{"User already exists","L'utilisateur existe déjà"}.
{"User JID","JID de l'utilisateur "}.
{"User JID","JID de l'utilisateur"}.
{"User (jid)","Utilisateur (jid)"}.
{"User Management","Gestion des utilisateurs"}.
{"User removed","Utilisateur supprimé"}.
{"User session not found","Session utilisateur non trouvée"}.
{"User session terminated","Session utilisateur terminée"}.
{"User ~ts","Utilisateur ~ts"}.
{"Username:","Nom d'utilisateur :"}.
{"Users are not allowed to register accounts so quickly","Les utilisateurs ne sont pas autorisés à enregistrer des comptes si rapidement"}.
{"Users Last Activity","Dernière activité des utilisateurs"}.
@ -440,15 +576,27 @@
{"Value of '~s' should be integer","La valeur de '~s' doit être un entier"}.
{"Value 'set' of 'type' attribute is not allowed","La valeur de l'attribut 'type' ne peut être 'set'"}.
{"vCard User Search","Recherche dans l'annnuaire"}.
{"View Queue","Afficher la file dattente"}.
{"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"}.
{"Visitor","Visiteur"}.
{"Voice request","Demande de voix"}.
{"Voice requests are disabled in this conference","Les demandes de voix sont désactivées dans cette conférence"}.
{"Wednesday","Mercredi"}.
{"When a new subscription is processed","Quand un nouvel abonnement est traité"}.
{"When to send the last published item","A quel moment envoyer le dernier élément publié"}.
{"Whether to allow subscriptions","Autoriser l'abonnement ?"}.
{"Whether an entity wants to receive or disable notifications","Quand une entité veut recevoir ou désactiver les notifications"}.
{"Whether owners or publisher should receive replies to items","Quand les propriétaires ou annonceurs doivent revoir des réponses à leurs éléments"}.
{"Whether to allow subscriptions","Autoriser ou non les abonnements"}.
{"Whether to notify owners about new subscribers and unsubscribes","Quand notifier le propriétaire à propos des nouvelles souscriptions et désinscriptions"}.
{"Wrong parameters in the web formulary","Paramètres erronés dans le formulaire Web"}.
{"Wrong xmlns","Xmlns incorrect"}.
{"XMPP Account Registration","Enregistrement de compte XMPP"}.
{"XMPP Domains","Domaines XMPP"}.
{"You are being removed from the room because of a system shutdown","Vous avez été éjecté du salon de discussion en raison de l'arrêt du système"}.
{"You are not joined to the channel","Vous n'avez pas rejoint ce canal"}.
{"You can later change your password using an XMPP client.","Vous pouvez modifier ultérieurement votre mot de passe à laide dun client XMPP."}.
{"You have been banned from this room","Vous avez été exclus de ce salon"}.
{"You have joined too many conferences","Vous avec rejoint trop de conférences"}.
{"You must fill in field \"Nickname\" in the form","Vous devez préciser le champ \"pseudo\" dans le formulaire"}.
@ -458,4 +606,6 @@
{"Your active privacy list has denied the routing of this stanza.","Votre règle de flitrage active a empêché le routage de ce stanza."}.
{"Your contact offline message queue is full. The message has been discarded.","La file d'attente de message de votre contact est pleine. Votre message a été détruit."}.
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","Vos messages pour ~s sont bloqués. Pour les débloquer, veuillez visiter ~s"}.
{"Your XMPP account was successfully registered.","Votre compte XMPP a été enregistré avec succès."}.
{"Your XMPP account was successfully unregistered.","Votre compte XMPP a été désinscrit avec succès."}.
{"You're not allowed to create nodes","Vous n'êtes pas autorisé à créer des nœuds"}.

View File

@ -181,7 +181,6 @@
{"Make room public searchable","Sala publicamente visible"}.
{"Malformed username","Nome de usuario mal formado"}.
{"March","Marzo"}.
{"Max # of items to persist","Máximo # de elementos que persisten"}.
{"Max payload size in bytes","Máximo tamaño do payload en bytes"}.
{"Maximum Number of Occupants","Número máximo de ocupantes"}.
{"May","Maio"}.

View File

@ -170,7 +170,6 @@
{"Make room public searchable","הפוך חדר לחדר שנתון לחיפוש פומבי"}.
{"Malformed username","שם משתמש פגום"}.
{"March","מרץ"}.
{"Max # of items to persist","מספר מרבי של פריטים לקיבוע"}.
{"Max payload size in bytes","גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte"}.
{"Maximum Number of Occupants","מספר מרבי של נוכחים"}.
{"May","מאי"}.

View File

@ -388,7 +388,6 @@
{"The query is only allowed from local users","A lekérdezés csak helyi felhasználóktól engedélyezett"}.
{"The query must not contain <item/> elements","A lekérdezés nem tartalmazhat <item/> elemeket"}.
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","A stanzának csak egyetlen <active/> elemet, egyetlen <default/> elemet vagy egyetlen <list/> elemet KELL tartalmaznia"}.
{"The username is not valid","A felhasználónév nem érvényes"}.
{"There was an error creating the account: ","Hiba történt a fiók létrehozásakor: "}.
{"There was an error deleting the account: ","Hiba történt a fiók törlésekor: "}.
{"This room is not anonymous","Ez a szoba nem névtelen"}.

View File

@ -227,7 +227,6 @@
{"Make room persistent","Buat ruangan menjadi permanent"}.
{"Make room public searchable","Buat ruangan dapat dicari"}.
{"March","Maret"}.
{"Max # of items to persist","Max item untuk bertahan"}.
{"Max payload size in bytes","Max kapasitas ukuran dalam bytes"}.
{"Maximum Number of Occupants","Maksimum Jumlah Penghuni"}.
{"May","Mei"}.
@ -423,7 +422,6 @@
{"the password is","kata sandinya"}.
{"The password was not changed","Kata sandi belum berubah"}.
{"The passwords are different","Kata sandi berbeda"}.
{"The username is not valid","Nama pengguna tidak valid"}.
{"There was an error changing the password: ","Ada kesalahan saat merubah kata kunci: "}.
{"There was an error creating the account: ","Ada kesalahan saat membuat akun: "}.
{"There was an error deleting the account: ","Ada kesalahan saat menghapus akun: "}.

View File

@ -145,7 +145,6 @@
{"Make room persistent","Rendere la stanza persistente"}.
{"Make room public searchable","Rendere la sala visibile al pubblico"}.
{"March","Marzo"}.
{"Max # of items to persist","Numero massimo di elementi da conservare persistentemente"}.
{"Max payload size in bytes","Dimensione massima del contenuto del messaggio in byte"}.
{"Maximum Number of Occupants","Numero massimo di occupanti"}.
{"May","Maggio"}.

View File

@ -191,7 +191,6 @@
{"Make room public searchable","チャットルームを検索可"}.
{"Malformed username","不正な形式のユーザー名"}.
{"March","3月"}.
{"Max # of items to persist","アイテムの最大保存数"}.
{"Max payload size in bytes","最大ぺイロードサイズ (byte)"}.
{"Maximum file size","最大ファイルサイズ"}.
{"Maximum Number of Occupants","最大在室者数"}.
@ -367,7 +366,6 @@
{"The password of your XMPP account was successfully changed.","XMPP アカウントのパスワード変更に成功しました。"}.
{"The password was not changed","このパスワードは変更されませんでした"}.
{"The passwords are different","このパスワードが違います"}.
{"The username is not valid","ユーザー名が正しくありません"}.
{"There was an error creating the account: ","アカウントの作成中にエラーが発生しました: "}.
{"There was an error deleting the account: ","アカウントの削除中にエラーが発生しました: "}.
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","大文字と小文字は区別しません: macbeth は MacBeth や Macbeth と同じです。"}.

View File

@ -150,7 +150,6 @@
{"Make room persistent","Chatruimte blijvend maken"}.
{"Make room public searchable","Chatruimte doorzoekbaar maken"}.
{"March","Maart"}.
{"Max # of items to persist","Maximum aantal in het geheugen te bewaren items"}.
{"Max payload size in bytes","Maximumgrootte van bericht in bytes"}.
{"Maximum Number of Occupants","Maximum aantal aanwezigen"}.
{"May","Mei"}.

View File

@ -165,7 +165,6 @@
{"Make room persistent","Gjør rommet vedvarende"}.
{"Make room public searchable","Gjør rommet offentlig søkbart"}.
{"March","mars"}.
{"Max # of items to persist","Høyeste # elementer som skal lagres"}.
{"Maximum file size","Maksimal filstørrelse"}.
{"Maximum Number of History Messages Returned by Room","Maksimalt antall historikkmeldinger tilbudt av rommet"}.
{"May","mai"}.
@ -333,7 +332,6 @@
{"The query must not contain <item/> elements","Spørringen kan ikke inneholde <item/>-elementer"}.
{"The room subject can be modified by participants","Romemnet kan endres av dets deltagere"}.
{"The sender of the last received message","Avsender for sist mottatte melding"}.
{"The username is not valid","Brukernavnet er ikke gyldig"}.
{"There was an error creating the account: ","En feil inntraff under oppretting av kontoen: "}.
{"There was an error deleting the account: ","En feil inntraff under sletting av kontoen: "}.
{"This room is not anonymous","Dette rommet er ikke anonymt"}.

View File

@ -181,7 +181,6 @@
{"Make room public searchable","Pozwól wyszukiwać pokój"}.
{"Malformed username","Nieprawidłowa nazwa użytkownika"}.
{"March","Marzec"}.
{"Max # of items to persist","Maksymalna liczba przechowywanych przedmiotów"}.
{"Max payload size in bytes","Maksymalna wielkość powiadomienia w bajtach"}.
{"Maximum Number of Occupants","Maksymalna liczba uczestników"}.
{"May","Maj"}.

View File

@ -20,6 +20,7 @@
{"Access model","Modelo de acesso"}.
{"Account doesn't exist","A conta não existe"}.
{"Action on user","Ação no usuário"}.
{"Add a hat to a user","Adiciona um chapéu num usuário"}.
{"Add Jabber ID","Adicionar ID jabber"}.
{"Add New","Adicionar novo"}.
{"Add User","Adicionar usuário"}.
@ -78,6 +79,7 @@
{"Changing role/affiliation is not allowed","Não é permitida a alteração da função/afiliação"}.
{"Channel already exists","O canal já existe"}.
{"Channel does not exist","O canal não existe"}.
{"Channel JID","Canal JID"}.
{"Channels","Canais"}.
{"Characters not allowed:","Caracteres não aceitos:"}.
{"Chatroom configuration modified","Configuração da sala de bate-papo modificada"}.
@ -97,6 +99,7 @@
{"Configuration","Configuração"}.
{"Connected Resources:","Recursos conectados:"}.
{"Contact Addresses (normally, room owner or owners)","Endereços de contato (normalmente, o proprietário ou os proprietários da sala)"}.
{"Contrib Modules","Módulos contrib"}.
{"Country","País"}.
{"CPU Time:","Tempo da CPU:"}.
{"Current Discussion Topic","Assunto em discussão"}.
@ -136,6 +139,7 @@
{"Elements","Elementos"}.
{"Email Address","Endereço de e-mail"}.
{"Email","Email"}.
{"Enable hats","Ativa chapéus"}.
{"Enable logging","Permitir criação de logs"}.
{"Enable message archiving","Habilitar arquivamento de mensagens"}.
{"Enabling push without 'node' attribute is not supported","Abilitar push sem o atributo 'node' não é suportado"}.
@ -170,6 +174,8 @@
{"Full List of Room Admins","Lista completa dos administradores das salas"}.
{"Full List of Room Owners","Lista completa dos proprietários das salas"}.
{"Full Name","Nome completo"}.
{"Get List of Online Users","Obter a lista de usuários online"}.
{"Get List of Registered Users","Obter a lista de usuários registrados"}.
{"Get Number of Online Users","Obter Número de Usuários Online"}.
{"Get Number of Registered Users","Obter Número de Usuários Registrados"}.
{"Get Pending","Obter os pendentes"}.
@ -186,6 +192,9 @@
{"has been kicked because of an affiliation change","foi desconectado porque por afiliação inválida"}.
{"has been kicked because the room has been changed to members-only","foi desconectado porque a política da sala mudou, só membros são permitidos"}.
{"has been kicked","foi removido"}.
{"Hat title","Título do chapéu"}.
{"Hat URI","URI do chapéu"}.
{"Hats limit exceeded","O limite dos chapéus foi excedido"}.
{"Host unknown","Máquina desconhecida"}.
{"Host","Máquina"}.
{"HTTP File Upload","Upload de arquivo HTTP"}.
@ -208,6 +217,8 @@
{"Incorrect value of 'action' attribute","Valor incorreto do atributo 'action'"}.
{"Incorrect value of 'action' in data form","Valor incorreto de 'action' no formulário de dados"}.
{"Incorrect value of 'path' in data form","Valor incorreto de 'path' no formulário de dados"}.
{"Installed Modules:","Módulos instalados:"}.
{"Install","Instalar"}.
{"Insufficient privilege","Privilégio insuficiente"}.
{"Internal server error","Erro interno do servidor"}.
{"Invalid 'from' attribute in forwarded message","Atributo 'from' inválido na mensagem reenviada"}.
@ -224,6 +235,8 @@
{"January","Janeiro"}.
{"JID normalization denied by service policy","Normalização JID negada por causa da política de serviços"}.
{"JID normalization failed","A normalização JID falhou"}.
{"Joined MIX channels of ~ts","Entrou no canais MIX do ~ts"}.
{"Joined MIX channels:","Uniu-se aos canais MIX:"}.
{"joins the room","Entrar na sala"}.
{"July","Julho"}.
{"June","Junho"}.
@ -237,6 +250,8 @@
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","Bits menos significativos do hash sha-256 do texto devem ser iguais ao rótulo hexadecimal"}.
{"leaves the room","Sair da sala"}.
{"List of rooms","Lista de salas"}.
{"List of users with hats","Lista os usuários com chapéus"}.
{"List users with hats","Lista os usuários com chapéus"}.
{"Logging","Registrando no log"}.
{"Low level update script","Script de atualização low level"}.
{"Make participants list public","Tornar pública a lista de participantes"}.
@ -249,7 +264,7 @@
{"Malformed username","Nome de usuário inválido"}.
{"MAM preference modification denied by service policy","Modificação de preferência MAM negada por causa da política de serviços"}.
{"March","Março"}.
{"Max # of items to persist","Máximo # de elementos que persistem"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","Máximo # de itens para persistir ou `max` para nenhum limite específico que não seja um servidor imposto como máximo"}.
{"Max payload size in bytes","Máximo tamanho do payload em bytes"}.
{"Maximum file size","Tamanho máximo do arquivo"}.
{"Maximum Number of History Messages Returned by Room","Quantidade máxima das mensagens do histórico que foram devolvidas por sala"}.
@ -340,8 +355,9 @@
{"Number of Offline Messages","Quantidade das mensagens offline"}.
{"Number of online users","Número de usuários online"}.
{"Number of registered users","Número de usuários registrados"}.
{"Number of seconds after which to automatically purge items","Quantidade de segundos para excluir os itens automaticamente"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","Quantidade de segundos após limpar automaticamente os itens ou `max` para nenhum limite específico que não seja um servidor imposto máximo"}.
{"Occupants are allowed to invite others","As pessoas estão autorizadas a convidar outras pessoas"}.
{"Occupants are allowed to query others","Os ocupantes estão autorizados a consultar os outros"}.
{"Occupants May Change the Subject","As pessoas talvez possam alterar o assunto"}.
{"October","Outubro"}.
{"Offline Messages","Mensagens offline"}.
@ -368,11 +384,13 @@
{"Only those on a whitelist may subscribe and retrieve items","Apenas aqueles presentes em uma lista branca podem se inscrever e recuperar os itens"}.
{"Organization Name","Nome da organização"}.
{"Organization Unit","Departamento/Unidade"}.
{"Other Modules Available:","Outros módulos disponíveis:"}.
{"Outgoing s2s Connections","Conexões s2s de Saída"}.
{"Outgoing s2s Connections:","Saída das conexões s2s:"}.
{"Owner privileges required","Se requer privilégios de proprietário da sala"}.
{"Packet relay is denied by service policy","A retransmissão de pacote é negada por causa da política de serviço"}.
{"Packet","Pacote"}.
{"Participant ID","ID do participante"}.
{"Participant","Participante"}.
{"Password Verification:","Verificação da Senha:"}.
{"Password Verification","Verificação de Senha"}.
@ -419,6 +437,7 @@
{"Registered Users","Usuários Registrados"}.
{"Register","Registrar"}.
{"Remote copy","Cópia remota"}.
{"Remove a hat from a user","Remove um chapéu de um usuário"}.
{"Remove All Offline Messages","Remover Todas as Mensagens Offline"}.
{"Remove User","Remover usuário"}.
{"Remove","Remover"}.
@ -474,6 +493,7 @@
{"Shut Down Service","Parar Serviço"}.
{"SOCKS5 Bytestreams","Bytestreams SOCKS5"}.
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes XMPP podem armazenar a sua senha no seu computador, só faça isso no seu computador particular por questões de segurança."}.
{"Sources Specs:","Especificações das fontes:"}.
{"Specify the access model","Especificar os modelos de acesso"}.
{"Specify the event message type","Especificar o tipo de mensagem para o evento"}.
{"Specify the publisher model","Especificar o modelo do publicante"}.
@ -519,8 +539,10 @@
{"The JIDs of those to contact with questions","Os JIDs daqueles para entrar em contato com perguntas"}.
{"The JIDs of those with an affiliation of owner","Os JIDs daqueles com uma afiliação de proprietário"}.
{"The JIDs of those with an affiliation of publisher","Os JIDs daqueles com uma afiliação de editor"}.
{"The list of all online users","A lista de todos os usuários online"}.
{"The list of all users","A lista de todos os usuários"}.
{"The list of JIDs that may associate leaf nodes with a collection","A lista dos JIDs que podem associar as páginas dos nós em uma coleção"}.
{"The maximum number of child nodes that can be associated with a collection","A quantidade máxima dos nós relacionados que podem ser associados com uma coleção"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","A quantidade máxima de nós relacionados que podem ser associados a uma coleção ou `máximo` para nenhum limite específico que não seja um servidor imposto no máximo"}.
{"The minimum number of milliseconds between sending any two notification digests","O número mínimo de milissegundos entre o envio do resumo das duas notificações"}.
{"The name of the node","O nome do nó"}.
{"The node is a collection node","O nó é um nó da coleção"}.
@ -545,7 +567,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","O tipo dos dados do nó, normalmente definido pelo espaço dos nomes da carga útil (caso haja)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","O URL da transformação XSL que pode ser aplicada nas cargas úteis para gerar um elemento apropriado no corpo da mensagem."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","A URL de uma transformação XSL que pode ser aplicada ao formato de carga útil para gerar um Formulário de Dados válido onde o cliente possa exibir usando um mecanismo genérico de renderização do Formulários de Dados"}.
{"The username is not valid","O nome do usuário não é válido"}.
{"There was an error changing the password: ","Houve um erro ao alterar a senha: "}.
{"There was an error creating the account: ","Houve um erro ao criar esta conta: "}.
{"There was an error deleting the account: ","Houve um erro ao deletar esta conta: "}.
@ -584,6 +605,7 @@
{"Unauthorized","Não Autorizado"}.
{"Unexpected action","Ação inesperada"}.
{"Unexpected error condition: ~p","Condição de erro inesperada: ~p"}.
{"Uninstall","Desinstalar"}.
{"Unregister an XMPP account","Excluir uma conta XMPP"}.
{"Unregister","Deletar registro"}.
{"Unselect All","Desmarcar todos"}.
@ -594,7 +616,10 @@
{"Update ~p","Atualizar ~p"}.
{"Update plan","Plano de Atualização"}.
{"Update script","Script de atualização"}.
{"Update specs to get modules source, then install desired ones.","Atualize as especificações para obter a fonte dos módulos e instale os que desejar."}.
{"Update Specs","Atualizar as especificações"}.
{"Update","Atualizar"}.
{"Upgrade","Atualização"}.
{"Uptime:","Tempo de atividade:"}.
{"URL for Archived Discussion Logs","A URL para o arquivamento dos registros da discussão"}.
{"User already exists","Usuário já existe"}.
@ -617,6 +642,7 @@
{"Value of '~s' should be integer","Valor de '~s' deveria ser um inteiro"}.
{"Value 'set' of 'type' attribute is not allowed","Valor 'set' não permitido para atributo 'type'"}.
{"vCard User Search","Busca de Usuário vCard"}.
{"View joined MIX channels","Exibir os canais MIX aderidos"}.
{"View Queue","Exibir a fila"}.
{"View Roster","Ver a lista"}.
{"Virtual Hosts","Hosts virtuais"}.

View File

@ -20,6 +20,7 @@
{"Access model","Modelo de acesso"}.
{"Account doesn't exist","A conta não existe"}.
{"Action on user","Acção no utilizador"}.
{"Add a hat to a user","Adiciona um chapéu num utilizador"}.
{"Add Jabber ID","Adicionar ID jabber"}.
{"Add New","Adicionar novo"}.
{"Add User","Adicionar utilizador"}.
@ -136,6 +137,7 @@
{"Elements","Elementos"}.
{"Email Address","Endereço de e-mail"}.
{"Email","Email"}.
{"Enable hats","Ativa chapéus"}.
{"Enable logging","Permitir criação de logs"}.
{"Enable message archiving","Ativar arquivamento de mensagens"}.
{"Enabling push without 'node' attribute is not supported","Abilitar push sem o atributo 'node' não é suportado"}.
@ -186,6 +188,9 @@
{"has been kicked because of an affiliation change","foi desconectado porque por afiliação inválida"}.
{"has been kicked because the room has been changed to members-only","foi desconectado porque a política da sala mudou, só membros são permitidos"}.
{"has been kicked","foi removido"}.
{"Hat title","Título do chapéu"}.
{"Hat URI","URI do chapéu"}.
{"Hats limit exceeded","O limite dos chapéus foi excedido"}.
{"Host unknown","Máquina desconhecida"}.
{"Host","Máquina"}.
{"HTTP File Upload","Upload de ficheiros por HTTP"}.
@ -237,6 +242,8 @@
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","Bits menos significativos do hash sha-256 do texto devem ser iguais ao rótulo hexadecimal"}.
{"leaves the room","Sair da sala"}.
{"List of rooms","Lista de salas"}.
{"List of users with hats","Lista os utilizadores com chapéus"}.
{"List users with hats","Lista os utilizadores com chapéus"}.
{"Logging","Registando no log"}.
{"Low level update script","Script de atualização low level"}.
{"Make participants list public","Tornar pública a lista de participantes"}.
@ -249,7 +256,7 @@
{"Malformed username","Nome de utilizador inválido"}.
{"MAM preference modification denied by service policy","Modificação de preferência MAM negada por causa da política de serviços"}.
{"March","Março"}.
{"Max # of items to persist","Máximo # de elementos que persistem"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","Máximo # de itens para persistir ou `max` para nenhum limite específico que não seja um servidor imposto como máximo"}.
{"Max payload size in bytes","Máximo tamanho do payload em bytes"}.
{"Maximum file size","Tamanho máximo do ficheiro"}.
{"Maximum Number of History Messages Returned by Room","Quantidade máxima das mensagens do histórico que foram devolvidas por sala"}.
@ -340,7 +347,7 @@
{"Number of Offline Messages","Quantidade das mensagens offline"}.
{"Number of online users","Quantidade de utilizadores online"}.
{"Number of registered users","Quantidade de utilizadores registados"}.
{"Number of seconds after which to automatically purge items","Quantidade de segundos para excluir os itens automaticamente"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","Quantidade de segundos após limpar automaticamente os itens ou `max` para nenhum limite específico que não seja um servidor imposto máximo"}.
{"Occupants are allowed to invite others","As pessoas estão autorizadas a convidar outras pessoas"}.
{"Occupants May Change the Subject","As pessoas talvez possam alterar o assunto"}.
{"October","Outubro"}.
@ -419,6 +426,7 @@
{"Registered Users:","Utilizadores registados:"}.
{"Register","Registar"}.
{"Remote copy","Cópia remota"}.
{"Remove a hat from a user","Remove um chapéu de um utilizador"}.
{"Remove All Offline Messages","Remover Todas as Mensagens Offline"}.
{"Remove User","Eliminar utilizador"}.
{"Remove","Remover"}.
@ -520,7 +528,7 @@
{"The JIDs of those with an affiliation of owner","Os JIDs daqueles com uma afiliação de proprietário"}.
{"The JIDs of those with an affiliation of publisher","Os JIDs daqueles com uma afiliação de editor"}.
{"The list of JIDs that may associate leaf nodes with a collection","A lista dos JIDs que podem associar as páginas dos nós numa coleção"}.
{"The maximum number of child nodes that can be associated with a collection","A quantidade máxima dos nós relacionados que podem ser associados com uma coleção"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","A quantidade máxima de nós relacionados que podem ser associados a uma coleção ou `máximo` para nenhum limite específico que não seja um servidor imposto no máximo"}.
{"The minimum number of milliseconds between sending any two notification digests","A quantidade mínima de milissegundos entre o envio do resumo das duas notificações"}.
{"The name of the node","O nome do nó"}.
{"The node is a collection node","O nó é um nó da coleção"}.
@ -545,7 +553,6 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","O tipo dos dados do nó, normalmente definido pelo espaço dos nomes da carga útil (caso haja)"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","O URL da transformação XSL que pode ser aplicada nas cargas úteis para gerar um elemento apropriado no corpo da mensagem."}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","A URL de uma transformação XSL que pode ser aplicada ao formato de carga útil para gerar um Formulário de Dados válido onde o cliente possa exibir usando um mecanismo genérico de renderização do Formulários de Dados"}.
{"The username is not valid","O nome do utilizador não é válido"}.
{"There was an error changing the password: ","Houve um erro ao alterar a palavra-passe: "}.
{"There was an error creating the account: ","Houve um erro ao criar esta conta: "}.
{"There was an error deleting the account: ","Houve um erro ao deletar esta conta: "}.

View File

@ -7,6 +7,7 @@
{" has set the subject to: "," установил(а) тему: "}.
{"A friendly name for the node","Легко запоминаемое имя для узла"}.
{"A password is required to enter this room","Чтобы войти в эту конференцию, нужен пароль"}.
{"A Web Page","Веб-страница"}.
{"Accept","Принять"}.
{"Access denied by service policy","Доступ запрещён политикой службы"}.
{"Account doesn't exist","Учётная запись не существует"}.
@ -20,6 +21,7 @@
{"All activity","Вся статистика"}.
{"All Users","Все пользователи"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","Разрешить этому Jabber ID подписаться на данный узел?"}.
{"Allow this person to register with the room?","Разрешить пользователю зарегистрироваться в комнате?"}.
{"Allow users to change the subject","Разрешить пользователям изменять тему"}.
{"Allow users to query other users","Разрешить iq-запросы к пользователям"}.
{"Allow users to send invites","Разрешить пользователям посылать приглашения"}.
@ -201,7 +203,6 @@
{"Malformed username","Недопустимое имя пользователя"}.
{"MAM preference modification denied by service policy","Изменение настроек архива сообщений запрещено политикой службы"}.
{"March","марта"}.
{"Max # of items to persist","Максимальное число сохраняемых публикаций"}.
{"Max payload size in bytes","Максимальный размер полезной нагрузки в байтах"}.
{"Maximum Number of Occupants","Максимальное количество участников"}.
{"May","мая"}.
@ -411,7 +412,6 @@
{"The query is only allowed from local users","Запрос доступен только для локальных пользователей"}.
{"The query must not contain <item/> elements","Запрос не должен содержать элементов <item/>"}.
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","Строфа может содержать только один элемент <active/>, один элемент <default/> или один элемент <list/>"}.
{"The username is not valid","Недопустимое имя пользователя"}.
{"There was an error creating the account: ","Ошибка при создании аккаунта:"}.
{"There was an error deleting the account: ","Ошибка при удалении аккаунта:"}.
{"This room is not anonymous","Эта комната не анонимная"}.

View File

@ -144,7 +144,6 @@
{"Make room persistent","Nastaviť miestnosť ako trvalú"}.
{"Make room public searchable","Nastaviť miestnosť ako verejne prehľadávateľnú"}.
{"March","Marec"}.
{"Max # of items to persist","Maximálny počet položiek, ktoré je možné natrvalo uložiť"}.
{"Max payload size in bytes","Maximálny náklad v bajtoch"}.
{"Maximum Number of Occupants","Počet účastníkov"}.
{"May","Máj"}.

View File

@ -331,7 +331,6 @@
{"The password was not changed","Fjalëkalimi su ndryshua"}.
{"The passwords are different","Fjalëkalimet janë të ndryshëm"}.
{"The sender of the last received message","Dërguesi i mesazhit të fundit të marrë"}.
{"The username is not valid","Emri i përdoruesit sështë i vlefshëm"}.
{"There was an error changing the password: ","Pati një gabim në ndryshimin e fjalëkalimit: "}.
{"There was an error creating the account: ","Pati një gabim në krijimin e llogarisë: "}.
{"This room is not anonymous","Kjo dhomë sështë anonime"}.

View File

@ -129,7 +129,6 @@
{"Make room persistent","Gör rummet permanent"}.
{"Make room public searchable","Gör rummet publikt sökbart"}.
{"March","Mars"}.
{"Max # of items to persist","Högsta antal dataposter som sparas"}.
{"Max payload size in bytes","Högsta innehållsstorlek i bytes"}.
{"Maximum Number of Occupants","Maximalt antal av användare"}.
{"May","Maj"}.

View File

@ -110,7 +110,6 @@
{"Make room persistent","สร้างเป็นห้องถาวร"}.
{"Make room public searchable","สร้างเป็นห้องที่บุคคลทั่วไปสามารถค้นหาได้"}.
{"March","มีนาคม"}.
{"Max # of items to persist","จำนวนสูงสุดของรายการที่ยืนยัน"}.
{"Max payload size in bytes","ขนาดสูงสุดของส่วนของข้อมูล (payload) มีหน่วยเป็นไบต์"}.
{"Maximum Number of Occupants","จำนวนผู้ครอบครองห้องสูงสุด"}.
{"May","พฤษภาคม"}.

View File

@ -143,7 +143,6 @@
{"Make room persistent","Odayı kalıcı hale getir"}.
{"Make room public searchable","Odayı herkes tarafından aranabilir hale getir"}.
{"March","Mart"}.
{"Max # of items to persist","Kalıcı hale getirilecek en fazla öğe sayısı"}.
{"Max payload size in bytes","En fazla yük (payload) boyutu (bayt olarak)"}.
{"Maximum Number of Occupants","Odada En Fazla Bulunabilecek Kişi Sayısı"}.
{"May","Mayıs"}.

View File

@ -3,12 +3,18 @@
%% To improve translations please read:
%% https://docs.ejabberd.im/developer/extending-ejabberd/localization/
{" (Add * to the end of field to match substring)"," Заповніть поля для пошуку користувача Jabber (Додайте * в кінець поля для пошуку підрядка)"}.
{" has set the subject to: "," встановив(ла) тему: "}.
{"# participants","# учасників"}.
{"A description of the node","Опис вузла"}.
{"A friendly name for the node","Псевдонім для вузла"}.
{"A password is required to enter this room","Щоб зайти в цю конференцію, необхідно ввести пароль"}.
{"A Web Page","Веб-сторінка"}.
{"Accept","Прийняти"}.
{"Access denied by service policy","Доступ заборонений політикою служби"}.
{"Account doesn't exist","Обліковий запис не існує"}.
{"Action on user","Дія над користувачем"}.
{"Add a hat to a user","Додати капелюх користувачу"}.
{"Add Jabber ID","Додати Jabber ID"}.
{"Add New","Додати"}.
{"Add User","Додати користувача"}.
@ -17,7 +23,9 @@
{"Administrator privileges required","Необхідні права адміністратора"}.
{"All activity","Вся статистика"}.
{"All Users","Всі користувачі"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","Чи дозволити цьому Jabber ID підписатись новини наданого вузла"}.
{"Allow subscription","Дозволити підписку"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","Дозволити цьому Jabber ID підписатись на даний pubsub-вузол?"}.
{"Allow this person to register with the room?","Дозволити цій людині зареєструватися в кімнаті?"}.
{"Allow users to change the subject","Дозволити користувачам змінювати тему"}.
{"Allow users to query other users","Дозволити iq-запити до користувачів"}.
{"Allow users to send invites","Дозволити користувачам надсилати запрошення"}.
@ -27,17 +35,41 @@
{"Allow visitors to send status text in presence updates","Дозволити відвідувачам відсилати текст статусу в оновленнях присутності"}.
{"Allow visitors to send voice requests","Дозволити відвідувачам надсилати голосові запрошення"}.
{"Announcements","Сповіщення"}.
{"Answer associated with a picture","Відповідь, пов’язана зі зображенням"}.
{"Answer associated with a video","Відповідь, пов'язана з відео"}.
{"Answer associated with speech","Відповідь, пов'язана з мовленням"}.
{"Answer to a question","Відповідь на запитання"}.
{"Anyone in the specified roster group(s) may subscribe and retrieve items","Будь-хто в зазначеному списку груп(и) може підписатися та отримати елементи"}.
{"Anyone may associate leaf nodes with the collection","Будь-хто може зв'язати вузли листів з колекцією"}.
{"Anyone may publish","Будь-хто може опублікувати"}.
{"Anyone may subscribe and retrieve items","Будь-хто може підписатися та отримати елементи"}.
{"Anyone with Voice","Усі, хто має голос"}.
{"April","квітня"}.
{"Attribute 'channel' is required for this request","Для цього запиту потрібен атрибут \"канал\""}.
{"Attribute 'id' is mandatory for MIX messages","Для MIX повідомлень потрібен атрибут \"id\""}.
{"Attribute 'jid' is not allowed here","Атрибут 'jid' тут заборонений"}.
{"Attribute 'node' is not allowed here","Атрибут \"вузол\" тут заборонений"}.
{"August","серпня"}.
{"Automatic node creation is not enabled","Автоматичне створення вузлів не ввімкнено"}.
{"Backup Management","Керування резервним копіюванням"}.
{"Backup of ~p","Резервне копіювання ~p"}.
{"Backup to File at ","Резервне копіювання в файл на "}.
{"Backup","Резервне копіювання"}.
{"Bad format","Неправильний формат"}.
{"Birthday","День народження"}.
{"Both the username and the resource are required","Потрібне ім'я користувача та ресурс"}.
{"Bytestream already activated","Потік байтів вже активовано"}.
{"Cannot remove active list","Неможливо видалити активний список"}.
{"Cannot remove default list","Неможливо видалити список за промовчанням"}.
{"CAPTCHA web page","Адреса капчі"}.
{"Challenge ID","ID виклику"}.
{"Change Password","Змінити пароль"}.
{"Change User Password","Змінити Пароль Користувача"}.
{"Changing password is not allowed","Зміна пароля заборонена"}.
{"Changing role/affiliation is not allowed","Зміна ролі/рангу заборонена"}.
{"Channel already exists","Канал уже існує"}.
{"Channel does not exist","Канал не існує"}.
{"Channels","Канали"}.
{"Characters not allowed:","Заборонені символи:"}.
{"Chatroom configuration modified","Конфігурація кімнати змінилась"}.
{"Chatroom is created","Створено кімнату"}.
@ -47,41 +79,55 @@
{"Chatrooms","Кімнати"}.
{"Choose a username and password to register with this server","Виберіть назву користувача та пароль для реєстрації на цьому сервері"}.
{"Choose storage type of tables","Оберіть тип збереження таблиць"}.
{"Choose whether to approve this entity's subscription.","Вирішіть, чи задовольнити запит цього об'єкту на підписку"}.
{"Choose whether to approve this entity's subscription.","Вирішіть, чи задовольнити запит цього об'єкту на підписку."}.
{"City","Місто"}.
{"Client acknowledged more stanzas than sent by server","Клієнт підтвердив більше повідомлень, ніж було відправлено сервером"}.
{"Commands","Команди"}.
{"Conference room does not exist","Конференція не існує"}.
{"Configuration of room ~s","Конфігурація кімнати ~s"}.
{"Configuration","Конфігурація"}.
{"Connected Resources:","Підключені ресурси:"}.
{"Contact Addresses (normally, room owner or owners)","Контактні адреси (зазвичай, власника або власників кімнати)"}.
{"Country","Країна"}.
{"CPU Time:","Процесорний час:"}.
{"Current Discussion Topic","Поточна тема обговорення"}.
{"Database failure","Помилка база даних"}.
{"Database Tables at ~p","Таблиці бази даних на ~p"}.
{"Database Tables Configuration at ","Конфігурація таблиць бази даних на "}.
{"Database","База даних"}.
{"December","грудня"}.
{"Default users as participants","Зробити користувачів учасниками за замовчуванням"}.
{"Delete content","Видалити вміст"}.
{"Delete message of the day on all hosts","Видалити повідомлення дня на усіх хостах"}.
{"Delete message of the day","Видалити повідомлення дня"}.
{"Delete Selected","Видалити виділені"}.
{"Delete table","Видалити таблицю"}.
{"Delete User","Видалити Користувача"}.
{"Deliver event notifications","Доставляти сповіщення про події"}.
{"Deliver payloads with event notifications","Доставляти разом з повідомленнями про публікації самі публікації"}.
{"Description:","Опис:"}.
{"Disc only copy","Тільки диск"}.
{"'Displayed groups' not added (they do not exist!): ","\"Відображені групи\" не додано (вони не існують!): "}.
{"Displayed:","Відображено:"}.
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","Нікому не кажіть свій пароль, навіть адміністраторам XMPP-сервера."}.
{"Dump Backup to Text File at ","Копіювання в текстовий файл на "}.
{"Dump to Text File","Копіювання в текстовий файл"}.
{"Duplicated groups are not allowed by RFC6121","RFC6121 забороняє дублювати групи"}.
{"Edit Properties","Змінити параметри"}.
{"Either approve or decline the voice request.","Підтвердить або відхилите голосовий запит"}.
{"Either approve or decline the voice request.","Підтвердіть або відхиліть голосовий запит."}.
{"ejabberd HTTP Upload service","Служба відвантаження по HTTP для ejabberd"}.
{"ejabberd MUC module","ejabberd MUC модуль"}.
{"ejabberd Multicast service","Мультікаст ejabberd сервіс"}.
{"ejabberd Publish-Subscribe module","Модуль ejabberd Публікації-Підписки"}.
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}.
{"ejabberd vCard module","ejabberd vCard модуль"}.
{"ejabberd Web Admin","Веб-інтерфейс Адміністрування ejabberd"}.
{"ejabberd","ejabberd"}.
{"Elements","Елементи"}.
{"Email Address","Адреса ел. пошти"}.
{"Email","Електронна пошта"}.
{"Enable logging","Включити журнал роботи"}.
{"Enable hats","Увімкнути капелюхи"}.
{"Enable logging","Увімкнути журнал роботи"}.
{"Enable message archiving","Ввімкнути архівацію повідомлень"}.
{"End User Session","Закінчити Сеанс Користувача"}.
{"Enter nickname you want to register","Введіть псевдонім, який ви хочете зареєструвати"}.
@ -90,16 +136,29 @@
{"Enter path to jabberd14 spool file","Введіть шлях до файла зі спула jabberd14"}.
{"Enter path to text file","Введіть шлях до текстового файла"}.
{"Enter the text you see","Введіть текст, що ви бачите"}.
{"Erlang XMPP Server","Ерланґ XMPP Сервер"}.
{"Error","Помилка"}.
{"Exclude Jabber IDs from CAPTCHA challenge","Пропускати ці Jabber ID без CAPTCHA-запиту"}.
{"Export all tables as SQL queries to a file:","Експорт усіх таблиць, як SQL запити, у файл"}.
{"Export all tables as SQL queries to a file:","Експортувати всі таблиці у файл як SQL запити:"}.
{"Export data of all users in the server to PIEFXIS files (XEP-0227):","Експорт даних всіх користувачів сервера до файлу PIEFXIS (XEP-0227):"}.
{"Export data of users in a host to PIEFXIS files (XEP-0227):","Експорт даних користувачів домена до файлу PIEFXIS (XEP-0227):"}.
{"External component failure","Помилка зовнішнього компонента"}.
{"External component timeout","Тайм-аут зовнішнього компонента"}.
{"Failed to activate bytestream","Не вдалося активувати потік байтів"}.
{"Failed to extract JID from your voice request approval","Помилка витягнення JID з вашого схвалення голосового запиту"}.
{"Failed to map delegated namespace to external component","Не вдалося зіставити делегований простір імен із зовнішнім компонентом"}.
{"Failed to parse HTTP response","Не вдалося розібрати HTTP-відповідь"}.
{"Failed to process option '~s'","Не вдалося обробити параметр \"~s\""}.
{"Family Name","Прізвище"}.
{"FAQ Entry","Запис в ЧаПи"}.
{"February","лютого"}.
{"File larger than ~w bytes","Файл більший, ніж ~w байт"}.
{"Fill in the form to search for any matching XMPP User","Заповніть форму для пошуку будь-якого відповідного користувача XMPP"}.
{"Friday","П'ятниця"}.
{"From ~ts","Від ~ts"}.
{"From","Від кого"}.
{"Full List of Room Admins","Повний перелік адміністраторів кімнати"}.
{"Full List of Room Owners","Повний перелік власників кімнати"}.
{"Full Name","Повне ім'я"}.
{"Get Number of Online Users","Отримати Кількість Підключених Користувачів"}.
{"Get Number of Registered Users","Отримати Кількість Зареєстрованих Користувачів"}.
@ -107,6 +166,7 @@
{"Get User Password","Отримати Пароль Користувача"}.
{"Get User Statistics","Отримати Статистику по Користувачу"}.
{"Grant voice to this person?","Надати голос персоні?"}.
{"Groups that will be displayed to the members","Групи, які показуватимуться учасникам"}.
{"Groups","Групи"}.
{"Group","Група"}.
{"has been banned","заборонили вхід в кімнату"}.
@ -114,8 +174,11 @@
{"has been kicked because of an affiliation change","вигнано з кімнати внаслідок зміни рангу"}.
{"has been kicked because the room has been changed to members-only","вигнано з кімнати тому, що вона стала тільки для учасників"}.
{"has been kicked","вигнали з кімнати"}.
{"Host unknown","Невідоме ім'я сервера"}.
{"Host","Хост"}.
{"If you don't see the CAPTCHA image here, visit the web page.","Якщо ви не бачите зображення капчі, перейдіть за за цією адресою."}.
{"HTTP File Upload","Відвантаження файлів по HTTP"}.
{"Idle connection","Неактивне підключення"}.
{"If you don't see the CAPTCHA image here, visit the web page.","Якщо ви не бачите зображення CAPTCHA, перейдіть за адресою."}.
{"Import Directory","Імпорт з директорії"}.
{"Import File","Імпорт з файла"}.
{"Import user data from jabberd14 spool file:","Імпорт користувачів з файла спула jabberd14:"}.
@ -123,27 +186,46 @@
{"Import users data from a PIEFXIS file (XEP-0227):","Імпорт даних користовучів з файлу PIEFXIS (XEP-0227):"}.
{"Import users data from jabberd14 spool directory:","Імпорт користувачів з діректорії спула jabberd14:"}.
{"Import Users from Dir at ","Імпортування користувача з директорії на "}.
{"Import Users From jabberd14 Spool Files","Імпорт користувачів з jabberd14 файлів \"Spool\""}.
{"Import Users From jabberd14 Spool Files","Імпорт користувачів з jabberd14 файлів \"Spool\""}.
{"Improper domain part of 'from' attribute","Неправильна доменна частина атрибута \"from\""}.
{"Improper message type","Неправильний тип повідомлення"}.
{"Incoming s2s Connections:","Вхідні s2s-з'єднання:"}.
{"Incorrect CAPTCHA submit","Неправильний ввід CAPTCHA"}.
{"Incorrect data form","Неправильна форма даних"}.
{"Incorrect password","Неправильний пароль"}.
{"Incorrect value of 'action' attribute","Неправильне значення атрибута \"action\""}.
{"Incorrect value of 'action' in data form","Неправильне значення \"action\" у формі даних"}.
{"Incorrect value of 'path' in data form","Неправильне значення \"path\" у формі даних"}.
{"Insufficient privilege","Недостатньо привілеїв"}.
{"Internal server error","Внутрішня помилка сервера"}.
{"Invalid 'from' attribute in forwarded message","Неприйнятний атрибут \"from\" у пересланому повідомленні"}.
{"Invalid node name","Неприйнятне ім'я вузла"}.
{"Invalid 'previd' value","Неприйнятне значення \"previd\""}.
{"Invitations are not allowed in this conference","Запрошення на цю конференцію не допускаються"}.
{"IP addresses","IP адреси"}.
{"is now known as","змінив(ла) псевдонім на"}.
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Не дозволяється відправляти помилкові повідомлення в кімнату. Учасник (~s) відправив помилкове повідомлення (~s), та був виганий з кімнати"}.
{"It is not allowed to send private messages of type \"groupchat\"","Не дозволяється надсилати приватні повідомлення типу \"groupchat\""}.
{"It is not allowed to send private messages to the conference","Не дозволяється надсилати приватні повідомлення в конференцію"}.
{"It is not allowed to send private messages to the conference","Не дозволяється надсилати приватні повідомлення в конференцію"}.
{"It is not allowed to send private messages","Приватні повідомлення не дозволені"}.
{"Jabber ID","Jabber ID"}.
{"January","січня"}.
{"JID normalization failed","Помилка нормалізації JID"}.
{"joins the room","увійшов(ла) в кімнату"}.
{"July","липня"}.
{"June","червня"}.
{"Just created","Щойно створено"}.
{"Label:","Мітка:"}.
{"Last Activity","Останнє підключення"}.
{"Last login","Останнє підключення"}.
{"Last message","Останнє повідомлення"}.
{"Last month","За останній місяць"}.
{"Last year","За останній рік"}.
{"leaves the room","вийшов(ла) з кімнати"}.
{"List of rooms","Перелік кімнат"}.
{"List of users with hats","Список користувачів із капелюхами"}.
{"List users with hats","Список користувачів із капелюхами"}.
{"Logging","Журналювання"}.
{"Low level update script","Низькорівневий сценарій поновлення"}.
{"Make participants list public","Зробити список учасників видимим всім"}.
{"Make room CAPTCHA protected","Зробити кімнату захищеною капчею"}.
@ -152,44 +234,89 @@
{"Make room password protected","Зробити кімнату захищеною паролем"}.
{"Make room persistent","Зробити кімнату постійною"}.
{"Make room public searchable","Зробити кімнату видимою всім"}.
{"Malformed username","Неправильне ім’я користувача"}.
{"March","березня"}.
{"Max # of items to persist","Максимальне число збережених публікацій"}.
{"Max payload size in bytes","Максимальний розмір корисного навантаження в байтах"}.
{"Maximum file size","Макс. розмір файлу"}.
{"Maximum Number of History Messages Returned by Room","Максимальна кількість повідомлень історії на кімнату"}.
{"Maximum number of items to persist","Максимальна кількість елементів для збереження"}.
{"Maximum Number of Occupants","Максимальна кількість учасників"}.
{"May","травня"}.
{"Members not added (inexistent vhost!): ","Учасників не додано (вірт. сервер не існує!): "}.
{"Membership is required to enter this room","В цю конференцію можуть входити тільки її члени"}.
{"Members:","Члени:"}.
{"Memory","Пам'ять"}.
{"Message body","Тіло повідомлення"}.
{"Message not found in forwarded payload","Повідомлення не знайдено в пересланому вмісті"}.
{"Messages from strangers are rejected","Повідомлення від незнайомців відхиляються"}.
{"Messages of type headline","Повідомлення типу \"заголовок\""}.
{"Messages of type normal","Повідомлення типу \"звичайні\""}.
{"Middle Name","По-батькові"}.
{"Minimum interval between voice requests (in seconds)","Мінімальний інтервал між голосовими запитами (в секундах)"}.
{"Moderator privileges required","Необхідні права модератора"}.
{"Moderator","Модератор"}.
{"Modified modules","Змінені модулі"}.
{"Module failed to handle the query","Модулю не вдалося обробити запит"}.
{"Monday","Понеділок"}.
{"Multicast","Мультікаст"}.
{"Multiple <item/> elements are not allowed by RFC6121","Кілька елементів <item/> не дозволені RFC6121"}.
{"Multi-User Chat","Багато-користувальницький чат"}.
{"Name","Назва"}.
{"Name:","Назва:"}.
{"Neither 'jid' nor 'nick' attribute found","Не знайдено ні атрибута \"jid\", ні \"nick\""}.
{"Neither 'role' nor 'affiliation' attribute found","Не знайдено ні атрибута \"role\", ні \"affiliation\""}.
{"Never","Ніколи"}.
{"New Password:","Новий Пароль:"}.
{"Nickname can't be empty","Псевдонім не може бути порожнім"}.
{"Nickname Registration at ","Реєстрація псевдоніма на "}.
{"Nickname ~s does not exist in the room","Псевдонім ~s в кімнаті відсутній"}.
{"Nickname","Псевдонім"}.
{"No address elements found","Не знайдено елементів адреси"}.
{"No addresses element found","Не знайдено елемента адрес"}.
{"No 'affiliation' attribute found","Не знайдено атрибут \"affiliation\""}.
{"No available resource found","Не знайдено доступного ресурсу"}.
{"No body provided for announce message","Тіло оголошення має бути непустим"}.
{"No child elements found","Не знайдено дочірніх елементів"}.
{"No data form found","Не знайдено форми даних"}.
{"No Data","Немає даних"}.
{"No features available","Немає доступних функцій"}.
{"No <forwarded/> element found","Вузол <forwarded/> не знайдено"}.
{"No hook has processed this command","Жоден хук не обробив цю команду"}.
{"No info about last activity found","Не знайдено інформації про останню діяльність"}.
{"No 'item' element found","Елемент \"item\" не знайдено"}.
{"No items found in this query","У цьому запиті не знайдено жодного елемента"}.
{"No limit","Без обмежень"}.
{"No module is handling this query","Жоден модуль не може обробити цей запит"}.
{"No node specified","Вузол не вказано"}.
{"No 'password' found in data form","Не знайдено \"пароль\" у формі даних"}.
{"No 'password' found in this query","Не знайдено \"пароль\" у цьому запиті"}.
{"No 'path' found in data form","Не знайдено \"path\" у формі даних"}.
{"No pending subscriptions found","Не знайдено очікуваних рішення підписок"}.
{"No privacy list with this name found","Немає списку конфіденційності з такою назвою"}.
{"No private data found in this query","Приватних даних у цьому запиті не знайдено"}.
{"No running node found","Не знайдено запущеного вузла"}.
{"No services available","Немає доступних сервісів"}.
{"No statistics found for this item","Для цього елемента статистичні дані не знайдено"}.
{"No 'to' attribute found in the invitation","У запрошенні не знайдено атрибут \"до\""}.
{"Node already exists","Вузол уже існує"}.
{"Node ID","ID вузла"}.
{"Node index not found","Індекс вузла не знайдено"}.
{"Node not found","Вузол не знайдено"}.
{"Node ~p","Вузол ~p"}.
{"Nodeprep has failed","Не вдалося виконати Nodeprep"}.
{"Nodes","Вузли"}.
{"Node","Вузол"}.
{"None","Немає"}.
{"Not allowed","Не дозволяється"}.
{"Not Found","не знайдено"}.
{"Not subscribed","Не підписаний"}.
{"Notify subscribers when items are removed from the node","Повідомляти абонентів про видалення публікацій із збірника"}.
{"Notify subscribers when the node configuration changes","Повідомляти абонентів про зміни в конфігурації збірника"}.
{"Notify subscribers when the node is deleted","Повідомляти абонентів про видалення збірника"}.
{"November","листопада"}.
{"Number of answers required","Кількість необхідних відповідей"}.
{"Number of occupants","Кількість присутніх"}.
{"Number of Offline Messages","Кількість автономних повідомлень"}.
{"Number of online users","Кількість підключених користувачів"}.
{"Number of registered users","Кількість зареєстрованих користувачів"}.
{"October","грудня"}.
@ -200,19 +327,26 @@
{"Online Users","Підключені користувачі"}.
{"Online Users:","Підключені користувачі:"}.
{"Online","Підключений"}.
{"Only admins can see this","Тільки адміністратори можуть це бачити"}.
{"Only collection node owners may associate leaf nodes with the collection","Лише власники вузлів колекції можуть асоціювати листові вузли з колекцією"}.
{"Only deliver notifications to available users","Доставляти повідомленнями тільки доступним користувачам"}.
{"Only <enable/> or <disable/> tags are allowed","Дозволені лише теги <enable/> або <disable/>"}.
{"Only <list/> element is allowed in this query","У цьому запиті дозволено лише елемент <list/>"}.
{"Only members may query archives of this room","Тільки модератори можуть запитувати архіви цієї кімнати"}.
{"Only moderators and participants are allowed to change the subject in this room","Тільки модератори та учасники можуть змінювати тему в цій кімнаті"}.
{"Only moderators are allowed to change the subject in this room","Тільки модератори можуть змінювати тему в цій кімнаті"}.
{"Only moderators can approve voice requests","Тільки модератори можуть схвалювати голосові запити"}.
{"Only occupants are allowed to send messages to the conference","Тільки присутнім дозволяється надсилати повідомленняя в конференцію"}.
{"Only occupants are allowed to send queries to the conference","Тільки присутнім дозволяється відправляти запити в конференцію"}.
{"Only publishers may publish","Тільки видавці можуть публікувати"}.
{"Only service administrators are allowed to send service messages","Тільки адміністратор сервісу може надсилати службові повідомлення"}.
{"Only those on a whitelist may associate leaf nodes with the collection","Лише ті, хто входить до білого списку, можуть асоціювати листові вузли з колекцією"}.
{"Organization Name","Назва організації"}.
{"Organization Unit","Відділ організації"}.
{"Outgoing s2s Connections","Вихідні s2s-з'єднання"}.
{"Outgoing s2s Connections:","Вихідні s2s-з'єднання:"}.
{"Owner privileges required","Необхідні права власника"}.
{"Packet relay is denied by service policy","Пересилання пакетів заборонене політикою сервісу"}.
{"Packet","Пакет"}.
{"Participant","Учасник"}.
{"Password Verification","Перевірка Пароля"}.
@ -222,22 +356,25 @@
{"Path to Dir","Шлях до директорії"}.
{"Path to File","Шлях до файла"}.
{"Pending","Очікування"}.
{"Period: ","Період"}.
{"Period: ","Період: "}.
{"Persist items to storage","Зберегати публікації до сховища"}.
{"Ping","Пінг"}.
{"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.","Зауважте, що ця опція відповідає за резервне копіювання тільки вбудованної бази даних Mnesia. Якщо Ви також використовуєте інше сховище для даних (наприклад за допомогою модуля ODBC), то його резервне копіювання потрібно робити окремо."}.
{"Please, wait for a while before sending new voice request","Будь ласка, почекайте деякий час перед тим, як знову відправляти голосовий запит"}.
{"Pong","Понг"}.
{"Present real Jabber IDs to","Зробити реальні Jabber ID учасників видимими"}.
{"Previous session not found","Попередній сеанс не знайдено"}.
{"private, ","приватна, "}.
{"Publish-Subscribe","Публікація-Підписка"}.
{"PubSub subscriber request","Запит на підписку PubSub"}.
{"Purge all items when the relevant publisher goes offline","Видалити всі елементи, коли особа, що їх опублікувала, вимикається від мережі"}.
{"Push record not found","Push-запис не знайдено"}.
{"Queries to the conference members are not allowed in this room","Запити до користувачів в цій конференції заборонені"}.
{"RAM and disc copy","ОЗП та диск"}.
{"RAM copy","ОЗП"}.
{"Really delete message of the day?","Насправді, видалити повідомлення дня?"}.
{"Recipient is not in the conference room","Адресата немає в конференції"}.
{"Register an XMPP account","Зареєструвати XMPP-запис"}.
{"Registered Users","Зареєстровані користувачі"}.
{"Registered Users:","Зареєстровані користувачі:"}.
{"Register","Реєстрація"}.
@ -255,15 +392,20 @@
{"Restore plain text backup immediately:","Відновити з текстової резервної копії негайно:"}.
{"Restore","Відновлення з резервної копії"}.
{"Roles for which Presence is Broadcasted","Ролі для яких поширюється наявність"}.
{"Roles that May Send Private Messages","Ролі, що можуть надсилати приватні повідомлення"}.
{"Room Configuration","Конфігурація кімнати"}.
{"Room creation is denied by service policy","Створювати конференцію заборонено політикою служби"}.
{"Room description","Опис кімнати"}.
{"Room Occupants","Учасники кімнати"}.
{"Room terminates","Кімната припиняється"}.
{"Room title","Назва кімнати"}.
{"Roster groups allowed to subscribe","Дозволені для підписки групи ростера"}.
{"Roster of ~ts","Список контактів ~ts"}.
{"Roster size","Кількість контактів"}.
{"Roster:","Список контактів:"}.
{"RPC Call Error","Помилка виклику RPC"}.
{"Running Nodes","Працюючі вузли"}.
{"~s invites you to the room ~s","~s запрошує вас до кімнати ~s"}.
{"Saturday","Субота"}.
{"Script check","Перевірка сценарію"}.
{"Search Results for ","Результати пошуку в "}.
@ -292,26 +434,46 @@
{"Store plain text backup:","Зберегти текстову резервну копію:"}.
{"Subject","Тема"}.
{"Submitted","Відправлено"}.
{"Submit","Відправити"}.
{"Submit","Надіслати"}.
{"Subscriber Address","Адреса абонента"}.
{"Subscription","Підписка"}.
{"Sunday","Неділя"}.
{"That nickname is already in use by another occupant","Псевдонім зайнято кимось з присутніх"}.
{"That nickname is registered by another person","Псевдонім зареєстровано кимось іншим"}.
{"The CAPTCHA is valid.","Перевірку капчею закінчено успішно"}.
{"The account was not unregistered","Обліковий запис не було видалено"}.
{"The CAPTCHA is valid.","Перевірку CAPTCHA успішно завершено."}.
{"The CAPTCHA verification has failed","Перевірку капчею не пройдено"}.
{"The collections with which a node is affiliated","Колекція, до якої входить вузол"}.
{"The password is too weak","Пароль надто простий"}.
{"the password is","пароль:"}.
{"There was an error creating the account: ","Помилка при створенні акаунту:"}.
{"the password is","паролем є"}.
{"The presence states for which an entity wants to receive notifications","Стан присутності, для якого сутність хоче отримувати сповіщення"}.
{"The query is only allowed from local users","Запит дозволено лише від локальних користувачів"}.
{"The query must not contain <item/> elements","Запит не повинен містити елементів <item/>"}.
{"The room subject can be modified by participants","Тема кімнати може бути змінена учасниками"}.
{"The sender of the last received message","Відправник останнього отриманого повідомлення"}.
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","Строфа ПОВИННА містити лише один елемент <active/>, один елемент <default/> або один елемент <list/>"}.
{"The subscription identifier associated with the subscription request","Ідентифікатор підписки, пов’язаний із запитом на підписку"}.
{"There was an error changing the password: ","Помилка при зміні пароля: "}.
{"There was an error creating the account: ","Помилка при створенні облікового запису: "}.
{"There was an error deleting the account: ","Помилка при видаленні акаунту: "}.
{"This page allows to unregister an XMPP account in this XMPP server.","Ця сторінка дозволяє видалити свій обліковий запис з XMPP-сервера."}.
{"This room is not anonymous","Ця кімната не анонімна"}.
{"Thursday","Четвер"}.
{"Time delay","Час затримки"}.
{"Timed out waiting for stream resumption","Час очікування на відновлення потоку закінчився"}.
{"Time","Час"}.
{"To register, visit ~s","Щоб зареєструватися, відвідайте ~s"}.
{"To ~ts","До ~ts"}.
{"Token TTL","Токен TTL"}.
{"Too many active bytestreams","Надто багато активних потоків байтів"}.
{"Too many CAPTCHA requests","Надто багато CAPTCHA-запитів"}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Забагато (~p) помилок авторизації з цієї IP адреси (~s). Адресу буде розблоковано о ~s UTC"}.
{"Too many child elements","Надто багато дочірніх елементів"}.
{"Too many <item/> elements","Надто багато елементів <item/>"}.
{"Too many <list/> elements","Надто багато елементів <list/>"}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Забагато (~p) помилок авторизації з цієї IP адреси (~s). Адресу буде розблоковано о ~s UTC"}.
{"Too many receiver fields were specified","Вказано забагато одержувачів"}.
{"Too many unacked stanzas","Занадто багато пакетів без відповідей"}.
{"Too many users in this conference","Надто багато користувачів у цій конференції"}.
{"Total rooms","Всього кімнат"}.
{"To","Кому"}.
{"Traffic rate limit is exceeded","Швидкість передачі інформації було перевищено"}.
@ -319,10 +481,18 @@
{"Transactions Committed:","Транзакції завершені:"}.
{"Transactions Logged:","Транзакції запротокольовані:"}.
{"Transactions Restarted:","Транзакції перезапущені:"}.
{"~ts's Offline Messages Queue","Черга автономних повідомлень ~ts"}.
{"Tuesday","Вівторок"}.
{"Unable to generate a CAPTCHA","Нема можливості згенерувати капчу"}.
{"Unable to register route on existing local domain","Неможливо зареєструвати маршрут на наявному локальному домені"}.
{"Unauthorized","Не авторизовано"}.
{"Unexpected action","Несподівана дія"}.
{"Unexpected error condition: ~p","Умова несподіваної помилки: ~p"}.
{"Unregister an XMPP account","Видалити обліковий запис XMPP"}.
{"Unregister","Видалити"}.
{"Unselect All","Скасувати виділення з усіх"}.
{"Unsupported <index/> element","Непідтримуваний елемент <index/>"}.
{"Unsupported version","Непідтримувана версія"}.
{"Update message of the day (don't send)","Оновити повідомлення дня (не надсилати)"}.
{"Update message of the day on all hosts (don't send)","Оновити повідомлення дня на всіх хостах (не надсилати)"}.
{"Update plan","План оновлення"}.
@ -330,15 +500,26 @@
{"Update script","Сценарій поновлення"}.
{"Update","Обновити"}.
{"Uptime:","Час роботи:"}.
{"URL for Archived Discussion Logs","URL-адреса для журналів архівних обговорень"}.
{"User already exists","Користувач уже існує"}.
{"User JID","JID Користувача"}.
{"User (jid)","Користувач (jid)"}.
{"User Management","Управління Користувачами"}.
{"User removed","Користувача видалено"}.
{"User session not found","Сеанс користувача не знайдено"}.
{"User session terminated","Сеанс користувача припинено"}.
{"User ~ts","Користувач ~ts"}.
{"Username:","Ім'я користувача:"}.
{"Users are not allowed to register accounts so quickly","Користувачам не дозволено так часто реєструвати облікові записи"}.
{"Users Last Activity","Статистика останнього підключення користувачів"}.
{"Users","Користувачі"}.
{"User","Користувач"}.
{"Validate","Затвердити"}.
{"Value of '~s' should be boolean","Значення \"~s\" має бути логічним"}.
{"Value of '~s' should be datetime string","Значення \"~s\" має бути рядком дати і часу"}.
{"Value of '~s' should be integer","Значення \"~s\" має бути цілим числом"}.
{"vCard User Search","Пошук користувачів по vCard"}.
{"View Queue","Переглянути чергу"}.
{"Virtual Hosts","віртуальні хости"}.
{"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}.
{"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}.
@ -346,9 +527,24 @@
{"Voice requests are disabled in this conference","Голосові запити відключені в цій конференції"}.
{"Voice request","Голосовий запит"}.
{"Wednesday","Середа"}.
{"When a new subscription is processed","Під час обробки нової підписки"}.
{"When to send the last published item","Коли надсилати останній опублікований елемент"}.
{"Whether owners or publisher should receive replies to items","Чи повинні власники або видавець отримувати відповіді на елементи"}.
{"Whether the node is a leaf (default) or a collection","Чи є вузол листом (типово) чи колекцією"}.
{"Whether to allow subscriptions","Дозволяти підписку"}.
{"Whether to make all subscriptions temporary, based on subscriber presence","Чи робити всі підписки тимчасовими, залежно від присутності читача"}.
{"Whether to notify owners about new subscribers and unsubscribes","Чи повідомляти власників про нових читачів та їх втрату"}.
{"Who may associate leaf nodes with a collection","Хто може пов’язувати листові вузли з колекцією"}.
{"Wrong parameters in the web formulary","Неправильні параметри у веб-формі"}.
{"Wrong xmlns","Неправильний xmlns"}.
{"XMPP Account Registration","Реєстрація облікового запису XMPP"}.
{"XMPP Domains","Домени XMPP"}.
{"XMPP URI of Associated Publish-Subscribe Node","XMPP URI-адреса асоційованого вузла публікацій-підписок"}.
{"You are being removed from the room because of a system shutdown","Ви будете видалені з кімнати через завершення роботи системи"}.
{"You are not joined to the channel","Ви не приєднані до каналу"}.
{"You can later change your password using an XMPP client.","Пізніше ви можете змінити пароль за допомогою XMPP-клієнта."}.
{"You have been banned from this room","Вам заборонено входити в цю конференцію"}.
{"You have joined too many conferences","Ви приєднані до надто великої кількості конференцій"}.
{"You must fill in field \"Nickname\" in the form","Вам необхідно заповнити поле \"Псевдонім\" у формі"}.
{"You need a client that supports x:data and CAPTCHA to register","Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:data"}.
{"You need a client that supports x:data to register the nickname","Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:data"}.
@ -356,3 +552,6 @@
{"Your active privacy list has denied the routing of this stanza.","Маршрутизація цієї строфи була відмінена активним списком приватності."}.
{"Your contact offline message queue is full. The message has been discarded.","Черга повідомлень, що не були доставлені, переповнена. Повідомлення не було збережено."}.
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s"}.
{"Your XMPP account was successfully registered.","Ваш обліковий запис XMPP успішно зареєстровано."}.
{"Your XMPP account was successfully unregistered.","Ваш обліковий запис XMPP успішно видалено."}.
{"You're not allowed to create nodes","Вам заборонено створювати вузли"}.

View File

@ -110,7 +110,6 @@
{"Make room persistent","Tạo phòng bền vững"}.
{"Make room public searchable","Tạo phòng có thể tìm kiếm công khai"}.
{"March","Tháng Ba"}.
{"Max # of items to persist","Số mục tối đa để lưu trữ"}.
{"Max payload size in bytes","Kích thước dung lượng byte tối đa"}.
{"Maximum Number of Occupants","Số Lượng Người Tham Dự Tối Đa"}.
{"May","Tháng Năm"}.

View File

@ -153,7 +153,6 @@
{"Make room persistent","Rinde li såle permaninte"}.
{"Make room public searchable","Rinde li såle di berdelaedje cweråve publicmint"}.
{"March","måss"}.
{"Max # of items to persist","Nombe macsimoms di cayets permanints"}.
{"Max payload size in bytes","Contnou macsimom en octets"}.
{"Maximum Number of Occupants","Nombe macsimom di prezints"}.
{"May","may"}.

View File

@ -4,7 +4,7 @@
%% https://docs.ejabberd.im/developer/extending-ejabberd/localization/
{" (Add * to the end of field to match substring)"," (在字段末添加*来匹配子串)"}.
{" has set the subject to: ","已将标题设置为: "}.
{" has set the subject to: "," 已将标题设置为: "}.
{"# participants","# 个参与人"}.
{"A description of the node","该节点的描述"}.
{"A friendly name for the node","该节点的友好名称"}.
@ -20,10 +20,11 @@
{"Access model","访问模型"}.
{"Account doesn't exist","账号不存在"}.
{"Action on user","对用户的动作"}.
{"Add a hat to a user","给用户添加头衔"}.
{"Add Jabber ID","添加Jabber ID"}.
{"Add New","添加新用户"}.
{"Add User","添加用户"}.
{"Administration of ","管理"}.
{"Administration of ","管理 "}.
{"Administration","管理"}.
{"Administrator privileges required","需要管理员权限"}.
{"All activity","所有活动"}.
@ -62,7 +63,7 @@
{"Automatic node creation is not enabled","未启用自动节点创建"}.
{"Backup Management","备份管理"}.
{"Backup of ~p","~p的备份"}.
{"Backup to File at ","备份文件位于"}.
{"Backup to File at ","备份文件位于 "}.
{"Backup","备份"}.
{"Bad format","格式错误"}.
{"Birthday","出生日期"}.
@ -78,6 +79,7 @@
{"Changing role/affiliation is not allowed","不允许修改角色/单位"}.
{"Channel already exists","频道已存在"}.
{"Channel does not exist","频道不存在"}.
{"Channel JID","频道 JID"}.
{"Channels","频道"}.
{"Characters not allowed:","不允许字符:"}.
{"Chatroom configuration modified","聊天室配置已修改"}.
@ -97,12 +99,13 @@
{"Configuration","配置"}.
{"Connected Resources:","已连接资源:"}.
{"Contact Addresses (normally, room owner or owners)","联系人地址 (通常为房间持有人)"}.
{"Contrib Modules","Contrib 模块"}.
{"Country","国家"}.
{"CPU Time:","CPU时间"}.
{"Current Discussion Topic","当前讨论话题"}.
{"Database failure","数据库失败"}.
{"Database Tables at ~p","位于~p的数据库表"}.
{"Database Tables Configuration at ","数据库表格配置位于"}.
{"Database Tables Configuration at ","数据库表格配置位于 "}.
{"Database","数据库"}.
{"December","十二月"}.
{"Default users as participants","用户默认被视为参与人"}.
@ -119,12 +122,12 @@
{"'Displayed groups' not added (they do not exist!): ","'显示的群组' 未被添加 (它们不存在!): "}.
{"Displayed:","已显示:"}.
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","不要将密码告诉任何人, 就算是XMPP服务器的管理员也不可以."}.
{"Dump Backup to Text File at ","转储备份到文本文件于"}.
{"Dump Backup to Text File at ","将备份转储到位于以下位置的文本文件 "}.
{"Dump to Text File","转储到文本文件"}.
{"Duplicated groups are not allowed by RFC6121","按照RFC6121的规则不允许有重复的群组"}.
{"Dynamically specify a replyto of the item publisher","为项目发布者动态指定一个 replyto"}.
{"Edit Properties","编辑属性"}.
{"Either approve or decline the voice request.","接受或拒绝声音请求"}.
{"Either approve or decline the voice request.","接受或拒绝声音请求."}.
{"ejabberd HTTP Upload service","ejabberd HTTP 上传服务"}.
{"ejabberd MUC module","ejabberd MUC 模块"}.
{"ejabberd Multicast service","ejabberd多重映射服务"}.
@ -136,6 +139,7 @@
{"Elements","元素"}.
{"Email Address","电邮地址"}.
{"Email","电子邮件"}.
{"Enable hats","启用头衔"}.
{"Enable logging","启用服务器端聊天记录"}.
{"Enable message archiving","启用消息归档"}.
{"Enabling push without 'node' attribute is not supported","不支持未使用'node'属性就开启推送"}.
@ -170,10 +174,12 @@
{"Full List of Room Admins","房间管理员完整列表"}.
{"Full List of Room Owners","房间持有人完整列表"}.
{"Full Name","全名"}.
{"Get List of Online Users","获取在线用户列表"}.
{"Get List of Registered Users","获取注册用户列表"}.
{"Get Number of Online Users","获取在线用户数"}.
{"Get Number of Registered Users","获取注册用户数"}.
{"Get Pending","获取挂起"}.
{"Get User Last Login Time","获取用户上次登时间"}.
{"Get User Last Login Time","获取用户上次登时间"}.
{"Get User Password","获取用户密码"}.
{"Get User Statistics","获取用户统计"}.
{"Given Name","中间名"}.
@ -186,6 +192,9 @@
{"has been kicked because of an affiliation change","因联属关系改变而被踢出"}.
{"has been kicked because the room has been changed to members-only","因该房间改为只对会员开放而被踢出"}.
{"has been kicked","已被踢出"}.
{"Hat title","头衔标题"}.
{"Hat URI","头衔 URI"}.
{"Hats limit exceeded","已超过头衔限制"}.
{"Host unknown","主人未知"}.
{"Host","主机"}.
{"HTTP File Upload","HTTP文件上传"}.
@ -194,10 +203,10 @@
{"Import Directory","导入目录"}.
{"Import File","导入文件"}.
{"Import user data from jabberd14 spool file:","从 jabberd14 Spool 文件导入用户数据:"}.
{"Import User from File at ","导入用户的文件位于"}.
{"Import User from File at ","从以下位置的文件导入用户 "}.
{"Import users data from a PIEFXIS file (XEP-0227):","从 PIEFXIS 文件 (XEP-0227) 导入用户数据:"}.
{"Import users data from jabberd14 spool directory:","从jabberd14 Spool目录导入用户数据:"}.
{"Import Users from Dir at ","导入用户的目录位于"}.
{"Import Users from Dir at ","从以下位置目录导入用户 "}.
{"Import Users From jabberd14 Spool Files","从 jabberd14 Spool 文件导入用户"}.
{"Improper domain part of 'from' attribute","不恰当的'from'属性域名部分"}.
{"Improper message type","不恰当的消息类型"}.
@ -208,6 +217,8 @@
{"Incorrect value of 'action' attribute","'action' 属性的值不正确"}.
{"Incorrect value of 'action' in data form","数据表单中 'action' 的值不正确"}.
{"Incorrect value of 'path' in data form","数据表单中 'path' 的值不正确"}.
{"Installed Modules:","已安装的模块:"}.
{"Install","安装"}.
{"Insufficient privilege","权限不足"}.
{"Internal server error","内部服务器错误"}.
{"Invalid 'from' attribute in forwarded message","转发的信息中 'from' 属性的值无效"}.
@ -224,19 +235,23 @@
{"January","一月"}.
{"JID normalization denied by service policy","JID规范化被服务策略拒绝"}.
{"JID normalization failed","JID规范化失败"}.
{"Joined MIX channels of ~ts","加入了 ~ts 的 MIX 频道"}.
{"Joined MIX channels:","加入了 MIX 频道:"}.
{"joins the room","加入房间"}.
{"July","七月"}.
{"June","六月"}.
{"Just created","刚刚创建"}.
{"Label:","标签:"}.
{"Last Activity","上次活动"}.
{"Last login","上次登"}.
{"Last login","上次登"}.
{"Last message","最近消息"}.
{"Last month","上个月"}.
{"Last year","上一年"}.
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","文本的SHA-256哈希的最低有效位应等于十六进制标签"}.
{"leaves the room","离开房间"}.
{"List of rooms","房间列表"}.
{"List of users with hats","有头衔用户的列表"}.
{"List users with hats","有头衔用户列表"}.
{"Logging","正在记录"}.
{"Low level update script","低级别更新脚本"}.
{"Make participants list public","公开参与人列表"}.
@ -249,7 +264,7 @@
{"Malformed username","用户名无效"}.
{"MAM preference modification denied by service policy","MAM偏好被服务策略拒绝"}.
{"March","三月"}.
{"Max # of items to persist","允许持久化的最大内容条目数"}.
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","要保留的最大项目数 #`max`表示除了服务器强加的最大值之外没有特定限制"}.
{"Max payload size in bytes","最大有效负载字节数"}.
{"Maximum file size","最大文件大小"}.
{"Maximum Number of History Messages Returned by Room","房间返回的历史消息最大值"}.
@ -288,7 +303,7 @@
{"Never","从未"}.
{"New Password:","新密码:"}.
{"Nickname can't be empty","昵称不能为空"}.
{"Nickname Registration at ","昵称注册于"}.
{"Nickname Registration at ","昵称注册于 "}.
{"Nickname ~s does not exist in the room","昵称~s不在该房间"}.
{"Nickname","昵称"}.
{"No address elements found","没有找到地址的各元素"}.
@ -326,6 +341,7 @@
{"Node ~p","节点~p"}.
{"Nodeprep has failed","Nodeprep 已失效"}.
{"Nodes","节点"}.
{"Node","节点"}.
{"None","无"}.
{"Not allowed","不允许"}.
{"Not Found","没有找到"}.
@ -339,8 +355,9 @@
{"Number of Offline Messages","离线消息数量"}.
{"Number of online users","在线用户数"}.
{"Number of registered users","注册用户数"}.
{"Number of seconds after which to automatically purge items","自动清除项目要等待的秒数"}.
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","等待多少秒后自动清除项目“max”表示除服务器施加的最大值外没有特定限制"}.
{"Occupants are allowed to invite others","允许成员邀请其他人"}.
{"Occupants are allowed to query others","成员可查询其他人"}.
{"Occupants May Change the Subject","成员可以修改主题"}.
{"October","十月"}.
{"Offline Messages","离线消息"}.
@ -367,11 +384,13 @@
{"Only those on a whitelist may subscribe and retrieve items","仅白名单用户可以订阅和检索内容项"}.
{"Organization Name","组织名称"}.
{"Organization Unit","组织单位"}.
{"Other Modules Available:","其他可用模块:"}.
{"Outgoing s2s Connections","出站 s2s 连接"}.
{"Outgoing s2s Connections:","出站 s2s 连接:"}.
{"Owner privileges required","需要持有人权限"}.
{"Packet relay is denied by service policy","包中继被服务策略拒绝"}.
{"Packet","数据包"}.
{"Participant ID","参与者 ID"}.
{"Participant","参与人"}.
{"Password Verification:","密码确认:"}.
{"Password Verification","确认密码"}.
@ -418,6 +437,7 @@
{"Registered Users:","注册用户:"}.
{"Register","注册"}.
{"Remote copy","远程复制"}.
{"Remove a hat from a user","移除用户头衔"}.
{"Remove All Offline Messages","移除所有离线消息"}.
{"Remove User","删除用户"}.
{"Remove","移除"}.
@ -428,7 +448,7 @@
{"Resources","资源"}.
{"Restart Service","重启服务"}.
{"Restart","重启"}.
{"Restore Backup from File at ","要恢复的备份文件位于"}.
{"Restore Backup from File at ","从以下位置的文件恢复备份 "}.
{"Restore binary backup after next ejabberd restart (requires less memory):","在下次 ejabberd 重启后恢复二进制备份(需要的内存更少):"}.
{"Restore binary backup immediately:","立即恢复二进制备份:"}.
{"Restore plain text backup immediately:","立即恢复普通文本备份:"}.
@ -455,7 +475,7 @@
{"Search Results for ","搜索结果属于关键词 "}.
{"Search the text","搜索文本"}.
{"Search until the date","搜索截至日期"}.
{"Search users in ","搜索用户于"}.
{"Search users in ","在以下位置搜索用户 "}.
{"Select All","全选"}.
{"Send announcement to all online users on all hosts","发送通知给所有主机的在线用户"}.
{"Send announcement to all online users","发送通知给所有在线用户"}.
@ -473,6 +493,7 @@
{"Shut Down Service","关闭服务"}.
{"SOCKS5 Bytestreams","SOCKS5 字节流"}.
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","某些 XMPP 客户端可以在计算机里存储你的密码. 处于安全考虑, 请仅在你的个人计算机里使用该功能."}.
{"Sources Specs:","源参数:"}.
{"Specify the access model","指定访问范例"}.
{"Specify the event message type","指定事件消息类型"}.
{"Specify the publisher model","指定发布人范例"}.
@ -518,8 +539,10 @@
{"The JIDs of those to contact with questions","问题联系人的JID"}.
{"The JIDs of those with an affiliation of owner","隶属所有人的JID"}.
{"The JIDs of those with an affiliation of publisher","隶属发布人的JID"}.
{"The list of all online users","所有在线用户列表"}.
{"The list of all users","所有用户列表"}.
{"The list of JIDs that may associate leaf nodes with a collection","可以将叶节点与集合关联的JID列表"}.
{"The maximum number of child nodes that can be associated with a collection","可以与集合关联的最大子节点数"}.
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","可以与集合关联的最大子节点数“max”表示除服务器施加的最大值外没有特定限制"}.
{"The minimum number of milliseconds between sending any two notification digests","发送任何两个通知摘要之间的最小毫秒数"}.
{"The name of the node","该节点的名称"}.
{"The node is a collection node","该节点是集合节点"}.
@ -544,13 +567,12 @@
{"The type of node data, usually specified by the namespace of the payload (if any)","节点数据的类型, 如果有, 通常由有效负载的名称空间指定"}.
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","XSL转换的URL可以将其应用于有效负载以生成适当的消息正文元素。"}.
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","XSL转换的URL, 可以将其应用于有效负载格式, 以生成有效的数据表单结果, 客户端可以使用通用数据表单呈现引擎来显示该结果"}.
{"The username is not valid","用户名无效"}.
{"There was an error changing the password: ","修改密码出错: "}.
{"There was an error creating the account: ","帐户创建出错: "}.
{"There was an error deleting the account: ","帐户删除失败: "}.
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","此处不区分大小写: macbeth 与 MacBeth 和 Macbeth 是一样的."}.
{"This page allows to register an XMPP account in this XMPP server. Your JID (Jabber ID) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","本页面允许在此服务器上注册XMPP帐户. 你的JID (Jabber ID) 的形式如下: 用户名@服务器. 请仔细阅读说明并正确填写相应字段."}.
{"This page allows to unregister an XMPP account in this XMPP server.","此页面允许在此XMPP服务器上注销XMPP帐户"}.
{"This page allows to unregister an XMPP account in this XMPP server.","此页面允许在此 XMPP 服务器上注销 XMPP 帐户"}.
{"This room is not anonymous","此房间不是匿名房间"}.
{"This service can not process the address: ~s","此服务无法处理地址: ~s"}.
{"Thursday","星期四"}.
@ -565,7 +587,7 @@
{"Too many child elements","太多子元素"}.
{"Too many <item/> elements","太多 <item/> 元素"}.
{"Too many <list/> elements","太多 <list/> 元素"}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","来自IP地址(~p)的(~s)失败认证太多. 该地址将在UTC时间~s被禁用."}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","来自IP地址(~p)的(~s)失败认证太多。将在UTC时间 ~s 解除对该地址的封锁"}.
{"Too many receiver fields were specified","指定的接收者字段太多"}.
{"Too many unacked stanzas","未被确认的节太多"}.
{"Too many users in this conference","该会议的用户太多"}.
@ -583,6 +605,7 @@
{"Unauthorized","未认证的"}.
{"Unexpected action","意外行为"}.
{"Unexpected error condition: ~p","意外错误条件: ~p"}.
{"Uninstall","卸载"}.
{"Unregister an XMPP account","注销XMPP帐户"}.
{"Unregister","取消注册"}.
{"Unselect All","取消全选"}.
@ -593,7 +616,10 @@
{"Update plan","更新计划"}.
{"Update ~p","更新~p"}.
{"Update script","更新脚本"}.
{"Update specs to get modules source, then install desired ones.","更新参数获取模块源,然后安装所需的模块。"}.
{"Update Specs","更新参数"}.
{"Update","更新"}.
{"Upgrade","升级"}.
{"Uptime:","正常运行时间:"}.
{"URL for Archived Discussion Logs","已归档对话日志的URL"}.
{"User already exists","用户已存在"}.
@ -616,6 +642,7 @@
{"Value of '~s' should be integer","'~s' 的值应为整数"}.
{"Value 'set' of 'type' attribute is not allowed","不允许 'type' 属性的 'set' 值"}.
{"vCard User Search","vCard用户搜索"}.
{"View joined MIX channels","查看已加入的 MIX 频道"}.
{"View Queue","查看队列"}.
{"View Roster","查看花名册"}.
{"Virtual Hosts","虚拟主机"}.
@ -656,7 +683,7 @@
{"You need a client that supports x:data to register the nickname","您需要一个支持 x:data 的客户端来注册昵称"}.
{"You need an x:data capable client to search","您需要一个兼容 x:data 的客户端来搜索"}.
{"Your active privacy list has denied the routing of this stanza.","你的活跃私聊列表拒绝了在此房间进行路由分发."}.
{"Your contact offline message queue is full. The message has been discarded.","您的联系人离线消息队列已满. 消息已被丢弃"}.
{"Your contact offline message queue is full. The message has been discarded.","您的联系人离线消息队列已满。消息已被丢弃。"}.
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","您发送给~s的消息已被阻止. 要解除阻止, 请访问 ~s"}.
{"Your XMPP account was successfully registered.","你的XMPP帐户注册成功."}.
{"Your XMPP account was successfully unregistered.","你的XMPP帐户注销成功."}.

BIN
rebar vendored

Binary file not shown.

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@ -19,8 +19,8 @@
%%%----------------------------------------------------------------------
{deps, [{base64url, ".*", {git, "https://github.com/dvv/base64url", {tag, "1.0.1"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.29"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.21"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.30"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.22"}}},
{if_var_true, tools,
{ejabberd_po, ".*", {git, "https://github.com/processone/ejabberd-po", {branch, "main"}}}},
{if_var_true, elixir,
@ -30,40 +30,51 @@
{if_var_true, redis,
{eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.2.0"}}}},
{if_var_true, sip,
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.43"}}}},
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.48"}}}},
{if_var_true, zlib,
{ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.10"}}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.13"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.47"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.32"}}},
{ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.12"}}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.16"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.49"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.34"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.5"}}},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.9.0"}}},
{lager, ".*", {git, "https://github.com/erlang-lager/lager", {tag, "3.9.1"}}},
{if_version_above, "19",
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.1.1"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.1.0"}}} % for R19 and below
},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.1"}}},
{if_version_below, "22",
{lager, ".*", {git, "https://github.com/erlang-lager/lager", {tag, "3.9.1"}}}
},
{if_var_true, lua,
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "v0.3"}}}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.14"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {tag, "1.0.13"}}},
{if_not_rebar3,
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "1.0"}}}
}},
{if_var_true, lua,
{if_rebar3,
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "1.0.0"}}}
}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.15"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {tag, "1.0.20"}}},
{if_var_true, mysql,
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.19"}}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.10"}}},
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.20"}}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.11"}}},
{if_var_true, pgsql,
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.12"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.23"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.8"}}},
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.19"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.25"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.9"}}},
{if_not_rebar3, %% Needed because modules are not fully migrated to new structure and mix
{if_var_true, elixir,
{rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
{if_var_true, sqlite,
{sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.13"}}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.27"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.29"}}},
{if_var_true, stun,
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.44"}}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.5.4"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.12"}}}
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.2.6"}}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.6.0"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.14"}}}
]}.
{gitonly_deps, [elixir, luerl]}.
{gitonly_deps, [elixir]}.
{if_var_true, latest_deps,
{floating_deps, [cache_tab,
@ -94,6 +105,8 @@
{erl_opts, [nowarn_deprecated_function,
{i, "include"},
{if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}},
{if_version_above, "20", {d, 'HAVE_ERL_ERROR'}},
{if_version_above, "20", {d, 'HAVE_URI_STRING'}},
{if_version_below, "21", {d, 'USE_OLD_HTTP_URI'}},
{if_version_below, "22", {d, 'LAGER'}},
{if_version_below, "21", {d, 'NO_CUSTOMIZE_HOSTNAME_CHECK'}},
@ -101,15 +114,14 @@
{if_version_below, "23", {d, 'USE_OLD_PG2'}},
{if_version_below, "24", {d, 'COMPILER_REPORTS_ONLY_LINES'}},
{if_version_below, "24", {d, 'SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL'}},
{if_var_match, db_type, mssql, {d, 'mssql'}},
{if_version_below, "25", {d, 'OTP_BELOW_25'}},
{if_var_false, debug, no_debug_info},
{if_var_true, debug, debug_info},
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
{if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATEWAY_WORKAROUND'}},
{if_var_true, sip, {d, 'SIP'}},
{if_var_true, stun, {d, 'STUN'}},
{if_have_fun, {erl_error, format_exception, 6}, {d, 'HAVE_ERL_ERROR'}},
{src_dirs, [src,
{if_rebar3, sql},
{if_var_true, tools, tools},
@ -177,14 +189,12 @@
{sys_config, "./rel/sys.config"},
{vm_args, "./rel/vm.args"},
{overlay_vars, "vars.config"},
{extended_start_script, true},
{overlay, [{mkdir, "var/log/ejabberd"},
{mkdir, "var/lock"},
{mkdir, "var/lib/ejabberd"},
{mkdir, "etc/ejabberd"},
{copy, "rel/files/erl", "\{\{erts_vsn\}\}/bin/erl"}, % in rebar2 this prepends erts-
{overlay, [{mkdir, "logs"},
{mkdir, "database"},
{mkdir, "conf"},
{copy, "rel/files/erl", "erts-\{\{erts_vsn\}\}/bin/erl"},
{template, "ejabberdctl.template", "bin/ejabberdctl"},
{copy, "inetrc", "etc/ejabberd/inetrc"},
{copy, "inetrc", "conf/inetrc"},
{copy, "tools/captcha*.sh", "lib/ejabberd-\{\{release_version\}\}/priv/bin/"},
{copy, "rel/files/install_upgrade.escript", "bin/install_upgrade.escript"}]}
]}.
@ -193,20 +203,29 @@
{dev_mode, false},
{include_erts, true},
{include_src, true},
{generate_start_script, false},
{overlay, [{copy, "sql/*", "lib/ejabberd-\{\{release_version\}\}/priv/sql/"},
{copy, "ejabberdctl.cfg.example", "etc/ejabberd/ejabberdctl.cfg"},
{copy, "ejabberd.yml.example", "etc/ejabberd/ejabberd.yml"}]}]}]},
{copy, "ejabberdctl.cfg.example", "conf/ejabberdctl.cfg"},
{copy, "ejabberd.yml.example", "conf/ejabberd.yml"}]}]}]},
{dev, [{post_hooks, [{release, "rel/setup-dev.sh"}]},
{relx, [{debug_info, keep},
{dev_mode, true},
{include_erts, true},
{include_src, false},
{overlay, [{copy, "ejabberdctl.cfg.example", "etc/ejabberd/ejabberdctl.cfg.example"},
{copy, "ejabberd.yml.example", "etc/ejabberd/ejabberd.yml.example"},
{copy, "test/ejabberd_SUITE_data/ca.pem", "etc/ejabberd/"},
{copy, "test/ejabberd_SUITE_data/cert.pem", "etc/ejabberd/"}]}]}]},
{generate_start_script, true},
{extended_start_script, true},
{overlay, [{copy, "ejabberdctl.cfg.example", "conf/ejabberdctl.cfg.example"},
{copy, "ejabberd.yml.example", "conf/ejabberd.yml.example"},
{copy, "test/ejabberd_SUITE_data/ca.pem", "conf/"},
{copy, "test/ejabberd_SUITE_data/cert.pem", "conf/"}]}]}]},
{test, [{erl_opts, [nowarn_export_all]}]}]}.
{alias, [{relive, [{shell, "--apps ejabberd \
--config rel/relive.config \
--script rel/relive.escript \
--name ejabberd@localhost"}]}
]}.
%% Local Variables:
%% mode: erlang
%% End:

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@ -387,8 +387,8 @@ Rules = [
]}]), []},
{[plugins], IsRebar3 and (os:getenv("GITHUB_ACTIONS") == "true"),
AppendList([{coveralls, {git,
"https://github.com/RoadRunnr/coveralls-erl.git",
{branch, "feature/git-info"}}} ]), []},
"https://github.com/processone/coveralls-erl.git",
{branch, "addjsonfile"}}} ]), []},
{[overrides], [post_hook_configure], SystemDeps == false,
AppendList2(GenDepsConfigure), [], []},
{[ct_extra_params], [eunit_compile_opts], true,

BIN
rebar3

Binary file not shown.

3
rel/relive.config Normal file
View File

@ -0,0 +1,3 @@
[{mnesia, [{dir, "_build/relive/database"}]},
{ejabberd, [{config, "_build/relive/conf/ejabberd.yml"},
{log_path, "_build/relive/logs/ejabberd.log"}]}].

26
rel/relive.escript Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env escript
main(_) ->
Base = "_build/relive",
prepare(Base, "", none),
prepare(Base, "conf", {os, cmd, "rel/setup-relive.sh"}),
prepare(Base, "database", none),
prepare(Base, "logs", none),
c:erlangrc([os:cmd("echo -n $HOME")]),
ok.
prepare(BaseDir, SuffixDir, MFA) ->
Dir = filename:join(BaseDir, SuffixDir),
case file:make_dir(Dir) of
ok ->
io:format("Preparing relive dir ~s...~n", [Dir]),
case MFA of
none -> ok;
{M, F, A} -> M:F(A)
end;
{error, eexist} ->
ok;
{error, LogsError} ->
io:format("Error creating dir ~s: ~p~n", [Dir, LogsError]),
halt(1)
end.

View File

@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2013-2021, Evgeniy Khramtsov
%%% @copyright (C) 2013-2022, Evgeniy Khramtsov
%%% @doc
%%%
%%% @end
@ -88,16 +88,15 @@ Sys = [{lib_dirs, []},
end, OTPApps).
Overlay = [
{mkdir, "var/log/ejabberd"},
{mkdir, "var/lock"},
{mkdir, "var/lib/ejabberd"},
{mkdir, "etc/ejabberd"},
{mkdir, "logs"},
{mkdir, "database"},
{mkdir, "conf"},
{mkdir, "doc"},
{template, "files/erl", "\{\{erts_vsn\}\}/bin/erl"},
{template, "../ejabberdctl.template", "bin/ejabberdctl"},
{copy, "../ejabberdctl.cfg.example", "etc/ejabberd/ejabberdctl.cfg"},
{copy, "../ejabberd.yml.example", "etc/ejabberd/ejabberd.yml"},
{copy, "../inetrc", "etc/ejabberd/inetrc"},
{copy, "../ejabberdctl.cfg.example", "conf/ejabberdctl.cfg"},
{copy, "../ejabberd.yml.example", "conf/ejabberd.yml"},
{copy, "../inetrc", "conf/inetrc"},
{copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"}
],

View File

@ -2,10 +2,10 @@ echo -n "===> Preparing dev configuration files: "
PWD_DIR=`pwd`
REL_DIR=$PWD_DIR/_build/dev/rel/ejabberd/
CON_DIR=$REL_DIR/etc/ejabberd/
CON_DIR=$REL_DIR/conf/
[ -z "$REL_DIR_TEMP" ] && REL_DIR_TEMP=$REL_DIR
CON_DIR_TEMP=$REL_DIR_TEMP/etc/ejabberd/
CON_DIR_TEMP=$REL_DIR_TEMP/conf/
BIN_DIR_TEMP=$REL_DIR_TEMP/bin/
cd $CON_DIR_TEMP

30
rel/setup-relive.sh Executable file
View File

@ -0,0 +1,30 @@
PWD_DIR=`pwd`
REL_DIR=$PWD_DIR/_build/relive/
CON_DIR=$REL_DIR/conf/
[ -z "$REL_DIR_TEMP" ] && REL_DIR_TEMP=$REL_DIR
CON_DIR_TEMP=$REL_DIR_TEMP/conf/
make ejabberdctl.relive
chmod +x ejabberdctl.relive
mv ejabberdctl.relive $REL_DIR/ejabberdctl
cp inetrc $CON_DIR/
cp ejabberdctl.cfg.example $CON_DIR/ejabberdctl.cfg.example
cp ejabberd.yml.example $CON_DIR/ejabberd.yml.example
cp test/ejabberd_SUITE_data/ca.pem $CON_DIR
cp test/ejabberd_SUITE_data/cert.pem $CON_DIR
cd $CON_DIR_TEMP
sed -i "s|# certfiles:|certfiles:\n - $CON_DIR/cert.pem|g" ejabberd.yml.example
sed -i "s|certfiles:|ca_file: $CON_DIR/ca.pem\ncertfiles:|g" ejabberd.yml.example
sed -i 's|^acl:$|acl:\n admin: [user: admin]|g' ejabberd.yml.example
[ ! -f "$CON_DIR/ejabberd.yml" ] \
&& echo -n "ejabberd.yml " \
&& mv ejabberd.yml.example ejabberd.yml
sed -i "s|#' POLL|EJABBERD_BYPASS_WARNINGS=true\n\n#' POLL|g" ejabberdctl.cfg.example
[ ! -f "$CON_DIR/ejabberdctl.cfg" ] \
&& echo -n "ejabberdctl.cfg " \
&& mv ejabberdctl.cfg.example ejabberdctl.cfg

View File

@ -1,2 +1,2 @@
[{ejabberd, [{config, "etc/ejabberd/ejabberd.yml"},
{log_path, "var/log/ejabberd/ejabberd.log"}]}].
[{ejabberd, [{config, "conf/ejabberd.yml"},
{log_path, "logs/ejabberd.log"}]}].

View File

@ -4,7 +4,7 @@
## Cookie for distributed erlang
#-setcookie ejabberd
-mnesia dir \"var/lib/ejabberd\"
-mnesia dir \"database\"
## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
## (Disabled by default..use with caution!)

View File

@ -1,14 +0,0 @@
## Customize flags given to the VM: https://erlang.org/doc/man/erl.html
## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here
-boot ../releases/<%= @version %>/start_clean
-boot_var RELEASE_LIB ../lib
## Number of dirty schedulers doing IO work (file, sockets, and others)
##+SDio 5
## Increase number of concurrent ports/sockets
##+Q 65536
## Tweak GC to run more often
##-env ERL_FULLSWEEP_AFTER 10

View File

@ -1,5 +1,5 @@
--
-- ejabberd, Copyright (C) 2002-2021 ProcessOne
-- ejabberd, Copyright (C) 2002-2022 ProcessOne
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
@ -285,6 +285,7 @@ CREATE TABLE muc_room (
);
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host);
CREATE INDEX i_muc_room_host_created_at ON muc_room (host, created_at);
CREATE TABLE muc_registered (
jid text NOT NULL,
@ -330,6 +331,7 @@ CREATE TABLE muc_room_subscribers (
);
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers(host, jid);
CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers(jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers(host, room, jid);
CREATE TABLE motd (

Some files were not shown because too many files have changed in this diff Show More