24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-24 22:25:47 +02:00

Compare commits

..

No commits in common. "master" and "21.07" have entirely different histories.

441 changed files with 8574 additions and 33798 deletions

View File

@ -1 +1,4 @@
FROM ghcr.io/processone/devcontainer:latest
# Update the VARIANT arg to pick an Elixir version: latest, 1.11.4, etc.
ARG VARIANT=latest
FROM ghcr.io/processone/elixir:${VARIANT}

View File

@ -1,7 +1,48 @@
{
"name": "ejabberd",
"build": {"dockerfile": "Dockerfile"},
"extensions": ["erlang-ls.erlang-ls"],
"postCreateCommand": ".devcontainer/prepare-container.sh",
"remoteUser": "vscode"
// "dockerComposeFile": "docker-compose.yml",
"build": {
"dockerfile": "Dockerfile",
"args": {
"VARIANT": "latest" // 1.11.4
}
},
"workspaceFolder": "/workspace",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.defaultProfile.linux": "/bin/zsh",
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["pgourlain.erlang", "jakebecker.elixir-ls"],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [5222, 5280, 5269],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "sh .devcontainer/post-create.sh",
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"portsAttributes": {
"1883": {
"label": "MQTT"
},
"5222": {
"label": "XMPP C2S"
},
"5223": {
"label": "Legacy XMPP C2S"
},
"5269": {
"label": "XMPP S2S"
},
"5280": {
"label": "ejabberd HTTP"
},
"5443": {
"label": "ejabberd HTTPS"
}
}
}

View File

@ -0,0 +1,8 @@
ejabberd:
image: ejabberd/ecs
ports:
- 5222:5222
- 5223:5223
- 5269:5269
- 5280:5280
- 1883:1883

View File

@ -1,3 +0,0 @@
echo "export PATH=/workspaces/ejabberd/_build/relive:$PATH" >>$HOME/.bashrc
echo "COOKIE" >$HOME/.erlang.cookie
chmod 400 $HOME/.erlang.cookie

View File

@ -1,46 +1,3 @@
.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
/.github/container/Dockerfile

View File

@ -6,7 +6,8 @@ assignees: ''
---
Before creating a ticket, please consider if this should fit the [discussion forum](https://github.com/processone/ejabberd/discussions) better.
Before creating a ticket, please consider if this should fit the discussion forum better:
https://github.com/processone/ejabberd/discussions
## Environment

View File

@ -7,20 +7,17 @@ assignees: ''
---
Before creating a ticket, please consider if this should fit the [discussion forum](https://github.com/processone/ejabberd/discussions) better.
Before creating a ticket, please consider if this should fit the discussion forum better:
https://github.com/processone/ejabberd/discussions
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when...
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,192 +0,0 @@
#' Define default build variables
## specifc ARGs for METHOD='direct'
ARG OTP_VSN='26.2'
ARG ELIXIR_VSN='1.16.2'
## specifc ARGs for METHOD='package'
ARG ALPINE_VSN='3.19'
## general ARGs
ARG UID='9000'
ARG USER='ejabberd'
ARG HOME="opt/$USER"
ARG METHOD='direct'
ARG BUILD_DIR="/$USER"
ARG VERSION='master'
################################################################################
#' METHOD='direct' - build and install ejabberd directly from source
FROM docker.io/erlang:${OTP_VSN}-alpine AS direct
RUN apk -U add --no-cache \
autoconf \
automake \
bash \
build-base \
curl \
expat-dev \
file \
gd-dev \
git \
jpeg-dev \
libpng-dev \
libwebp-dev \
linux-pam-dev \
openssl-dev \
sqlite-dev \
yaml-dev \
zlib-dev
ARG ELIXIR_VSN
RUN wget -O - https://github.com/elixir-lang/elixir/archive/v$ELIXIR_VSN.tar.gz \
| tar -xzf -
WORKDIR elixir-$ELIXIR_VSN
RUN make install clean
RUN mix local.hex --force \
&& mix local.rebar --force
ARG BUILD_DIR
COPY / $BUILD_DIR/
WORKDIR $BUILD_DIR
RUN mv .github/container/ejabberdctl.template . \
&& ./autogen.sh \
&& ./configure --with-rebar=mix --enable-all \
&& make deps \
&& make rel
WORKDIR /rootfs
ARG VERSION
ARG HOME
RUN mkdir -p $HOME $HOME-$VERSION \
&& cp -r $BUILD_DIR/_build/prod/rel/ejabberd/* $HOME-$VERSION \
&& mv $HOME-$VERSION/conf $HOME/conf
RUN cp -p $BUILD_DIR/tools/captcha*.sh $HOME-$VERSION/lib
RUN find "$HOME-$VERSION/bin" -name 'ejabberd' -delete \
&& find "$HOME-$VERSION/releases" -name 'COOKIE' -delete
RUN wget -O "$HOME/conf/cacert.pem" 'https://curl.se/ca/cacert.pem' \
&& sed -i '/^loglevel:/a \ \
\nca_file: /opt/ejabberd/conf/cacert.pem \
\ncertfiles: \
\n - /opt/ejabberd/conf/server.pem' "$HOME/conf/ejabberd.yml"
################################################################################
#' METHOD='package' - install ejabberd from binary tarball package
FROM docker.io/alpine:${ALPINE_VSN} AS package
COPY tarballs/ejabberd-*-linux-musl-*.tar.gz /tmp/
WORKDIR /rootfs
ARG HOME
RUN home_root_dir=$(echo $HOME | sed 's|\(.*\)/.*|\1 |') \
&& mkdir -p $home_root_dir \
&& ARCH=$(uname -m | sed -e 's/x86_64/x64/;s/aarch64/arm64/') \
&& tar -xzf /tmp/ejabberd-*-linux-musl-$ARCH.tar.gz -C $home_root_dir
################################################################################
#' Prepare ejabberd for runtime
FROM ${METHOD} AS ejabberd
RUN apk -U add --no-cache \
git \
libcap \
openssl
WORKDIR /rootfs
ARG HOME
RUN mkdir -p usr/local/bin $HOME/conf $HOME/database $HOME/logs $HOME/upload
ARG BUILD_DIR
RUN if [ ! -d $HOME/.ejabberd-modules ]; \
then \
if [ -d $BUILD_DIR/.ejabberd-modules ]; \
then cp -r $BUILD_DIR/.ejabberd-modules $HOME; \
else git clone https://github.com/processone/ejabberd-contrib --depth 1 \
$HOME/.ejabberd-modules/sources/ejabberd-contrib; \
fi \
fi
RUN export PEM=$HOME/conf/server.pem \
&& openssl req -x509 \
-batch \
-nodes \
-newkey rsa:4096 \
-keyout $PEM \
-out $PEM \
-days 3650 \
-subj "/CN=localhost"
RUN home_root_dir=$(echo $HOME | sed 's|\(.*\)/.*|\1 |') \
&& setcap 'cap_net_bind_service=+ep' $(find $home_root_dir -name beam.smp) \
&& echo -e \
"#!/bin/sh \
\n[ -z \$ERLANG_NODE_ARG ] && export ERLANG_NODE_ARG=ejabberd@localhost \
\nexport CONFIG_DIR=/$HOME/conf \
\nexport LOGS_DIR=/$HOME/logs \
\nexport SPOOL_DIR=/$HOME/database \
\nexec /$(find $home_root_dir -name ejabberdctl) \"\$@\"" \
> usr/local/bin/ejabberdctl \
&& chmod +x usr/local/bin/* \
&& scanelf --needed --nobanner --format '%n#p' --recursive $home_root_dir \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e $home_root_dir" $1 " ]") == 0 { next } { print "so:" $1 }' \
| sed -e "s|so:libc.so|so:libc.musl-$(uname -m).so.1|" \
> /tmp/runDeps
ARG UID
RUN chown -R $UID:$UID $HOME
################################################################################
#' METHOD='direct' - Remove erlang/OTP & rebar3
FROM docker.io/erlang:${OTP_VSN}-alpine AS runtime-direct
RUN apk del .erlang-rundeps \
&& rm -f $(which rebar3) \
&& find /usr -type d -name 'erlang' -exec rm -rf {} + \
&& find /usr -type l -exec test ! -e {} \; -delete
################################################################################
#' METHOD='package' - define runtime base image
FROM docker.io/alpine:${ALPINE_VSN} AS runtime-package
################################################################################
#' Update alpine, finalize runtime environment
FROM runtime-${METHOD} AS runtime
COPY --from=ejabberd /tmp/runDeps /tmp/runDeps
RUN apk -U upgrade --available --no-cache \
&& apk add --no-cache \
$(cat /tmp/runDeps) \
so:libcap.so.2 \
so:libtdsodbc.so.0 \
tini \
&& ln -fs /usr/lib/libtdsodbc.so.0 /usr/lib/libtdsodbc.so
ARG USER
ARG UID
ARG HOME
RUN addgroup $USER -g $UID \
&& adduser -s /sbin/nologin -D -u $UID -h /$HOME -G $USER $USER
################################################################################
#' Build together production image
FROM scratch AS prod
ARG USER
ARG HOME
COPY --from=runtime / /
COPY --from=ejabberd /rootfs /
HEALTHCHECK \
--interval=1m \
--timeout=5s \
--start-period=5s \
--retries=10 \
CMD ejabberdctl status
WORKDIR /$HOME
USER $USER
VOLUME ["/$HOME"]
EXPOSE 1883 4369-4399 5210 5222 5269 5280 5443
ENTRYPOINT ["/sbin/tini","--","ejabberdctl"]
CMD ["foreground"]

View File

@ -1,294 +0,0 @@
@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

View File

@ -1,466 +0,0 @@
#!/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}}"
EPMD="{{epmd}}"
IEX="{{iexpath}}"
COOKIE_FILE="$HOME"/.erlang.cookie
[ -n "$ERLANG_COOKIE" ] && [ ! -f "$COOKIE_FILE" ] && echo "$ERLANG_COOKIE" > "$COOKIE_FILE" && chmod 400 "$COOKIE_FILE"
# 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}}"}"
: "${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"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${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" $ERLANG_OPTS -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
if [ "$(echo "$INET_DIST_INTERFACE2" | grep -o "," | wc -l)" -eq 7 ] ; then
INET_DIST_INTERFACE2="$INET_DIST_INTERFACE2 -proto_dist inet6_tcp"
fi
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="\
$(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")\
$EJABBERD_OPTS"
[ -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_current_user) exec "$@" ;;
as_install_user) su -s /bin/sh -c 'exec "$0" "$@"' "$INSTALLUSER" -- "$@" ;;
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 exit and detach this shell from ejabberd, press:"
echo " control+g and then q"
echo ""
#vt100 echo "Please do NOT use control+c in this debug shell !"
#vt100 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 and detach this shell from ejabberd, press:"
echo " control+g and then q"
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
}
check_etop_result()
{
result=$?
if [ $result -eq 1 ] ; then
echo ""
echo "It seems there was some problem running 'ejabberdctl etop'."
echo "Is the error message something like this?"
echo " Failed to load module 'etop' because it cannot be found..."
echo "Then probably ejabberd was compiled with development tools disabled."
echo "To use 'etop', recompile ejabberd with: ./configure --enable-tools"
echo ""
exit $result
fi
}
check_iex_result()
{
result=$?
if [ $result -eq 127 ] ; then
echo ""
echo "It seems there was some problem finding 'iex' binary from Elixir."
echo "Probably ejabberd was compiled with Rebar3 and Elixir disabled, like:"
echo " ./configure"
echo "which is equivalent to:"
echo " ./configure --with-rebar=rebar3 --disable-elixir"
echo "To use 'iex', recompile ejabberd enabling Elixir or using Mix:"
echo " ./configure --enable-elixir"
echo " ./configure --with-rebar=mix"
echo ""
exit $result
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() {
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.*\([0-9][0-9]\).*|\1|g')"
if [ $ERTSVERSION -lt 11 ] ; then # otp 23.0 includes erts 11.0
# Erlang/OTP lower than 23, which doesn's support dynamic node code
N=1
PF=$(( $$ % 97 ))
while
case $# in
0) NN="${PF}-${N}-${ERLANG_NODE}"
;;
1) NN="${PF}-${N}-${1}-${ERLANG_NODE}"
;;
2) NN="${PF}-${N}-${1}@${2}"
;;
esac
N=$(( N + 1 + ( $$ % 5 ) ))
"$EPMD" -names 2>/dev/null | grep -q " ${NN%@*} "
do :; done
echo $NN
else
# Erlang/OTP 23 or higher: use native dynamic node code
# https://www.erlang.org/patches/otp-23.0#OTP-13812
if [ "$ERLANG_NODE" != "${ERLANG_NODE%.*}" ]; then
echo "undefined@${ERLANG_NODE#*@}"
else
echo "undefined"
fi
fi
}
# 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#* ; }
HEAD2=${HEAD#\! *}
echo ":> ejabberdctl $HEAD2"
$0 $HEAD2
ctlstatus=$?
if [ $ctlstatus -ne 0 ] ; then
if [ "$HEAD" != "$HEAD2" ] ; then
echo ":> FAILURE in command '$HEAD2' !!! Ignoring result"
else
echo ":> FAILURE in command '$HEAD' !!! Stopping ejabberd..."
$0 halt > /dev/null
exit $ctlstatus
fi
fi
[ "$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 \
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
-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 -remsh "$ERLANG_NODE" \
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
-s etop \
-output text
check_etop_result
;;
iexdebug)
debugwarning
set_dist_client
exec_iex "$(uid debug)" --remsh "$ERLANG_NODE"
check_iex_result
;;
iexlive)
livewarning
exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS"
check_iex_result
;;
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 'net_kernel:connect_node('"'$PEER'"')' \
-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 \
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
-s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
result=$?
case $result in
2|3) help;;
*) :;;
esac
exit $result
;;
esac

View File

@ -25,8 +25,15 @@ jobs:
strategy:
fail-fast: false
matrix:
otp: ['20.0', '25', '26', '27']
runs-on: ubuntu-20.04
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 }}
services:
redis:
image: redis
@ -35,52 +42,29 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Test shell scripts
if: matrix.otp == '26'
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
uses: erlef/setup-beam@v1
- name: Get previous Erlang/OTP
uses: ErlGang/setup-erlang@master
if: matrix.otp != 24.0
with:
otp-version: ${{ matrix.otp }}
- name: Get a compatible Rebar3
if: matrix.otp < 24
run: |
rm rebar3
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
chmod +x rebar3
- name: Install MS SQL Server
run: |
docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=ejabberd_Test1" \
-v $(pwd)/test/docker/db/mssql/initdb/initdb_mssql.sql:/initdb_mssql.sql:ro \
-v $(pwd)/sql/mssql.sql:/mssql.sql:ro \
-v $(pwd)/sql/mssql.new.sql:/mssql.new.sql:ro \
-p 1433:1433 --name ejabberd-mssql "mcr.microsoft.com/mssql/server:2019-latest"
sleep 10
- name: Prepare databases
run: |
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -i /initdb_mssql.sql
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -d ejabberd_test -i /mssql.sql
sudo systemctl start mysql.service
sudo systemctl start postgresql.service
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
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 DATABASE ejabberd_test;"
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
@ -93,105 +77,97 @@ 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: Remove syntax_tools from release
run: sed -i 's|, syntax_tools||g' src/ejabberd.app.src.script
- name: Prepare rebar
id: 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
- name: Cache rebar
uses: actions/cache@v4
- name: Cache rebar2
if: matrix.rebar == 2
uses: actions/cache@v2
with:
path: |
~/.cache/rebar3/
key: ${{matrix.otp}}-${{hashFiles('rebar.config')}}
deps/
dialyzer/
ebin/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
- name: Download test logs
if: matrix.otp == '26' && 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: Cache rebar3
if: matrix.rebar == 3
uses: actions/cache@v2
with:
path: ~/.cache/rebar3/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=./rebar3 \
[[ ${{ matrix.rebar }} = 2 ]] && REBAR=rebar || REBAR=`which rebar3`
./configure --with-rebar=$REBAR \
--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
- 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)
sed -i -e 's/ct:pal/ct:log/' test/suite.erl
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
- run: make test
- name: Check results
if: always() && (steps.ct.outcome != 'skipped' || steps.ct2.outcome != 'skipped')
id: ctresults
if: always()
run: |
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
[[ -d _build ]] && ln -s _build/test/logs/ logs \
&& ln `find _build/ -name "*dialyzer_warnings"` \
logs/dialyzer.log \
|| ln dialyzer/error.log logs/dialyzer.log
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: 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: Send to coveralls
if: matrix.otp == '26'
if: matrix.otp == 24.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DIAGNOSTIC=1 ./rebar3 as test coveralls send
rebar3 as test coveralls send
curl -v -k https://coveralls.io/webhook \
--header "Content-Type: application/json" \
--data '{"repo_name":"$GITHUB_REPOSITORY",
@ -199,110 +175,64 @@ jobs:
"payload":{"build_num":$GITHUB_RUN_ID,
"status":"done"}}'
- name: Upload test logs
if: always() && steps.ct.outcome == 'failure' && github.repository == 'processone/ejabberd'
uses: peaceiris/actions-gh-pages@v4
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
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'
fetch-depth: 150
- name: Get last git tag
run: |
CTRUN=`ls -la _build/test/logs/last | sed 's|.*-> ||'`
echo "::notice::View CT results: https://processone.github.io/ecil/logs/$CTRUN/"
- name: Check for changes to trigger schema upgrade test
uses: dorny/paths-filter@v3
id: filter
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:
filters: |
sql:
- 'sql/**'
- 'src/mod_admin_update_sql.erl'
- name: Prepare for schema upgrade test
id: prepupgradetest
if: ${{ steps.filter.outputs.sql == 'true' }}
otp-version: ${{ matrix.otp }}
- name: Get a compatible Rebar3
run: |
[[ -d logs ]] && rm -rf logs
[[ -d _build/test/logs ]] && rm -rf _build/test/logs || true
sed -i 's|update_sql, false|update_sql, true|g' test/suite.erl
- name: Run DB tests on upgraded schema (mssql, mysql, pgsql)
run: CT_BACKENDS=mssql,mysql,pgsql make test
if: always() && steps.prepupgradetest.outcome != 'skipped'
id: ctupgradedschema
- name: Check results
if: always() && steps.ctupgradedschema.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.ctupgradedschema.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 '{}' ';'
- name: Prepare new schema
run: |
[[ -d logs ]] && rm -rf logs
[[ -d _build/test/logs ]] && rm -rf _build/test/logs || true
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -Q "drop database [ejabberd_test];"
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -Q "drop login [ejabberd_test];"
mysql -u root -proot -e "DROP DATABASE ejabberd_test;"
sudo -u postgres psql -c "DROP DATABASE ejabberd_test;"
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -i /initdb_mssql.sql
docker exec ejabberd-mssql /opt/mssql-tools/bin/sqlcmd -U SA -P ejabberd_Test1 -S localhost -d ejabberd_test -i /mssql.new.sql
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
mysql -u root -proot -e "GRANT ALL ON ejabberd_test.*
TO 'ejabberd_test'@'localhost';"
sudo -u postgres psql -c "CREATE DATABASE ejabberd_test;"
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
- name: Run DB tests on new schema (mssql, mysql, pgsql)
run: CT_BACKENDS=mssql,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 '{}' ';'
- name: Upload CT logs
if: failure()
uses: actions/upload-artifact@v4
wget https://github.com/erlang/rebar3/releases/download/3.15.2/rebar3 \
&& chmod +x rebar3
- name: Cache Rebar3
uses: actions/cache@v2
with:
name: ejabberd-ct-logs-${{matrix.otp}}
#
# 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: _build/test/logs
retention-days: 14
path: ~/.cache/rebar3/
key: ${{matrix.otp}}-${{matrix.rebar}}-${{hashFiles('rebar.config')}}
- name: Prepare libraries
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
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

View File

@ -1,123 +0,0 @@
name: Container
on:
schedule:
- cron: '22 2 */6 * *' # every 6 days to avoid gha cache being evicted
push:
paths-ignore:
- '.devcontainer/**'
- 'examples/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
container:
name: Container
runs-on: ubuntu-22.04
permissions:
packages: write
steps:
- name: Check out repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache build directory
uses: actions/cache@v4
with:
path: ~/build/
key: ${{runner.os}}-ctr-ct-ng-1.26.0
- name: Get erlang/OTP version for bootstrapping
run: |
echo "OTP_VSN=$(awk '/^otp_vsn=/ {{gsub(/[^0-9.rc-]/, ""); print}}' tools/make-binaries)" >> $GITHUB_ENV
echo "ELIXIR_VSN=$(awk '/^elixir_vsn=/ {{gsub(/[^0-9.]/, ""); print}}' tools/make-binaries)" >> $GITHUB_ENV
- 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 erlang/OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VSN }}
elixir-version: ${{ env.ELIXIR_VSN }}
version-type: strict
- 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: Build musl-libc based binary archives
run: |
sed -i "s|targets='.*'|targets='x86_64-linux-musl aarch64-linux-musl'|" tools/make-binaries
mv .github/container/ejabberdctl.template .
CHECK_DEPS=false tools/make-binaries
- name: Collect packages
run: |
mkdir tarballs
mv ejabberd-*.tar.gz tarballs
- name: Checkout ejabberd-contrib
uses: actions/checkout@v4
with:
repository: processone/ejabberd-contrib
path: .ejabberd-modules/sources/ejabberd-contrib
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get git describe
id: gitdescribe
run: echo "ver=$(git describe --tags)" >> $GITHUB_OUTPUT
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
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@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
build-args: |
METHOD=package
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 }}

View File

@ -1,84 +0,0 @@
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-22.04
steps:
- name: Cache build directory
uses: actions/cache@v4
with:
path: ~/build/
key: ${{runner.os}}-ct-ng-1.26.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/.local/share/gem/ruby/*/bin >> $GITHUB_PATH
- name: Check out repository code
uses: actions/checkout@v4
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@v4
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-22.04
if: github.ref_type == 'tag'
steps:
- name: Download packages
uses: actions/download-artifact@v4
with:
name: ejabberd-packages
- name: Draft Release
uses: softprops/action-gh-release@v2
with:
draft: true
files: ejabberd-packages/*

View File

@ -1,433 +0,0 @@
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: ['20', '25', '26', '27']
rebar: ['rebar', 'rebar3']
exclude:
- otp: '27'
rebar: 'rebar'
runs-on: ubuntu-22.04
container:
image: erlang:${{ matrix.otp }}
steps:
- uses: actions/checkout@v4
- name: Get compatible Rebar binaries
if: matrix.otp < 24
run: |
rm rebar
rm rebar3
wget https://github.com/processone/ejabberd/raw/21.12/rebar
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
chmod +x rebar
chmod +x rebar3
- name: Prepare libraries
run: |
apt-get -qq update
apt-get purge -y libgd3 nginx
apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=./${{ matrix.rebar }} \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-elixir \
--disable-tools \
--disable-odbc
make
- run: make xref
- name: Prepare rel (rebar2)
if: matrix.rebar == 'rebar'
run: |
mkdir -p _build/prod && ln -s `pwd`/rel/ _build/prod/rel
mkdir -p _build/dev && ln -s `pwd`/rel/ _build/dev/rel
- 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: Run install
run: |
make install
/tmp/ejabberd/sbin/ejabberdctl start \
&& /tmp/ejabberd/sbin/ejabberdctl started
/tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass
/tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log
/tmp/ejabberd/sbin/ejabberdctl stop \
&& /tmp/ejabberd/sbin/ejabberdctl stopped
- name: View logs
run: |
echo "===> Registered:"
cat registered.log
echo "===> Prod:"
cat _build/prod/rel/ejabberd/logs/*
echo "===> Dev:"
cat _build/dev/rel/ejabberd/logs/*
echo "===> Install:"
cat /tmp/ejabberd/var/log/ejabberd/*
- name: Check logs
run: |
grep -q '^user1$' registered.log
grep -q '^user2$' registered.log
grep -q '^user3$' 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/rel/ -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/rel/ -empty -name error.log)
grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
test $(find /tmp/ejabberd/var/log/ejabberd/ -empty -name error.log)
- name: View logs failures
if: always()
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
cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log
cat /tmp/ejabberd/var/log/ejabberd/error.log
rebar3-elixir:
name: Rebar3+Elixir
strategy:
fail-fast: false
matrix:
otp: ['23.0', '25', '26', '27']
elixir: ['1.13', '1.15', '1.16', '1.17']
exclude:
- otp: '23.0'
elixir: '1.15'
- otp: '23.0'
elixir: '1.16'
- otp: '23.0'
elixir: '1.17'
- otp: '26'
elixir: '1.13'
- otp: '27'
elixir: '1.13'
- otp: '27'
elixir: '1.15'
- otp: '27'
elixir: '1.16'
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Get specific Erlang/OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- name: Get compatible Rebar binaries
if: matrix.otp < 24
run: |
rm rebar
rm rebar3
wget https://github.com/processone/ejabberd/raw/21.12/rebar
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
chmod +x rebar
chmod +x rebar3
- 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: Enable ModPresenceDemo and an Elixir dependency
run: |
sed -i "s|^modules:|modules:\n 'ModPresenceDemo': {}|g" ejabberd.yml.example
cat ejabberd.yml.example
sed -i 's|^{deps, \[\(.*\)|{deps, [{decimal, ".*", {git, "https://github.com/ericmj/decimal", {branch, "main"}}},\n \1|g' rebar.config
cat rebar.config
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=./rebar3 \
--prefix=/tmp/ejabberd \
--enable-all \
--disable-odbc
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: Run install
run: |
make install
/tmp/ejabberd/sbin/ejabberdctl start \
&& /tmp/ejabberd/sbin/ejabberdctl started
/tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass
/tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log
/tmp/ejabberd/sbin/ejabberdctl stop \
&& /tmp/ejabberd/sbin/ejabberdctl stopped
- name: View logs
if: always()
run: |
echo "===> Registered:"
cat registered.log
echo "===> Prod:"
cat _build/prod/rel/ejabberd/logs/*
echo "===> Dev:"
cat _build/dev/rel/ejabberd/logs/*
echo "===> Install:"
cat /tmp/ejabberd/var/log/ejabberd/*
- name: Check logs
if: always()
run: |
grep -q '^user1$' registered.log
grep -q '^user2$' registered.log
grep -q '^user3$' registered.log
grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log
grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log
grep -q 'module Presence Demo' _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
grep -q 'module Presence Demo' _build/dev/rel/ejabberd/logs/ejabberd.log
test $(find _build/dev/ -empty -name error.log)
grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
grep -q 'module Presence Demo' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
test $(find /tmp/ejabberd/var/log/ejabberd/ -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
cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log
cat /tmp/ejabberd/var/log/ejabberd/error.log
mix:
name: Mix
strategy:
fail-fast: false
matrix:
otp: ['23.0', '25', '26', '27']
elixir: ['1.13', '1.15', '1.16', '1.17']
exclude:
- otp: '23.0'
elixir: '1.15'
- otp: '23.0'
elixir: '1.16'
- otp: '23.0'
elixir: '1.17'
- otp: '26'
elixir: '1.13'
- otp: '27'
elixir: '1.13'
- otp: '27'
elixir: '1.15'
- otp: '27'
elixir: '1.16'
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- 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: Enable ModPresenceDemo and an Elixir dependency
run: |
sed -i "s|^modules:|modules:\n 'ModPresenceDemo': {}|g" ejabberd.yml.example
cat ejabberd.yml.example
sed -i 's|^{deps, \(.*\)|{deps, \1\n {decimal, ".*", {git, "https://github.com/ericmj/decimal", {branch, "main"}}}, |g' rebar.config
cat rebar.config
- name: Unlock Jose dependency on older Erlang
if: matrix.otp < 24
run: |
mix deps.unlock jose
- name: Compile
run: |
./autogen.sh
./configure --with-rebar=mix \
--prefix=/tmp/ejabberd \
--enable-all
make
- run: make xref
- run: make dialyzer
- run: make edoc
- 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: Run install
run: |
make install
/tmp/ejabberd/sbin/ejabberdctl start \
&& /tmp/ejabberd/sbin/ejabberdctl started
/tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass
/tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log
/tmp/ejabberd/sbin/ejabberdctl stop \
&& /tmp/ejabberd/sbin/ejabberdctl stopped
- name: View logs
if: always()
run: |
echo "===> Registered:"
cat registered.log
echo "===> Prod:"
cat _build/prod/rel/ejabberd/logs/*
echo "===> Dev:"
cat _build/dev/rel/ejabberd/logs/*
echo "===> Install:"
cat /tmp/ejabberd/var/log/ejabberd/*
- name: Check logs
if: always()
run: |
grep -q '^user1$' registered.log
grep -q '^user2$' registered.log
grep -q '^user3$' registered.log
grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log
grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log
grep -q 'module Presence Demo' _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
grep -q 'module Presence Demo' _build/dev/rel/ejabberd/logs/ejabberd.log
test $(find _build/dev/ -empty -name error.log)
grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
grep -q 'module Presence Demo' /tmp/ejabberd/var/log/ejabberd/ejabberd.log
test $(find /tmp/ejabberd/var/log/ejabberd/ -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
cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log
cat /tmp/ejabberd/var/log/ejabberd/error.log

12
.gitignore vendored
View File

@ -5,10 +5,8 @@
\#*#
.#*
.edts
.tool-versions
*.dump
/Makefile
/doc
/config.log
/config.status
/config/releases.exs
@ -17,7 +15,6 @@
/*.cache
/deps/
/.deps-update/
/.ejabberd-modules/
/ebin/
/ejabberd.init
/ejabberd.service
@ -34,16 +31,9 @@
/priv/bin/captcha*sh
/priv/sql
/rel/ejabberd
/recompile.log
/_build
/database/
/.rebar
/rebar.lock
/log/
Mnesia.nonode@nohost/
/TAGS
/tags
# Binaries created with tools/make-{binaries,installers,packages}:
/ejabberd_*.deb
/ejabberd-*.rpm
/ejabberd-*.run
/ejabberd-*.tar.gz

View File

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

View File

@ -1,5 +0,0 @@
{
"recommendations": [
"erlang-ls.erlang-ls"
]
}

49
.vscode/launch.json vendored
View File

@ -1,49 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Relive",
"type": "erlang",
"request": "launch",
"runinterminal": [
".vscode/relive.sh"
],
"projectnode": "ejabberd@localhost",
"cookie": "COOKIE",
"timeout": 300,
"cwd": "${workspaceRoot}"
},
{
"name": "Relive (alternate)",
"type": "erlang",
"request": "launch",
"runinterminal": [
"./rebar3", "shell",
"--apps", "ejabberd",
"--config", "rel/relive.config",
"--script", "rel/relive.escript",
"--name", "ejabberd@localhost",
"--setcookie", "COOKIE"
],
"projectnode": "ejabberd@localhost",
"cookie": "COOKIE",
"timeout": 300,
"cwd": "${workspaceRoot}"
},
{
"name": "Attach",
"type": "erlang",
"request": "attach",
"runinterminal": [
"./rebar3", "shell",
"--sname", "clean@localhost",
"--setcookie", "COOKIE",
"--start-clean"
],
"projectnode": "ejabberd@localhost",
"cookie": "COOKIE",
"timeout": 300,
"cwd": "${workspaceRoot}"
}
]
}

6
.vscode/relive.sh vendored
View File

@ -1,6 +0,0 @@
[ ! -f Makefile ] \
&& ./autogen.sh \
&& ./configure --with-rebar=./rebar3 \
&& make deps
make relive

13
.vscode/settings.json vendored
View File

@ -1,13 +0,0 @@
{
"editor.tabSize": 8,
"remote.portsAttributes": {
"1883": {"label": "MQTT", "onAutoForward": "silent"},
"4369": {"label": "EPMD", "onAutoForward": "silent"},
"5222": {"label": "XMPP C2S", "onAutoForward": "silent"},
"5223": {"label": "XMPP C2S (legacy)", "onAutoForward": "silent"},
"5269": {"label": "XMPP S2S", "onAutoForward": "silent"},
"5280": {"label": "HTTP", "onAutoForward": "silent"},
"5443": {"label": "HTTPS", "onAutoForward": "silent"},
"7777": {"label": "XMPP SOCKS5 (proxy65)", "onAutoForward": "silent"}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at the email address: conduct AT process-one.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at conduct@process-one.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

View File

@ -1,122 +0,0 @@
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/install/source/
Requirements
------------
To compile ejabberd you need:
- GNU Make
- GCC
- Libexpat ≥ 1.95
- Libyaml ≥ 0.1.4
- Erlang/OTP ≥ 20.0
- 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, for Elixir support. It is recommended Elixir 1.13.4 or higher
and Erlang/OTP 23.0 or higher.
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
make prod
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
```

View File

@ -1,457 +0,0 @@
[![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=ejabberd&sort=semver&logo=docker)](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
`ejabberd` Container Image
==========================
[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 image available in
[ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd),
built using the files in `.github/container/`.
This image is based in Alpine 3.19, includes Erlang/OTP 26.2 and Elixir 1.16.1.
Alternatively, there is also the `ecs` container image available in
[docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/),
built using the
[docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs)
repository.
Check the [differences between `ejabberd` and `ecs` images](https://github.com/processone/docker-ejabberd/blob/master/ecs/HUB-README.md#alternative-image-in-github).
If you are using a Windows operating system, check the tutorials mentioned in
[ejabberd Docs > Docker Image](https://docs.ejabberd.im/admin/install/container/#ejabberd-container-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/install/next-steps/#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 this option:
```yaml
captcha_cmd: /opt/ejabberd-22.04/lib/captcha.sh
```
Finally, reload the configuration file or restart the container:
```bash
docker exec ejabberd ejabberdctl reload_config
```
If the CAPTCHA image is not visible, there may be a problem generating it
(the ejabberd log file may show some error message);
or the image URL may not be correctly detected by ejabberd,
in that case you can set the correct URL manually, for example:
```yaml
captcha_url: https://localhost:5443/captcha
```
For more details about CAPTCHA options, please check the
[CAPTCHA](https://docs.ejabberd.im/admin/configuration/basic/#captcha)
documentation section.
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 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.
By default failure of any of commands executed that way would
abort start, this can be disabled by prefixing commands with `!`
Example usage (or check the [full example](#customized-example)):
```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`:
```sh
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:
```sh
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
```
Build 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
### Direct build
Build ejabberd Community Server container image from ejabberd master git repository:
```bash
docker buildx build \
-t personal/ejabberd \
-f .github/container/Dockerfile \
.
```
### Podman build
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
- to start with command `live`, you may want to 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
podman run --name eja1 -it -e EJABBERD_BYPASS_WARNINGS=true -p 5222:5222 localhost/ejabberd live
```
### Package build for `arm64`
By default, `.github/container/Dockerfile` builds this container by directly compiling ejabberd,
it is a fast and direct method.
However, a problem with QEMU prevents building the container in QEMU using Erlang/OTP 25
for the `arm64` architecture.
Providing `--build-arg METHOD=package` is an alternate method to build the container
used by the Github Actions workflow that provides `amd64` and `arm64` container images.
It first builds an ejabberd binary package, and later installs it in the image.
That method avoids using QEMU, so it can build `arm64` container images, but is extremely
slow the first time it's used, and consequently not recommended for general use.
In this case, to build the ejabberd container image for arm64 architecture:
```bash
docker buildx build \
--build-arg METHOD=package \
--platform linux/arm64 \
-t personal/ejabberd:$VERSION \
-f .github/container/Dockerfile \
.
```
Composer Examples
-----------------
### Minimal Example
This is the barely minimal file to get a usable ejabberd.
Store it as `docker-compose.yml`:
```yaml
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
```
Create and start the container with the command:
```bash
docker-compose up
```
### Customized Example
This example shows the usage of several customizations:
it uses a local configuration file,
stores the mnesia database in a local path,
registers an account when it's created,
and checks the number of registered accounts every time it's started.
Download or copy the ejabberd configuration file:
```bash
wget https://raw.githubusercontent.com/processone/ejabberd/master/ejabberd.yml.example
mv ejabberd.yml.example ejabberd.yml
```
Create the database directory and allow the container access to it:
```bash
mkdir database
sudo chown 9000:9000 database
```
Now write this `docker-compose.yml` file:
```yaml
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
- CTL_ON_CREATE=register admin localhost asd
- CTL_ON_START=registered_users localhost ;
status
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
volumes:
- ./ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro
- ./database:/opt/ejabberd/database
```
### Clustering Example
In this example, the main container is created first.
Once it is fully started and healthy, a second container is created,
and once ejabberd is started in it, it joins the first one.
An account is registered in the first node when created (and
we ignore errors that can happen when doing that - for example
whenn account already exists),
and it should exist in the second node after join.
Notice that in this example the main container does not have access
to the exterior; the replica exports the ports and can be accessed.
```yaml
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
- ERLANG_NODE_ARG=ejabberd@main
- ERLANG_COOKIE=dummycookie123
- CTL_ON_CREATE=! register admin localhost asd
replica:
image: ghcr.io/processone/ejabberd
container_name: replica
depends_on:
main:
condition: service_healthy
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
environment:
- ERLANG_NODE_ARG=ejabberd@replica
- ERLANG_COOKIE=dummycookie123
- CTL_ON_CREATE=join_cluster ejabberd@main
- CTL_ON_START=registered_users localhost ;
status
```

View File

@ -3,21 +3,21 @@
We'd love for you to contribute to our source code and to make ejabberd even better than it is
today! Here are the guidelines we'd like you to follow:
* [Code of Conduct](#code-of-conduct)
* [Questions and Problems](#questions-bugs-features)
* [Issues and Bugs](#found-an-issue-or-bug)
* [Feature Requests](#missing-a-feature)
* [Issue Submission Guidelines](#issue-submission-guidelines)
* [Pull Request Submission Guidelines](#pull-request-submission-guidelines)
* [Signing the CLA](#signing-the-contributor-license-agreement-cla)
* [Code of Conduct](#coc)
* [Questions and Problems](#question)
* [Issues and Bugs](#issue)
* [Feature Requests](#feature)
* [Issue Submission Guidelines](#submit)
* [Pull Request Submission Guidelines](#submit-pr)
* [Signing the CLA](#cla)
## Code of Conduct
## <a name="coc"></a> Code of Conduct
Help us keep ejabberd community open-minded and inclusive. Please read and follow our [Code of Conduct][coc].
## Questions, Bugs, Features
## <a name="requests"></a> Questions, Bugs, Features
### Got a Question or Problem?
### <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports
and feature requests. You've got much better chances of getting your question answered on dedicated
@ -34,16 +34,16 @@ To save your and our time, we will systematically close all issues that are requ
support and redirect people to the section you are reading right now.
Other channels for support are:
- ejabberd XMPP room: [ejabberd@conference.process-one.net][muc]
- [ejabberd XMPP room logs][logs]
- [ejabberd Mailing List][list]
- [ejabberd XMPP room][muc]: ejabberd@conference.process-one.net
- [ejabberd XMPP room logs][logs]
### Found an Issue or Bug?
### <a name="issue"></a> Found an Issue or Bug?
If you find a bug in the source code, you can help us by submitting an issue to our
[GitHub Repository][github]. Even better, you can submit a Pull Request with a fix.
### Missing a Feature?
### <a name="feature"></a> Missing a Feature?
You can request a new feature by submitting an issue to our [GitHub Repository][github-issues].
@ -52,9 +52,9 @@ If you would like to implement a new feature then consider what kind of change i
* **Major Changes** that you wish to contribute to the project should be discussed first in an
[GitHub issue][github-issues] that clearly outlines the changes and benefits of the feature.
* **Small Changes** can directly be crafted and submitted to the [GitHub Repository][github]
as a Pull Request. See the section about [Pull Request Submission Guidelines](#pull-request-submission-guidelines).
as a Pull Request. See the section about [Pull Request Submission Guidelines](#submit-pr).
## Issue Submission Guidelines
## <a name="submit"></a> Issue Submission Guidelines
Before you submit your issue search the archive, maybe your question was already answered.
@ -64,7 +64,7 @@ the effort we can spend fixing issues and adding new features, by not reporting
The "[new issue][github-new-issue]" form contains a number of prompts that you should fill out to
make it easier to understand and categorize the issue.
## Pull Request Submission Guidelines
## <a name="submit-pr"></a> Pull Request Submission Guidelines
By submitting a pull request for a code or doc contribution, you need to have the right
to grant your contribution's copyright license to ProcessOne. Please check [ProcessOne CLA][cla]
@ -123,7 +123,7 @@ restarted.
That's it! Thank you for your contribution!
## Signing the Contributor License Agreement (CLA)
## <a name="cla"></a> Signing the Contributor License Agreement (CLA)
Upon submitting a Pull Request, we will ask you to sign our CLA if you haven't done
so before. It's a quick process, we promise, and you will be able to do it all online
@ -147,3 +147,4 @@ gives us the option to relicense the code with a more permissive license in the
[doc-repo]: https://github.com/processone/docs.ejabberd.im
[developer-setup]: https://docs.ejabberd.im/developer/
[cla]: https://www.process-one.net/resources/ejabberd-cla.pdf
[license]: https://github.com/processone/ejabberd/blob/master/COPYING

View File

@ -1,22 +1,8 @@
#.
#' definitions
#
ESCRIPT = @ESCRIPT@
REBAR = @rebar@
REBAR = @ESCRIPT@ @rebar@
MIX = @rebar@
AWK = @AWK@
INSTALL = @INSTALL@
MKDIR_P = @MKDIR_P@
SED = @SED@
ERL = @ERL@
EPMD = @EPMD@
IEX = @IEX@
INSTALLUSER=@INSTALLUSER@
INSTALLGROUP=@INSTALLGROUP@
REBAR_ENABLE_ELIXIR = @elixir@
prefix = @prefix@
exec_prefix = @exec_prefix@
@ -24,27 +10,27 @@ exec_prefix = @exec_prefix@
DESTDIR =
# /etc/ejabberd/
ETCDIR = @sysconfdir@/ejabberd
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd
# /bin/
BINDIR = @bindir@
BINDIR = $(DESTDIR)@bindir@
# /sbin/
SBINDIR = @sbindir@
SBINDIR = $(DESTDIR)@sbindir@
# /lib/
LIBDIR = @libdir@
LIBDIR = $(DESTDIR)@libdir@
# /lib/ejabberd/
EJABBERDDIR = @libdir@/ejabberd
EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd
# /share/doc/ejabberd
PACKAGE_TARNAME = @PACKAGE_TARNAME@
datarootdir = @datarootdir@
DOCDIR = @docdir@
DOCDIR = $(DESTDIR)@docdir@
# /share/doc/man/man5
MANDIR = @mandir@/man5
MANDIR = $(DESTDIR)@mandir@/man5
# /usr/lib/ejabberd/ebin/
BEAMDIR = $(EJABBERDDIR)/ebin
@ -80,15 +66,18 @@ SQLDIR = $(PRIVDIR)/sql
LUADIR = $(PRIVDIR)/lua
# /var/lib/ejabberd/
SPOOLDIR = @localstatedir@/lib/ejabberd
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
# /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
# /var/log/ejabberd/
LOGDIR = @localstatedir@/log/ejabberd
#.
#' install user
#
LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd
INSTALLUSER=@INSTALLUSER@
# if no user was enabled, don't set privileges or ownership
ifeq ($(INSTALLUSER),)
O_USER=
@ -103,25 +92,19 @@ else
CHOWN_OUTPUT=&1
INIT_USER=$(INSTALLUSER)
endif
# if no group was enabled, don't set privileges or ownership
INSTALLGROUP=@INSTALLGROUP@
ifneq ($(INSTALLGROUP),)
G_USER=-g $(INSTALLGROUP)
endif
#.
#' rebar / rebar3 / mix
#
ifeq "$(notdir $(MIX))" "mix"
REBAR_VER:=6
REBAR_VER_318:=0
ifeq "$(MIX)" "mix"
IS_REBAR:=6
else
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)}')
IS_REBAR:=$(shell expr `$(REBAR) --version | awk -F '[ .]' '/rebar / {print $$2}'`)
endif
ifeq "$(REBAR_VER)" "6"
ifeq "$(IS_REBAR)" "6"
REBAR=$(MIX)
SKIPDEPS=
LISTDEPS=deps.tree
@ -130,52 +113,23 @@ ifeq "$(REBAR_VER)" "6"
DEPSBASE=_build
DEPSDIR=$(DEPSBASE)/dev/lib
GET_DEPS= deps.get
CONFIGURE_DEPS=(cd deps/eimp; ./configure)
CONFIGURE_DEPS=
EBINDIR=$(DEPSDIR)/ejabberd/ebin
XREFOPTIONS=graph
EDOCPRE=MIX_ENV=edoc
EDOCTASK=docs --proglang erlang
CLEANARG=--deps
ELIXIR_LIBDIR_RAW=$(shell elixir -e "IO.puts(:filename.dirname(:code.lib_dir(:elixir)))" -e ":erlang.halt")
ELIXIR_LIBDIR=":$(ELIXIR_LIBDIR_RAW)"
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
REL_LIB_DIR = _build/dev/rel/ejabberd/lib
COPY_REL_TARGET = dev
GET_DEPS_TRANSLATIONS=MIX_ENV=translations $(REBAR) $(GET_DEPS)
DEPSDIR_TRANSLATIONS=deps
else
ifeq ($(REBAR_ENABLE_ELIXIR),true)
ELIXIR_LIBDIR_RAW=$(shell elixir -e "IO.puts(:filename.dirname(:code.lib_dir(:elixir)))" -e ":erlang.halt")
ELIXIR_LIBDIR=":$(ELIXIR_LIBDIR_RAW)"
EXPLICIT_ELIXIR_COMPILE=MIX_ENV=default mix compile.elixir
EXPLICIT_ELIXIR_COMPILE_DEV=MIX_ENV=dev mix compile.elixir
PREPARE_ELIXIR_SCRIPTS=$(MKDIR_P) rel/overlays; cp $(ELIXIR_LIBDIR_RAW)/../bin/iex rel/overlays/; cp $(ELIXIR_LIBDIR_RAW)/../bin/elixir rel/overlays/; sed -i 's|ERTS_BIN=$$|ERTS_BIN=$$SCRIPT_PATH/../../erts-{{erts_vsn}}/bin/|' rel/overlays/elixir
endif
ifeq "$(REBAR_VER)" "3"
ifeq "$(IS_REBAR)" "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) as dev release
RELIVECMD=$(REBAR) as dev relive
REL_LIB_DIR = _build/dev/rel/ejabberd/lib
COPY_REL_TARGET = dev
GET_DEPS_TRANSLATIONS=$(REBAR) as translations $(GET_DEPS)
DEPSDIR_TRANSLATIONS=_build/translations/lib
REBARDEV=REBAR_PROFILE=dev $(REBAR) release
else
SKIPDEPS=skip_deps=true
LISTDEPS=-q list-deps
@ -186,47 +140,35 @@ 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"
REL_LIB_DIR = rel/ejabberd/lib
COPY_REL_TARGET = rel
endif
endif
#.
#' main targets
#
all: scripts deps src
all: deps src
deps: $(DEPSDIR)/.got
$(DEPSDIR)/.got:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
$(MKDIR_P) $(DEPSDIR)
mkdir -p $(DEPSDIR)
$(REBAR) $(GET_DEPS) && :> $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
$(DEPSDIR)/.built: $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
$(REBAR) compile && :> $(DEPSDIR)/.built
src: $(DEPSDIR)/.built
$(REBAR) $(SKIPDEPS) compile
$(EXPLICIT_ELIXIR_COMPILE)
update:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
$(REBAR) $(UPDATEDEPS) && :> $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
xref: all
$(REBAR) $(SKIPDEPS) xref $(XREFOPTIONS)
$(REBAR) $(SKIPDEPS) xref
hooks: all
tools/hook_deps.sh $(EBINDIR)
@ -235,45 +177,11 @@ options: all
tools/opt_types.sh ejabberd_option $(EBINDIR)
translations:
$(GET_DEPS_TRANSLATIONS)
tools/prepare-tr.sh $(DEPSDIR_TRANSLATIONS)
tools/prepare-tr.sh $(DEPSDIR)
doap:
tools/generate-doap.sh
#.
#' edoc
#
edoc: edoc_files edoc_compile
$(EDOCPRE) $(REBAR) $(EDOCTASK)
edoc_compile: deps
$(EDOCPRE) $(REBAR) compile
edoc_files: _build/edoc/docs.md _build/edoc/logo.png
_build/edoc/docs.md: edoc_compile
echo "For much more detailed and complete ejabberd documentation, " \
"go to the [ejabberd Docs](https://docs.ejabberd.im/) site." \
> _build/edoc/docs.md
_build/edoc/logo.png: edoc_compile
wget https://docs.ejabberd.im/assets/img/footer_logo_e.png -O _build/edoc/logo.png
#.
#' format / indent
#
format:
tools/rebar3-format.sh $(REBAR)
indent:
tools/emacs-indent.sh
#.
#' copy-files
#
edoc:
$(ERL) -noinput +B -eval \
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1))
@ -286,7 +194,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,$(DESTDIR)$(call TO_DEST_SINGLE,$(subst /, ,$(path)))))
TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(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))))
@ -327,7 +235,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 $< $@
@ -341,15 +249,7 @@ $(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 $< $@
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))
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)
.PHONY: $(call TO_DEST,$(DEPS_FILES) $(MAIN_DIRS) $(DEPS_DIRS))
@ -360,251 +260,152 @@ copy-files:
copy-files-sub: copy-files-sub2
#.
#' copy-files-rel
#
copy-files-rel: $(COPY_REL_TARGET)
install: copy-files
#
# Libraries
(cd $(REL_LIB_DIR) && find . -follow -type f ! -executable -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;)
# 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" \
-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*{{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
#
# *.so:
(cd $(REL_LIB_DIR) && find . -follow -type f -executable -name *.so -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;)
# 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
#
# Executable files
(cd $(REL_LIB_DIR) && find . -follow -type f -executable ! -name *.so -exec $(INSTALL) -vDm 550 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;)
#.
#' uninstall-librel
#
uninstall-librel:
(cd $(REL_LIB_DIR) && find . -follow -type f -exec rm -fv -v $(DESTDIR)$(LIBDIR)/{} \;)
(cd $(REL_LIB_DIR) && find . -follow -depth -type d -exec rm -dv -v $(DESTDIR)$(LIBDIR)/{} \;)
#.
#' relive
#
relive:
$(EXPLICIT_ELIXIR_COMPILE_DEV)
$(RELIVECMD)
relivelibdir=$(shell pwd)/$(DEPSDIR)
relivedir=$(shell pwd)/_build/relive
CONFIG_DIR = ${relivedir}/conf
SPOOL_DIR = ${relivedir}/database
LOGS_DIR = ${relivedir}/logs
#.
#' scripts
#
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}}*${BINDIR}*g" \
-e "s*{{libdir}}*${relivelibdir}${ELIXIR_LIBDIR}*g" \
-e "s*ERTS_VSN*# ERTS_VSN*g" \
-e "s*{{iexpath}}*${IEX}*g" \
-e "s*{{erl}}*${ERL}*g" \
-e "s*{{epmd}}*${EPMD}*g" ejabberdctl.template \
> ejabberdctl.relive
ejabberd.init:
# Init script
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" \
-e "s*@installuser@*$(INIT_USER)*g" ejabberd.init.template \
> ejabberd.init
chmod 755 ejabberd.init
ejabberd.service:
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" \
-e "s*@installuser@*$(INIT_USER)*g" ejabberd.service.template \
#
# Service script
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*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}${ELIXIR_LIBDIR}*g" \
-e "s*ERTS_VSN*# ERTS_VSN*g" \
-e "s*{{iexpath}}*${IEX}*g" \
-e "s*{{erl}}*${ERL}*g" \
-e "s*{{epmd}}*${EPMD}*g" ejabberdctl.template \
> ejabberdctl.example
scripts: ejabberd.init ejabberd.service ejabberdctl.example
#.
#' install
#
install: copy-files install-main
install-rel: copy-files-rel install-main
install-main:
#
# 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) $(DESTDIR)$(SPOOLDIR)
$(CHOWN_COMMAND) -R $(INSTALLUSER) $(DESTDIR)$(SPOOLDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(DESTDIR)$(SPOOLDIR)
$(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)
#
# Log directory
$(INSTALL) -d -m 750 $(O_USER) $(DESTDIR)$(LOGDIR)
$(CHOWN_COMMAND) -R $(INSTALLUSER) $(DESTDIR)$(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(DESTDIR)$(LOGDIR)
$(INSTALL) -d -m 750 $(O_USER) $(LOGDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(LOGDIR)
#
# Documentation
$(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL) -d $(DESTDIR)$(DOCDIR)
$(INSTALL) -d $(MANDIR)
$(INSTALL) -d $(DOCDIR)
[ -f man/ejabberd.yml.5 ] \
&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(DESTDIR)$(MANDIR) \
&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(MANDIR) \
|| echo "Man page not included in sources"
$(INSTALL) -m 644 COPYING $(DESTDIR)$(DOCDIR)
#.
#' uninstall
#
$(INSTALL) -m 644 COPYING $(DOCDIR)
uninstall: uninstall-binary
uninstall-rel: uninstall-binary uninstall-librel
uninstall-binary:
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)
rm -f $(DESTDIR)$(MANDIR)/ejabberd.yml.5
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)
uninstall-all: uninstall-binary
rm -rf $(DESTDIR)$(ETCDIR)
rm -rf $(DESTDIR)$(EJABBERDDIR)
rm -rf $(DESTDIR)$(SPOOLDIR)
rm -rf $(DESTDIR)$(LOGDIR)
#.
#' clean
#
rm -rf $(ETCDIR)
rm -rf $(EJABBERDDIR)
rm -rf $(SPOOLDIR)
rm -rf $(CTLLOCKDIR)
rm -rf $(LOGDIR)
clean:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
rm -rf test/*.beam
rm -f rebar.lock
rm -f ejabberdctl.example ejabberd.init ejabberd.service
$(REBAR) clean $(CLEANARG)
$(REBAR) clean
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
#.
#' releases
#
rel: prod
prod:
$(PREPARE_ELIXIR_SCRIPTS)
rel:
$(REBARREL)
DEV_CONFIG = _build/dev/rel/ejabberd/conf/ejabberd.yml
DEV_CONFIG = _build/dev/rel/ejabberd/etc/ejabberd/ejabberd.yml
dev $(DEV_CONFIG):
$(PREPARE_ELIXIR_SCRIPTS)
$(REBARDEV)
#.
#' tags
#
TAGS:
etags src/*.erl
#.
#' makefile
#
etags *.erl
Makefile: Makefile.in
#.
#' dialyzer
#
ifeq "$(REBAR_VER)" "6" # Mix
dialyzer:
MIX_ENV=test $(REBAR) dialyzer
else
ifeq "$(REBAR_VER)" "3" # Rebar3
ifeq "$(IS_REBAR)" "3"
dialyzer:
$(REBAR) dialyzer
else # Rebar2
else
deps := $(wildcard $(DEPSDIR)/*/ebin)
dialyzer/erlang.plt:
@$(MKDIR_P) dialyzer
@mkdir -p dialyzer
@dialyzer --build_plt --output_plt dialyzer/erlang.plt \
-o dialyzer/erlang.log --apps kernel stdlib sasl crypto \
public_key ssl mnesia inets odbc compiler erts \
@ -612,13 +413,13 @@ dialyzer/erlang.plt:
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
dialyzer/deps.plt:
@$(MKDIR_P) dialyzer
@mkdir -p dialyzer
@dialyzer --build_plt --output_plt dialyzer/deps.plt \
-o dialyzer/deps.log $(deps); \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
dialyzer/ejabberd.plt:
@$(MKDIR_P) dialyzer
@mkdir -p dialyzer
@dialyzer --build_plt --output_plt dialyzer/ejabberd.plt \
-o dialyzer/ejabberd.log ebin; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
@ -640,11 +441,6 @@ dialyzer: erlang_plt deps_plt ejabberd_plt
--get_warnings -o dialyzer/error.log ebin; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
endif
endif
#.
#' test
#
test:
@echo "************************** NOTICE ***************************************"
@ -653,53 +449,32 @@ test:
@cd priv && ln -sf ../sql
$(REBAR) $(SKIPDEPS) ct
#.
#' phony
#
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean prod rel \
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
install uninstall uninstall-binary uninstall-all translations deps test \
all dev doap help install-rel relive scripts uninstall-rel update \
erlang_plt deps_plt ejabberd_plt xref hooks options format indent
#.
#' help
#
quicktest erlang_plt deps_plt ejabberd_plt xref hooks options
help:
@echo ""
@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 " [all] Compile dependencies and ejabberd"
@echo " src Compile ejabberd"
@echo " deps Get dependencies"
@echo " update Update dependencies' source code"
@echo " clean Clean binary files"
@echo " distclean Clean completely the development files"
@echo ""
@echo " install Install ejabberd to /usr/local"
@echo " install-rel Install ejabberd to /usr/local (using release)"
@echo " uninstall Uninstall ejabberd (buggy)"
@echo " uninstall-rel Uninstall ejabberd (using release)"
@echo " uninstall-all Uninstall also configuration, logs, mnesia... (buggy)"
@echo ""
@echo " prod Build a production release"
@echo " rel Build a production release"
@echo " dev Build a development release"
@echo " relive Start a live ejabberd in _build/relive/"
@echo ""
@echo " doap Generate DOAP file"
@echo " edoc Generate EDoc documentation [mix]"
@echo " edoc Generate edoc documentation (unused)"
@echo " options Generate ejabberd_option.erl"
@echo " translations Extract translation files"
@echo " TAGS Generate tags file for text editors"
@echo ""
@echo " format Format source code using rebar3_format [rebar3]"
@echo " indent Indent source code using erlang-mode [emacs]"
@echo " translations Extract translation files (requires --enable-tools)"
@echo " tags Generate tags file for text editors"
@echo ""
@echo " dialyzer Run Dialyzer static analyzer"
@echo " hooks Run hooks validator"
@echo " test Run Common Tests suite [rebar3]"
@echo " xref Run cross reference analysis [rebar3]"
#.
#'
# vim: foldmarker=#',#. foldmethod=marker:
@echo " test Run Common Tests suite"
@echo " xref Run cross reference analysis"

288
README.md
View File

@ -1,132 +1,208 @@
ejabberd Community Edition
==========================
<p align="center">
<img src="https://www.process-one.net/wp-content/uploads/2022/05/ejabberd-logo-rounded-index.png">
</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://formulae.brew.sh/formula/ejabberd" alt="homebrew version">
<img src="https://img.shields.io/homebrew/v/ejabberd" /></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=ecs&logo=docker" /></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=ejabberd&sort=semver&logo=docker" /></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" /></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>
<a href="https://docs.ejabberd.im/" alt="ejabberd Docs">
<img src="https://img.shields.io/github/v/tag/processone/docs.ejabberd.im?sort=semver&logo=&label=docs&logoWidth=0" /></a>
</p>
[![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.
[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 the list of [supported protocols in ProcessOne][xeps]
and [XMPP.org][xmppej].
Installation
Key Features
------------
There are several ways to install ejabberd:
- **Cross-platform**
ejabberd runs under Microsoft Windows and Unix-derived systems such as
Linux, FreeBSD and NetBSD.
- Source code: compile yourself, see [COMPILE](COMPILE.md)
- Installers: [ProcessOne Download][p1download] and [GitHub Releases][releases] for releases, [GitHub Actions](https://github.com/processone/ejabberd/actions/workflows/installers.yml) for master branch (run/deb/rpm for x64 and arm64)
- `ecs` container image: [Docker Hub][hubecs] and [Github Packages][packagesecs], see [ecs README][docker-ecs-readme] (for x64)
- `ejabberd` container image: [Github Packages][packages] for releases and master branch, see [CONTAINER](CONTAINER.md) (for x64 and arm64)
- Using your [Operating System package][osp]
- Using the [Homebrew][homebrew] package manager
- **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.
Documentation
-------------
Additional Features
-------------------
Please check the [ejabberd Docs][docs] website.
Moreover, ejabberd comes with a wide range of other state-of-the-art features:
When compiling from source code, you can get some help with:
- **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:
./configure --help
make help
Once ejabberd is installed, try:
ejabberdctl help
man ejabberd.yml
Development
-----------
Bug reports and features are tracked using [GitHub Issues][issues],
please check [CONTRIBUTING](CONTRIBUTING.md) for details.
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.
Translations can be improved online [using Weblate][weblate]
or in your local machine as explained in [Localization][localization].
To start ejabberd in development mode from the repository directory, you can
type a command like:
Documentation for developers is available in [ejabberd docs: Developers][docs-dev].
There are nightly builds of ejabberd, both for `master` branch and for Pull Requests:
- Installers: go to [GitHub Actions: Installers](https://github.com/processone/ejabberd/actions/workflows/installers.yml), open the most recent commit, on the bottom of that commit page, download the `ejabberd-packages.zip` artifact.
- `ejabberd` container image: go to [ejabberd Github Packages][packages]
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].
EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -pa deps/elixir/lib/*/ebin/ -s ejabberd
Community
---------
Translation
-----------
There are several places to get in touch with other ejabberd developers and administrators:
Using any gettext editor, you can improve the translation files found in
`priv/msgs/*.po`, and then submit your changes.
- ejabberd XMPP chatroom: [ejabberd@conference.process-one.net][muc]
- [GitHub Discussions][discussions]
- [Stack Overflow][stackoverflow]
Alternatively, a simple way to improve translations is using our Weblate project:
https://hosted.weblate.org/projects/ejabberd/ejabberd-po/
License
-------
ejabberd is released under the GNU General Public License v2 (see [COPYING](COPYING)),
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/
[homebrew]: https://docs.ejabberd.im/admin/install/homebrew/
[hubecs]: https://hub.docker.com/r/ejabberd/ecs/
[im]: https://ejabberd.im/
[issues]: https://github.com/processone/ejabberd/issues
[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/install/os-package/
[p1contact]: https://www.process-one.net/en/company/contact/
[p1download]: https://www.process-one.net/en/ejabberd/downloads/
[p1home]: https://www.process-one.net/en/ejabberd/
[packages]: https://github.com/processone/ejabberd/pkgs/container/ejabberd
[packagesecs]: https://github.com/processone/docker-ejabberd/pkgs/container/ecs
[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/
[xmppej]: https://xmpp.org/software/servers/ejabberd/
Links
-----
- Documentation: https://docs.ejabberd.im
- Community site: https://www.ejabberd.im
- ejabberd commercial offering and support: https://www.process-one.net/en/ejabberd

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 dependencies. Useful if dependencies might change prior to compilation when configure is run."}
{desc, "A rebar plugin to allow explicitly running ./configure on depdendencies. Useful if dependencies might change prior to compilation when configure is run."}
]),
{ok, rebar_state:add_provider(State, Provider)}.

View File

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

View File

@ -1,18 +1,16 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 24.02` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
REQUIRE_ERLANG_MIN="9.0.5 (Erlang/OTP 20.0)"
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])
REQUIRE_ERLANG_MIN="8.3 (Erlang/OTP 19.3)"
REQUIRE_ERLANG_MAX="100.0.0 (No Max)"
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_AWK
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_PROG_SED
if test "x$GCC" = "xyes"; then
@ -21,7 +19,8 @@ fi
# Checks Erlang runtime and compiler
AC_ARG_WITH(erlang,
AS_HELP_STRING([--with-erlang=dir],[search for erlang in dir]),
AC_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
@ -30,42 +29,19 @@ fi
])
AC_ARG_WITH(rebar,
AS_HELP_STRING([--with-rebar=bin],[use as build tool the rebar/rebar3/mix binary specified]),
AC_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="rebar3"
rebar="rebar"
else
rebar="$with_rebar"
fi
], [rebar="unconfigured"])
], [rebar="rebar"])
AC_PATH_TOOL(ERL, erl, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(ERLC, erlc, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(EPMD, epmd, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(REBAR, rebar, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(REBAR3, rebar3, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(ELIXIR, elixir, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(IEX, iex, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(MIX, mix, , [${extra_erl_path}$PATH])
if test "$rebar" = unconfigured; then
if test "x$ELIXIR" = "x" -o "x$IEX" = "x" -o "x$MIX" = "x"; then
if test "x$REBAR3" = "x"; then
rebar="rebar3"
else
rebar=$REBAR3
fi
else
rebar=$MIX
fi
fi
if test "x$rebar" = "xrebar" -a "x$REBAR" = "x" ; then
rebar="./rebar"
fi
if test "x$rebar" = "xrebar3" -a "x$REBAR3" = "x" ; then
rebar="./rebar3"
fi
AC_ERLANG_NEED_ERL
AC_ERLANG_NEED_ERLC
@ -94,15 +70,15 @@ AC_CONFIG_FILES([Makefile
vars.config])
AC_ARG_ENABLE(all,
[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)])],
[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)])],
[case "${enableval}" in
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 ;;
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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
esac],[])
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug],[enable debug information (default: yes)])],
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
@ -110,7 +86,7 @@ AC_ARG_ENABLE(debug,
esac],[if test "x$debug" = "x"; then debug=true; fi])
AC_ARG_ENABLE(elixir,
[AS_HELP_STRING([--enable-elixir],[enable Elixir support in Rebar3 (default: no)])],
[AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])],
[case "${enableval}" in
yes) elixir=true ;;
no) elixir=false ;;
@ -118,7 +94,8 @@ AC_ARG_ENABLE(elixir,
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
AC_ARG_ENABLE(erlang-version-check,
[AS_HELP_STRING([--enable-erlang-version-check],[Check Erlang/OTP version (default: yes)])])
[AC_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])
@ -129,7 +106,7 @@ case "$enable_erlang_version_check" in
esac
AC_ARG_ENABLE(full_xml,
[AS_HELP_STRING([--enable-full-xml],[use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
[AC_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 ;;
@ -138,7 +115,7 @@ esac],[full_xml=false])
ENABLEGROUP=""
AC_ARG_ENABLE(group,
[AS_HELP_STRING([--enable-group[[=GROUP]]], [specify the group of the account defined in --enable-user (default: no)])],
[AS_HELP_STRING([--enable-group[[[[=GROUP]]]]], [allow this system group to start ejabberd (default: no)])],
[case "${enableval}" in
yes) ENABLEGROUP=`groups |head -n 1` ;;
no) ENABLEGROUP="" ;;
@ -151,7 +128,7 @@ if test "$ENABLEGROUP" != ""; then
fi
AC_ARG_ENABLE(latest_deps,
[AS_HELP_STRING([--enable-latest-deps],[makes rebar use latest commits for dependencies instead of tagged versions (default: no)])],
[AC_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 ;;
@ -159,7 +136,7 @@ AC_ARG_ENABLE(latest_deps,
esac],[if test "x$latest_deps" = "x"; then latest_deps=false; fi])
AC_ARG_ENABLE(lua,
[AS_HELP_STRING([--enable-lua],[enable Lua support, to import from Prosody (default: no)])],
[AC_HELP_STRING([--enable-lua], [enable Lua support, to import from Prosody (default: no)])],
[case "${enableval}" in
yes) lua=true ;;
no) lua=false ;;
@ -167,15 +144,15 @@ AC_ARG_ENABLE(lua,
esac],[if test "x$lua" = "x"; then lua=false; fi])
AC_ARG_ENABLE(mssql,
[AS_HELP_STRING([--enable-mssql],[use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
[AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
[case "${enableval}" in
yes) mssql=true ;;
no) mssql=false ;;
yes) db_type=mssql; mssql=true ;;
no) db_type=generic; mssql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[if test "x$mssql" = "x"; then mssql=false; fi])
esac],[db_type=generic])
AC_ARG_ENABLE(mysql,
[AS_HELP_STRING([--enable-mysql],[enable MySQL support (default: no)])],
[AC_HELP_STRING([--enable-mysql], [enable MySQL support (default: no)])],
[case "${enableval}" in
yes) mysql=true ;;
no) mysql=false ;;
@ -183,7 +160,7 @@ AC_ARG_ENABLE(mysql,
esac],[if test "x$mysql" = "x"; then mysql=false; fi])
AC_ARG_ENABLE(new_sql_schema,
[AS_HELP_STRING([--enable-new-sql-schema],[use new SQL schema by default (default: no)])],
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
[case "${enableval}" in
yes) new_sql_schema=true ;;
no) new_sql_schema=false ;;
@ -191,7 +168,7 @@ AC_ARG_ENABLE(new_sql_schema,
esac],[new_sql_schema=false])
AC_ARG_ENABLE(odbc,
[AS_HELP_STRING([--enable-odbc],[enable pure ODBC support (default: no)])],
[AC_HELP_STRING([--enable-odbc], [enable pure ODBC support (default: no)])],
[case "${enableval}" in
yes) odbc=true ;;
no) odbc=false ;;
@ -199,7 +176,7 @@ AC_ARG_ENABLE(odbc,
esac],[if test "x$odbc" = "x"; then odbc=false; fi])
AC_ARG_ENABLE(pam,
[AS_HELP_STRING([--enable-pam],[enable PAM support (default: no)])],
[AC_HELP_STRING([--enable-pam], [enable PAM support (default: no)])],
[case "${enableval}" in
yes) pam=true ;;
no) pam=false ;;
@ -207,7 +184,7 @@ AC_ARG_ENABLE(pam,
esac],[if test "x$pam" = "x"; then pam=false; fi])
AC_ARG_ENABLE(pgsql,
[AS_HELP_STRING([--enable-pgsql],[enable PostgreSQL support (default: no)])],
[AC_HELP_STRING([--enable-pgsql], [enable PostgreSQL support (default: no)])],
[case "${enableval}" in
yes) pgsql=true ;;
no) pgsql=false ;;
@ -215,7 +192,7 @@ AC_ARG_ENABLE(pgsql,
esac],[if test "x$pgsql" = "x"; then pgsql=false; fi])
AC_ARG_ENABLE(redis,
[AS_HELP_STRING([--enable-redis],[enable Redis support (default: no)])],
[AC_HELP_STRING([--enable-redis], [enable Redis support (default: no)])],
[case "${enableval}" in
yes) redis=true ;;
no) redis=false ;;
@ -223,7 +200,7 @@ AC_ARG_ENABLE(redis,
esac],[if test "x$redis" = "x"; then redis=false; fi])
AC_ARG_ENABLE(roster_gateway_workaround,
[AS_HELP_STRING([--enable-roster-gateway-workaround],[turn on workaround for processing gateway subscriptions (default: no)])],
[AC_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 ;;
@ -231,7 +208,7 @@ AC_ARG_ENABLE(roster_gateway_workaround,
esac],[roster_gateway_workaround=false])
AC_ARG_ENABLE(sip,
[AS_HELP_STRING([--enable-sip],[enable SIP support (default: no)])],
[AC_HELP_STRING([--enable-sip], [enable SIP support (default: no)])],
[case "${enableval}" in
yes) sip=true ;;
no) sip=false ;;
@ -239,7 +216,7 @@ AC_ARG_ENABLE(sip,
esac],[if test "x$sip" = "x"; then sip=false; fi])
AC_ARG_ENABLE(sqlite,
[AS_HELP_STRING([--enable-sqlite],[enable SQLite support (default: no)])],
[AC_HELP_STRING([--enable-sqlite], [enable SQLite support (default: no)])],
[case "${enableval}" in
yes) sqlite=true ;;
no) sqlite=false ;;
@ -247,7 +224,7 @@ AC_ARG_ENABLE(sqlite,
esac],[if test "x$sqlite" = "x"; then sqlite=false; fi])
AC_ARG_ENABLE(stun,
[AS_HELP_STRING([--enable-stun],[enable STUN/TURN support (default: yes)])],
[AC_HELP_STRING([--enable-stun], [enable STUN/TURN support (default: yes)])],
[case "${enableval}" in
yes) stun=true ;;
no) stun=false ;;
@ -255,7 +232,7 @@ AC_ARG_ENABLE(stun,
esac],[if test "x$stun" = "x"; then stun=true; fi])
AC_ARG_ENABLE(system_deps,
[AS_HELP_STRING([--enable-system-deps],[makes rebar use locally installed dependencies instead of downloading them (default: no)])],
[AC_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 ;;
@ -263,7 +240,7 @@ AC_ARG_ENABLE(system_deps,
esac],[if test "x$system_deps" = "x"; then system_deps=false; fi])
AC_ARG_ENABLE(tools,
[AS_HELP_STRING([--enable-tools],[include debugging/development tools (default: no)])],
[AC_HELP_STRING([--enable-tools], [build development tools (default: no)])],
[case "${enableval}" in
yes) tools=true ;;
no) tools=false ;;
@ -272,7 +249,7 @@ esac],[if test "x$tools" = "x"; then tools=false; fi])
ENABLEUSER=""
AC_ARG_ENABLE(user,
[AS_HELP_STRING([--enable-user[[=USER]]], [allow this system user to start ejabberd (default: no)])],
[AS_HELP_STRING([--enable-user[[[[=USER]]]]], [allow this system user to start ejabberd (default: no)])],
[case "${enableval}" in
yes) ENABLEUSER=`whoami` ;;
no) ENABLEUSER="" ;;
@ -285,7 +262,7 @@ if test "$ENABLEUSER" != ""; then
fi
AC_ARG_ENABLE(zlib,
[AS_HELP_STRING([--enable-zlib],[enable Stream Compression (XEP-0138) using zlib (default: yes)])],
[AC_HELP_STRING([--enable-zlib], [enable Stream Compression (XEP-0138) using zlib (default: yes)])],
[case "${enableval}" in
yes) zlib=true ;;
no) zlib=false ;;
@ -306,13 +283,11 @@ case "`uname`" in
;;
esac
AC_MSG_RESULT([build tool to use (change using --with-rebar): $rebar])
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)
@ -333,28 +308,3 @@ AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
AC_OUTPUT
AS_CASE([$rebar],
[*rebar3], [
deps=""
AS_IF([test "x$stun" = "xfalse"], [deps="stun,$deps"])
AS_IF([test "x$sqlite" = "xfalse"], [deps="sqlite3,$deps"])
AS_IF([test "x$pgsql" = "xfalse"], [deps="p1_pgsql,$deps"])
AS_IF([test "x$mysql" = "xfalse"], [deps="p1_mysql,$deps"])
AS_IF([test "x$zlib" = "xfalse"], [deps="ezlib,$deps"])
AS_IF([test "x$sip" = "xfalse"], [deps="esip,$deps"])
AS_IF([test "x$redis" = "xfalse"], [deps="eredis,$deps"])
AS_IF([test "x$pam" = "xfalse"], [deps="epam,$deps"])
AS_IF([test "x$deps" = "x"], [],
[AC_MSG_NOTICE([unlocking disabled rebar3 dependencies: $deps])
$rebar unlock "$deps"])
deps=""
ERLANG_VERSION=m4_esyscmd([erl -noinput -noshell -eval 'erlang:display(list_to_integer(erlang:system_info(otp_release))), halt().'])
AS_IF([test "$ERLANG_VERSION" -lt "21"], [deps="luerl,$deps"])
AS_IF([test "$ERLANG_VERSION" -lt "22"], [deps="lager,$deps"])
AS_IF([test "$ERLANG_VERSION" -le "23"], [deps="jose,$deps"])
AS_IF([test "$ERLANG_VERSION" -ge "27"], [deps="jiffy,$deps"])
AS_IF([test "x$deps" = "x"], [],
[AC_MSG_NOTICE([unlocking rebar3 dependencies for old Erlang/OTP: $deps])
$rebar unlock "$deps"])
])

View File

@ -1,795 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://usefulinc.com/ns/doap#"
xmlns:xmpp="https://linkmauve.fr/ns/xmpp-doap#"
xmlns:schema="https://schema.org/">
<Project>
<name>ejabberd</name>
<shortdesc>XMPP Server with MQTT Broker and SIP Service</shortdesc>
<description>Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP Server, MQTT Broker, SIP Service)</description>
<created>2002-11-16</created>
<os>BSD</os>
<os>Linux</os>
<os>macOS</os>
<os>Windows</os>
<programming-langauge>Erlang</programming-langauge>
<programming-langauge>C</programming-langauge>
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-jabber"/>
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-server"/>
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-xmpp"/>
<homepage rdf:resource="https://www.ejabberd.im"/>
<download-page rdf:resource="https://www.process-one.net/en/ejabberd/downloads/"/>
<download-mirror rdf:resource="https://github.com/processone/ejabberd/tags"/>
<license rdf:resource="https://raw.githubusercontent.com/processone/ejabberd/master/COPYING"/>
<schema:logo rdf:resource="https://docs.ejabberd.im/assets/img/footer_logo_e@2x.png"/>
<bug-database rdf:resource="https://github.com/processone/ejabberd/issues"/>
<support-forum rdf:resource="xmpp:ejabberd@conference.process-one.net?join"/>
<repository>
<GitRepository>
<location rdf:resource="https://github.com/processone/ejabberd.git"/>
<browse rdf:resource="https://github.com/processone/ejabberd"/>
</GitRepository>
</repository>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc3261"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc3920"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc3921"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc5766"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc5802"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6120"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6121"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6122"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6455"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7395"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7590"/>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0004.html"/>
<xmpp:version>2.9</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0012.html"/>
<xmpp:version>2.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_last</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0013.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since>16.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0016.html"/>
<xmpp:version>1.6</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_privacy</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0022.html"/>
<xmpp:version>1.4</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0023.html"/>
<xmpp:version>1.3</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0030.html"/>
<xmpp:version>2.4</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_disco</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0033.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since>15.04</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_multicast</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0039.html"/>
<xmpp:version>0.6.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_stats</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0045.html"/>
<xmpp:version>1.25</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_muc</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0049.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_private</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0050.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_adhoc</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0054.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_vcard</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0055.html"/>
<xmpp:version>1.3</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_vcard</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0059.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0060.html"/>
<xmpp:version>1.14</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_pubsub</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0065.html"/>
<xmpp:version>1.8</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_proxy65</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0077.html"/>
<xmpp:version>2.4</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_register</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0078.html"/>
<xmpp:version>2.5</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_legacy_auth</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0085.html"/>
<xmpp:version>2.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_client_state</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0086.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0092.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_version</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0106.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0114.html"/>
<xmpp:version>1.6</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_service</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0115.html"/>
<xmpp:version>1.5</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_caps</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0124.html"/>
<xmpp:version>1.11</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_bosh</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0133.html"/>
<xmpp:version>1.3.0</xmpp:version>
<xmpp:since>13.10</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_configure</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0138.html"/>
<xmpp:version>2.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_c2s</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0153.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_vcard</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0156.html"/>
<xmpp:version>1.4.0</xmpp:version>
<xmpp:since>22.05</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_host_meta</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0157.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_disco</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0158.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_captcha</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0160.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_pubsub</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0170.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0175.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_auth_anonymous</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0176.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_stun</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0185.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_s2s_dialback</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0191.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_blocking</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0198.html"/>
<xmpp:version>1.5.2</xmpp:version>
<xmpp:since>14.05</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_stream_mgmt</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0199.html"/>
<xmpp:version>2.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_ping</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0202.html"/>
<xmpp:version>2.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_time</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0203.html"/>
<xmpp:version>2.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0205.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0206.html"/>
<xmpp:version>1.4</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_bosh</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0212.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0215.html"/>
<xmpp:version>0.7</xmpp:version>
<xmpp:since>20.04</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_stun_disco</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0216.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0220.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_s2s, mod_s2s_dialback</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0227.html"/>
<xmpp:version>1.1</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_piefxis</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0231.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>ejabberd_captcha</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0237.html"/>
<xmpp:version>1.3</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_roster</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0243.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0248.html"/>
<xmpp:version>0.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_pubsub</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_muc</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0270.html"/>
<xmpp:version>1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0279.html"/>
<xmpp:version>0.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_sic</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0280.html"/>
<xmpp:version>0.13.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_carboncopy</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0313.html"/>
<xmpp:version>0.6.1</xmpp:version>
<xmpp:since>15.06</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0317.html"/>
<xmpp:version>0.1</xmpp:version>
<xmpp:since>21.12</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_muc_room, conversejs/prosody compatible</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0328.html"/>
<xmpp:version>0.1</xmpp:version>
<xmpp:since>19.09</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_jidprep</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0334.html"/>
<xmpp:version>0.2</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mam, mod_muc_log, mod_offline</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0352.html"/>
<xmpp:version>0.1</xmpp:version>
<xmpp:since>14.12</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_client_state</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0355.html"/>
<xmpp:version>0.4.1</xmpp:version>
<xmpp:since>16.09</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_delegation</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0356.html"/>
<xmpp:version>0.2.1</xmpp:version>
<xmpp:since>16.09</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_privilege</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0357.html"/>
<xmpp:version>0.2</xmpp:version>
<xmpp:since>17.08</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_push</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
<xmpp:version>0.5.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0363.html"/>
<xmpp:version>0.2</xmpp:version>
<xmpp:since>15.10</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_http_upload</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0368.html"/>
<xmpp:version>1.1.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0369.html"/>
<xmpp:version>0.14.1</xmpp:version>
<xmpp:since>16.03</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mix</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0386.html"/>
<xmpp:version>0.3.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0388.html"/>
<xmpp:version>0.4.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0398.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>18.03</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_avatar</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0402.html"/>
<xmpp:version>1.1.3</xmpp:version>
<xmpp:since>23.10</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_private</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0405.html"/>
<xmpp:version>0.3.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mix_pam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0410.html"/>
<xmpp:version>1.1.0</xmpp:version>
<xmpp:since>18.12</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_muc_room</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0411.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>18.12</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_private</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0421.html"/>
<xmpp:version>0.1.0</xmpp:version>
<xmpp:since>23.10</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_muc_occupantid</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
<xmpp:version>0.4.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0425.html"/>
<xmpp:version>0.2.1</xmpp:version>
<xmpp:since>23.04</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0440.html"/>
<xmpp:version>0.4.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0441.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since></xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0474.html"/>
<xmpp:version>0.3.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status></xmpp:status>
<xmpp:note></xmpp:note>
</xmpp:SupportedXep>
</implements>
</Project>
</rdf:RDF>

View File

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

View File

@ -36,17 +36,17 @@ listen:
-
port: 5223
ip: "::"
tls: true
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
starttls_required: true
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
-
port: 5443
ip: "::"

View File

@ -47,28 +47,10 @@
#INET_DIST_INTERFACE=127.0.0.1
#.
#' 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
#' 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
@ -108,11 +90,10 @@
#.
#' ERL_OPTIONS: Additional Erlang options
#
# The next variable allows to specify additional options passed to
# all commands using erlang interpreter. This applies to starting
# ejabberd server itself but also auxiliary commands like for example
# starting debug shell. See erl(1) for list of commands that can be
# used here.
# The next variable allows to specify additional options passed to erlang while
# starting ejabberd. Some useful options are -noshell, -detached, -heart. When
# ejabberd is started from an init.d script options -noshell and -detached are
# added implicitly. See erl(1) for more info.
#
# It might be useful to add "-pa /usr/local/lib/ejabberd/ebin" if you
# want to add local modules in this path.
@ -121,20 +102,6 @@
#
#ERL_OPTIONS=""
#.
#' EJABBERD_OPTS: Additional Erlang options to start ejabberd
#
# The next variable allows to specify additional options passed to erlang while
# starting ejabberd. Some useful options are -noshell, -detached, -heart. When
# ejabberd is started from an init.d script options -noshell and -detached are
# added implicitly. See erl(1) for more info.
#
# For example you can use value "-heart -env HEART_BEAT_TIMEOUT 120 -env ERL_CRASH_DUMP_SECONDS 60"
#
# Default: ""
#
#EJABBERD_OPTS=""
#.
#' ERLANG_NODE: Erlang node name
#

View File

@ -12,11 +12,9 @@ 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}}"
IEX="{{iexpath}}"
INSTALLUSER="{{installuser}}"
# check the proper system user is used
@ -50,24 +48,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) CONFIG_DIR=$2; shift 2;;
-d|--config-dir) ETC_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}}"}"
: "${EJABBERD_CONFIG_PATH:="$CONFIG_DIR/ejabberd.yml"}"
: "${EJABBERDCTL_CONFIG_PATH:="$CONFIG_DIR/ejabberdctl.cfg"}"
: "${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"}"
# Allows passing extra Erlang command-line arguments in vm.args file
: "${VMARGS:="$CONFIG_DIR/vm.args"}"
# shellcheck source=ejabberdctl.cfg.example
: "${VMARGS:="$ETC_DIR/vm.args"}"
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_DOC_PATH:="{{docdir}}"}"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# define erl parameters
@ -76,56 +74,43 @@ 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" $ERLANG_OPTS -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
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
if [ "$(echo "$INET_DIST_INTERFACE2" | grep -o "," | wc -l)" -eq 7 ] ; then
INET_DIST_INTERFACE2="$INET_DIST_INTERFACE2 -proto_dist inet6_tcp"
fi
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="$CONFIG_DIR"/inetrc
ERL_INETRC="$ETC_DIR"/inetrc
# define ejabberd parameters
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")\
$EJABBERD_OPTS"
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")"
[ -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()
{
case $EXEC_CMD in
as_install_user) su -s /bin/sh -c 'exec "$0" "$@"' "$INSTALLUSER" -- "$@" ;;
as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;;
as_current_user) "$@" ;;
esac
}
@ -143,6 +128,14 @@ 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,16 +146,14 @@ debugwarning()
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
echo "To exit and detach this shell from ejabberd, press:"
echo " control+g and then q"
echo "To detach this shell from ejabberd, press:"
echo " control+c, control+c"
echo ""
#vt100 echo "Please do NOT use control+c in this debug shell !"
#vt100 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 _
read -r input
echo ""
fi
}
@ -178,70 +169,31 @@ livewarning()
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
echo "To exit and detach this shell from ejabberd, press:"
echo " control+g and then q"
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 _
read -r input
echo ""
fi
}
check_etop_result()
{
result=$?
if [ $result -eq 1 ] ; then
echo ""
echo "It seems there was some problem running 'ejabberdctl etop'."
echo "Is the error message something like this?"
echo " Failed to load module 'etop' because it cannot be found..."
echo "Then probably ejabberd was compiled with development tools disabled."
echo "To use 'etop', recompile ejabberd with: ./configure --enable-tools"
echo ""
exit $result
fi
}
check_iex_result()
{
result=$?
if [ $result -eq 127 ] ; then
echo ""
echo "It seems there was some problem finding 'iex' binary from Elixir."
echo "Probably ejabberd was compiled with Rebar3 and Elixir disabled, like:"
echo " ./configure"
echo "which is equivalent to:"
echo " ./configure --with-rebar=rebar3 --disable-elixir"
echo "To use 'iex', recompile ejabberd enabling Elixir or using Mix:"
echo " ./configure --enable-elixir"
echo " ./configure --with-rebar=mix"
echo ""
exit $result
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 " 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 ""
echo "Optional parameters when starting an ejabberd node:"
echo " --config-dir dir Config ejabberd: $CONFIG_DIR"
echo " --config-dir dir Config ejabberd: $ETC_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"
@ -251,40 +203,20 @@ help()
}
# dynamic node name helper
uid() {
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.*\([0-9][0-9]\).*|\1|g')"
if [ $ERTSVERSION -lt 11 ] ; then # otp 23.0 includes erts 11.0
# Erlang/OTP lower than 23, which doesn's support dynamic node code
N=1
PF=$(( $$ % 97 ))
while
case $# in
0) NN="${PF}-${N}-${ERLANG_NODE}"
;;
1) NN="${PF}-${N}-${1}-${ERLANG_NODE}"
;;
2) NN="${PF}-${N}-${1}@${2}"
;;
esac
N=$(( N + 1 + ( $$ % 5 ) ))
"$EPMD" -names 2>/dev/null | grep -q " ${NN%@*} "
do :; done
echo $NN
else
# Erlang/OTP 23 or higher: use native dynamic node code
# https://www.erlang.org/patches/otp-23.0#OTP-13812
if [ "$ERLANG_NODE" != "${ERLANG_NODE%.*}" ]; then
echo "undefined@${ERLANG_NODE#*@}"
else
echo "undefined"
fi
fi
uid()
{
uuid=$(uuidgen 2>/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
}
@ -292,7 +224,6 @@ 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."
@ -321,9 +252,7 @@ wait_status()
if [ $timeout -eq 0 ] ; then
status="$1"
else
exec_erl "$(uid ctl)" -hidden -noinput \
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
-s ejabberd_ctl \
exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null
status="$?"
fi
@ -359,49 +288,35 @@ 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 -remsh "$ERLANG_NODE" -s etop \
-output text
check_etop_result
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"
check_iex_result
;;
iexlive)
livewarning
exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS"
check_iex_result
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 'net_kernel:connect_node('"'$PEER'"')' \
-eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
-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 \
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
-s ejabberd_ctl \
exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
result=$?
case $result in

View File

@ -1,42 +0,0 @@
[
{
elvis,
[
{config,
[#{dirs => ["src"],
filter => "*.erl",
ruleset => erl_files,
rules => [{elvis_style, line_length, #{limit => 100,
skip_comments => false}},
{elvis_text_style, no_tabs, disable},
{elvis_style, no_debug_call, disable},
{elvis_style, operator_spaces, disable},
{elvis_style, invalid_dynamic_call, disable},
{elvis_style, variable_naming_convention, #{ regex => ".*" }},
{elvis_style, dont_repeat_yourself, #{min_complexity => 20}}
]
},
#{dirs => ["."],
filter => "Makefile.in",
ruleset => makefiles,
rules => [{elvis_style, line_length, #{limit => 100,
skip_comments => false}},
{elvis_style, no_tabs, disable},
{elvis_style, dont_repeat_yourself, #{min_complexity => 20}}
]
},
#{dirs => ["."],
filter => "rebar.config",
ruleset => rebar_config,
rules => [{elvis_style, line_length, #{limit => 100,
skip_comments => false}},
{elvis_style, no_tabs, disable},
{elvis_style, dont_repeat_yourself, #{min_complexity => 20}}
]
}
}
]
}
]
}
].

View File

@ -1,32 +0,0 @@
otp_path: "/usr/lib/erlang"
plt_path: "_build/default/rebar3_24.3.3_plt"
#code_reload:
# node: ejabberd@localhost
apps_dirs:
- "_build/default/lib/*"
deps_dirs:
- "_build/default/lib/*"
include_dirs:
- "_build/default/lib"
- "_build/default/lib/*/include"
- "include"
macros:
- name: DEPRECATED_GET_STACKTRACE
- name: HAVE_ERL_ERROR
- name: HAVE_URI_STRING
- name: OTP_BELOW_25
- name: SIP
- name: STUN
diagnostics:
# enabled:
# - crossref
disabled:
# - dialyzer
- unused_includes # Otherwise it complains about unused logger.hrl
lenses:
disabled:
- ct-run-test
- function-references
- server-info
- show-behaviour-usages
- suggest-spec

View File

@ -0,0 +1,66 @@
#!/usr/bin/perl
use Unix::Syslog qw(:macros :subs);
my $domain = $ARGV[0] || "example.com";
while(1)
{
# my $rin = '',$rout;
# vec($rin,fileno(STDIN),1) = 1;
# $ein = $rin;
# my $nfound = select($rout=$rin,undef,undef,undef);
my $buf = "";
syslog LOG_INFO,"waiting for packet";
my $nread = sysread STDIN,$buf,2;
do { syslog LOG_INFO,"port closed"; exit; } unless $nread == 2;
my $len = unpack "n",$buf;
my $nread = sysread STDIN,$buf,$len;
my ($op,$user,$host,$password) = split /:/,$buf;
#$user =~ s/\./\//og;
my $jid = "$user\@$domain";
my $result;
syslog(LOG_INFO,"request (%s)", $op);
SWITCH:
{
$op eq 'auth' and do
{
$result = 1;
},last SWITCH;
$op eq 'setpass' and do
{
$result = 1;
},last SWITCH;
$op eq 'isuser' and do
{
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'tryregister' and do
{
$result = 1;
},last SWITCH;
$op eq 'removeuser' and do
{
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'removeuser3' and do
{
$result = 1;
},last SWITCH;
};
my $out = pack "nn",2,$result ? 1 : 0;
syswrite STDOUT,$out;
}
closelog;

75
examples/mtr/ejabberd Normal file
View File

@ -0,0 +1,75 @@
#!/bin/sh
#
# PROVIDE: ejabberd
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
HOME=/usr/pkg/jabber D=/usr/pkg/jabber/ejabberd export HOME
name="ejabberd"
rcvar=$name
if [ -r /etc/rc.conf ]
then
. /etc/rc.conf
else
eval ${rcvar}=YES
fi
# $flags from environment overrides ${rcvar}_flags
if [ -n "${flags}" ]
then
eval ${rcvar}_flags="${flags}"
fi
checkyesno()
{
eval _value=\$${1}
case $_value in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0 ;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1 ;;
*)
echo "\$${1} is not set properly."
return 1
;;
esac
}
cmd=${1:-start}
case ${cmd} in
force*)
cmd=${cmd#force}
eval ${rcvar}=YES
;;
esac
if checkyesno ${rcvar}
then
else
exit 0
fi
case ${cmd} in
start)
if [ -x $D/src ]; then
echo "Starting ${name}."
cd $D/src
ERL_MAX_PORTS=32000 export ERL_MAX_PORTS
ulimit -n $ERL_MAX_PORTS
su jabber -c "/usr/pkg/bin/erl -sname ejabberd -s ejabberd -heart -detached -sasl sasl_error_logger '{file, \"ejabberd-sasl.log\"}' &" \
1>/dev/null 2>&1
fi
;;
stop)
echo "rpc:call('ejabberd@`hostname -s`', init, stop, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdstop"
;;
restart)
echo "rpc:call('ejabberd@`hostname -s`', init, restart, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdrestart"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac

View File

@ -0,0 +1,81 @@
#!/bin/sh
echo '1. fetch, compile, and install erlang'
if [ ! pkg_info erlang 1>/dev/null 2>&1 ]; then
cd /usr/pkgsrc/lang/erlang
make fetch-list|sh
make
make install
fi
if pkg_info erlang | grep -q erlang-9.1nb1; then
else
echo "erlang-9.1nb1 not installed" 1>&2
exit 1
fi
echo '2. install crypt_drv.so'
if [ ! -d /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib ] ; then
mkdir -p /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/crypto_drv.so ]; then
cp work/otp*/lib/crypto/priv/*/*/crypto_drv.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '3. compile and install elibcrypto.so'
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/elibcrypto.so ]; then
cd /usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/crypto/c_src
ld -r -u CRYPTO_set_mem_functions -u MD5 -u MD5_Init -u MD5_Update \
-u MD5_Final -u SHA1 -u SHA1_Init -u SHA1_Update -u SHA1_Final \
-u des_set_key -u des_ncbc_encrypt -u des_ede3_cbc_encrypt \
-L/usr/lib -lcrypto -o ../priv/obj/i386--netbsdelf/elibcrypto.o
cc -shared \
-L/usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/erl_interface/obj/i386--netbsdelf \
-o ../priv/obj/i386--netbsdelf/elibcrypto.so \
../priv/obj/i386--netbsdelf/elibcrypto.o -L/usr/lib -lcrypto
cp ../priv/obj/i386--netbsdelf/elibcrypto.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '4. compile and install ssl_esock'
if [ ! -f /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/bin/ssl_esock ]; then
cd /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/obj/
make
fi
echo '5. initial ejabberd configuration'
cd /usr/pkg/jabber/ejabberd/src
./configure
echo '6. edit ejabberd Makefiles'
for M in Makefile mod_*/Makefile; do
if [ ! -f $M.orig ]; then
mv $M $M.orig
sed -e s%/usr/local%/usr/pkg%g < $M.orig > $M
fi
done
echo '7. compile ejabberd'
gmake
for A in mod_muc mod_pubsub; do
(cd $A; gmake)
done
echo ''
echo 'now edit ejabberd.cfg'
echo ''
echo 'to start ejabberd: erl -sname ejabberd -s ejabberd'

65
examples/mtr/ejabberd.cfg Normal file
View File

@ -0,0 +1,65 @@
% jabber.dbc.mtview.ca.us
override_acls.
{acl, admin, {user, "mrose", "jabber.dbc.mtview.ca.us"}}.
{access, announce, [{allow, admin},
{deny, all}]}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{access, configure, [{allow, admin},
{deny, all}]}.
{access, disco_admin, [{allow, admin},
{deny, all}]}.
{access, muc_admin, [{allow, admin},
{deny, all}]}.
{access, register, [{deny, all}]}.
{access, s2s_shaper, [{fast, all}]}.
{auth_method, internal}.
{host, "jabber.dbc.mtview.ca.us"}.
{outgoing_s2s_port, 5269}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{welcome_message, none}.
{listen, [{5222, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper}]},
{5223, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper},
{ssl, [{certfile, "/etc/openssl/certs/ejabberd.pem"}]}]},
{5269, ejabberd_s2s_in,
[{shaper, s2s_shaper}]}]}.
{modules, [
{mod_register, []},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]},
{mod_private, []},
{mod_muc, []},
{mod_pubsub, []},
{mod_time, []},
{mod_last, []},
{mod_version, []}
]}.
% Local Variables:
% mode: erlang
% End:

44
include/adhoc.hrl Normal file
View File

@ -0,0 +1,44 @@
%%%----------------------------------------------------------------------
%%%
%%% 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-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -19,30 +19,13 @@
%%%----------------------------------------------------------------------
-type aterm() :: {atom(), atype()}.
-type atype() :: integer | string | binary | any | atom |
-type atype() :: integer | string | binary |
{tuple, [aterm()]} | {list, aterm()}.
-type rterm() :: {atom(), rtype()}.
-type rtype() :: integer | string | atom | any |
-type rtype() :: integer | string | atom |
{tuple, [rterm()]} | {list, rterm()} |
rescode | restuple.
%% The 'any' and 'atom' argument types and 'any' result type
%% should only be used %% by commands with tag 'internal',
%% which are meant to be used only internally in ejabberd,
%% and not called using external frontends.
%% The purpose of a command can either be:
%% - informative: its purpose is to obtain information
%% - modifier: its purpose is to produce some change in the server
%%
%% A modifier command should be designed just to produce its desired side-effect,
%% and its result term should just be success or failure: rescode or restuple.
%%
%% ejabberd_web_admin:make_command/2 considers that commands
%% with result type different than rescode or restuple
%% are commands that can be safely executed automatically
%% to get information and build the web page.
-type oauth_scope() :: atom().
%% ejabberd_commands OAuth ReST ACL definition:
@ -76,7 +59,6 @@
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()] | '_',
@ -84,24 +66,42 @@
args_example = none :: none | [any()] | '_',
result_example = none :: any()}).
-type ejabberd_commands() :: #ejabberd_commands{name :: atom(),
tags :: [atom()],
desc :: string(),
longdesc :: string(),
version :: integer(),
note :: string(),
weight :: integer(),
module :: atom(),
function :: atom(),
args :: [aterm()],
policy :: open | restricted | admin | user,
access :: [{atom(),atom(),atom()}|atom()],
definer :: atom(),
result :: rterm(),
args_rename :: [{atom(),atom()}],
args_desc :: none | [string()] | '_',
result_desc :: none | string() | '_',
args_example :: none | [any()] | '_',
result_example :: any()
}.
%% TODO Fix me: Type is not up to date
-type ejabberd_commands() :: #ejabberd_commands{name :: atom(),
tags :: [atom()],
desc :: string(),
longdesc :: string(),
version :: integer(),
module :: atom(),
function :: atom(),
args :: [aterm()],
policy :: open | restricted | admin | user,
access :: [{atom(),atom(),atom()}|atom()],
result :: rterm()}.
%% @type ejabberd_commands() = #ejabberd_commands{
%% name = atom(),
%% tags = [atom()],
%% desc = string(),
%% longdesc = string(),
%% module = atom(),
%% function = atom(),
%% args = [aterm()],
%% result = rterm()
%% }.
%% desc: Description of the command
%% args: Describe the accepted arguments.
%% This way the function that calls the command can format the
%% arguments before calling.
%% @type atype() = integer | string | {tuple, [aterm()]} | {list, aterm()}.
%% Allowed types for arguments are integer, string, tuple and list.
%% @type rtype() = integer | string | atom | {tuple, [rterm()]} | {list, rterm()} | rescode | restuple.
%% A rtype is either an atom or a tuple with two elements.
%% @type aterm() = {Name::atom(), Type::atype()}.
%% An argument term is a tuple with the term name and the term type.
%% @type rterm() = {Name::atom(), Type::rtype()}.
%% A result term is a tuple with the term name and the term type.

View File

@ -0,0 +1,30 @@
%%%----------------------------------------------------------------------
%%%
%%% 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-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -34,14 +34,12 @@
format_query :: fun(),
format_res :: fun(),
args :: fun(),
flags :: non_neg_integer(),
loc :: {module(), pos_integer()}}).
-else.
-record(sql_query, {hash :: binary(),
format_query :: fun(),
format_res :: fun(),
args :: fun(),
flags :: non_neg_integer(),
loc :: {module(), {pos_integer(), pos_integer()}}}).
-endif.
@ -50,26 +48,3 @@
boolean :: fun((boolean()) -> binary()),
in_array_string :: fun((binary()) -> binary()),
like_escape :: fun(() -> binary())}).
-record(sql_index, {columns,
unique = false :: boolean(),
meta = #{}}).
-record(sql_column, {name :: binary(),
type,
default = false,
opts = []}).
-record(sql_table, {name :: binary(),
columns :: [#sql_column{}],
indices = [] :: [#sql_index{}],
post_create}).
-record(sql_schema, {version :: integer(),
tables :: [#sql_table{}],
update = []}).
-record(sql_references, {table :: binary(),
column :: binary()}).
-record(sql_schema_info,
{db_type :: pgsql | mysql | sqlite,
db_version :: any(),
new_schema = true :: boolean()}).

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -62,11 +62,6 @@
[{<<"type">>, Type}, {<<"name">>, Name},
{<<"value">>, Value}])).
-define(INPUTPH(Type, Name, Value, PlaceHolder),
?XA(<<"input">>,
[{<<"type">>, Type}, {<<"name">>, Name},
{<<"value">>, Value}, {<<"placeholder">>, PlaceHolder}])).
-define(INPUTT(Type, Name, Value),
?INPUT(Type, Name, (translate:translate(Lang, Value)))).
@ -100,27 +95,16 @@
-define(XRES(Text),
?XAC(<<"p">>, [{<<"class">>, <<"result">>}], Text)).
-define(DIVRES(Elements),
?XAE(<<"div">>, [{<<"class">>, <<"result">>}], Elements)).
%% Guide Link
-define(XREST(Text), ?XRES((translate:translate(Lang, Text)))).
-define(GL(Ref, Title),
?XAE(<<"div">>, [{<<"class">>, <<"guidelink">>}],
[?XAE(<<"a">>,
[{<<"href">>, <<"https://docs.ejabberd.im/", Ref/binary>>},
[{<<"href">>, <<"https://docs.ejabberd.im/admin/configuration/", Ref/binary>>},
{<<"target">>, <<"_blank">>}],
[?C(<<"docs: ", Title/binary>>)])])).
%% h1 with a Guide Link
-define(H1GLraw(Name, Ref, Title),
[?XC(<<"h1">>, Name), ?GL(Ref, Title), ?BR]).
-define(H1GL(Name, RefConf, Title),
?H1GLraw(Name, <<"admin/configuration/", RefConf/binary>>, Title)).
-define(ANCHORL(Ref),
?XAE(<<"div">>, [{<<"class">>, <<"anchorlink">>}],
[?XAE(<<"a">>,
[{<<"href">>, <<"#", Ref/binary>>}],
[?C(<<"<=">>)])])).
-define(H1GL(Name, Ref, Title),
[?XC(<<"h1">>, Name), ?GL(Ref, Title)]).

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -26,8 +26,7 @@
bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid(),
packet = #xmlel{} :: xmlel() | message(),
nick = <<"">> :: binary(),
type = chat :: chat | groupchat,
origin_id = <<"">> :: binary()}).
type = chat :: chat | groupchat}).
-record(archive_prefs,
{us = {<<"">>, <<"">>} :: {binary(), binary()},

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -38,7 +38,7 @@
description = <<"">> :: binary(),
allow_change_subj = true :: boolean(),
allow_query_users = true :: boolean(),
allowpm = anyone :: anyone | participants | moderators | none,
allow_private_messages = true :: boolean(),
allow_private_messages_from_visitors = anyone :: anyone | moderators | nobody ,
allow_visitor_status = true :: boolean(),
allow_visitor_nickchange = true :: boolean(),
@ -65,7 +65,6 @@
captcha_whitelist = (?SETS):empty() :: gb_sets:set(),
mam = false :: boolean(),
pubsub = <<"">> :: binary(),
enable_hats = false :: boolean(),
lang = ejabberd_option:language() :: binary()
}).
@ -88,16 +87,6 @@
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(),
@ -117,16 +106,15 @@
jid = #jid{} :: jid(),
config = #config{} :: config(),
users = #{} :: users(),
muc_subscribers = #muc_subscribers{} :: #muc_subscribers{},
subscribers = #{} :: subscribers(),
subscriber_nicks = #{} :: subscriber_nicks(),
last_voice_request_time = treap:empty() :: treap:treap(),
robots = #{} :: robots(),
nicks = #{} :: nicks(),
affiliations = #{} :: affiliations(),
roles = #{} :: roles(),
history = #lqueue{} :: lqueue(),
subject = [] :: [text()],
subject_author = {<<"">>, #jid{}} :: {binary(), jid()},
hats_users = #{} :: map(), % FIXME on OTP 21+: #{ljid() => #{binary() => binary()}},
subject_author = <<"">> :: binary(),
just_created = erlang:system_time(microsecond) :: true | integer(),
activity = treap:empty() :: treap:treap(),
room_shaper = none :: ejabberd_shaper:shaper(),
@ -138,4 +126,5 @@
-type robots() :: #{jid() => {binary(), stanza()}}.
-type nicks() :: #{binary() => [ljid()]}.
-type affiliations() :: #{ljid() => affiliation() | {affiliation(), binary()}}.
-type roles() :: #{ljid() => role() | {role(), binary()}}.
-type subscribers() :: #{ljid() => #subscriber{}}.
-type subscriber_nicks() :: #{binary() => [ljid()]}.

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -2,7 +2,7 @@
%%% RFC 1928 constants.
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,5 +1,5 @@
%%%----------------------------------------------------------------------
%%% ejabberd, Copyright (C) 2017-2024 ProcessOne
%%% ejabberd, Copyright (C) 2017-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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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

View File

@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
%%% 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
@ -18,11 +18,5 @@
%%%
%%%----------------------------------------------------------------------
-record(room_version,
{id :: binary(),
%% use the same field names as in Synapse
knock_restricted_join_rule :: boolean(),
enforce_int_power_levels :: boolean(),
implicit_room_creator :: boolean(),
updated_redaction_rules :: boolean()
}).
-record(vcard_xupdate, {us = {<<>>, <<>>} :: {binary(), binary()},
hash = <<>> :: binary()}).

View File

@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2002-2024 ProcessOne, SARL. All Rights Reserved.
%%% @copyright (C) 2002-2021 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-2024 ProcessOne
%%% 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
@ -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, 1000).
-define(MAXITEMS, 10).
%% this is currently a hard limit.
%% Would be nice to have it configurable.

0
install-sh Executable file → Normal file
View File

View File

@ -41,7 +41,7 @@ defmodule Ejabberd.Config.Attr do
"""
@spec validate([attr]) :: [{:ok, attr}] | [{:error, attr, atom()}]
def validate(attrs) when is_list(attrs), do: Enum.map(attrs, &valid_attr?/1)
def validate(attr), do: validate([attr])
def validate(attr), do: validate([attr]) |> List.first
@doc """
Returns the type of an attribute, given its name.

View File

@ -36,8 +36,8 @@ defmodule Ejabberd.Config do
case force do
true ->
Ejabberd.Config.Store.stop()
Ejabberd.Config.Store.start_link()
Ejabberd.Config.Store.stop
Ejabberd.Config.Store.start_link
do_init(file_path)
false ->
if not init_already_executed, do: do_init(file_path)
@ -105,8 +105,11 @@ defmodule Ejabberd.Config do
Code.eval_file(file_path) |> extract_and_store_module_name()
# Getting start/0 config
[module] = Ejabberd.Config.Store.get(:module_name)
call_start_func_and_store_data(module)
Ejabberd.Config.Store.get(:module_name)
|> case do
nil -> IO.puts "[ ERR ] Configuration module not found."
[module] -> call_start_func_and_store_data(module)
end
# Fetching git modules and install them
get_modules_parsed_in_order()

View File

@ -13,6 +13,7 @@ defmodule Ejabberd.Config.EjabberdHook do
@doc """
Register a hook to ejabberd.
"""
@spec start(EjabberdHook.t) :: none
def start(%EjabberdHook{hook: hook, opts: opts, fun: fun}) do
host = Keyword.get(opts, :host, :global)
priority = Keyword.get(opts, :priority, 50)

View File

@ -7,14 +7,13 @@ defmodule Ejabberd.Config.EjabberdModule do
the already existing Elixir.Module.
"""
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validation
alias Ejabberd.Config.Attr
@type t :: %{module: atom, attrs: [Attr.attr]}
@type t :: %{module: atom, attrs: [Attr.t]}
defstruct [:module, :attrs]
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validation
@doc """
Given a list of modules / single module
it runs different validators on them.
@ -30,6 +29,7 @@ defmodule Ejabberd.Config.EjabberdModule do
a git attribute and tries to fetch the repo,
then, it install them through :ext_mod.install/1
"""
@spec fetch_git_repos([EjabberdModule.t]) :: none()
def fetch_git_repos(modules) do
modules
|> Enum.filter(&is_git_module?/1)
@ -60,7 +60,7 @@ defmodule Ejabberd.Config.EjabberdModule do
defp fetch_and_store_repo_source_if_not_exists(path, repo) do
unless File.exists?(path) do
IO.puts "[info] Fetching: #{repo}"
:os.cmd(~c"git clone #{repo} #{path}")
:os.cmd('git clone #{repo} #{path}')
end
end

View File

@ -17,9 +17,9 @@ defmodule Ejabberd.Config.EjabberdLogger do
end
defp do_log_errors({:ok, _mod}), do: nil
defp do_log_errors({:error, _mod, errors}), do: (Enum.each errors, &do_log_errors/1)
defp do_log_errors({:attribute, errors}), do: (Enum.each errors, &log_attribute_error/1)
defp do_log_errors({:dependency, errors}), do: (Enum.each errors, &log_dependency_error/1)
defp do_log_errors({:error, _mod, errors}), do: Enum.each errors, &do_log_errors/1
defp do_log_errors({:attribute, errors}), do: Enum.each errors, &log_attribute_error/1
defp do_log_errors({:dependency, errors}), do: Enum.each errors, &log_dependency_error/1
defp log_attribute_error({{attr_name, _val}, :attr_not_supported}), do:
IO.puts "[ WARN ] Annotation @#{attr_name} is not supported."

View File

@ -14,12 +14,15 @@ defmodule Ejabberd.Config.OptsFormatter do
Look at how Config.get_ejabberd_opts/0 is constructed for
more informations.
"""
@spec format_opts_for_ejabberd(map) :: list()
@spec format_opts_for_ejabberd([{atom(), any()}]) :: list()
def format_opts_for_ejabberd(opts) do
opts
|> format_attrs_for_ejabberd
end
defp format_attrs_for_ejabberd(opts) when is_list(opts),
do: Enum.map opts, &format_attrs_for_ejabberd/1
defp format_attrs_for_ejabberd({:listeners, mods}),
do: {:listen, format_listeners_for_ejabberd(mods)}
@ -29,9 +32,6 @@ defmodule Ejabberd.Config.OptsFormatter do
defp format_attrs_for_ejabberd({key, opts}) when is_atom(key),
do: {key, opts}
defp format_attrs_for_ejabberd(opts),
do: (Enum.map opts, &format_attrs_for_ejabberd/1)
defp format_mods_for_ejabberd(mods) do
Enum.map mods, fn %EjabberdModule{module: mod, attrs: attrs} ->
{mod, attrs[:opts]}

View File

@ -3,12 +3,12 @@ defmodule Ejabberd.Config.Validation do
Module used to validate a list of modules.
"""
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validator
@type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
@type mod_validation_result :: {:ok, EjabberdModule.t} | {:error, EjabberdModule.t, map}
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validator
@doc """
Given a module or a list of modules it runs validators on them
and returns {:ok, mod} or {:error, mod, errors}, for each

View File

@ -3,13 +3,12 @@ defmodule Ejabberd.Config.Validator.Attrs do
Validator module used to validate attributes.
"""
import Ejabberd.Config.ValidatorUtility
alias Ejabberd.Config.Attr
alias Ejabberd.Config.EjabberdModule
# TODO: Duplicated from validator.ex !!!
@type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
import Ejabberd.Config.ValidatorUtility
alias Ejabberd.Config.Attr
@doc """
Given a module (with the form used for validation)
it runs Attr.validate/1 on each attribute and
@ -18,9 +17,9 @@ defmodule Ejabberd.Config.Validator.Attrs do
@spec validate(mod_validation) :: mod_validation
def validate({modules, mod, errors}) do
errors = Enum.reduce mod.attrs, errors, fn(attr, err) ->
case Attr.validate([attr]) do
[{:ok, _attr}] -> err
[{:error, attr, cause}] -> put_error(err, :attribute, {attr, cause})
case Attr.validate(attr) do
{:ok, _attr} -> err
{:error, attr, cause} -> put_error(err, :attribute, {attr, cause})
end
end

View File

@ -4,8 +4,6 @@ defmodule Ejabberd.Config.Validator.Dependencies do
with the @dependency annotation.
"""
alias Ejabberd.Config.EjabberdModule
# TODO: Duplicated from validator.ex !!!
@type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
import Ejabberd.Config.ValidatorUtility

View File

@ -4,6 +4,8 @@ defmodule Ejabberd.Config.ValidatorUtility do
Imports utility functions for working with validation structures.
"""
alias Ejabberd.Config.EjabberdModule
@doc """
Inserts an error inside the errors collection, for the given key.
If the key doesn't exists then it creates an empty collection
@ -20,6 +22,7 @@ defmodule Ejabberd.Config.ValidatorUtility do
Given a list of modules it extracts and returns a list
of the module names (which are Elixir.Module).
"""
@spec extract_module_names(EjabberdModule.t) :: [atom]
def extract_module_names(modules) when is_list(modules) do
modules
|> Enum.map(&Map.get(&1, :module))

View File

@ -7,7 +7,7 @@ defmodule Ejabberd.ConfigUtil do
@doc """
Returns true when the config file is based on elixir.
"""
@spec is_elixir_config(binary) :: boolean
@spec is_elixir_config(list) :: boolean
def is_elixir_config(filename) when is_list(filename) do
is_elixir_config(to_string(filename))
end

View File

@ -14,15 +14,15 @@ defmodule Mix.Tasks.Ejabberd.Deps.Tree do
def run(_argv) do
# First we need to start manually the store to be available
# during the compilation of the config file.
Ejabberd.Config.Store.start_link()
Ejabberd.Config.Store.start_link
Ejabberd.Config.init(:ejabberd_config.path())
Mix.shell().info "ejabberd modules"
Mix.shell.info "ejabberd modules"
Ejabberd.Config.Store.get(:modules)
|> Enum.reverse # Because of how mods are stored inside the store
|> format_mods
|> Mix.shell().info
|> Mix.shell.info
end
defp format_mods(mods) when is_list(mods) do

View File

@ -2,19 +2,19 @@ defmodule ModPresenceDemo do
use Ejabberd.Module
def start(host, _opts) do
info("Starting ejabberd module Presence Demo")
info('Starting ejabberd module Presence Demo')
Ejabberd.Hooks.add(:set_presence_hook, host, __MODULE__, :on_presence, 50)
:ok
end
def stop(host) do
info("Stopping ejabberd module Presence Demo")
info('Stopping ejabberd module Presence Demo')
Ejabberd.Hooks.delete(:set_presence_hook, host, __MODULE__, :on_presence, 50)
:ok
end
def on_presence(user, _server, _resource, _packet) do
info("Receive presence for #{user}")
info('Receive presence for #{user}')
:none
end
@ -27,7 +27,7 @@ defmodule ModPresenceDemo do
end
def mod_doc() do
%{:desc => "This is just a demonstration."}
%{:desc => 'This is just a demonstration.'}
end
end

View File

@ -75,7 +75,7 @@ EOF
if test "x`cat conftest.out`" != "xok"; then
AC_MSG_RESULT([failed])
X="`cat conftest.out`"
if test "[$3]" = "warn"; then
if test "[$3]" == "warn"; then
AC_MSG_WARN([$X])
else
AC_MSG_FAILURE([$X])

File diff suppressed because it is too large Load Diff

287
mix.exs
View File

@ -3,35 +3,28 @@ defmodule Ejabberd.MixProject do
def project do
[app: :ejabberd,
source_url: "https://github.com/processone/ejabberd",
version: version(),
description: description(),
elixir: elixir_required_version(),
elixir: "~> 1.4",
elixirc_paths: ["lib"],
compile_path: ".",
compilers: [:asn1, :yecc] ++ Mix.compilers(),
compilers: [:asn1] ++ Mix.compilers,
erlc_options: erlc_options(),
erlc_paths: ["asn1", "src"],
# Elixir tests are starting the part of ejabberd they need
aliases: [test: "test --no-start"],
start_permanent: Mix.env() == :prod,
language: :erlang,
dialyzer: dialyzer(),
releases: releases(),
package: package(),
docs: docs(),
deps: deps()]
end
def version do
case config(:vsn) do
:false -> "0.0.0" # ./configure wasn't run: vars.config not created
~c"0.0" -> "0.0.0" # the full git repository wasn't downloaded
~c"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}.0"
vsn -> String.replace(:erlang.list_to_binary(vsn), ~r/\.0+([0-9])/, ".\\1")
'0.0' -> "0.0.0" # the full git repository wasn't downloaded
vsn -> String.replace(:erlang.list_to_binary(vsn), ~r/0+([0-9])/, "\\1")
end
end
@ -43,25 +36,23 @@ defmodule Ejabberd.MixProject do
def application do
[mod: {:ejabberd_app, []},
applications: [:idna, :inets, :kernel, :sasl, :ssl, :stdlib, :mix,
:fast_tls, :fast_xml, :fast_yaml, :jose,
:p1_utils, :stringprep, :syntax_tools, :yconf, :xmpp]
++ cond_apps(),
included_applications: [:mnesia, :os_mon,
:cache_tab, :eimp, :mqtree, :p1_acme,
:p1_oauth2, :pkix]
++ cond_included_apps()]
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_oauth2, :pkix, :xmpp]
++ cond_apps()]
end
defp dialyzer do
[
plt_add_apps: [
:mnesia, :odbc, :os_mon, :stdlib,
:eredis, :luerl,
:cache_tab, :eimp, :epam, :esip, :ezlib, :mqtree,
:p1_acme, :p1_mysql, :p1_oauth2, :p1_pgsql, :pkix,
:sqlite3, :stun, :xmpp],
]
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
@ -80,41 +71,20 @@ defmodule Ejabberd.MixProject do
end
end
defp if_type_exported(module, typeDef, okResult) do
try do
{:ok, concrete} = :dialyzer_utils.get_core_from_beam(:code.which(module))
{:ok, types} = :dialyzer_utils.get_record_and_type_info(concrete)
if Map.has_key?(types, typeDef) do
okResult
else
[]
end
rescue
_ -> []
end
end
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include", deps_include()]
result = [{:d, :ELIXIR_ENABLED}] ++
includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"])
result = [:debug_info, {:d, :ELIXIR_ENABLED}] ++
cond_options() ++
Enum.map(includes, fn (path) -> {:i, path} end) ++
if_version_above(~c"20", [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_above(~c"20", [{:d, :HAVE_URI_STRING}]) ++
if_version_above(~c"20", [{:d, :HAVE_ERL_ERROR}]) ++
if_version_below(~c"21", [{:d, :USE_OLD_HTTP_URI}]) ++
if_version_below(~c"22", [{:d, :LAGER}]) ++
if_version_below(~c"21", [{:d, :NO_CUSTOMIZE_HOSTNAME_CHECK}]) ++
if_version_below(~c"23", [{:d, :USE_OLD_CRYPTO_HMAC}]) ++
if_version_below(~c"23", [{:d, :USE_OLD_PG2}]) ++
if_version_below(~c"24", [{:d, :COMPILER_REPORTS_ONLY_LINES}]) ++
if_version_below(~c"24", [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) ++
if_version_below(~c"24", [{:d, :OTP_BELOW_24}]) ++
if_version_below(~c"25", [{:d, :OTP_BELOW_25}]) ++
if_version_below(~c"26", [{:d, :OTP_BELOW_26}]) ++
if_version_below(~c"27", [{:d, :OTP_BELOW_27}]) ++
if_type_exported(:odbc, {:opaque, :connection_reference, 0}, [{:d, :ODBC_HAS_TYPES}])
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_below('21', [{:d, :USE_OLD_HTTP_URI}]) ++
if_version_below('22', [{:d, :LAGER}]) ++
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}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end
@ -122,36 +92,42 @@ defmodule Ejabberd.MixProject do
defp cond_options do
for {:true, option} <- [{config(:sip), {:d, :SIP}},
{config(:stun), {:d, :STUN}},
{config(:debug), :debug_info},
{not config(:debug), {:debug_info, false}},
{config(:roster_gateway_workaround), {:d, :ROSTER_GATEWAY_WORKAROUND}},
{config(:roster_gateway_workaround), {:d, :ROSTER_GATWAY_WORKAROUND}},
{config(:new_sql_schema), {:d, :NEW_SQL_SCHEMA}}
], do:
option
end
defp deps do
[{:cache_tab, "~> 1.0"},
{:dialyxir, "~> 1.2", only: [:test], runtime: false},
[{:base64url, "~> 0.0.1"},
{:cache_tab, "~> 1.0"},
{:distillery, "~> 2.0"},
{:eimp, "~> 1.0"},
{:ex_doc, "~> 0.31", only: [:dev, :edoc], runtime: false},
{:fast_tls, ">= 1.1.18"},
{:fast_xml, ">= 1.1.51"},
{: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"},
{:mqtree, "~> 1.0"},
{:p1_acme, git: "https://github.com/processone/p1_acme", branch: "master"},
{:p1_acme, "~> 1.0"},
{:p1_mysql, "~> 1.0"},
{:p1_oauth2, "~> 0.6"},
{:p1_pgsql, "~> 1.1"},
{:p1_utils, "~> 1.0"},
{:pkix, git: "https://github.com/processone/pkix"},
{:stringprep, ">= 1.0.26"},
{:xmpp, git: "https://github.com/processone/xmpp", override: true},
{:pkix, "~> 1.0"},
{:stringprep, ">= 1.0.26", override: true},
{:stun, "~> 1.0"},
{:xmpp, "~> 1.5"},
{:yconf, "~> 1.0"}]
++ cond_deps()
end
defp deps_include() do
if Mix.Project.umbrella?() do
defp deps_include(deps) do
base = if Mix.Project.umbrella?() do
"../../deps"
else
case Mix.Project.deps_paths()[:ejabberd] do
@ -159,46 +135,21 @@ defmodule Ejabberd.MixProject do
_ -> ".."
end
end
Enum.map(deps, fn dep -> base<>"/#{dep}/include" end)
end
defp cond_deps do
for {:true, dep} <- [{config(:pam), {:epam, "~> 1.0"}},
{Mix.env() == :translations,
{:ejabberd_po, git: "https://github.com/processone/ejabberd-po.git"}},
{Mix.env() == :dev,
{:exsync, "~> 0.2"}},
{config(:redis), {:eredis, "~> 1.2.0"}},
{config(:sip), {:esip, "~> 1.0"}},
{config(:zlib), {:ezlib, "~> 1.0"}},
{if_version_above(~c"23", true), {:jose, "~> 1.11.10"}},
{if_version_below(~c"24", true), {:jose, "1.11.1"}},
{if_version_below(~c"27", true), {:jiffy, "~> 1.1.1"}},
{if_version_below(~c"22", true), {:lager, "~> 3.9.1"}},
{config(:lua), {:luerl, "~> 1.2.0"}},
{config(:mysql), {:p1_mysql, git: "https://github.com/processone/p1_mysql" }},
{config(:pgsql), {:p1_pgsql, git: "https://github.com/processone/p1_pgsql"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}},
{config(:stun), {:stun, "~> 1.0"}}], do:
{config(:lua), {:luerl, "~> 0.3.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}}], do:
dep
end
defp cond_apps do
for {:true, app} <- [{config(:stun), :stun},
{Map.has_key?(System.get_env(), "RELIVE"), :exsync},
{if_version_below(~c"27", true), :jiffy},
{config(:tools), :observer}], do:
app
end
defp cond_included_apps do
for {:true, app} <- [{config(:pam), :epam},
{config(:lua), :luerl},
{config(:redis), :eredis},
{Mix.env() == :edoc, :ex_doc},
{Mix.env() == :test, :dialyxir},
{if_version_below(~c"22", true), :lager},
for {:true, app} <- [{config(:redis), :eredis},
{config(:mysql), :p1_mysql},
{config(:sip), :esip},
{config(:odbc), :odbc},
{config(:pgsql), :p1_pgsql},
{config(:sqlite), :sqlite3}], do:
@ -211,27 +162,17 @@ defmodule Ejabberd.MixProject do
"COPYING", "README.md",
"mix.exs", "rebar.config", "rebar.config.script", "vars.config"],
maintainers: ["ProcessOne"],
licenses: ["GPL-2.0-or-later"],
links: %{"ejabberd.im" => "https://www.ejabberd.im",
"ejabberd Docs" => "http://docs.ejabberd.im",
"GitHub" => "https://github.com/processone/ejabberd",
licenses: ["GPLv2"],
links: %{"Site" => "https://www.ejabberd.im",
"Documentation" => "http://docs.ejabberd.im",
"Source" => "https://github.com/processone/ejabberd",
"ProcessOne" => "http://www.process-one.net/"}]
end
defp vars do
filepath = case Application.fetch_env(:ejabberd, :vars_config_path) do
:error ->
"vars.config"
{:ok, path} ->
path
end
config2 = case :file.consult(filepath) do
case :file.consult("vars.config") do
{:ok,config} -> config
_ -> [stun: true, zlib: true]
end
case Mix.env() do
:dev -> List.keystore(config2, :tools, 0, {:tools, true})
_ -> config2
_ -> [zlib: true]
end
end
@ -242,35 +183,6 @@ 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) > ~c"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]
@ -293,16 +205,11 @@ defmodule Ejabberd.MixProject do
libdir: config(:libdir),
sysconfdir: config(:sysconfdir),
localstatedir: config(:localstatedir),
config_dir: config(:config_dir),
logs_dir: config(:logs_dir),
spool_dir: config(:spool_dir),
vsn: version(),
iexpath: config(:iexpath),
docdir: config(:docdir),
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"
@ -312,14 +219,14 @@ defmodule Ejabberd.MixProject do
execute = fn(command) ->
case function_exported?(System, :shell, 1) do
true ->
System.shell(command, into: IO.stream())
System.shell(command)
false ->
:os.cmd(to_charlist(command))
end
end
# Mix/Elixir lower than 1.11.0 use config/releases.exs instead of runtime.exs
case Version.match?(System.version(), "~> 1.11") do
case Version.match?(System.version, ">= 1.11.0") do
true ->
:ok
false ->
@ -328,88 +235,46 @@ 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.example2a")
Mix.Generator.copy_template("ejabberdctl.example2a", "ejabberdctl.example2b", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2b > 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)
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)
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}/conf/ca.pem")
Mix.Generator.copy_file("test/ejabberd_SUITE_data/cert.pem", "#{ro}/conf/cert.pem")
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")
".example"
_ -> ""
end
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")
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)
Enum.each(File.ls!("sql"),
fn x ->
Mix.Generator.copy_file("sql/#{x}", "#{ro}/lib/ejabberd-#{release.version}/priv/sql/#{x}")
end)
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
Mix.Generator.create_directory("#{ro}/var/lib/ejabberd")
case Mix.env() do
:dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh mix")
:dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh")
_ -> :ok
end
release
end
defp docs do
[
main: "readme",
logo: "_build/edoc/logo.png",
source_ref: "master",
extra_section: "", # No need for Pages section name, it's the only one
api_reference: false, # API section has just Elixir, hide it
filter_modules: "aaaaa", # Module section has just Elixir modules, hide them
extras: [
"README.md": [title: "Readme"],
"COMPILE.md": [title: "Compile and Install"],
"CONTAINER.md": [title: "Container Image"],
"CONTRIBUTING.md": [title: "Contributing"],
"CONTRIBUTORS.md": [title: "Contributors"],
"CODE_OF_CONDUCT.md": [title: "Code of Conduct"],
"CHANGELOG.md": [title: "ChangeLog"],
"COPYING": [title: "Copying License"],
"_build/edoc/docs.md": [title: "&xrArr; ejabberd Docs"]
],
groups_for_extras: [
"": Path.wildcard("*.md") ++ ["COPYING"],
"For more documentation": "_build/edoc/docs.md"
]
]
end
end
defmodule Mix.Tasks.Compile.Asn1 do
@ -422,7 +287,7 @@ defmodule Mix.Tasks.Compile.Asn1 do
def run(args) do
{opts, _, _} = OptionParser.parse(args, switches: [force: :boolean])
project = Mix.Project.config()
project = Mix.Project.config
source_paths = project[:asn1_paths] || ["asn1"]
dest_paths = project[:asn1_target] || ["src"]
mappings = Enum.zip(source_paths, dest_paths)
@ -444,7 +309,7 @@ defmodule Mix.Tasks.Compile.Asn1 do
end
def manifests, do: [manifest()]
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)
defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest)
def clean, do: Erlang.clean(manifest())
end

View File

@ -1,39 +1,36 @@
%{
"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"},
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"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.14", "aa0b85d27f4ef3a756ae995179df952a0721237e83c6b79d644347b75016681a", [:rebar3], [], "hexpm", "2f3449e72885a72a6c2a843f561add0fc2f70d7a21f61456930a547473d4d989"},
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm", "d9b5abef2c2c8aba8f32aa018203e0b3dc8b1157773b254ab1d4c2002317f1e1"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"esip": {:hex, :esip, "1.0.52", "a2840287c493a4280e6fba57a257706843b025c315875e38b03fd07190e22dba", [:rebar3], [{:fast_tls, "1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.2.12", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "6f00165395900500aa262ce0297162d93931c78c1464d89fd0edc6e3d6bc011f"},
"ex_doc": {:hex, :ex_doc, "0.33.0", "690562b153153c7e4d455dc21dab86e445f66ceba718defe64b0ef6f0bd83ba0", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "3f69adc28274cb51be37d09b03e4565232862a4b10288a3894587b0131412124"},
"exsync": {:hex, :exsync, "0.4.1", "0a14fe4bfcb80a509d8a0856be3dd070fffe619b9ba90fec13c58b316c176594", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "cefb22aa805ec97ffc5b75a4e1dc54bcaf781e8b32564bf74abbe5803d1b5178"},
"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.19", "f52731a4b35259fa06cf23e2a0732920ad9efce7c3d68377f129a474998747bb", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "db34322c8782d4c5139ccb80709d8ec8c38089b44262edd0c2f660ac495bd389"},
"fast_xml": {:hex, :fast_xml, "1.1.51", "a7f8c6942591632309099386d5c339c89997ac2bbdd1216f6c196dee6d7828a9", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "7fce41b7d1a4ba438a2d7a088dabe74a3ca0739f1af2abcb77e62daf43e0409a"},
"fast_yaml": {:hex, :fast_yaml, "1.0.36", "65413a34a570fd4e205a460ba602e4ee7a682f35c22d2e1c839025dbf515105c", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "1abe8f758fc2a86b08edff80bbc687cfd41ebc1412cfec0ef4a0acfcd032052f"},
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jiffy": {:hex, :jiffy, "1.1.1", "aca10f47aa91697bf24ab9582c74e00e8e95474c7ef9f76d4f1a338d0f5de21b", [:rebar3], [], "hexpm", "62e1f0581c3c19c33a725c781dfa88410d8bff1bbafc3885a2552286b4785c4c"},
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
"luerl": {:hex, :luerl, "1.2.0", "60f05f4240f0e7c148ddb79b67b8ff972734aad237aa74c83d0748b8214c8ef0", [:rebar3], [], "hexpm", "9cafd4f6094ff0f5a9d278fd81d60d3e026c820bdfb6cacd4b1bd909f21b525d"},
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
"mqtree": {:hex, :mqtree, "1.0.16", "f8f8b4971e4ca94313ba9bcaaa1aa1077daaba5e3fd3468ffb491420a4cc3593", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c87d1c95575db65af29b795c9daa3bed43f5c1bf84072a74469659bcf53594eb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"p1_acme": {:git, "https://github.com/processone/p1_acme", "176b4a8c67627c3229fbea3c05d82a5d567e6e49", [branch: "master"]},
"p1_mysql": {:git, "https://github.com/processone/p1_mysql", "0dccb755a60cda61d41e7b092b344d38d1ebc802", []},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.14", "1c5f82535574de87e2059695ac4b91f8f9aebacbc1c80287dae6f02552d47aea", [:rebar3], [], "hexpm", "1fd3ac474e43722d9d5a87c6df8d36f698ed87af7bb81cbbb66361451d99ae8f"},
"p1_pgsql": {:git, "https://github.com/processone/p1_pgsql", "fe0bb2a2a2ae21cd9fc48b81520cfce508520a56", []},
"p1_utils": {:hex, :p1_utils, "1.0.25", "2d39b5015a567bbd2cc7033eeb93a7c60d8c84efe1ef69a3473faa07fa268187", [:rebar3], [], "hexpm", "9219214428f2c6e5d3187ff8eb9a8783695c2427420be9a259840e07ada32847"},
"pkix": {:git, "https://github.com/processone/pkix", "03be27c7168449bdfeb8c5b6cc0f800f71f8cfe9", []},
"sqlite3": {:hex, :sqlite3, "1.1.14", "f9ea0cff8540865fdfdb7e24eef34dc46677364b1c070896e99b5bf08c8a7fd7", [:rebar3], [], "hexpm", "85054b6ca297343c159ed6794a473ff2c8eeabd854b6fe02f711c0bfd373ce86"},
"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.12", "a65df67a8aaaecb6a94d687977b2e9f161820819910cb97bbe26a3525356525b", [:rebar3], [{:fast_tls, "1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "a2055032b6d338d0454142004bcb12fafb0c64ab1f273f1d0c6923ebbc8ede40"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"xmpp": {:git, "https://github.com/processone/xmpp", "a1fb778bd385d832f913e564558152ea507dac37", []},
"yconf": {:hex, :yconf, "1.0.15", "e22998b3d7728270bdd06162a9515bd142b14fae8927cbdbd3ef639c32aa6f7a", [:rebar3], [{:fast_yaml, "1.0.36", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "7ff2ab24d3c9833842716b9aaaa01a8f96641a7695cbb701b03445c4def01117"},
"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"},
"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"},
"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"},
"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"},
"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"},
}

View File

@ -136,7 +136,11 @@ ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {
margin-bottom: -1px;
}
thead tr td {
background: #cae7e4;
background: #3eaffa;
color: #fff;
}
thead tr td a {
color: #fff;
}
td.copy {
text-align: center;
@ -223,29 +227,22 @@ h3 {
padding-top: 25px;
width: 70%;
}
div.anchorlink {
display: inline-block;
float: right;
margin-top: 1em;
margin-right: 1em;
}
div.anchorlink a {
padding: 3px;
background: #cae7e4;
font-size: 0.75em;
color: black;
}
div.guidelink,
p[dir=ltr] {
display: inline-block;
float: right;
margin-top: 1em;
margin: 0;
margin-right: 1em;
}
div.guidelink a,
p[dir=ltr] a {
display: inline-block;
border-radius: 3px;
padding: 3px;
background: #3eaffa;
font-size: 0.75em;
color: #fff;
}
@ -268,7 +265,7 @@ input,
select {
font-size: 1em;
}
.result {
p.result {
border: 1px;
border-style: dashed;
border-color: #FE8A02;
@ -287,18 +284,3 @@ select {
color: #cb2431;
transition: none;
}
h3.api {
border-bottom: 1px solid #b6b6b6;
}
details > summary {
background-color: #dbeceb;
border: none;
cursor: pointer;
list-style: none;
padding: 8px;
}
details > pre, details > p {
background-color: #e6f1f0;
margin: 0;
padding: 10px;
}

View File

@ -16,14 +16,12 @@ a.roomjid {color: #336699; font-size: 24px; font-weight: bold; font-family: sans
div.logdate {color: #663399; font-size: 20px; font-weight: bold; font-family: sans-serif; letter-spacing: 2px; border-bottom: #224466 solid 1pt; margin-left:80pt; margin-top:20px;}
div.roomsubject {color: #336699; font-size: 18px; font-family: sans-serif; margin-left: 80pt; margin-bottom: 10px;}
div.rc {color: #336699; font-size: 12px; font-family: sans-serif; margin-left: 50%; text-align: right; background: #f3f6f9; border-bottom: 1px solid #336699; border-right: 4px solid #336699;}
div.rct {font-weight: bold; background: #e3e6e9; padding-right: 10px; cursor: pointer;}
div.rct:hover {text-decoration: underline;}
div.rct {font-weight: bold; background: #e3e6e9; padding-right: 10px;}
div.rcos {padding-right: 10px;}
div.rcoe {color: green;}
div.rcod {color: red;}
div.rcoe:after {content: ": v";}
div.rcod:after {content: ": x";}
div.rcot:after {}
div.jl {display: none;}
.legend {width: 100%; margin-top: 30px; border-top: #224466 solid 1pt; padding: 10px 0px 10px 0px; text-align: left; font-family: monospace; letter-spacing: 2px;}
.w3c {position: absolute; right: 10px; width: 60%; text-align: right; font-family: monospace; letter-spacing: 1px;}

View File

@ -1 +0,0 @@
.sortable thead th:not(.no-sort){cursor:pointer}.sortable thead th:not(.no-sort)::after,.sortable thead th:not(.no-sort)::before{transition:color .1s ease-in-out;font-size:1.2em;color:rgba(0,0,0,0)}.sortable thead th:not(.no-sort)::after{margin-left:3px;content:"▸"}.sortable thead th:not(.no-sort):hover::after{color:inherit}.sortable thead th:not(.no-sort)[aria-sort=descending]::after{color:inherit;content:"▾"}.sortable thead th:not(.no-sort)[aria-sort=ascending]::after{color:inherit;content:"▴"}.sortable thead th:not(.no-sort).indicator-left::after{content:""}.sortable thead th:not(.no-sort).indicator-left::before{margin-right:3px;content:"▸"}.sortable thead th:not(.no-sort).indicator-left:hover::before{color:inherit}.sortable thead th:not(.no-sort).indicator-left[aria-sort=descending]::before{color:inherit;content:"▾"}.sortable thead th:not(.no-sort).indicator-left[aria-sort=ascending]::before{color:inherit;content:"▴"}/*# sourceMappingURL=sortable-base.min.css.map */

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -6,14 +6,3 @@ function sh(e) {
document.getElementById(e).style.display='none';
}
}
// Show/Hide join/leave elements
function jlf() {
var es = document.getElementsByClassName('jl');
for (var i = 0; i < es.length; i++) {
if (es[i].style.display === 'block') {
es[i].style.display = 'none';
} else {
es[i].style.display = 'block';
}
}
}

View File

@ -1,3 +0,0 @@
document.addEventListener("click",function(c){try{function h(b,a){return b.nodeName===a?b:h(b.parentNode,a)}var v=c.shiftKey||c.altKey,d=h(c.target,"TH"),m=d.parentNode,n=m.parentNode,g=n.parentNode;function p(b){var a;return v?b.dataset.sortAlt:null!==(a=b.dataset.sort)&&void 0!==a?a:b.textContent}if("THEAD"===n.nodeName&&g.classList.contains("sortable")&&!d.classList.contains("no-sort")){var q,f=m.cells,r=+d.dataset.sortTbr;for(c=0;c<f.length;c++)f[c]===d?q=+d.dataset.sortCol||c:f[c].setAttribute("aria-sort",
"none");f="descending";if("descending"===d.getAttribute("aria-sort")||g.classList.contains("asc")&&"ascending"!==d.getAttribute("aria-sort"))f="ascending";d.setAttribute("aria-sort",f);var w="ascending"===f,x=g.classList.contains("n-last"),t=function(b,a,e){a=p(a.cells[e]);b=p(b.cells[e]);if(x){if(""===a&&""!==b)return-1;if(""===b&&""!==a)return 1}e=+a-+b;a=isNaN(e)?a.localeCompare(b):e;return w?-a:a};for(c=0;c<g.tBodies.length;c++){var k=g.tBodies[c],u=[].slice.call(k.rows,0);u.sort(function(b,a){var e=
t(b,a,q);return 0!==e||isNaN(r)?e:t(b,a,r)});var l=k.cloneNode();l.append.apply(l,u);g.replaceChild(l,k)}}}catch(h){}});

View File

@ -1,11 +0,0 @@
%% 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!): ","لم تتم إضافة \"المجموعات المعروضة\" (فهي غير موجودة!): "}.

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