Compare commits

..

1 Commits

Author SHA1 Message Date
Alexey Shchepin c8065b4be2 Added release tags
SVN Revision: 306
2005-04-17 00:21:31 +00:00
652 changed files with 8926 additions and 206629 deletions
-1
View File
@@ -1 +0,0 @@
FROM ghcr.io/processone/devcontainer:latest
-7
View File
@@ -1,7 +0,0 @@
{
"name": "ejabberd",
"build": {"dockerfile": "Dockerfile"},
"extensions": ["erlang-ls.erlang-ls"],
"postCreateCommand": ".devcontainer/prepare-container.sh",
"remoteUser": "vscode"
}
-3
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
-46
View File
@@ -1,46 +0,0 @@
.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
-31
View File
@@ -1,31 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
assignees: ''
---
Before creating a ticket, please consider if this should fit the [discussion forum](https://github.com/processone/ejabberd/discussions) better.
## Environment
- ejabberd version: 18.09
- Erlang version: `erl +V`
- OS: Linux (Debian)
- Installed from: source | distro package | official deb/rpm | official binary installer | other
## Configuration (only if needed): grep -Ev '^$|^\s*#' ejabberd.yml
```yaml
loglevel: 4
...
```
## Errors from error.log/crash.log
No errors
## Bug description
Please, give us a precise description (what does not work, what is expected, etc.)
-26
View File
@@ -1,26 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Kind:Feature
assignees: ''
---
Before creating a ticket, please consider if this should fit the [discussion forum](https://github.com/processone/ejabberd/discussions) better.
**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...
**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.
-20
View File
@@ -1,20 +0,0 @@
We are open to contributions for ejabberd, as GitHub pull requests (PR).
Here are a few points to consider before submitting your PR. (You can
remove the whole text after reading.)
1. Does this PR address an issue? Please reference it in the PR
description.
2. Have you properly described the proposed change?
3. Please make sure the change is atomic and does only touch the needed
modules. If you have other changes/fixes to provide, please submit
them as separate PRs.
4. If your change or new feature involves storage backends, did you make
sure your change works with all backends?
5. Do you provide tests? How can we check the behavior of the code?
6. Did you consider documentation changes in the
processone/docs.ejabberd.im repository?
-155
View File
@@ -1,155 +0,0 @@
name: 'Manage Database'
inputs:
for:
default: ""
description: 'One or more databases to manage:
mysql, pgsql, redis, mssql'
do:
default: ""
description: 'One or more tasks to do:
install, start, user, create, drop, dump'
dump-suffix:
default: ""
description: 'Suffix to append to the dump file name'
mssql-schema:
default: ""
description: 'SQL schema for the MSSQL database:
singlehost or multihost'
runs:
using: "composite"
steps:
############################################################# Install #####
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'install')
shell: sh
run: |
sudo sed -i 's/yes/no/g' /etc/initramfs-tools/update-initramfs.conf
sudo rm -f /var/lib/man-db/auto-update || echo ok
sudo apt-get -q update
sudo apt-get -q -y install postgresql
- if: contains(inputs.for, 'redis') && contains(inputs.do, 'install')
shell: sh
run: |
sudo sed -i 's/yes/no/g' /etc/initramfs-tools/update-initramfs.conf
sudo rm -f /var/lib/man-db/auto-update || echo ok
sudo apt-get -q update
sudo apt-get -q -y install redis-server
- if: contains(inputs.for, 'mssql') && contains(inputs.do, 'install')
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: tdsodbc
- if: contains(inputs.for, 'mssql') && contains(inputs.do, 'install')
shell: sh
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
docker exec ejabberd-mssql /opt/mssql-tools18/bin/sqlcmd \
-C -U SA -P ejabberd_Test1 -S localhost -i /initdb_mssql.sql
- if: contains(inputs.for, 'mssql') && contains(inputs.do, 'install')
&& inputs.mssql-schema == 'singlehost'
shell: sh
run: |
docker exec ejabberd-mssql /opt/mssql-tools18/bin/sqlcmd \
-C -U SA -P ejabberd_Test1 -S localhost -d ejabberd_test \
-i /mssql.sql
- if: contains(inputs.for, 'mssql') && contains(inputs.do, 'install')
&& inputs.mssql-schema == 'multihost'
shell: sh
run: |
docker exec ejabberd-mssql /opt/mssql-tools18/bin/sqlcmd \
-C -U SA -P ejabberd_Test1 -S localhost -d ejabberd_test \
-i /mssql.new.sql
############################################################### Start #####
- if: contains(inputs.for, 'mysql') && contains(inputs.do, 'start')
shell: sh
run: |
sudo systemctl start mysql.service
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'start')
shell: sh
run: |
sudo systemctl start postgresql.service
pg_isready
################################################################ User #####
- if: contains(inputs.for, 'mysql') && contains(inputs.do, 'user')
shell: sh
run: |
mysql -u root -proot -e "CREATE USER 'ejabberd_test'@'localhost'
IDENTIFIED BY 'ejabberd_test';"
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'user')
shell: sh
run: |
sudo -u postgres psql -c "CREATE USER ejabberd_test
WITH PASSWORD 'ejabberd_test';"
################################################################ Dump #####
- if: contains(inputs.for, 'mysql') && contains(inputs.do, 'dump')
shell: sh
run: |
sudo mysqldump -u root -proot ejabberd_test \
> mysql-${{ inputs.dump-suffix }}.sql
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'dump')
shell: sh
run: |
sudo -u postgres pg_dump ejabberd_test \
> pgsql-${{ inputs.dump-suffix }}.sql
################################################################ Drop #####
- if: contains(inputs.for, 'mysql') && contains(inputs.do, 'drop')
shell: sh
run: |
mysql -u root -proot -e "DROP DATABASE ejabberd_test;"
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'drop')
shell: sh
run: |
sudo -u postgres psql -c "DROP DATABASE ejabberd_test;"
############################################################## Create #####
- if: contains(inputs.for, 'mysql') && contains(inputs.do, 'create')
shell: sh
run: |
mysql -u root -proot -e "CREATE DATABASE ejabberd_test;"
mysql -u root -proot -e "GRANT ALL ON ejabberd_test.*
TO 'ejabberd_test'@'localhost';"
- if: contains(inputs.for, 'pgsql') && contains(inputs.do, 'create')
shell: sh
run: |
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 -c "GRANT ALL ON SCHEMA public TO ejabberd_test;"
sudo -u postgres psql -c "ALTER DATABASE ejabberd_test
OWNER 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;"
-195
View File
@@ -1,195 +0,0 @@
name: 'Manage ejabberd'
inputs:
for:
default: ""
description: 'Release method, one of:
prod, dev, install, run, deb'
do:
default: ""
description: 'One or more tasks to perform:
deploy, no_acme, no_tls,
start, register, update_sql, stop,
check, logs'
username:
default: "user1"
description: 'Username part of the account JID'
host:
default: "localhost"
description: 'Host part of the account JID'
tool:
default: "rebar3"
description: 'Build tool to use:
rebar or rebar3 (only relevant to make rebar2)'
rel_name_vsn:
default: ""
description: 'Base name of installer files'
configure:
default: ""
description: 'Options to append to ./configure'
runs:
using: "composite"
steps:
- name: Path Definitions
id: path
shell: bash
run: |
case ${{ inputs.for }} in
'prod')
BASE="_build/prod/rel/ejabberd"
echo "conf=$BASE/conf" >> $GITHUB_OUTPUT
echo "logs=$BASE/logs" >> $GITHUB_OUTPUT
echo "ectl=$BASE/bin/ejabberdctl" >> $GITHUB_OUTPUT
;;
'dev')
BASE="_build/dev/rel/ejabberd"
echo "conf=$BASE/conf" >> $GITHUB_OUTPUT
echo "logs=$BASE/logs" >> $GITHUB_OUTPUT
echo "ectl=$BASE/bin/ejabberdctl" >> $GITHUB_OUTPUT
;;
'install')
BASE="/tmp/ejabberd"
echo "conf=$BASE/etc/ejabberd" >> $GITHUB_OUTPUT
echo "logs=$BASE/var/log/ejabberd" >> $GITHUB_OUTPUT
echo "ectl=$BASE/sbin/ejabberdctl" >> $GITHUB_OUTPUT
;;
'deb')
BASE="/opt/ejabberd"
echo "base=$BASE" >> $GITHUB_OUTPUT
echo "conf=$BASE/conf" >> $GITHUB_OUTPUT
echo "logs=$BASE/logs" >> $GITHUB_OUTPUT
echo "ectl=sudo /opt/${{ inputs.rel_name_vsn }}/bin/ejabberdctl" >> $GITHUB_OUTPUT
;;
'run')
BASE="$HOME/opt/ejabberd"
echo "base=$BASE" >> $GITHUB_OUTPUT
echo "conf=$BASE/conf" >> $GITHUB_OUTPUT
echo "logs=$BASE/logs" >> $GITHUB_OUTPUT
echo "ectl=$HOME/opt/${{ inputs.rel_name_vsn }}/bin/ejabberdctl" >> $GITHUB_OUTPUT
;;
esac
############################################################# Compile #####
- if: contains(inputs.do, 'compile')
shell: sh
run: |
TOOL=${{ inputs.tool }}
[ "${TOOL%3}" = "rebar" ] && TOOL="./$TOOL"
./autogen.sh
./configure --with-rebar=$TOOL \
--prefix=/tmp/ejabberd \
--enable-all ${{ inputs.configure }}
sed -i 's|, syntax_tools||g' src/ejabberd.app.src.script
REBAR_PROFILE=test make
############################################################## Deploy #####
- if: contains(inputs.do, 'deploy') &&
inputs.for == 'prod' && inputs.tool == 'rebar'
shell: sh
run: |
mkdir -p _build/prod && ln -s `pwd`/rel/ _build/prod/rel
- if: contains(inputs.do, 'deploy') &&
inputs.for == 'dev' && inputs.tool == 'rebar'
shell: sh
run: |
mkdir -p _build/dev && ln -s `pwd`/rel/ _build/dev/rel
- if: contains(inputs.do, 'deploy') &&
(inputs.for == 'prod' ||
inputs.for == 'dev' ||
inputs.for == 'install')
shell: sh
run: |
make ${{ inputs.for }}
- if: contains(inputs.do, 'deploy') &&
inputs.for == 'deb'
shell: sh
run: |
sudo dpkg -i $(ls -1 *.deb)
- if: contains(inputs.do, 'deploy') &&
inputs.for == 'run'
shell: sh
run: |
./$(ls -1 *.run)
################################################################ ACME #####
- if: contains(inputs.do, 'no_acme')
shell: sh
run: |
sed -i 's/loglevel/acme:\n auto: false\nloglevel/g' \
${{ steps.path.outputs.conf }}/ejabberd.yml
################################################################# TLS #####
- if: contains(inputs.do, 'no_tls') &&
inputs.for == 'dev'
shell: sh
run: |
sed -i 's/starttls_required: true/starttls_required: false/g' \
${{ steps.path.outputs.conf }}/ejabberd.yml
############################################################### Start #####
- if: contains(inputs.do, 'start')
shell: sh
run: |
${{ steps.path.outputs.ectl }} start
${{ steps.path.outputs.ectl }} started
############################################################ Register #####
- if: contains(inputs.do, 'register')
shell: sh
run: |
${{ steps.path.outputs.ectl }} \
register ${{ inputs.username }} ${{ inputs.host }} s0mePass
${{ steps.path.outputs.ectl }} \
registered_users ${{ inputs.host }} >> registered.log
grep -q '${{ inputs.username }}' registered.log
########################################################### UpdateSQL #####
- if: contains(inputs.do, 'update_sql')
shell: sh
run: |
${{ steps.path.outputs.ectl }} \
update_sql
################################################################ Stop #####
- if: contains(inputs.do, 'stop')
shell: sh
run: |
${{ steps.path.outputs.ectl }} stop
${{ steps.path.outputs.ectl }} stopped
############################################################### Check #####
- if: contains(inputs.do, 'check')
shell: sh
run: |
grep -q 'is started' ${{ steps.path.outputs.logs }}/ejabberd.log
grep -q 'is stopped' ${{ steps.path.outputs.logs }}/ejabberd.log
test $(find ${{ steps.path.outputs.logs }}/ -empty -name error.log)
################################################################ Logs #####
- if: contains(inputs.do, 'logs') || failure()
shell: sh
run: |
SUDO=sudo
[ "${{ inputs.for }}" = "deb" ] || SUDO=""
echo "::group::View ejabberd.log"
$SUDO cat ${{ steps.path.outputs.logs }}/ejabberd.log
echo "::endgroup::"
echo "::group::View error.log"
$SUDO cat ${{ steps.path.outputs.logs }}/error.log
echo "::endgroup::"
-208
View File
@@ -1,208 +0,0 @@
#' Define default build variables
ARG OTP_VSN='28.4.1.0'
ARG ELIXIR_VSN='1.19.5'
ARG UID='9000'
ARG USER='ejabberd'
ARG HOME="opt/$USER"
ARG BUILD_DIR="/$USER"
ARG VERSION='master'
################################################################################
#' Compile ejabberdapi
FROM docker.io/golang:1.25-alpine AS api
RUN go install -v \
github.com/processone/ejabberd-api/cmd/ejabberd@master \
&& mv bin/ejabberd bin/ejabberdapi
################################################################################
#' build and install ejabberd directly from source
FROM docker.io/erlang:${OTP_VSN}-alpine AS ejabberd
RUN apk -U add --no-cache \
ca-certificates \
autoconf \
automake \
bash \
build-base \
curl \
expat-dev \
file \
gd-dev \
git \
jpeg-dev \
libpng-dev \
libwebp-dev \
linux-pam-dev \
npm \
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
ENV ERL_FLAGS="+JPperf true"
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 . \
&& mv .github/container/ejabberd.yml.example . \
&& ./autogen.sh \
&& ./configure --with-rebar=mix --enable-all \
&& make deps \
&& make prod
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'
#' Prepare ejabberd for runtime
RUN apk -U add --no-cache \
git \
libcap \
openssl
RUN mkdir -p usr/local/bin $HOME/conf $HOME/database $HOME/logs $HOME/upload
COPY --from=api /go/bin/ejabberdapi usr/local/bin/
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 sed -i 's|^#CTL_OVER_HTTP=|CTL_OVER_HTTP=../|' "$HOME/conf/ejabberdctl.cfg"
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 EMA=\"\$EJABBERD_MACRO_ADMIN\" \
\nexport HOST=\"\${EJABBERD_MACRO_HOST:-localhost}\" \
\nif [ -n \"\$EMA\" ] \
\nthen \
\n if [ \"\$EMA\" != \"\${EMA%%@*}\" ] \
\n then \
\n export USERNAME=\"\${EMA%%@*}\" \
\n export HOST=\"\${EMA##*@}\" \
\n else \
\n export USERNAME=\"\$EMA\" \
\n export SHOW_WARNING=\"true\" \
\n fi \
\nelif [ -n \"\$REGISTER_ADMIN_PASSWORD\" ] \
\nthen \
\n export USERNAME=\"admin\" \
\nelse \
\n export USERNAME=\"\$(od -A n -N 8 -t x8 /dev/urandom)\" \
\nfi \
\nexport EJABBERD_MACRO_ADMIN=\"\$USERNAME@\$HOST\" \
\n[ -n \"\$SHOW_WARNING\" ] && echo \"WARNING: The EJABBERD_MACRO_ADMIN environment variable was set to '\$EMA', but it should include the host... I'll overwrite it to become '\$EJABBERD_MACRO_ADMIN'.\" \
\n[ -n \"\$CTL_ON_CREATE\" ] && export SEPARATOR=\";\" \
\n[ -n \"\$REGISTER_ADMIN_PASSWORD\" ] && export CTL_ON_CREATE=\"register \${EJABBERD_MACRO_ADMIN%%@*} \${EJABBERD_MACRO_ADMIN##*@} \$REGISTER_ADMIN_PASSWORD \$SEPARATOR \$CTL_ON_CREATE\" \
\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
RUN cp /rootfs/$HOME-$VERSION/lib/captcha*.sh usr/local/bin/
RUN mkdir $HOME/sql \
&& find /rootfs/$HOME-$VERSION/lib/ -name *.sql -exec cp {} $HOME/sql \; -exec cp {} $HOME/database \;
################################################################################
#' Remove erlang/OTP & rebar3
FROM docker.io/erlang:${OTP_VSN}-alpine AS runtime
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
#' Update alpine, finalize runtime environment
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 \
curl \
tini \
&& rm /tmp/runDeps
ARG USER
ARG UID
ARG HOME
RUN addgroup $USER -g $UID \
&& adduser -s /sbin/nologin -D -u $UID -h /$HOME -G $USER $USER
RUN ln -fs /usr/local/bin/ /opt/ejabberd/bin
RUN rm -rf /home \
&& ln -fs /opt /home
################################################################################
#' Build together production image
FROM scratch
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 1880 1883 4369-4399 5210 5222 5269 5280 5443 5478 7777 50000-50099
ENTRYPOINT ["/sbin/tini","--","ejabberdctl"]
CMD ["foreground"]
@@ -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
-289
View File
@@ -1,289 +0,0 @@
###
### ejabberd configuration file
###
### The parameters used in this configuration file are explained at
###
### https://docs.ejabberd.im/admin/configuration
###
### The configuration file is written in YAML.
### *******************************************************
### ******* !!! WARNING !!! *******
### ******* YAML IS INDENTATION SENSITIVE *******
### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******
### *******************************************************
### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.
###
define_macro:
HOST: localhost
## ADMIN: ... # set by /usr/local/bin/ejabberdctl
PORT_C2S: 5222
PORT_C2S_TLS: 5223
PORT_S2S: 5269
PORT_HTTP_TLS: 5443
PORT_HTTP: 5280
PORT_BROWSER: 1880
PORT_STUN: 5478
PORT_TURN_MIN: 50000
PORT_TURN_MAX: 50099
PORT_MQTT: 1883
PORT_PROXY65: 7777
STARTTLS_REQUIRED: true
hosts:
- HOST
loglevel: info
## If you already have certificates, list them here
# certfiles:
# - /etc/letsencrypt/live/domain.tld/fullchain.pem
# - /etc/letsencrypt/live/domain.tld/privkey.pem
ca_file: /opt/ejabberd/conf/cacert.pem
certfiles:
- /opt/ejabberd/conf/server.pem
listen:
-
port: PORT_C2S
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: STARTTLS_REQUIRED
-
port: PORT_C2S_TLS
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
-
port: PORT_S2S
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
-
port: PORT_HTTP_TLS
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/websocket: ejabberd_http_ws
-
port: PORT_HTTP
ip: "::"
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
-
port: PORT_BROWSER
ip: "::"
module: ejabberd_http
request_handlers:
/: ejabberd_web_admin
-
port: "unix:../sockets/ctl_over_http.sock"
module: ejabberd_http
unix_socket:
mode: '0600'
request_handlers:
/ctl: ejabberd_ctl
-
port: PORT_STUN
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
turn_min_port: PORT_TURN_MIN
turn_max_port: PORT_TURN_MAX
## The server's public IPv4 address:
# turn_ipv4_address: "203.0.113.3"
## The server's public IPv6 address:
# turn_ipv6_address: "2001:db8::3"
-
port: PORT_MQTT
ip: "::"
module: mod_mqtt
backlog: 1000
s2s_use_starttls: optional
acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
admin:
user:
- ADMIN
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
api_permissions:
"console commands":
from: ejabberd_ctl
who: all
what: "*"
"webadmin commands":
from: ejabberd_web_admin
who: admin
what: "*"
"adhoc commands":
from: mod_adhoc_api
who: admin
what: "*"
"http access":
from: mod_http_api
who:
access:
allow:
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number
shaper:
normal:
rate: 3000
burst_size: 20000
fast: 100000
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
100: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
modules:
mod_adhoc: {}
mod_adhoc_api: {}
mod_admin_extra: {}
mod_announce:
access: announce
mod_avatar: {}
mod_blocking: {}
mod_bosh: {}
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_disco: {}
mod_fail2ban: {}
mod_http_api: {}
mod_http_upload:
put_url: https://@HOST_URL_ENCODE@:5443/upload
custom_headers:
"Access-Control-Allow-Origin": "https://@HOST@"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_last: {}
mod_mam:
## Mnesia is limited to 2GB, better to use an SQL backend
## For small servers SQLite is a good fit and is very easy
## to configure. Uncomment this when you have SQL configured:
## db_type: sql
assume_mam_usage: true
default: always
mod_mqtt: {}
mod_muc:
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
default_room_options:
mam: true
mod_muc_admin: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_proxy65:
access: local
max_connections: 5
port: PORT_PROXY65
mod_pubsub:
access_createnode: pubsub_createnode
plugins:
- flat
- pep
force_node_config:
## Avoid buggy clients to make their bookmarks public
storage:bookmarks:
access_model: whitelist
mod_push: {}
mod_push_keepalive: {}
mod_register:
## Only accept registration requests from the "trusted"
## network (see access_rules section above).
## Think twice before enabling registration from any
## address. See the Jabber SPAM Manifesto for details:
## https://github.com/ge0rg/jabber-spam-fighting-manifesto
ip_access: trusted_network
mod_roster:
versioning: true
mod_s2s_bidi: {}
mod_s2s_dialback: {}
mod_shared_roster: {}
mod_stream_mgmt:
resend_on_timeout: if_offline
mod_stun_disco: {}
mod_vcard: {}
mod_vcard_xupdate: {}
mod_version:
show_os: false
### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8
-652
View File
@@ -1,652 +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%@*}" ] && ERLANG_NODE="$ERLANG_NODE@$(hostname -s)"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# backward support for old mnesia spool dir path
: "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}"
[ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD"
# 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
# Only required for Erlang/OTP 25:
export ERL_FLAGS="$ERL_FLAGS -enable-feature maybe_expr"
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,$(uname -s) in
as_install_user,OpenBSD)
su -s /bin/sh "$INSTALLUSER" -c 'exec "$0" "$@"' "$@"
;;
as_install_user,NetBSD)
su "$INSTALLUSER" -c 'exec "$0" "$@"' -- "$@"
;;
as_install_user,*)
su -s /bin/sh -c 'exec "$0" "$@"' "$INSTALLUSER" -- "$@"
;;
as_current_user,*)
"$@"
;;
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 stop ejabberd gracefully:"
echo " ejabberd:stop()."
echo "To quit erlang immediately, 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()
{
ECSIMAGE_DBPATH=$HOME/database/$ERLANG_NODE
[ ! -d "$ECSIMAGE_DBPATH" ] && ln -s $HOME/database $HOME/database/$ERLANG_NODE
[ -n "$ERL_DIST_PORT" ] && {
netstat -nl | grep ":5210" >/dev/null && {
echo "Error: The file ejabberdctl.cfg has configured ERL_DIST_PORT=$ERL_DIST_PORT"
echo " but the port 5210 is already in use."
echo " Stop that program or configure a different ERL_DIST_PORT"
echo ""
netstat -nlp | grep ":5210"
echo ""
}
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()
{
wait_status_node "$ERLANG_NODE" $1 $2 $3
}
wait_status_node()
{
CONNECT_NODE=$1
shift
# 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('"'$CONNECT_NODE'"')' \
-s ejabberd_ctl \
-extra "$CONNECT_NODE" $NO_TIMEOUT status > /dev/null
status="$?"
fi
done
[ $timeout -gt 0 ]
}
exec_other_command()
{
exec_other_command_node $ERLANG_NODE "$@"
}
exec_other_command_node()
{
CONNECT_NODE=$1
shift
if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
|| [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
|| [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
run_erl "$(uid ctl)" -hidden -noinput \
-eval 'net_kernel:connect_node('"'$CONNECT_NODE'"')' \
-s ejabberd_ctl \
-extra "$CONNECT_NODE" $NO_TIMEOUT "$@"
result=$?
case $result in
3) help;;
*) :;;
esac
return $result
else
exec_ctl_over_http_socket "$@"
fi
}
exec_ctl_over_http_socket()
{
COMMAND=${1}
CARGS=""
while [ $# -gt 0 ]; do
[ -z "$CARGS" ] && CARGS="[" || CARGS="${CARGS}, "
CARGS="${CARGS}\"$1\""
shift
done
CARGS="${CARGS}]"
TEMPHEADERS=temp-headers.log
curl \
--unix-socket ${CTL_OVER_HTTP} \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "${CARGS}" \
--dump-header ${TEMPHEADERS} \
--no-progress-meter \
"http://localhost/ctl/${COMMAND}"
result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
rm ${TEMPHEADERS}
case $result in
2|3) exec_other_command help ${COMMAND};;
*) :;;
esac
exit $result
}
# 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
}
printe()
{
printf "\n"
printf "\e[1;40;32m==> %s\e[0m\n" "$1"
}
## Function copied from tools/make-installers
user_agrees()
{
question="$*"
if [ -t 0 ]
then
printe "$question (y/n) [n]"
read -r response
case "$response" in
[Yy]|[Yy][Ee][Ss])
return 0
;;
[Nn]|[Nn][Oo]|'')
return 1
;;
*)
echo 'Please respond with "yes" or "no".'
user_agrees "$question"
;;
esac
else # Assume 'yes' if not running interactively.
return 0
fi
}
mnesia_change()
{
ERLANG_NODE_OLD="$1"
[ "$ERLANG_NODE_OLD" = "" ] \
&& echo "Error: Please provide the old erlang node name, for example:" \
&& echo " ejabberdctl mnesia_change ejabberd@oldmachine" \
&& exit 1
SPOOL_DIR_BACKUP=$SPOOL_DIR/$ERLANG_NODE_OLD-backup/
OLDFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE_OLD.backup
NEWFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE.backup
printe "This changes your mnesia database from node name '$ERLANG_NODE_OLD' to '$ERLANG_NODE'"
[ -d "$SPOOL_DIR_BACKUP" ] && printe "WARNING! A backup of old node already exists in $SPOOL_DIR_BACKUP"
if ! user_agrees "Do you want to proceed?"
then
echo 'Operation aborted.'
exit 1
fi
printe "Starting ejabberd with old node name $ERLANG_NODE_OLD ..."
exec_erl "$ERLANG_NODE_OLD" $EJABBERD_OPTS -detached
wait_status_node $ERLANG_NODE_OLD 0 30 2
result=$?
case $result in
1) echo "There was a problem starting ejabberd with the old erlang node name. " \
&& echo "Check for log errors in $EJABBERD_LOG_PATH" \
&& exit $result;;
*) :;;
esac
exec_other_command_node $ERLANG_NODE_OLD "status"
printe "Making backup of old database to file $OLDFILE ..."
mkdir $SPOOL_DIR_BACKUP
exec_other_command_node $ERLANG_NODE_OLD backup "$OLDFILE"
printe "Changing node name in new backup file $NEWFILE ..."
exec_other_command_node $ERLANG_NODE_OLD mnesia_change_nodename "$ERLANG_NODE_OLD" "$ERLANG_NODE" "$OLDFILE" "$NEWFILE"
printe "Stopping old ejabberd..."
exec_other_command_node $ERLANG_NODE_OLD "stop"
wait_status_node $ERLANG_NODE_OLD 3 30 2 && stop_epmd
printe "Moving old mnesia spool files to backup subdirectory $SPOOL_DIR_BACKUP ..."
mv $SPOOL_DIR/*.DAT $SPOOL_DIR_BACKUP
mv $SPOOL_DIR/*.DCD $SPOOL_DIR_BACKUP
mv $SPOOL_DIR/*.LOG $SPOOL_DIR_BACKUP
printe "Starting ejabberd with new node name $ERLANG_NODE ..."
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached
wait_status 0 30 2
exec_other_command "status"
printe "Installing fallback of new mnesia..."
exec_other_command install_fallback "$NEWFILE"
printe "Stopping new ejabberd..."
exec_other_command "stop"
wait_status 3 30 2 && stop_epmd
printe "Finished, now you can start ejabberd normally"
}
# 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'"')])' \
-eval 'halt(case net_adm:ping('"'$PEER'"') of pong -> 0; pang -> 1 end).' \
-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
;;
mnesia_change)
mnesia_change $2
;;
post_waiter)
post_waiter_waiting
;;
*)
set_dist_client
exec_other_command "$@"
;;
esac
-38
View File
@@ -1,38 +0,0 @@
# Configuration for Lock Threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 365
# Skip issues and pull requests created before a given timestamp. Timestamp must
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
skipCreatedBefore: false
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
exemptLabels: []
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
# exemptLabels:
# - help-wanted
# lockLabel: outdated
# pulls:
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo
-417
View File
@@ -1,417 +0,0 @@
name: CI
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
pull_request:
paths-ignore:
- '.devcontainer/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
env:
DEV: _build/dev/rel/ejabberd
jobs:
############################################################### Compile #####
compile:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['28']
steps:
- uses: actions/checkout@v6
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libexpat1-dev libgd-dev libpam0g-dev
libsqlite3-dev libwebp-dev libyaml-dev
- name: Cache rebar3
uses: actions/cache@v5
with:
path: |
~/.cache/rebar3/
_build/default/lib/
key: ci-${{ matrix.otp }}-${{hashFiles('rebar.*')}}
- name: Compile
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: compile
tool: rebar3
configure: --disable-elixir
- name: Compress compiled.tar
run: |
tar -cvf /tmp/compiled.tar .
- uses: actions/upload-artifact@v6
with:
name: compiled-${{ matrix.otp }}
path: /tmp/compiled.tar
retention-days: 1
########################################################## Static Tests #####
static:
needs: compile
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['28']
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: actions/download-artifact@v7
with:
name: compiled-${{ matrix.otp }}
- run: tar -xf compiled.tar
- name: Test shell scripts
run: |
shellcheck ejabberd.init.template
shellcheck -x ejabberdctl.template
shellcheck .vscode/relive.sh
shellcheck rel/setup-dev.sh
shellcheck rel/setup-relive.sh
shellcheck test/ejabberd_SUITE_data/gencerts.sh
shellcheck tools/captcha.sh
shellcheck tools/emacs-indent.sh
shellcheck tools/generate-doap.sh
shellcheck tools/prepare-tr.sh
shellcheck tools/rebar3-format.sh
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- run: make testeunit
- run: make elvis
if: matrix.otp > '25'
- run: make install -s
######################################################### Dynamic Tests #####
dynamic:
needs: compile
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['28']
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.otp < '28'
with:
packages: libexpat1-dev libgd-dev libpam0g-dev
libsqlite3-dev libwebp-dev libyaml-dev
- uses: actions/download-artifact@v7
with:
name: compiled-${{ matrix.otp }}
- run: tar -xf compiled.tar
- name: Check production release
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: deploy, start, stop, check
- name: Start development release
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: deploy, no_tls, start, register
username: user123
- name: Run XMPP Interoperability Tests against CI server
if: matrix.otp == '28'
continue-on-error: true
uses: XMPP-Interop-Testing/xmpp-interop-tests-action@v1.7.2
with:
domain: 'localhost'
adminAccountUsername: 'user123'
adminAccountPassword: 's0mePass'
disabledSpecifications: RFC6121,XEP-0030,XEP-0045,XEP-0054,XEP-0060,
XEP-0080,XEP-0115,XEP-0118,XEP-0215,XEP-0347,
XEP-0363,XEP-0384,XEP-0421
- name: Stop development release
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: stop, check
- name: View production logs
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: logs
- name: View development logs
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: logs
##################################################### Common Test Suite #####
ct:
needs: compile
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['28']
backend: [agnostic, extauth, ldap, mnesia, mysql, pgsql, redis, sqlite]
schema: [single, multi]
exclude:
- backend: agnostic
schema: single
- backend: extauth
schema: single
- backend: ldap
schema: single
- backend: mnesia
schema: single
- backend: redis
schema: single
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: actions/download-artifact@v7
with:
name: compiled-${{ matrix.otp }}
- run: tar -xf compiled.tar
- name: Prepare database
uses: ./.github/actions/manage-database
with:
for: ${{ matrix.backend }}
do: install, start, user, create
- name: Setup multihost SQL schema
if: matrix.schema == 'multi'
run: |
sed -i 's|multihost_schema, false|multihost_schema, true|g' \
test/suite.erl
- name: Run tests
id: ct
run: CT_BACKENDS=${{ matrix.backend }} make test
- name: Send to coveralls
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DIAGNOSTIC=1 ./rebar3 as test coveralls send
- name: Check results
if: always() && (steps.ct.outcome != 'skipped')
id: ctresults
run: |
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View logs
if: always()
run: |
echo "::group::ejabberd.log"
find logs/ -name ejabberd.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::error.log"
find logs/ -name error.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::exunit.log"
find logs/ -name exunit.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::suite.log (only failures)"
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
echo "::endgroup::"
echo "::group::suite.log (complete)"
cat logs/suite.log
echo "::endgroup::"
- name: Upload CT logs
if: failure()
uses: actions/upload-artifact@v6
with:
name: ct-logs-${{ matrix.otp }}-${{ matrix.backend }}-${{ matrix.schema }}
path: _build/test/logs
retention-days: 14
############################################################# Coveralls #####
cover:
needs: ct
runs-on: ubuntu-24.04-arm
steps:
- name: Finish parallel upload to coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -v -k https://coveralls.io/webhook \
--header "Content-Type: application/json" \
--data '{"repo_name":"$GITHUB_REPOSITORY",
"repo_token":"$GITHUB_TOKEN",
"payload":{"build_num":$GITHUB_RUN_ID,
"status":"done"}}'
################################################################ Schema #####
schema:
needs: compile
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['28']
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: actions/download-artifact@v7
with:
name: compiled-${{ matrix.otp }}
- run: tar -xf compiled.tar
###################################### multi-changed ##
- name: Prepare databases
uses: ./.github/actions/manage-database
with:
for: mysql, pgsql
do: install, start, user, create
- name: Prepare configuration
run: |
CT_BACKENDS=mysql,pgsql ./rebar3 ct \
--suite=test/ejabberd_SUITE --group=configtest_single
make dev
cp test/ejabberd_SUITE_data/ejabberd.yml ${{ env.DEV }}/conf/
cp _build/test/logs/last/*.yml ${{ env.DEV }}/database/
echo "define_macro: [CONFIGTEST_CONFIG: {modules: {mod_muc: {}}}]" \
> ${{ env.DEV }}/database/configtest.yml
cp _build/test/logs/last/*.pem ${{ env.DEV }}/conf/
cp _build/test/logs/last/*.pem ${{ env.DEV }}/database/
- name: Run ejabberd
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: start, update_sql, stop, check, logs
username: user2
- name: Dump multihost databases
uses: ./.github/actions/manage-database
with:
for: mysql, pgsql
do: dump
dump-suffix: multi-changed
######################################### multi-auto ##
- name: Prepare databases
uses: ./.github/actions/manage-database
with:
for: mysql, pgsql
do: drop, create
- name: Configure multihost schema
run: |
sed -i 's|MULTIHOST_SCHEMA|true|g' ${{ env.DEV }}/conf/ejabberd.yml
- name: Run ejabberd for multihost
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: start, stop, check, logs
username: user2
- name: Dump multihost databases
uses: ./.github/actions/manage-database
with:
for: mysql, pgsql
do: dump
dump-suffix: multi-auto
############################################ compare ##
- name: View SQL schemas (mysql)
run: |
perl test/ejabberd_SUITE_data/sql_sort.pl \
<mysql-multi-auto.sql >mysql-multi2.sql
perl test/ejabberd_SUITE_data/sql_sort.pl \
<mysql-multi-changed.sql >mysql-changed2.sql
echo "::group::differences multi-auto > multi-changed"
diff -u mysql-multi2.sql mysql-changed2.sql || echo ok
echo "::endgroup::"
echo "::group::multi-auto.sql"
cat mysql-multi-auto.sql
echo "::endgroup::"
echo "::group::multi-changed.sql"
cat mysql-multi-changed.sql
echo "::endgroup::"
- name: View SQL schemas (pgsql)
run: |
perl test/ejabberd_SUITE_data/sql_sort.pl \
<pgsql-multi-auto.sql >pgsql-multi2.sql
perl test/ejabberd_SUITE_data/sql_sort.pl \
<pgsql-multi-changed.sql >pgsql-changed2.sql
echo "::group::differences (multi-auto > multi-changed)"
diff -u pgsql-multi2.sql pgsql-changed2.sql || echo ok
echo "::endgroup::"
echo "::group::multi-auto.sql"
cat pgsql-multi-auto.sql
echo "::endgroup::"
echo "::group::multi-changed.sql"
cat pgsql-multi-changed.sql
echo "::endgroup::"
- name: View ejabberd logs
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: logs
-119
View File
@@ -1,119 +0,0 @@
name: Container
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-24.04${{ matrix.suffix }}
strategy:
matrix:
platform: [amd64, arm64]
include:
- platform: amd64
suffix:
- platform: arm64
suffix: -arm
permissions:
packages: write
steps:
- name: Check out repository code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Checkout ejabberd-contrib
uses: actions/checkout@v6
with:
repository: processone/ejabberd-contrib
path: .ejabberd-modules/sources/ejabberd-contrib
- 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
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: suffix=--${{ matrix.platform }}
labels: |
org.opencontainers.image.revision=${{ steps.gitdescribe.outputs.ver }}
org.opencontainers.image.licenses=GPL-2.0
org.opencontainers.image.vendor=ProcessOne
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
build-args: |
VERSION=${{ steps.gitdescribe.outputs.ver }}
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
file: .github/container/Dockerfile
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/${{ matrix.platform }}
push: true
tags: ${{ steps.meta.outputs.tags }}
merge:
needs: [build]
runs-on: ubuntu-24.04
outputs:
image-uri: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.merge.outputs.digest }}
steps:
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta-amd
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: suffix=--amd64
- uses: docker/metadata-action@v5
id: meta-arm
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: suffix=--arm64
- uses: docker/metadata-action@v5
id: meta-result
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: int128/docker-manifest-create-action@v2
id: merge
with:
index-annotations: ${{ steps.metadata.outputs.labels }}
tags: ${{ steps.meta-result.outputs.tags }}
sources: |
${{ steps.meta-amd.outputs.tags }}
${{ steps.meta-arm.outputs.tags }}
#- uses: dataaxiom/ghcr-cleanup-action@v1
# with:
# dry-run: true
# delete-tags: '*--a??64'
# delete-untagged: true
# delete-ghost-images: true
# delete-partial-images: true
# delete-orphaned-images: true
-109
View File
@@ -1,109 +0,0 @@
name: Installers
on:
push:
paths-ignore:
- '.devcontainer/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
pull_request:
paths-ignore:
- '.devcontainer/**'
- 'lib/**'
- 'man/**'
- 'priv/**'
- '**.md'
jobs:
binaries:
runs-on: ubuntu-22.04${{ matrix.suffix }}
strategy:
matrix:
platform: [amd64, arm64]
include:
- platform: amd64
suffix:
- platform: arm64
suffix: -arm
steps:
- name: Check out repository code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Cache build directory
uses: actions/cache@v5
with:
path: ~/build/
key: installers-ubuntu-22.04-${{runner.arch}}-${{hashFiles('tools/make-binaries')}}
- 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: 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
- run: echo "rel_name_vsn=$(ls *.run | sed 's/-1-linux.*//g')" >> $GITHUB_OUTPUT
id: vsn
- name: Test RUN
uses: ./.github/actions/manage-ejabberd
with:
for: run
do: deploy, no_acme, start, register, stop, check, logs
username: user1
host: $(hostname --fqdn)
rel_name_vsn: ${{ steps.vsn.outputs.rel_name_vsn }}
- name: Test DEB
uses: ./.github/actions/manage-ejabberd
with:
for: deb
do: deploy, register, stop, logs
username: user1
host: $(hostname --fqdn)
rel_name_vsn: ${{ steps.vsn.outputs.rel_name_vsn }}
- name: Collect packages
run: |
mkdir ejabberd-packages
mv ejabberd_*.deb ejabberd-*.rpm ejabberd-*.run ejabberd-packages
- name: Upload packages
uses: actions/upload-artifact@v6
with:
name: ejabberd-packages-${{ matrix.platform }}
#
# 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@v7
with:
merge-multiple: true
- name: Draft Release
uses: softprops/action-gh-release@v2
with:
draft: true
files: ejabberd-packages/*
-270
View File
@@ -1,270 +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 #####
rebars:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['25', '26', '27', '28', '29']
rebar: ['rebar', 'rebar3']
exclude:
- otp: '27'
rebar: 'rebar'
- otp: '28'
rebar: 'rebar'
- otp: '29'
rebar: 'rebar'
container:
image: public.ecr.aws/docker/library/erlang:${{ matrix.otp }}
steps:
- uses: actions/checkout@v6
- name: Prepare libraries
run: |
apt-get -qq update
apt-get -q -y install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Cache rebar3
if: matrix.rebar == 'rebar3'
uses: actions/cache@v5
with:
path: |
~/.cache/rebar3/
_build/default/lib/
key: runtime-${{ matrix.otp }}-${{matrix.rebar}}-${{hashFiles('rebar.*')}}
- name: Compile
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: compile
tool: ${{ matrix.rebar }}
configure: --disable-elixir
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- run: make elvis
if: matrix.otp > '25' && matrix.rebar == 'rebar3'
- name: Production
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: deploy, start, register, stop, check, logs
tool: ${{ matrix.rebar }}
username: user1
- name: Development
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: deploy, start, register, stop, check, logs
tool: ${{ matrix.rebar }}
username: user2
- name: Installed
uses: ./.github/actions/manage-ejabberd
with:
for: install
do: deploy, start, register, stop, check, logs
tool: ${{ matrix.rebar }}
username: user3
####################################################### Rebar3 + Elixir #####
rebar3-elixir:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
elixir: ['1.14', '1.18', '1.19']
container:
image: public.ecr.aws/docker/library/elixir:${{ matrix.elixir }}
steps:
- uses: actions/checkout@v6
- name: Prepare libraries
run: |
apt-get -qq update
apt-get -q -y install libexpat1-dev libgd-dev libpam0g-dev \
libsqlite3-dev libwebp-dev libyaml-dev
- name: Enable Module.Example and an Elixir dependency
run: |
sed -i "s|^modules:|modules:\n 'Ejabberd.Module.Example': {}|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: Cache hex.pm
uses: actions/cache@v5
with:
path: |
~/.cache/rebar3/
key: runtime-${{matrix.elixir}}-${{hashFiles('rebar.*')}}
- name: Install Hex and Rebar3 manually on older Elixir
if: matrix.elixir < '1.15'
run: |
mix local.hex --force
mix local.rebar --force
- name: Compile
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: compile
tool: ./rebar3
- name: Test scripts, deps, eunit
run: |
make scripts deps
./rebar3 eunit --verbose
- run: make hooks
- run: make options
- run: make xref
#- run: make dialyzer
- run: make elvis
if: matrix.otp > '25'
- name: Production
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: deploy, start, register, stop, check, logs
username: user1
- name: Release
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: deploy, start, register, stop, check, logs
username: user2
- name: Installed
uses: ./.github/actions/manage-ejabberd
with:
for: install
do: deploy, start, register, stop, check, logs
username: user3
################################################################### Mix #####
mix:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
elixir: ['1.14', '1.18', '1.19']
container:
image: public.ecr.aws/docker/library/elixir:${{ matrix.elixir }}
steps:
- uses: actions/checkout@v6
- name: Prepare libraries
run: |
apt-get -qq update
apt-get -q -y 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 Module.Example and an Elixir dependency
run: |
sed -i "s|^modules:|modules:\n 'Ejabberd.Module.Example': {}|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: Cache hex.pm
uses: actions/cache@v5
with:
path: |
~/.hex/
key: runtime-${{matrix.elixir}}-${{hashFiles('mix.*')}}
- name: Install Hex and Rebar3 manually on older Elixir
if: matrix.elixir < '1.15'
run: |
mix local.hex --force
mix local.rebar --force
- name: Compile
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: compile
tool: mix
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- run: make elvis
if: matrix.otp > '25'
- run: make edoc
- name: Production
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: deploy, start, register, stop, check, logs
username: user1
- name: Development
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: deploy, start, register, stop, check, logs
username: user2
- name: Installed
uses: ./.github/actions/manage-ejabberd
with:
for: install
do: deploy, start, register, stop, check, logs
username: user3
-177
View File
@@ -1,177 +0,0 @@
name: Weekly
on:
schedule:
- cron: '30 9 * * 0'
jobs:
############################################################### Compile #####
test:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
otp: ['25', '26', '27', '28', '29.0-rc1']
steps:
- uses: actions/checkout@v6
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libexpat1-dev libgd-dev libpam0g-dev
libsqlite3-dev libwebp-dev libyaml-dev
- name: Compile
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: compile
tool: rebar3
configure: --disable-elixir --disable-mssql
########################################################## Static Tests #####
- name: Test shell scripts
run: |
shellcheck ejabberd.init.template
shellcheck -x ejabberdctl.template
shellcheck .vscode/relive.sh
shellcheck rel/setup-dev.sh
shellcheck rel/setup-relive.sh
shellcheck test/ejabberd_SUITE_data/gencerts.sh
shellcheck tools/captcha.sh
shellcheck tools/emacs-indent.sh
shellcheck tools/generate-doap.sh
shellcheck tools/prepare-tr.sh
shellcheck tools/rebar3-format.sh
- run: make hooks
- run: make options
- run: make xref
- run: make dialyzer
- run: make testeunit
- run: make elvis
if: matrix.otp > '25'
- run: make install -s
######################################################### Dynamic Tests #####
- name: Check production release
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: deploy, start, stop, check
- name: Start development release
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: deploy, no_tls, start, register
username: user123
- name: Stop development release
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: stop, check
- name: View production logs
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: prod
do: logs
- name: View development logs
if: always()
uses: ./.github/actions/manage-ejabberd
with:
for: dev
do: logs
##################################################### Common Test Suite #####
- name: Prepare database
uses: ./.github/actions/manage-database
with:
for: mysql, pgsql, redis
do: install, start, user, create
- name: Setup multihost SQL schema
run: |
sed -i 's|new_schema, false|new_schema, true|g' test/suite.erl
- name: Run tests
id: ct
run: make test
- name: Send to coveralls
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DIAGNOSTIC=1 ./rebar3 as test coveralls send
- name: Check results
if: always() && (steps.ct.outcome != 'skipped')
id: ctresults
run: |
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
ln `find logs/ -name suite.log` logs/suite.log
grep 'TEST COMPLETE' logs/suite.log
grep -q 'TEST COMPLETE,.* 0 failed' logs/suite.log
test $(find logs/ -empty -name error.log)
- name: View logs
if: always()
run: |
echo "::group::ejabberd.log"
find logs/ -name ejabberd.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::error.log"
find logs/ -name error.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::exunit.log"
find logs/ -name exunit.log -exec cat '{}' ';'
echo "::endgroup::"
echo "::group::suite.log (only failures)"
cat logs/suite.log | awk \
'BEGIN{RS="\n=case";FS="\n"} /=result\s*failed/ {print "=case" $0}'
echo "::endgroup::"
echo "::group::suite.log (complete)"
cat logs/suite.log
echo "::endgroup::"
- name: Upload CT logs
if: failure()
uses: actions/upload-artifact@v6
with:
name: ct-logs-${{ matrix.otp }}
path: _build/test/logs
retention-days: 14
############################################################# Coveralls #####
cover:
needs: test
if: always()
runs-on: ubuntu-24.04-arm
steps:
- name: Finish parallel upload to coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -v -k https://coveralls.io/webhook \
--header "Content-Type: application/json" \
--data '{"repo_name":"$GITHUB_REPOSITORY",
"repo_token":"$GITHUB_TOKEN",
"payload":{"build_num":$GITHUB_RUN_ID,
"status":"done"}}'
-52
View File
@@ -1,52 +0,0 @@
#
# You can add personal rules in your file .git/info/exclude
*.swp
*~
\#*#
.#*
.edts
.tool-versions
*.dump
/Makefile
/doc
/config.log
/config.status
/config/releases.exs
/configure
/aclocal.m4
/*.cache
/deps/
/.deps-update/
/.ejabberd-modules/
/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
/recompile.log
/_build
/database/
/.rebar
/log/
Mnesia.nonode@nohost/
/TAGS
/tags
# Binaries created with tools/make-{binaries,installers,packages}:
/ejabberd_*.deb
/ejabberd-*.rpm
/ejabberd-*.run
/ejabberd-*.tar.gz
/priv/mod_invites/static/bootstrap/
/priv/mod_invites/static/jquery/
/node_modules/
-4
View File
@@ -1,4 +0,0 @@
disable=SC2016,SC2086,SC2089,SC2090
external-sources=true
source=ejabberdctl.cfg.example
shell=sh
-5
View File
@@ -1,5 +0,0 @@
{
"recommendations": [
"erlang-ls.erlang-ls"
]
}
-66
View File
@@ -1,66 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Relive (Vim)",
"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": 900,
"cwd": "."
},
{
"name": "Relive (VSCode)",
"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
View File
@@ -1,6 +0,0 @@
[ ! -f Makefile ] \
&& ./autogen.sh \
&& ./configure --with-rebar=rebar3 \
&& make
make relive
-13
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"}
}
}
-1926
View File
File diff suppressed because it is too large Load Diff
-61
View File
@@ -1,61 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Guidelines for Respectful and Efficient Communication on Issues, Discussions, and PRs
To ensure that our maintainers can efficiently manage issues and provide timely updates, we kindly ask that all comments on GitHub tickets remain relevant to the topic of the issue. Please avoid posting comments solely to ping maintainers or ask for updates. If you need information on the status of an issue, consider the following:
- **Check the Issue Timeline:** Review the existing comments and updates on the issue before posting.
- **Use Reactions:** If you want to show that you are interested in an issue, use GitHub's reaction feature (e.g., thumbs up) instead of commenting.
- **Be Patient:** Understand that maintainers may be working on multiple tasks and will provide updates as soon as possible.
Additionally, please be aware that:
- **User Responses:** Users who report issues may no longer be using the software, may have switched to other projects, or may simply be busy. It is their right not to respond to follow-up questions or comments.
- **Maintainer Priorities:** Maintainers have the right to define their own priorities and schedule. They will address issues based on their availability and the project's needs.
By following these guidelines, you help us maintain a productive and respectful environment for everyone involved.
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## 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.
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.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://www.contributor-covenant.org/
[version]: https://www.contributor-covenant.org/version/1/4/
-126
View File
@@ -1,126 +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 ≥ 25.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.14.0, for Elixir support
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/download/ejabberd/
[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
The build tool automatically downloads and compiles the
erlang libraries that [ejabberd depends on][docs-repo].
[docs-repo]: https://docs.ejabberd.im/developer/repositories/
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
```
-1136
View File
File diff suppressed because it is too large Load Diff
-149
View File
@@ -1,149 +0,0 @@
# Contributing to ejabberd
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
Help us keep ejabberd community open-minded and inclusive. Please read and follow our [Code of Conduct][coc].
## Questions, Bugs, Features
### 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
support platforms, the best being [Stack Overflow][stackoverflow].
Stack Overflow is a much better place to ask questions since:
* there are thousands of people willing to help on Stack Overflow
* questions and answers stay available for public viewing so your question / answer might help
someone else
* Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general
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 Mailing List][list]
### 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?
You can request a new feature by submitting an issue to our [GitHub Repository][github-issues].
If you would like to implement a new feature then consider what kind of change it is:
* **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).
## Issue Submission Guidelines
Before you submit your issue search the archive, maybe your question was already answered.
If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize
the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
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
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]
for details.
Before you submit your pull request consider the following guidelines:
* Search [GitHub][github-pr] for an open or closed Pull Request
that relates to your submission. You don't want to duplicate effort.
* Create the [development environment][developer-setup]
* Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
* Test your changes and, if relevant, expand the automated test suite.
* Create your patch commit, including appropriate test cases.
* If the changes affect public APIs, change or add relevant [documentation][doc-repo].
* Commit your changes using a descriptive commit message.
```shell
git commit -a
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
* Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
* In GitHub, send a pull request to `ejabberd:master`. This will trigger the automated testing.
We will also notify you if you have not yet signed the [contribution agreement][cla].
* If you find that the tests have failed, look into the logs to find out
if your changes caused test failures, the commit message was malformed etc. If you find that the
tests failed or times out for unrelated reasons, you can ping a team member so that the build can be
restarted.
* If we suggest changes, then:
* Make the required updates.
* Test your changes and test cases.
* Commit your changes to your branch (e.g. `my-fix-branch`).
* Push the changes to your GitHub repository (this will update your Pull Request).
You can also amend the initial commits and force push them to the branch.
```shell
git rebase master -i
git push origin my-fix-branch -f
```
This is generally easier to follow, but separate commits are useful if the Pull Request contains
iterations that might be interesting to see side-by-side.
That's it! Thank you for your contribution!
## 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
Here's a link to the [ProcessOne Contribution License Agreement][cla].
This is part of the legal framework of the open-source ecosystem that adds some red tape,
but protects both the contributor and the company / foundation behind the project. It also
gives us the option to relicense the code with a more permissive license in the future.
[coc]: https://github.com/processone/ejabberd/blob/master/CODE_OF_CONDUCT.md
[stackoverflow]: https://stackoverflow.com/questions/tagged/ejabberd?sort=newest
[list]: https://web.archive.org/web/20230319174915/http://lists.jabber.ru/mailman/listinfo/ejabberd
[muc]: xmpp:ejabberd@conference.process-one.net
[github]: https://github.com/processone/ejabberd
[github-issues]: https://github.com/processone/ejabberd/issues
[github-new-issue]: https://github.com/processone/ejabberd/issues/new
[github-pr]: https://github.com/processone/ejabberd/pulls
[doc-repo]: https://github.com/processone/docs.ejabberd.im
[developer-setup]: https://docs.ejabberd.im/developer/
[cla]: https://cla.process-one.net/
-38
View File
@@ -1,38 +0,0 @@
# Contributors
We would like to thanks official ejabberd source code contributors:
- Sergey Abramyan
- Badlop
- Ludovic Bocquet
- Emilio Bustos
- Thiago Camargo
- Juan Pablo Carlino
- Paweł Chmielowski
- Gabriel Gatu
- Tsukasa Hamano
- Konstantinos Kallas
- Evgeny Khramtsov
- Ben Langfeld
- Peter Lemenkov
- Anna Mukharram
- Johan Oudinet
- Pablo Polvorin
- Mickaël Rémond
- Matthias Rieber
- Rafael Roemhild
- Christophe Romain
- Jérôme Sautret
- Sonny Scroggin
- Alexey Shchepin
- Shelley Shyan
- Stefan Strigler
- Radoslaw Szymczyszyn
- Stu Tomlinson
- Christian Ulrich
- Holger Weiß
Please, if you think we are missing your contribution, do not hesitate to contact us at ProcessOne.
In case you do not want to appear in this list, please, let us know as well.
Thanks !
+5 -8
View File
@@ -1,11 +1,8 @@
As a special exception, the authors give permission to link this program
with the OpenSSL library and distribute the resulting binary.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -306,9 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
+4
View File
@@ -0,0 +1,4 @@
2003-02-11 Alexey Shchepin <alexey@sevcom.net>
* (all): Version 0.1-alpha released
-756
View File
@@ -1,756 +0,0 @@
#.
#' definitions
#
# Only required for Erlang/OTP 25
MAYBE=ERL_FLAGS="-enable-feature maybe_expr"
ESCRIPT = @ESCRIPT@
REBAR = $(MAYBE) @rebar@ # rebar|rebar3|mix binary (or path to binary)
REBAR3 = @REBAR3@ # path to rebar3 binary
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@
DESTDIR =
# /etc/ejabberd/
ETCDIR = @sysconfdir@/ejabberd
# /bin/
BINDIR = @bindir@
# /sbin/
SBINDIR = @sbindir@
# /lib/
LIBDIR = @libdir@
# /lib/ejabberd/
EJABBERDDIR = @libdir@/ejabberd
# /share/doc/ejabberd
PACKAGE_TARNAME = @PACKAGE_TARNAME@
datarootdir = @datarootdir@
DOCDIR = @docdir@
# /share/doc/man/man5
MANDIR = @mandir@/man5
# /usr/lib/ejabberd/ebin/
BEAMDIR = $(EJABBERDDIR)/ebin
# /usr/lib/ejabberd/include/
INCLUDEDIR = $(EJABBERDDIR)/include
# /usr/lib/ejabberd/priv/
PRIVDIR = $(EJABBERDDIR)/priv
# /usr/lib/ejabberd/priv/bin
PBINDIR = $(PRIVDIR)/bin
# /usr/lib/ejabberd/priv/lib
SODIR = $(PRIVDIR)/lib
# /usr/lib/ejabberd/priv/msgs
MSGSDIR = $(PRIVDIR)/msgs
# /usr/lib/ejabberd/priv/css
CSSDIR = $(PRIVDIR)/css
# /usr/lib/ejabberd/priv/img
IMGDIR = $(PRIVDIR)/img
# /usr/lib/ejabberd/priv/js
JSDIR = $(PRIVDIR)/js
# /usr/lib/ejabberd/priv/sql
SQLDIR = $(PRIVDIR)/sql
# /usr/lib/ejabberd/priv/lua
LUADIR = $(PRIVDIR)/lua
# /var/lib/ejabberd/
SPOOLDIR = @localstatedir@/lib/ejabberd
# /var/log/ejabberd/
LOGDIR = @localstatedir@/log/ejabberd
#.
#' install user
#
# if no user was enabled, don't set privileges or ownership
ifeq ($(INSTALLUSER),)
O_USER=
G_USER=
CHOWN_COMMAND=echo
CHOWN_OUTPUT=/dev/null
INIT_USER=root
else
O_USER=-o $(INSTALLUSER)
G_USER=-g $(INSTALLUSER)
CHOWN_COMMAND=chown
CHOWN_OUTPUT=&1
INIT_USER=$(INSTALLUSER)
endif
# if no group was enabled, don't set privileges or ownership
ifneq ($(INSTALLGROUP),)
G_USER=-g $(INSTALLGROUP)
endif
#.
#' rebar / rebar3 / mix
#
ifeq "$(notdir $(MIX))" "mix"
REBAR_VER:=6
REBAR_VER_318:=0
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)}')
endif
ifeq "$(REBAR_VER)" "6"
REBAR=$(MAYBE) $(MIX)
SKIPDEPS=
LISTDEPS=deps.tree
UPDATEDEPS=deps.update
DEPSPATTERN="s/.*─ \([a-z0-9_]*\) .*/\1/p;"
DEPSBASE=_build
DEPSDIR=$(DEPSBASE)/dev/lib
GET_DEPS= deps.get
CONFIGURE_DEPS=(cd deps/eimp; ./configure)
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 $(MAYBE) $(IEX) --name ejabberd@localhost -S mix run
RELIVECTLCMD=$(ESCRIPT) rel/relive.escript ctl && _build/relivectl/ejabberdctl live
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"
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
RELIVECTLCMD=$(ESCRIPT) rel/relive.escript ctl && _build/relivectl/ejabberdctl live
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
else
SKIPDEPS=skip_deps=true
LISTDEPS=-q list-deps
UPDATEDEPS=update-deps
DEPSPATTERN="/ TAG / s/ .*// p; / REV / s/ .*// p; / BRANCH / s/ .*// p;"
DEPSBASE=deps
DEPSDIR=$(DEPSBASE)
GET_DEPS= get-deps
CONFIGURE_DEPS=$(REBAR) configure-deps
EBINDIR=ebin
XREFOPTIONS=
CLEANARG=
REBARREL=$(REBAR) generate
REBARDEV=@echo "Rebar2 detected... dev not supported.\
\nTry: make prod, or: ./configure --with-rebar=rebar3 ; make dev"
RELIVECMD=@echo "Rebar2 detected... relive not supported.\
\nTry: ./configure --with-rebar=rebar3 ; make relive"
RELIVECTLCMD=@echo "Rebar2 detected... relivectl not supported.\
\nTry: ./configure --with-rebar=rebar3 ; make relivectl"
REL_LIB_DIR = rel/ejabberd/lib
COPY_REL_TARGET = rel
endif
endif
#.
#' main targets
#
all: scripts deps src
deps: $(DEPSDIR)/.got invites-deps
$(DEPSDIR)/.got:
rm -rf $(DEPSDIR)/.got
rm -rf $(DEPSDIR)/.built
$(MKDIR_P) $(DEPSDIR)
$(REBAR) $(GET_DEPS) && :> $(DEPSDIR)/.got
$(CONFIGURE_DEPS)
$(DEPSDIR)/.built: $(DEPSDIR)/.got
$(REBAR) compile && :> $(DEPSDIR)/.built
ifeq (, $(shell which npm))
INSTALL_INVITES_DEPS=tools/dl_invites_page_deps.sh priv/mod_invites/static
else
INSTALL_INVITES_DEPS=npm install
endif
invites-deps: priv/mod_invites/static/bootstrap/ priv/mod_invites/static/jquery/
priv/mod_invites/static/bootstrap/:
$(INSTALL_INVITES_DEPS)
priv/mod_invites/static/jquery/:
$(INSTALL_INVITES_DEPS)
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: src
$(REBAR) $(SKIPDEPS) xref $(XREFOPTIONS)
hooks: src
tools/hook_deps.sh $(EBINDIR)
options: src
tools/opt_types.sh ejabberd_option $(EBINDIR)
translations:
$(GET_DEPS_TRANSLATIONS)
tools/prepare-tr.sh $(DEPSDIR_TRANSLATIONS)
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 $(REBAR3)
indent:
tools/emacs-indent.sh
#.
#' copy-files
#
JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1))
VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1))
DEPIX:=$(words $(subst /, ,$(DEPSDIR)))
LIBIX:=$(shell expr "$(DEPIX)" + 2)
ELIXIR_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 5,1000,$(1))
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)))))
FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path)))
FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w))))
ifeq ($(MAKECMDGOALS),copy-files-sub)
DEPS:=$(sort $(shell QUIET=1 $(REBAR) $(LISTDEPS) | $(SED) -ne $(DEPSPATTERN) ))
DEPS_FILES=$(call FILES_WILDCARD,$(foreach DEP,$(DEPS),$(DEPSDIR)/$(DEP)/ebin/*.beam $(DEPSDIR)/$(DEP)/ebin/*.app $(DEPSDIR)/$(DEP)/priv/* $(DEPSDIR)/$(DEP)/priv/lib/* $(DEPSDIR)/$(DEP)/priv/bin/* $(DEPSDIR)/$(DEP)/include/*.hrl $(DEPSDIR)/$(DEP)/COPY* $(DEPSDIR)/$(DEP)/LICENSE* $(DEPSDIR)/$(DEP)/lib/*/ebin/*.beam $(DEPSDIR)/$(DEP)/lib/*/ebin/*.app))
BINARIES=$(DEPSDIR)/epam/priv/bin/epam $(DEPSDIR)/eimp/priv/bin/eimp $(DEPSDIR)/fs/priv/mac_listener
DEPS_FILES_FILTERED=$(filter-out $(BINARIES) $(DEPSDIR)/elixir/ebin/elixir.app,$(DEPS_FILES))
DEPS_DIRS=$(sort $(DEPSDIR)/ $(foreach DEP,$(DEPS),$(DEPSDIR)/$(DEP)/) $(dir $(DEPS_FILES)))
MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,$(EBINDIR)/*.beam $(EBINDIR)/*.app priv/msgs/*.msg priv/css/*.css priv/img/*.png priv/js/*.js priv/lib/* priv/mod_invites/* priv/mod_invites/static/* priv/mod_invites/static/bootstrap/css/bootstrap.min.css priv/mod_invites/static/bootstrap/js/bootstrap.min.js priv/mod_invites/static/jquery/jquery.min.js \
priv/mod_invites/static/logos/* include/*.hrl COPYING))
MAIN_DIRS=$(sort $(dir $(MAIN_FILES)) priv/bin priv/sql priv/lua priv/mod_invites)
define DEP_VERSION_template
DEP_$(1)_VERSION:=$(shell $(SED) -e '/vsn/!d;s/.*, *"/$(1)-/;s/".*//' $(2) 2>/dev/null)
endef
DELETE_TARGET_SO=$(if $(subst X.soX,,X$(suffix $(1))X),,rm -f $(call TO_DEST,$(1));)
$(foreach DEP,$(DEPS),$(eval $(call DEP_VERSION_template,$(DEP),$(DEPSDIR)/$(DEP)/ebin/$(DEP).app)))
$(eval $(call DEP_VERSION_template,ejabberd,$(EBINDIR)/ejabberd.app))
define COPY_template
$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; $(call DELETE_TARGET_SO, $(1)) $$(INSTALL) -m 644 $(1) $(call TO_DEST,$(1))
endef
define COPY_BINARY_template
$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; rm -f $(call TO_DEST,$(1)); $$(INSTALL) -m 755 $$(O_USER) $(1) $(call TO_DEST,$(1))
endef
$(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file))))
$(foreach file,$(BINARIES),$(eval $(call COPY_BINARY_template,$(file))))
$(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))):
$(INSTALL) -d $@
$(call TO_DEST,priv/sql/lite.sql): sql/lite.sql $(call TO_DEST,priv/sql)
$(INSTALL) -m 644 $< $@
$(call TO_DEST,priv/sql/lite.new.sql): sql/lite.new.sql $(call TO_DEST,priv/sql)
$(INSTALL) -m 644 $< $@
$(call TO_DEST,priv/bin/captcha.sh): tools/captcha.sh $(call TO_DEST,priv/bin)
$(INSTALL) -m 755 $(O_USER) $< $@
$(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))
.PHONY: $(call TO_DEST,$(DEPS_FILES) $(MAIN_DIRS) $(DEPS_DIRS))
endif
copy-files:
$(MAKE) copy-files-sub
copy-files-sub: copy-files-sub2
#.
#' copy-files-rel
#
copy-files-rel: $(COPY_REL_TARGET)
#
# Libraries
(cd $(REL_LIB_DIR) && find . -follow -type f ! -executable -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;)
#
# *.so:
(cd $(REL_LIB_DIR) && find . -follow -type f -executable -name *.so -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;)
#
# 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)
relivectl:
$(EXPLICIT_ELIXIR_COMPILE_DEV)
$(RELIVECTLCMD)
relivelibdir=$(shell pwd)/$(DEPSDIR)
relivebase=$(shell pwd)/$(DEPSBASE)
#.
#' scripts
#
# Used for ejabberdctl.relive and ejabberdctl.relivectl
ejabberdctl.re%:
$(SED) -e "s*{{installuser}}*${INSTALLUSER}*g" \
-e "s*{{config_dir}}*${relivebase}/re${*}/conf*g" \
-e "s*{{logs_dir}}*${relivebase}/re${*}/logs*g" \
-e "s*{{spool_dir}}*${relivebase}/re${*}/database*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.re${*}
ejabberd.init:
$(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 \
> 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)
#
# Log directory
$(INSTALL) -d -m 750 $(O_USER) $(DESTDIR)$(LOGDIR)
$(CHOWN_COMMAND) -R $(INSTALLUSER) $(DESTDIR)$(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(DESTDIR)$(LOGDIR)
#
# Documentation
$(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL) -d $(DESTDIR)$(DOCDIR)
[ -f man/ejabberd.yml.5 ] \
&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(DESTDIR)$(MANDIR) \
|| echo "Man page not included in sources"
$(INSTALL) -m 644 COPYING $(DESTDIR)$(DOCDIR)
#.
#' uninstall
#
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
uninstall-all: uninstall-binary
rm -rf $(DESTDIR)$(ETCDIR)
rm -rf $(DESTDIR)$(EJABBERDDIR)
rm -rf $(DESTDIR)$(SPOOLDIR)
rm -rf $(DESTDIR)$(LOGDIR)
#.
#' clean
#
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
rm -rf priv/mod_invites/static/{jquery,bootstrap4}
$(REBAR) clean $(CLEANARG)
clean-rel:
rm -rf rel/ejabberd
distclean: clean clean-rel
rm -f aclocal.m4
rm -f config.status
rm -f config.log
rm -rf autom4te.cache
rm -rf $(EBINDIR)
rm -rf $(DEPSBASE)
rm -rf deps
rm -f Makefile
rm -f vars.config
#.
#' releases
#
rel: prod
prod:
$(PREPARE_ELIXIR_SCRIPTS)
$(REBARREL)
DEV_CONFIG = _build/dev/rel/ejabberd/conf/ejabberd.yml
dev $(DEV_CONFIG):
$(PREPARE_ELIXIR_SCRIPTS)
$(REBARDEV)
#.
#' tags
#
TAGS:
etags src/*.erl
#.
#' makefile
#
Makefile: Makefile.in
#.
#' dialyzer
#
ifeq "$(REBAR_VER)" "6" # Mix
dialyzer:
MIX_ENV=test $(REBAR) dialyzer
else
ifeq "$(REBAR_VER)" "3" # Rebar3
dialyzer:
$(REBAR) dialyzer
else # Rebar2
deps := $(wildcard $(DEPSDIR)/*/ebin)
dialyzer/erlang.plt:
@$(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 \
os_mon asn1 syntax_tools; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
dialyzer/deps.plt:
@$(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
@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
erlang_plt: dialyzer/erlang.plt
@dialyzer --plt dialyzer/erlang.plt --check_plt -o dialyzer/erlang.log; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
deps_plt: dialyzer/deps.plt
@dialyzer --plt dialyzer/deps.plt --check_plt -o dialyzer/deps.log; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
ejabberd_plt: dialyzer/ejabberd.plt
@dialyzer --plt dialyzer/ejabberd.plt --check_plt -o dialyzer/ejabberd.log; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
dialyzer: erlang_plt deps_plt ejabberd_plt
@dialyzer --plts dialyzer/*.plt --no_check_plt \
--get_warnings -o dialyzer/error.log ebin; \
status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
endif
endif
#.
#' elvis
#
elvis:
$(REBAR) lint
#.
#' test
#
test:
@echo "************************** NOTICE ***************************************"
@cat test/README
@echo "*************************************************************************"
@cd priv && ln -sf ../sql
$(REBAR) $(SKIPDEPS) ct
.PHONY: test-%
define test-group-target
test-$1:
$(REBAR) $(SKIPDEPS) ct --suite=test/ejabberd_SUITE --group=$1
endef
ifneq ($(filter test-%,$(MAKECMDGOALS)),)
group_to_test := $(patsubst test-%,%,$(filter test-%,$(MAKECMDGOALS)))
$(eval $(call test-group-target,$(group_to_test)))
endif
testeunit:
$(REBAR) $(SKIPDEPS) eunit --verbose
#.
#' phony
#
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean prod rel \
install uninstall uninstall-binary uninstall-all translations deps test testeunit \
all dev doap help install-rel relive scripts uninstall-rel update \
erlang_plt deps_plt ejabberd_plt xref hooks options format indent
#.
#' help
#
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 " 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 " dev Build a development release"
@echo " relive Start live using rebar3/mix tools"
@echo " relivectl Start live using ejabberdctl script"
@echo ""
@echo " doap Generate DOAP file"
@echo " edoc Generate EDoc documentation [mix]"
@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"
@echo " indent Indent source code using erlang-mode [emacs]"
@echo ""
@echo " dialyzer Run Dialyzer static analyzer"
@echo " elvis Run Elvis source code style reviewer [rebar3]"
@echo " hooks Run hooks validator"
@echo " test Run Common Tests suite [rebar3]"
@echo " testeunit Run EUnit suite [rebar3]"
@echo " test-<group> Run Common Test suite for specific group only [rebar3]"
@echo " xref Run cross reference analysis [rebar3]"
#.
#'
# vim: foldmarker=#',#. foldmethod=marker:
-136
View File
@@ -1,136 +0,0 @@
<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>
[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
------------
There are several ways to install ejabberd:
- Source code: compile yourself, see [COMPILE](COMPILE.md)
- Installers:
- [ProcessOne Download Page][p1download] or [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`)
- Docker Containers:
- `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
More info can be found in the `Installation` part of [ejabberd Docs](https://docs.ejabberd.im/admin/install/).
Documentation
-------------
Please check the [ejabberd Docs][docs] website.
When compiling from source code, you can get some help with:
./configure --help
make help
Once ejabberd is installed, try:
ejabberdctl help
man ejabberd.yml
Development
-----------
Bug reports and features are tracked using [GitHub Issues][issues],
please check [CONTRIBUTING](CONTRIBUTING.md) for details.
Translations can be improved online [using Weblate][weblate]
or in your local machine as explained in [Localization][localization].
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].
Security
--------
For information on how to report security vulnerabilities, please refer to the [SECURITY.md](SECURITY.md) file. It contains guidelines on how to report vulnerabilities privately and securely, ensuring that any issues are addressed in a timely and confidential manner.
Community
---------
There are several places to get in touch with other ejabberd developers and administrators:
- ejabberd XMPP chatroom: [ejabberd@conference.process-one.net][muc]
- [GitHub Discussions][discussions]
- [Stack Overflow][stackoverflow]
License
-------
- ejabberd is released under the __GNU General Public License v2__ (see [COPYING](COPYING))
- [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://www.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/contact/
[p1download]: https://www.process-one.net/download/ejabberd/
[p1home]: https://www.process-one.net/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/ejabberd-features/
[xmpp]: https://xmpp.org/
[xmppej]: https://xmpp.org/software/servers/ejabberd/
-45
View File
@@ -1,45 +0,0 @@
# Security Policy
## Supported Versions
We recommend that all users always use the latest version of ejabberd.
To ensure the best experience and security, upgrade to the latest version available on [this repo](https://github.com/processone/ejabberd).
## Reporting a Vulnerability
### Private Reporting
**Preferred Method**: Use GitHub's private vulnerability reporting system by clicking the "Report a Vulnerability" button in the [Security tab of this repository](https://github.com/processone/ejabberd/security). This ensures your report is securely transmitted and tracked.
**Alternative**: If you cannot use the GitHub system, send an email to **`contact@process-one.net`** with the following details:
- A clear description of the vulnerability.
- Steps to reproduce the issue.
- Any potential impact or exploitation scenarios.
### Response Time
We aim to acknowledge receipt of your report within 72 hours. You can expect regular updates on the status of your report.
### Resolution
If the vulnerability is confirmed, we will work on a patch or mitigation strategy.
We will notify you once the issue is resolved and coordinate a public disclosure if needed.
### Acknowledgements
We value and appreciate the contributions of security researchers and community members.
If you wish, we are happy to acknowledge your efforts publicly by listing your name (or alias) below in this document.
Please let us know if you would like to be recognized when reporting the vulnerability.
## Public Discussion
For general inquiries or discussions about the projects security, feel free to chat with us here:
- XMPP room: `ejabberd@conference.process-one.net`
- [GitHub Discussions](https://github.com/processone/ejabberd/discussions)
However, please note that if the issue is **critical** or potentially exploitable, **do not share it publicly**. Instead, we strongly recommend you contact the maintainers directly via the private reporting methods outlined above to ensure a secure and timely response.
Thank you for helping us improve the security of ejabberd!
+14
View File
@@ -0,0 +1,14 @@
admin interface
users management
node management
backup management
S2S timeouts
rewrite S2S key validation
iq:browse (?)
more correctly work with SRV DNS records (priority, weight, etc...)
karma
SSL
SASL
JEP-62,63 (?)
make roster set to work in one transaction
-2
View File
@@ -1,2 +0,0 @@
{erl_opts, [debug_info]}.
{deps, []}.
@@ -1,9 +0,0 @@
{application, configure_deps,
[{description, "A rebar3 plugin to explicitly run configure on dependencies"},
{vsn, "0.0.1"},
{registered, []},
{applications, [kernel, stdlib]},
{env,[]},
{modules, []},
{links, []}
]}.
@@ -1,8 +0,0 @@
-module(configure_deps).
-export([init/1]).
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
{ok, State1} = configure_deps_prv:init(State),
{ok, State1}.
@@ -1,54 +0,0 @@
-module(configure_deps_prv).
-export([init/1, do/1, format_error/1]).
-define(PROVIDER, 'configure-deps').
-define(DEPS, [install_deps]).
%% ===================================================================
%% Public API
%% ===================================================================
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
Provider = providers:create([
{namespace, default},
{name, ?PROVIDER}, % The 'user friendly' name of the task
{module, ?MODULE}, % The module implementation of the task
{bare, true}, % The task can be run by the user, always true
{deps, ?DEPS}, % The list of dependencies
{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."}
]),
{ok, rebar_state:add_provider(State, Provider)}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
Apps = rebar_state:project_apps(State) ++ lists:usort(rebar_state:all_deps(State)),
lists:foreach(fun do_app/1, Apps),
{ok, State}.
exec_configure({'configure-deps', Cmd}, Dir) ->
rebar_utils:sh(Cmd, [{cd, Dir}, {use_stdout, true}]);
exec_configure(_, Acc) -> Acc.
parse_pre_hooks({pre_hooks, PreHooks}, Acc) ->
lists:foldl(fun exec_configure/2, Acc, PreHooks);
parse_pre_hooks(_, Acc) -> Acc.
parse_additions({add, App, Additions}, {MyApp, Dir}) when App == MyApp ->
lists:foldl(fun parse_pre_hooks/2, Dir, Additions),
{MyApp, Dir};
parse_additions(_, Acc) -> Acc.
do_app(App) ->
Dir = rebar_app_info:dir(App),
Opts = rebar_app_info:opts(App),
Overrides = rebar_opts:get(Opts, overrides),
lists:foldl(fun parse_additions/2, {binary_to_atom(rebar_app_info:name(App), utf8), Dir}, Overrides).
-spec format_error(any()) -> iolist().
format_error(Reason) ->
io_lib:format("~p", [Reason]).
-3
View File
@@ -1,3 +0,0 @@
# generate a new autoconf
aclocal -I m4
autoconf -f
-164
View File
@@ -1,164 +0,0 @@
defmodule Ejabberd.ConfigFile do
use Ejabberd.Config
def start do
[loglevel: 4,
log_rotate_size: 10485760,
log_rotate_count: 1,
auth_method: :internal,
max_fsm_queue: 1000,
language: "en",
allow_contrib_modules: true,
hosts: ["localhost"],
shaper: shaper(),
acl: acl(),
access: access()]
end
defp shaper do
[normal: 1000,
fast: 50000,
max_fsm_queue: 1000]
end
defp acl do
[local:
[user_regexp: "", loopback: [ip: "127.0.0.0/8"]]]
end
defp access do
[max_user_sessions: [all: 10],
max_user_offline_messages: [admin: 5000, all: 100],
local: [local: :allow],
c2s: [blocked: :deny, all: :allow],
c2s_shaper: [admin: :none, all: :normal],
s2s_shaper: [all: :fast],
announce: [admin: :allow],
configure: [admin: :allow],
muc_admin: [admin: :allow],
muc_create: [local: :allow],
muc: [all: :allow],
pubsub_createnode: [local: :allow],
register: [all: :allow],
trusted_network: [loopback: :allow]]
end
listen :ejabberd_c2s do
@opts [
port: 5222,
max_stanza_size: 65536,
shaper: :c2s_shaper,
access: :c2s]
end
listen :ejabberd_s2s_in do
@opts [port: 5269]
end
listen :ejabberd_http do
@opts [
port: 5280,
web_admin: true,
http_bind: true,
captcha: true]
end
module :mod_adhoc do
end
module :mod_announce do
@opts [access: :announce]
end
module :mod_blocking do
end
module :mod_caps do
end
module :mod_carboncopy do
end
module :mod_client_state do
@opts [
queue_chat_states: true,
queue_presence: false]
end
module :mod_configure do
end
module :mod_disco do
end
module :mod_http_bind do
end
module :mod_last do
end
module :mod_muc do
@opts [
access: :muc,
access_create: :muc_create,
access_persistent: :muc_create,
access_admin: :muc_admin]
end
module :mod_offline do
@opts [access_max_user_messages: :max_user_offline_messages]
end
module :mod_ping do
end
module :mod_privacy do
end
module :mod_private do
end
module :mod_pubsub do
@opts [
access_createnode: :pubsub_createnode,
ignore_pep_from_offline: true,
last_item_cache: true,
plugins: ["flat", "hometree", "pep"]]
end
module :mod_register do
@opts [welcome_message: [
subject: "Welcome!",
body: "Hi.\nWelcome to this XMPP server"
],
ip_access: :trusted_network,
access: :register]
end
module :mod_roster do
end
module :mod_shared_roster do
end
module :mod_stats do
end
module :mod_time do
end
module :mod_version do
end
# Example of how to define a hook, called when the event
# specified is triggered.
#
# @event: Name of the event
# @opts: Params are optional. Available: :host and :priority.
# If missing, defaults are used. (host: :global | priority: 50)
# @callback Could be an anonymous function or a callback from a module,
# use the &ModuleName.function/arity format for that.
hook :register_user, [host: "localhost"], fn(user, server) ->
info("User registered: #{user} on #{server}")
end
end
-15
View File
@@ -1,15 +0,0 @@
import Config
rootdefault = case System.get_env("RELIVE", "false") do
"true" -> "_build/relive"
"false" -> ""
end
rootpath = System.get_env("RELEASE_ROOT", rootdefault)
config :ejabberd,
file: Path.join(rootpath, "conf/ejabberd.yml"),
log_path: Path.join(rootpath, "logs/ejabberd.log")
config :mnesia,
dir: Path.join(rootpath, "database/")
config :exsync,
reload_callback: {:ejabberd_admin, :update, []}
-375
View File
@@ -1,375 +0,0 @@
# -*- 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 26.03` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
AC_ARG_WITH(min-erlang,
AS_HELP_STRING([--with-min-erlang=version],[set minimal required erlang version, default to OTP25]),
[if test "X$withval" = "X"; then
REQUIRE_ERLANG_MIN="13.0 (Erlang/OTP 25.0)"
else
REQUIRE_ERLANG_MIN="$withval"
fi
], [REQUIRE_ERLANG_MIN="13.0 (Erlang/OTP 25.0)"])
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
CFLAGS="$CFLAGS -Wall"
fi
# Checks Erlang runtime and compiler
AC_ARG_WITH(erlang,
AS_HELP_STRING([--with-erlang=dir],[search for erlang in dir]),
[if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_erlang" = "X"; then
extra_erl_path=""
else
extra_erl_path="$with_erlang:$with_erlang/bin:"
fi
])
AC_ARG_WITH(rebar,
AS_HELP_STRING([--with-rebar=bin],[use as build tool the rebar/rebar3/mix binary specified]),
[if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_rebar" = "X"; then
rebar="rebar3"
else
rebar="$with_rebar"
fi
], [rebar="unconfigured"])
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
# Checks and sets ERLANG_ROOT_DIR and ERLANG_LIB_DIR variable
AC_ERLANG_SUBST_ROOT_DIR
# AC_ERLANG_SUBST_LIB_DIR
#locating escript
AC_PATH_PROG([ESCRIPT], [escript], [], [$ERLANG_ROOT_DIR/bin])
#locating make
AC_CHECK_PROG([MAKE], [make], [make], [])
if test "x$ESCRIPT" = "x"; then
AC_MSG_ERROR(['escript' was not found])
fi
if test "x$MAKE" = "x"; then
AC_MSG_ERROR(['make' was not found])
fi
# Change default prefix
AC_PREFIX_DEFAULT(/usr/local)
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)])],
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
esac],[])
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug],[enable debug information (default: yes)])],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) elixir=true ;;
no) elixir=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])])
case "$enable_erlang_version_check" in
yes|'')
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX])
;;
no)
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX],[warn])
;;
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)])],
[case "${enableval}" in
yes) full_xml=true ;;
no) full_xml=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-full-xml) ;;
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)])],
[case "${enableval}" in
yes) ENABLEGROUP=`groups |head -n 1` ;;
no) ENABLEGROUP="" ;;
*) ENABLEGROUP=$enableval
esac],
[])
if test "$ENABLEGROUP" != ""; then
echo "allow this system group to start ejabberd: $ENABLEGROUP"
AC_SUBST([INSTALLGROUP], [$ENABLEGROUP])
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)])],
[case "${enableval}" in
yes) latest_deps=true ;;
no) latest_deps=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) lua=true ;;
no) lua=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) mssql=true ;;
no) mssql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[if test "x$mssql" = "x"; then mssql=false; fi])
AC_ARG_ENABLE(mysql,
[AS_HELP_STRING([--enable-mysql],[enable MySQL support (default: no)])],
[case "${enableval}" in
yes) mysql=true ;;
no) mysql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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],[obsolete, use --enable-multihost-sql-schema instead (default: no)])],
[case "${enableval}" in
yes) multihost_sql_schema=true ;;
no) multihost_sql_schema=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
esac],[multihost_sql_schema=false])
AC_ARG_ENABLE(multihost_sql_schema,
[AS_HELP_STRING([--enable-multihost-sql-schema],[use multihost SQL schema by default (default: no)])],
[case "${enableval}" in
yes) multihost_sql_schema=true ;;
no) multihost_sql_schema=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-multihost-sql-schema) ;;
esac],[multihost_sql_schema=false])
AC_ARG_ENABLE(odbc,
[AS_HELP_STRING([--enable-odbc],[enable pure ODBC support (default: no)])],
[case "${enableval}" in
yes) odbc=true ;;
no) odbc=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) pam=true ;;
no) pam=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) pgsql=true ;;
no) pgsql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) redis=true ;;
no) redis=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) roster_gateway_workaround=true ;;
no) roster_gateway_workaround=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;;
esac],[roster_gateway_workaround=false])
AC_ARG_ENABLE(sip,
[AS_HELP_STRING([--enable-sip],[enable SIP support (default: no)])],
[case "${enableval}" in
yes) sip=true ;;
no) sip=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) sqlite=true ;;
no) sqlite=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) stun=true ;;
no) stun=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) system_deps=true ;;
no) system_deps=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --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)])],
[case "${enableval}" in
yes) tools=true ;;
no) tools=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;;
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)])],
[case "${enableval}" in
yes) ENABLEUSER=`whoami` ;;
no) ENABLEUSER="" ;;
*) ENABLEUSER=$enableval
esac],
[])
if test "$ENABLEUSER" != ""; then
echo "allow this system user to start ejabberd: $ENABLEUSER"
AC_SUBST([INSTALLUSER], [$ENABLEUSER])
fi
AC_ARG_ENABLE(zlib,
[AS_HELP_STRING([--enable-zlib],[enable Stream Compression (XEP-0138) using zlib (default: yes)])],
[case "${enableval}" in
yes) zlib=true ;;
no) zlib=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zlib) ;;
esac],[if test "x$zlib" = "x"; then zlib=true; fi])
case "`uname`" in
"Darwin")
# Darwin (macos) erlang-sqlite is built using amalgamated lib, so no external dependency
;;
*)
if test "$sqlite" = "true"; then
AX_LIB_SQLITE3([3.6.19])
if test "x$SQLITE3_VERSION" = "x"; then
AC_MSG_ERROR(SQLite3 library >= 3.6.19 was not found)
fi
fi
;;
esac
AC_MSG_RESULT([build tool to use (change using --with-rebar): $rebar])
AC_SUBST(roster_gateway_workaround)
AC_SUBST(multihost_sql_schema)
AC_SUBST(full_xml)
AC_SUBST(odbc)
AC_SUBST(mssql)
AC_SUBST(mysql)
AC_SUBST(pgsql)
AC_SUBST(sqlite)
AC_SUBST(pam)
AC_SUBST(zlib)
AC_SUBST(rebar)
AC_SUBST(redis)
AC_SUBST(elixir)
AC_SUBST(stun)
AC_SUBST(sip)
AC_SUBST(debug)
AC_SUBST(lua)
AC_SUBST(tools)
AC_SUBST(latest_deps)
AC_SUBST(system_deps)
AC_SUBST(CFLAGS)
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" -le "26"], [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"])
])
-20
View File
@@ -1,20 +0,0 @@
@if "x%1"=="x--help" goto usage
@set arg=dynamic
@if "x%1"=="x--static" set arg=static
@echo Configuring for %arg% build...
erlc configure.erl
erl -s configure -env arg %arg% -noshell
@goto end
:usage
@echo Usage: configure.bat
@echo or configure.bat --static
@echo or configure.bat --help
:end
-5
View File
@@ -1,5 +0,0 @@
{level, details}.
{incl_dirs, ["src", "ebin"]}.
{excl_mods, [eldap, 'ELDAPv3']}.
{export, "logs/all.coverdata"}.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

+105
View File
@@ -0,0 +1,105 @@
digraph messages {
//concentrate=true;
subgraph clusterclients {
client1 [shape = box];
client2 [shape = box];
client3 [shape = box];
style = dashed;
label = "Clients";
}
subgraph clusternode1 {
subgraph clusterc2s1 {
c2s11;
c2s12;
style = invis;
}
subgraph clusterservices1 {
service11;
service12;
service13;
style = invis;
}
//subgraph clusters2s1 {
//s2s11;
//s2s12;
//style = invis;
//}
c2s11 -> auth1;
c2s12 -> auth1;
auth1 -> c2s11;
auth1 -> c2s12;
c2s11 -> sm1;
c2s11 -> router1;
c2s12 -> sm1;
c2s12 -> router1;
router1 -> local1;
router1 -> service11;
router1 -> service12;
router1 -> service13;
router1 -> s2s11;
router1 -> s2s12;
service11 -> router1;
service12 -> router1;
service13 -> router1;
s2s11 -> router1;
s2s12 -> router1;
local1 -> sm1;
sm1 -> c2s11;
sm1 -> c2s12;
style = dashed;
label = "Node1";
}
subgraph clusternode2 {
c2s2 -> auth2;
auth2 -> c2s2;
c2s2 -> sm2;
c2s2 -> router2;
router2 -> local2;
router2 -> service21;
router2 -> s2s21;
service21 -> router2;
s2s21 -> router2;
local2 -> sm2;
sm2 -> c2s2;
style = dashed;
label = "Node2";
}
subgraph clusterservers {
server1 [shape = box];
server2 [shape = box];
server3 [shape = box];
style = dashed;
label = "Servers";
}
client1 -> c2s11;
client2 -> c2s12;
client3 -> c2s2;
c2s11 -> client1 [constraint=false];
c2s12 -> client2 [constraint=false];
c2s2 -> client3 [constraint=false];
s2s11 -> server1 [minlen = 2];
s2s12 -> server2 [minlen = 2];
s2s21 -> server3 [minlen = 2];
server1 -> s2s11 [constraint=false];
server2 -> s2s12 [constraint=false];
server3 -> s2s21 [constraint=false];
router1 -> router2;
router2 -> router1;
sm1 -> sm2;
sm2 -> sm1;
label = "Data Flows";
}
+766
View File
@@ -0,0 +1,766 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>Ejabberd Installation and Operation Guide</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.06">
</HEAD>
<BODY >
<!--HEVEA command line is: /usr/bin/hevea guide.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<H1 ALIGN=center>Ejabberd Installation and Operation Guide</H1>
<H3 ALIGN=center>Alexey Shchepin<BR>
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3>
<H3 ALIGN=center>February 11, 2003</H3><DIV ALIGN=center>
<IMG SRC="logo.png">
</DIV><BR>
<BR>
<!--TOC section Table of Contents-->
<H2>Table of Contents</H2><!--SEC END -->
<UL><LI>
<A HREF="#htoc1">1&nbsp;&nbsp;Introduction</A>
<LI><A HREF="#htoc2">2&nbsp;&nbsp;Installation</A>
<UL><LI>
<A HREF="#htoc3">2.1&nbsp;&nbsp;Installation Requirements</A>
<LI><A HREF="#htoc4">2.2&nbsp;&nbsp;Obtaining</A>
<LI><A HREF="#htoc5">2.3&nbsp;&nbsp;Compilation</A>
<LI><A HREF="#htoc6">2.4&nbsp;&nbsp;Starting</A>
</UL>
<LI><A HREF="#htoc7">3&nbsp;&nbsp;Configuration</A>
<UL><LI>
<A HREF="#htoc8">3.1&nbsp;&nbsp;Initial Configuration</A>
<UL><LI>
<A HREF="#htoc9">3.1.1&nbsp;&nbsp;Host Name</A>
<LI><A HREF="#htoc10">3.1.2&nbsp;&nbsp;Access Rules</A>
<LI><A HREF="#htoc11">3.1.3&nbsp;&nbsp;Listened Sockets</A>
<LI><A HREF="#htoc12">3.1.4&nbsp;&nbsp;Modules</A>
</UL>
<LI><A HREF="#htoc13">3.2&nbsp;&nbsp;Online Configuration and Monitoring</A>
<UL><LI>
<A HREF="#htoc14">3.2.1&nbsp;&nbsp;Node <TT>config</TT>: Global Configuration</A>
<LI><A HREF="#htoc15">3.2.2&nbsp;&nbsp;Node <TT>online users</TT>: List of Online Users</A>
<LI><A HREF="#htoc16">3.2.3&nbsp;&nbsp;Node <TT>all users</TT>: List of Registered User</A>
<LI><A HREF="#htoc17">3.2.4&nbsp;&nbsp;Node <TT>outgoing s2s</TT>: List of Outgoing S2S connections</A>
<LI><A HREF="#htoc18">3.2.5&nbsp;&nbsp;Node <TT>running nodes</TT>: List of Running <TT>ejabberd</TT> Nodes</A>
<LI><A HREF="#htoc19">3.2.6&nbsp;&nbsp;Node <TT>stopped nodes</TT>: List of Stopped Nodes</A>
</UL>
</UL>
<LI><A HREF="#htoc20">4&nbsp;&nbsp;Distribution</A>
<UL><LI>
<A HREF="#htoc21">4.1&nbsp;&nbsp;How it works</A>
<UL><LI>
<A HREF="#htoc22">4.1.1&nbsp;&nbsp;Router</A>
<LI><A HREF="#htoc23">4.1.2&nbsp;&nbsp;Local Router</A>
<LI><A HREF="#htoc24">4.1.3&nbsp;&nbsp;Session Manager</A>
<LI><A HREF="#htoc25">4.1.4&nbsp;&nbsp;S2S Manager</A>
</UL>
</UL>
<LI><A HREF="#htoc26">A&nbsp;&nbsp;Built-in Modules</A>
<UL><LI>
<A HREF="#htoc27">A.1&nbsp;&nbsp;Common Options</A>
<UL><LI>
<A HREF="#htoc28">A.1.1&nbsp;&nbsp;Option <TT>iqdisc</TT></A>
<LI><A HREF="#htoc29">A.1.2&nbsp;&nbsp;Option <TT>host</TT></A>
</UL>
<LI><A HREF="#htoc30">A.2&nbsp;&nbsp;<TT>mod_register</TT></A>
<LI><A HREF="#htoc31">A.3&nbsp;&nbsp;<TT>mod_roster</TT></A>
<LI><A HREF="#htoc32">A.4&nbsp;&nbsp;<TT>mod_configure</TT></A>
<LI><A HREF="#htoc33">A.5&nbsp;&nbsp;<TT>mod_disco</TT></A>
<LI><A HREF="#htoc34">A.6&nbsp;&nbsp;<TT>mod_stats</TT></A>
<LI><A HREF="#htoc35">A.7&nbsp;&nbsp;<TT>mod_vcard</TT></A>
<LI><A HREF="#htoc36">A.8&nbsp;&nbsp;<TT>mod_offline</TT></A>
<LI><A HREF="#htoc37">A.9&nbsp;&nbsp;<TT>mod_echo</TT></A>
<LI><A HREF="#htoc38">A.10&nbsp;&nbsp;<TT>mod_private</TT></A>
<LI><A HREF="#htoc39">A.11&nbsp;&nbsp;<TT>mod_time</TT></A>
<LI><A HREF="#htoc40">A.12&nbsp;&nbsp;<TT>mod_version</TT></A>
</UL>
<LI><A HREF="#htoc41">B&nbsp;&nbsp;I18n/L10n</A>
</UL>
<!--TOC section Introduction-->
<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="sec:intro"></A>
<TT>ejabberd</TT> is a Free and Open Source fault-tolerant distributed Jabber
server. It is writen mostly in Erlang.<BR>
<BR>
The main features of <TT>ejabberd</TT> is:
<UL><LI>
Distributed: You may run <TT>ejabberd</TT> on a cluster of machines and all of
them will serve one Jabber domain.
<LI>Fault-tolerance: You may setup an <TT>ejabberd</TT> cluster so that all the
information required for a properly working service will be stored
permanently on more then one node. This means that if one of the nodes
crashes, then the others will continue working without disruption.
You can also add or replace more nodes ``on the fly''.
<LI>Support for
<A HREF="http://www.jabber.org/jeps/jep-0030.html">JEP-0030</A>
(Service Discovery).
<LI>Support for
<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A>
(Statistics Gathering).
<LI>Support for <TT>xml:lang</TT> attribute in many XML elements.
<LI>JUD based on users vCards.
</UL>
<!--TOC section Installation-->
<H2><A NAME="htoc2">2</A>&nbsp;&nbsp;Installation</H2><!--SEC END -->
<A NAME="sec:installation"></A>
<!--TOC subsection Installation Requirements-->
<H3><A NAME="htoc3">2.1</A>&nbsp;&nbsp;Installation Requirements</H3><!--SEC END -->
<A NAME="sec:installreq"></A>
To compile <TT>ejabberd</TT>, you will need the following packages:
<UL><LI>
GNU Make;
<LI>GCC;
<LI>libexpat 1.95 or later;
<LI>Erlang/OTP R8B or later.
</UL>
<!--TOC subsection Obtaining-->
<H3><A NAME="htoc4">2.2</A>&nbsp;&nbsp;Obtaining</H3><!--SEC END -->
<A NAME="sec:obtaining"></A>
Currently no stable version has been released.<BR>
<BR>
The latest alpha version can be retrieved from CVS.
<UL><LI>
<TT>export CVSROOT=:pserver:cvs@www.jabber.ru:/var/spool/cvs</TT>
<LI><TT>cvs login</TT>
<LI>Press Enter when asked for a password
<LI><TT>cvs -z3 co ejabberd</TT>
</UL>
<!--TOC subsection Compilation-->
<H3><A NAME="htoc5">2.3</A>&nbsp;&nbsp;Compilation</H3><!--SEC END -->
<A NAME="sec:compilation"></A>
<PRE>
./configure
make
</PRE>
TBD<BR>
<BR>
<!--TOC subsection Starting-->
<H3><A NAME="htoc6">2.4</A>&nbsp;&nbsp;Starting</H3><!--SEC END -->
<A NAME="sec:starting"></A>
... To use more then 1024 connections, you will need to set environment
variable <TT>ERL_MAX_PORTS</TT>:
<PRE>
export ERL_MAX_PORTS=32000
</PRE>Note that with this value <TT>ejabberd</TT> will use more memory (approximately 6MB
more)...
<PRE>
erl -name ejabberd -s ejabberd
</PRE>
TBD<BR>
<BR>
<!--TOC section Configuration-->
<H2><A NAME="htoc7">3</A>&nbsp;&nbsp;Configuration</H2><!--SEC END -->
<A NAME="sec:configuration"></A>
<!--TOC subsection Initial Configuration-->
<H3><A NAME="htoc8">3.1</A>&nbsp;&nbsp;Initial Configuration</H3><!--SEC END -->
<A NAME="sec:initconfig"></A>
The configuration file is initially loaded the first time <TT>ejabberd</TT> is
executed, when it is parsed and stored in a database. Subsiquently the
configuration is loaded from the database and any commands in the configuration
file are appended to the entries in the database. The configuration file
consists of a sequence of Erlang terms. Parts of lines after <TT>`%'</TT> sign
are ignored. Each term is tuple, where first element is name of option, and
other are option values. E.&nbsp;g. if this file does not contain a ``host''
definition, then old value stored in the database will be used.<BR>
<BR>
To override old values stored in the database the following lines can be added
in config:
<PRE>
override_global.
override_local.
override_acls.
</PRE>With this lines old global or local options or ACLs will be removed before
adding new ones.<BR>
<BR>
<!--TOC subsubsection Host Name-->
<H4><A NAME="htoc9">3.1.1</A>&nbsp;&nbsp;Host Name</H4><!--SEC END -->
<A NAME="sec:confighostname"></A>
Option <TT>hostname</TT> defines name of Jabber domain that <TT>ejabberd</TT>
serves. E.&nbsp;g. to use <TT>jabber.org</TT> domain add following line in config:
<PRE>
{host, "jabber.org"}.
</PRE>
<!--TOC subsubsection Access Rules-->
<H4><A NAME="htoc10">3.1.2</A>&nbsp;&nbsp;Access Rules</H4><!--SEC END -->
<A NAME="sec:configaccess"></A>
Access control in <TT>ejabberd</TT> is performed via Access Control Lists (ACL). The
declarations of ACL in config file have following syntax:
<PRE>
{acl, &lt;aclname&gt;, {&lt;acltype&gt;, ...}}.
</PRE>
<TT>&lt;acltype&gt;</TT> can be one of following:
<DL COMPACT=compact><DT>
<B><TT>all</TT></B><DD> Matches all JIDs. Example:
<PRE>
{acl, all, all}.
</PRE><DT><B><TT>{user, &lt;username&gt;}</TT></B><DD> Matches local user with name
<TT>&lt;username&gt;</TT>. Example:
<PRE>
{acl, admin, {user, "aleksey"}}.
</PRE><DT><B><TT>{user, &lt;username&gt;, &lt;server&gt;}</TT></B><DD> Matches user with JID
<TT>&lt;username&gt;@&lt;server&gt;</TT> and any resource. Example:
<PRE>
{acl, admin, {user, "aleksey", "jabber.ru"}}.
</PRE><DT><B><TT>{server, &lt;server&gt;}</TT></B><DD> Matches any JID from server
<TT>&lt;server&gt;</TT>. Example:
<PRE>
{acl, jabberorg, {server, "jabber.org"}}.
</PRE><DT><B><TT>{user_regexp, &lt;regexp&gt;}</TT></B><DD> Matches local user with name that
matches <TT>&lt;regexp&gt;</TT>. Example:
<PRE>
{acl, tests, {user, "^test[0-9]*$"}}.
</PRE><DT><B><TT>{user_regexp, &lt;regexp&gt;, &lt;server&gt;}</TT></B><DD> Matches user with name
that matches <TT>&lt;regexp&gt;</TT> and from server <TT>&lt;server&gt;</TT>. Example:
<PRE>
{acl, tests, {user, "^test", "localhost"}}.
</PRE><DT><B><TT>{server_regexp, &lt;regexp&gt;}</TT></B><DD> Matches any JID from server that
matches <TT>&lt;regexp&gt;</TT>. Example:
<PRE>
{acl, icq, {server, "^icq\\."}}.
</PRE><DT><B><TT>{node_regexp, &lt;user_regexp&gt;, &lt;server_regexp&gt;}</TT></B><DD> Matches user
with name that matches <TT>&lt;user_regexp&gt;</TT> and from server that matches
<TT>&lt;server_regexp&gt;</TT>. Example:
<PRE>
{acl, aleksey, {node_regexp, "^aleksey", "^jabber.(ru|org)$"}}.
</PRE><DT><B><TT>{user_glob, &lt;glob&gt;}</TT></B><DD>
<DT><B><TT>{user_glob, &lt;glob&gt;, &lt;server&gt;}</TT></B><DD>
<DT><B><TT>{server_glob, &lt;glob&gt;}</TT></B><DD>
<DT><B><TT>{node_glob, &lt;user_glob&gt;, &lt;server_glob&gt;}</TT></B><DD> This is same as
above, but uses shell glob patterns instead of regexp. These patterns can
have following special characters:
<DL COMPACT=compact><DT>
<B><TT>*</TT></B><DD> matches any string including the null string.
<DT><B><TT>?</TT></B><DD> matches any single character.
<DT><B><TT>[...]</TT></B><DD> matches any of the enclosed characters. Character
ranges are specified by a pair of characters separated by a <TT>`-'</TT>.
If the first character after <TT>`['</TT> is a <TT>`!'</TT>, then any
character not enclosed is matched.
</DL>
</DL>
The following ACLs pre-defined:
<DL COMPACT=compact><DT>
<B><TT>all</TT></B><DD> Matches all JIDs.
<DT><B><TT>none</TT></B><DD> Matches none JIDs.
</DL>
An entry allowing or denying different services would look similar to this:
<PRE>
{access, &lt;accessname&gt;, [{allow, &lt;aclname&gt;},
{deny, &lt;aclname&gt;},
...
]}.
</PRE>When a JID is checked to have access to <TT>&lt;accessname&gt;</TT>, the server
sequentially checks if this JID mathes one of the ACLs that are second elements
in each tuple in list. If it is matched, then the first element of matched
tuple is returned else ``<TT>deny</TT>'' is returned.<BR>
<BR>
Example:
<PRE>
{access, configure, [{allow, admin}]}.
{access, something, [{deny, badmans},
{allow, all}]}.
</PRE>
Following access rules pre-defined:
<DL COMPACT=compact><DT>
<B><TT>all</TT></B><DD> Always return ``<TT>allow</TT>''
<DT><B><TT>none</TT></B><DD> Always return ``<TT>deny</TT>''
</DL>
<!--TOC subsubsection Shapers Configuration-->
<H4><A NAME="htoc11">3.1.3</A>&nbsp;&nbsp;Shapers Configuration</H4><!--SEC END -->
<A NAME="sec:configshaper"></A>
With shapers is possible to bound connection traffic. The declarations of
shapers in config file have following syntax:
<PRE>
{shaper, &lt;shapername&gt;, &lt;kind&gt;}.
</PRE>Currently implemented only one kind of shaper: <TT>maxrate</TT>. It have
following syntax:
<PRE>
{maxrate, &lt;rate&gt;}
</PRE>where <TT>&lt;rate&gt;</TT> means maximum allowed incomig rate in bytes/second.
E.&nbsp;g. to define shaper with name ``<TT>normal</TT>'' and maximum allowed rate
1000&nbsp;bytes/s, add following line in config:
<PRE>
{shaper, normal, {maxrate, 1000}}.
</PRE>
<!--TOC subsubsection Listened Sockets-->
<H4><A NAME="htoc12">3.1.4</A>&nbsp;&nbsp;Listened Sockets</H4><!--SEC END -->
<A NAME="sec:configlistened"></A>
Option <TT>listen</TT> defines list of listened sockets and what services
runned on them. Each element of list is a tuple with following elements:
<UL><LI>
Port number;
<LI>Module that serves this port;
<LI>Function in this module that starts connection (likely will be removed);
<LI>Options to this module.
</UL>
Currently three modules are implemented:
<DL COMPACT=compact><DT>
<B><TT>ejabberd_c2s</TT></B><DD> This module serves C2S connections.<BR>
<BR>
Following options defined:
<DL COMPACT=compact><DT>
<B><TT>{access, &lt;access rule&gt;}</TT></B><DD> This option defines access of users
to this C2S port. Default value is ``<TT>all</TT>''.
<DT><B><TT>{shaper, &lt;access rule&gt;}</TT></B><DD> This option is like previous, but
use shapers instead of ``<TT>allow</TT>'' and ``<TT>deny</TT>''. Default
value is ``<TT>none</TT>''.
</DL>
<DT><B><TT>ejabberd_s2s_in</TT></B><DD> This module serves incoming S2S connections.
<DT><B><TT>ejabberd_service</TT></B><DD> This module serves connections to Jabber
services (i.&nbsp;e. that use the <TT>jabber:component:accept</TT> namespace).
</DL>
For example, the following configuration defines that C2S connections are
listened on port 5222 and denied for user ``<TT>bad</TT>'', S2S on port 5269
and that service <TT>conference.jabber.org</TT> must be connected to port 8888
with a password ``<TT>secret</TT>''. Also all users except admins have traffic
limit 1000&nbsp;b/s.
<PRE>
{acl, blocked, {user, "bad"}}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{shaper, normal, {maxrate, 1000}}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{listen, [{5222, ejabberd_c2s, start, [{access, c2s},
{shaper, c2s_shaper}]},
{5269, ejabberd_s2s_in, start, []},
{8888, ejabberd_service, start,
[{host, "conference.jabber.org", [{password, "secret"}]}]}
]}.
</PRE>
<!--TOC subsubsection Modules-->
<H4><A NAME="htoc13">3.1.5</A>&nbsp;&nbsp;Modules</H4><!--SEC END -->
<A NAME="sec:configmodules"></A>
Option <TT>modules</TT> defines the list of modules that will be loaded after
<TT>ejabberd</TT> startup. Each list element is a tuple where first element is a
name of a module and second is list of options to this module. See
section&nbsp;<A HREF="#sec:modules">A</A> for detailed information on each module.<BR>
<BR>
Example:
<PRE>
{modules, [
{mod_register, []},
{mod_roster, []},
{mod_configure, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_echo, [{host, "echo.localhost"}]},
{mod_private, []},
{mod_time, [{iqdisc, no_queue}]},
{mod_version, []}
]}.
</PRE>
<!--TOC subsection Online Configuration and Monitoring-->
<H3><A NAME="htoc14">3.2</A>&nbsp;&nbsp;Online Configuration and Monitoring</H3><!--SEC END -->
<A NAME="sec:onlineconfig"></A>
To perform online reconfiguration of <TT>ejabberd</TT> you will need to have
<TT>mod_configure</TT> loaded (see section&nbsp;<A HREF="#sec:modconfigure">A.4</A>). It is also highly
recommended to load <TT>mod_disco</TT> as well (see section&nbsp;<A HREF="#sec:moddisco">A.5</A>),
because <TT>mod_configure</TT> is highly integrated with it. Additionally it is
recommended to use a disco- and xdata-capable client such as
<A HREF="http://www.jabber.ru/projects/tkabber/index_en.html">Tkabber</A>
(which was developed synchronously with <TT>ejabberd</TT>, its CVS version
supports most of <TT>ejabberd</TT> features).<BR>
<BR>
On disco query <TT>ejabberd</TT> returns following items:
<UL><LI>
Identity of server.
<LI>List of features, including defined namespaces.
<LI>List of JIDs from route table.
<LI>List of disco-nodes described in following subsections.
</UL>
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="disco.png">
<BR>
<DIV ALIGN=center>Figure 1: Tkabber Discovery window</DIV><BR>
<A NAME="fig:disco"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC subsubsection Node <TT>config</TT>: Global Configuration-->
<H4><A NAME="htoc15">3.2.1</A>&nbsp;&nbsp;Node <TT>config</TT>: Global Configuration</H4><!--SEC END -->
Under this node the following nodes exists:<BR>
<BR>
<!--TOC paragraph Node <TT>config/hostname</TT>-->
<H5>Node <TT>config/hostname</TT></H5><!--SEC END -->
Via <TT>jabber:x:data</TT> queries to this node possible to change host name of
this <TT>ejabberd</TT> server. (See figure&nbsp;<A HREF="#fig:hostname">2</A>) (Currently this works
correctly only after a restart)
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="confhostname.png">
<BR>
<DIV ALIGN=center>Figure 2: Editing of hostname</DIV><BR>
<A NAME="fig:hostname"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC paragraph Node <TT>config/acls</TT>-->
<H5>Node <TT>config/acls</TT></H5><!--SEC END -->
Via <TT>jabber:x:data</TT> queries to this node it is possible to edit ACLs list.
(See figure&nbsp;<A HREF="#fig:acls">3</A>)
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="confacls.png">
<BR>
<DIV ALIGN=center>Figure 3: Editing of ACLs</DIV><BR>
<A NAME="fig:acls"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC paragraph Node <TT>config/access</TT>-->
<H5>Node <TT>config/access</TT></H5><!--SEC END -->
Via <TT>jabber:x:data</TT> queries to this node it is possible to edit access
rules.<BR>
<BR>
<!--TOC paragraph Node <TT>config/remusers</TT>-->
<H5>Node <TT>config/remusers</TT></H5><!--SEC END -->
Via <TT>jabber:x:data</TT> queries to this node it is possible to remove users. If
removed user is online, then he will be disconnected. Also user-related data
(e.g. his roster) is removed (but appropriate module must be loaded).<BR>
<BR>
<!--TOC subsubsection Node <TT>online users</TT>: List of Online Users-->
<H4><A NAME="htoc16">3.2.2</A>&nbsp;&nbsp;Node <TT>online users</TT>: List of Online Users</H4><!--SEC END -->
<!--TOC subsubsection Node <TT>all users</TT>: List of Registered User-->
<H4><A NAME="htoc17">3.2.3</A>&nbsp;&nbsp;Node <TT>all users</TT>: List of Registered User</H4><!--SEC END -->
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="discoallusers.png">
<BR>
<DIV ALIGN=center>Figure 4: Discovery all users</DIV><BR>
<A NAME="fig:discoallusers"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC subsubsection Node <TT>outgoing s2s</TT>: List of Outgoing S2S connections-->
<H4><A NAME="htoc18">3.2.4</A>&nbsp;&nbsp;Node <TT>outgoing s2s</TT>: List of Outgoing S2S connections</H4><!--SEC END -->
<!--TOC subsubsection Node <TT>running nodes</TT>: List of Running <TT>ejabberd</TT> Nodes-->
<H4><A NAME="htoc19">3.2.5</A>&nbsp;&nbsp;Node <TT>running nodes</TT>: List of Running <TT>ejabberd</TT> Nodes</H4><!--SEC END -->
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="discorunnodes.png">
<BR>
<DIV ALIGN=center>Figure 5: Discovery running nodes</DIV><BR>
<A NAME="fig:discorunnodes"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC subsubsection Node <TT>stopped nodes</TT>: List of Stopped Nodes-->
<H4><A NAME="htoc20">3.2.6</A>&nbsp;&nbsp;Node <TT>stopped nodes</TT>: List of Stopped Nodes</H4><!--SEC END -->
TBD<BR>
<BR>
<!--TOC section Distribution-->
<H2><A NAME="htoc21">4</A>&nbsp;&nbsp;Distribution</H2><!--SEC END -->
<A NAME="sec:distribution"></A>
<!--TOC subsection How it works-->
<H3><A NAME="htoc22">4.1</A>&nbsp;&nbsp;How it works</H3><!--SEC END -->
<A NAME="sec:howitworks"></A>
A Jabber domain is served by one or more <TT>ejabberd</TT> nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
<TT>~ejabberd/.erlang.cookie</TT> must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc...<BR>
<BR>
Each <TT>ejabberd</TT> node must run following modules:
<UL><LI>
router;
<LI>local router.
<LI>session manager;
<LI>S2S manager;
</UL>
<!--TOC subsubsection Router-->
<H4><A NAME="htoc23">4.1.1</A>&nbsp;&nbsp;Router</H4><!--SEC END -->
This module is the main router of Jabber packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate <TT>ejabberd</TT> node or
process. If itdoes not exists in either table, then it sent to the S2S
manager.<BR>
<BR>
<!--TOC subsubsection Local Router-->
<H4><A NAME="htoc24">4.1.2</A>&nbsp;&nbsp;Local Router</H4><!--SEC END -->
This module routes packets which have a destination domain equal to this server
name. If destination JID has a node, then it routed to the session manager,
else it is processed depending on it's content.<BR>
<BR>
<!--TOC subsubsection Session Manager-->
<H4><A NAME="htoc25">4.1.3</A>&nbsp;&nbsp;Session Manager</H4><!--SEC END -->
This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.<BR>
<BR>
<!--TOC subsubsection S2S Manager-->
<H4><A NAME="htoc26">4.1.4</A>&nbsp;&nbsp;S2S Manager</H4><!--SEC END -->
This module routes packets to other Jabber servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.<BR>
<BR>
<!--TOC section Built-in Modules-->
<H2><A NAME="htoc27">A</A>&nbsp;&nbsp;Built-in Modules</H2><!--SEC END -->
<A NAME="sec:modules"></A>
<!--TOC subsection Common Options-->
<H3><A NAME="htoc28">A.1</A>&nbsp;&nbsp;Common Options</H3><!--SEC END -->
<A NAME="sec:modcommonopts"></A>
Following options used by many modules, so they described in separate section.<BR>
<BR>
<!--TOC subsubsection Option <TT>iqdisc</TT>-->
<H4><A NAME="htoc29">A.1.1</A>&nbsp;&nbsp;Option <TT>iqdisc</TT></H4><!--SEC END -->
Many modules define handlers for processing IQ queries of different namespaces
to this server or to user (e.&nbsp;g. to <TT>myjabber.org</TT> or to
<TT>user@myjabber.org</TT>). This option defines processing discipline of
these queries. Possible values are:
<DL COMPACT=compact><DT>
<B><TT>no_queue</TT></B><DD> All queries of namespace with this processing
discipline processed immediately. This also means that no other packets can
be processed until finished this. Hence this discipline is not recommended
if processing of query can take relative many time.
<DT><B><TT>one_queue</TT></B><DD> In this case created separate queue for processing
IQ queries of namespace with this discipline, and processing of this queue
done in parallel with processing of other packets. This discipline is most
recommended.
<DT><B><TT>parallel</TT></B><DD> In this case for all packets of namespace with this
discipline spawned separate Erlang process, so all this packets processed in
parallel. Although spawning of Erlang process have relative low cost, this
can broke server normal work, because Erlang have limit of 32000 processes.
</DL>
Example:
<PRE>
{modules, [
...
{mod_time, [{iqdisc, no_queue}]},
...
]}.
</PRE>
<!--TOC subsubsection Option <TT>host</TT>-->
<H4><A NAME="htoc30">A.1.2</A>&nbsp;&nbsp;Option <TT>host</TT></H4><!--SEC END -->
Some modules may act as services, and wants to have different domain name.
This option explicitly defines this name.<BR>
<BR>
Example:
<PRE>
{modules, [
...
{mod_echo, [{host, "echo.myjabber.org"}]},
...
]}.
</PRE>
<!--TOC subsection <TT>mod_register</TT>-->
<H3><A NAME="htoc31">A.2</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
<A NAME="sec:modregister"></A>
<!--TOC subsection <TT>mod_roster</TT>-->
<H3><A NAME="htoc32">A.3</A>&nbsp;&nbsp;<TT>mod_roster</TT></H3><!--SEC END -->
<A NAME="sec:modroster"></A>
<!--TOC subsection <TT>mod_configure</TT>-->
<H3><A NAME="htoc33">A.4</A>&nbsp;&nbsp;<TT>mod_configure</TT></H3><!--SEC END -->
<A NAME="sec:modconfigure"></A>
<!--TOC subsection <TT>mod_disco</TT>-->
<H3><A NAME="htoc34">A.5</A>&nbsp;&nbsp;<TT>mod_disco</TT></H3><!--SEC END -->
<A NAME="sec:moddisco"></A>
<!--TOC subsection <TT>mod_stats</TT>-->
<H3><A NAME="htoc35">A.6</A>&nbsp;&nbsp;<TT>mod_stats</TT></H3><!--SEC END -->
<A NAME="sec:modstats"></A>
This module adds support of
<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A> (Statistics Gathering).<BR>
<BR>
Options:
<DL COMPACT=compact><DT>
<B><TT>iqdisc</TT></B><DD> <TT>http://jabber.org/protocol/stats</TT> IQ queries
processing discipline.
</DL>
TBD about access.<BR>
<BR>
<!--TOC subsection <TT>mod_vcard</TT>-->
<H3><A NAME="htoc36">A.7</A>&nbsp;&nbsp;<TT>mod_vcard</TT></H3><!--SEC END -->
<A NAME="sec:modvcard"></A>
<!--TOC subsection <TT>mod_offline</TT>-->
<H3><A NAME="htoc37">A.8</A>&nbsp;&nbsp;<TT>mod_offline</TT></H3><!--SEC END -->
<A NAME="sec:modoffline"></A>
<!--TOC subsection <TT>mod_echo</TT>-->
<H3><A NAME="htoc38">A.9</A>&nbsp;&nbsp;<TT>mod_echo</TT></H3><!--SEC END -->
<A NAME="sec:modecho"></A>
<!--TOC subsection <TT>mod_private</TT>-->
<H3><A NAME="htoc39">A.10</A>&nbsp;&nbsp;<TT>mod_private</TT></H3><!--SEC END -->
<A NAME="sec:modprivate"></A>
This module adds support of
<A HREF="http://www.jabber.org/jeps/jep-0049.html">JEP-0049</A> (Private XML
Storage).<BR>
<BR>
Options:
<DL COMPACT=compact><DT>
<B><TT>iqdisc</TT></B><DD> <TT>jabber:iq:private</TT> IQ queries processing discipline.
</DL>
<!--TOC subsection <TT>mod_time</TT>-->
<H3><A NAME="htoc40">A.11</A>&nbsp;&nbsp;<TT>mod_time</TT></H3><!--SEC END -->
<A NAME="sec:modtime"></A>
This module answers UTC time on <TT>jabber:iq:time</TT> queries.<BR>
<BR>
Options:
<DL COMPACT=compact><DT>
<B><TT>iqdisc</TT></B><DD> <TT>jabber:iq:time</TT> IQ queries processing discipline.
</DL>
<!--TOC subsection <TT>mod_version</TT>-->
<H3><A NAME="htoc41">A.12</A>&nbsp;&nbsp;<TT>mod_version</TT></H3><!--SEC END -->
<A NAME="sec:modversion"></A>
This module answers <TT>ejabberd</TT> version on <TT>jabber:iq:version</TT> queries.<BR>
<BR>
Options:
<DL COMPACT=compact><DT>
<B><TT>iqdisc</TT></B><DD> <TT>jabber:iq:version</TT> IQ queries processing discipline.
</DL>
<!--TOC section I18n/L10n-->
<H2><A NAME="htoc42">B</A>&nbsp;&nbsp;I18n/L10n</H2><!--SEC END -->
<A NAME="sec:i18nl10n"></A>
Many modules supports <TT>xml:lang</TT> attribute inside IQ queries. E.&nbsp;g.
on figure&nbsp;<A HREF="#fig:discorus">6</A> (compare with figure&nbsp;<A HREF="#fig:disco">1</A>) showed reply
on following query:
<PRE>
&lt;iq id='5'
to='e.localhost'
type='get'&gt;
&lt;query xmlns='http://jabber.org/protocol/disco#items'
xml:lang='ru'/&gt;
&lt;/iq&gt;
</PRE>
<BLOCKQUOTE><DIV ALIGN=center><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<IMG SRC="discorus.png">
<BR>
<DIV ALIGN=center>Figure 6: Discovery result when <TT>xml:lang='ru'</TT></DIV><BR>
<A NAME="fig:discorus"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2>
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>
+738
View File
@@ -0,0 +1,738 @@
\documentclass[10pt]{article}
\usepackage{graphics}
\usepackage{hevea}
\usepackage{verbatim}
\newcommand{\logoscale}{0.7}
\newcommand{\imgscale}{0.58}
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
\newcommand{\insscaleimg}[2]{
\imgsrc{#2}{}
\begin{latexonly}
\scalebox{#1}{\includegraphics{#2}}
\end{latexonly}
}
\newcommand{\ns}[1]{\texttt{#1}}
\newcommand{\ejabberd}{\texttt{ejabberd}}
\newcommand{\Jabber}{Jabber}
\newcommand{\modregister}{\texttt{mod\_register}}
\newcommand{\modroster}{\texttt{mod\_roster}}
\newcommand{\modconfigure}{\texttt{mod\_configure}}
\newcommand{\moddisco}{\texttt{mod\_disco}}
\newcommand{\modstats}{\texttt{mod\_stats}}
\newcommand{\modvcard}{\texttt{mod\_vcard}}
\newcommand{\modoffline}{\texttt{mod\_offline}}
\newcommand{\modecho}{\texttt{mod\_echo}}
\newcommand{\modprivate}{\texttt{mod\_private}}
\newcommand{\modtime}{\texttt{mod\_time}}
\newcommand{\modversion}{\texttt{mod\_version}}
%\setcounter{tocdepth}{3}
\title{Ejabberd Installation and Operation Guide}
\author{Alexey Shchepin \\
\ahrefurl{mailto:alexey@sevcom.net} \\
\ahrefurl{xmpp:aleksey@jabber.ru}}
\date{February 11, 2003}
\begin{document}
\begin{titlepage}
\maketitle{}
{\centering
\insscaleimg{\logoscale}{logo.png}
\par
}
\end{titlepage}
%\newpage
\tableofcontents{}
\newpage
\section{Introduction}
\label{sec:intro}
\ejabberd{} is a Free and Open Source fault-tolerant distributed \Jabber{}
server. It is writen mostly in Erlang.
The main features of \ejabberd{} is:
\begin{itemize}
\item Distributed: You may run \ejabberd{} on a cluster of machines and all of
them will serve one Jabber domain.
\item Fault-tolerance: You may setup an \ejabberd{} cluster so that all the
information required for a properly working service will be stored
permanently on more then one node. This means that if one of the nodes
crashes, then the others will continue working without disruption.
You can also add or replace more nodes ``on the fly''.
\item Support for
\footahref{http://www.jabber.org/jeps/jep-0030.html}{JEP-0030}
(Service Discovery).
\item Support for
\footahref{http://www.jabber.org/jeps/jep-0039.html}{JEP-0039}
(Statistics Gathering).
\item Support for \ns{xml:lang} attribute in many XML elements.
\item JUD based on users vCards.
\end{itemize}
\section{Installation}
\label{sec:installation}
\subsection{Installation Requirements}
\label{sec:installreq}
To compile \ejabberd{}, you will need the following packages:
\begin{itemize}
\item GNU Make;
\item GCC;
\item libexpat 1.95 or later;
\item Erlang/OTP R8B or later.
\end{itemize}
\subsection{Obtaining}
\label{sec:obtaining}
Currently no stable version has been released.
The latest alpha version can be retrieved from CVS\@.
\begin{itemize}
\item \texttt{export CVSROOT=:pserver:cvs@www.jabber.ru:/var/spool/cvs}
\item \texttt{cvs login}
\item Press Enter when asked for a password
\item \texttt{cvs -z3 co ejabberd}
\end{itemize}
\subsection{Compilation}
\label{sec:compilation}
\begin{verbatim}
./configure
make
\end{verbatim}
TBD
%\subsection{Initial Configuration}
%\label{sec:initconfig}
\subsection{Starting}
\label{sec:starting}
\ldots{} To use more then 1024 connections, you will need to set environment
variable \texttt{ERL\_MAX\_PORTS}:
\begin{verbatim}
export ERL_MAX_PORTS=32000
\end{verbatim}
Note that with this value \ejabberd{} will use more memory (approximately 6MB
more)\ldots{}
\begin{verbatim}
erl -name ejabberd -s ejabberd
\end{verbatim}
TBD
\section{Configuration}
\label{sec:configuration}
\subsection{Initial Configuration}
\label{sec:initconfig}
%\verbatiminput{../src/ejabberd.cfg}
The configuration file is initially loaded the first time \ejabberd{} is
executed, when it is parsed and stored in a database. Subsiquently the
configuration is loaded from the database and any commands in the configuration
file are appended to the entries in the database. The configuration file
consists of a sequence of Erlang terms. Parts of lines after \texttt{`\%'} sign
are ignored. Each term is tuple, where first element is name of option, and
other are option values. E.\,g.\ if this file does not contain a ``host''
definition, then old value stored in the database will be used.
To override old values stored in the database the following lines can be added
in config:
\begin{verbatim}
override_global.
override_local.
override_acls.
\end{verbatim}
With this lines old global or local options or ACLs will be removed before
adding new ones.
\subsubsection{Host Name}
\label{sec:confighostname}
Option \texttt{hostname} defines name of \Jabber{} domain that \ejabberd{}
serves. E.\,g.\ to use \texttt{jabber.org} domain add following line in config:
\begin{verbatim}
{host, "jabber.org"}.
\end{verbatim}
%This option is mandatory.
\subsubsection{Access Rules}
\label{sec:configaccess}
Access control in \ejabberd{} is performed via Access Control Lists (ACL). The
declarations of ACL in config file have following syntax:
\begin{verbatim}
{acl, <aclname>, {<acltype>, ...}}.
\end{verbatim}
\texttt{<acltype>} can be one of following:
\begin{description}
\item[\texttt{all}] Matches all JIDs. Example:
\begin{verbatim}
{acl, all, all}.
\end{verbatim}
\item[\texttt{\{user, <username>\}}] Matches local user with name
\texttt{<username>}. Example:
\begin{verbatim}
{acl, admin, {user, "aleksey"}}.
\end{verbatim}
\item[\texttt{\{user, <username>, <server>\}}] Matches user with JID
\texttt{<username>@<server>} and any resource. Example:
\begin{verbatim}
{acl, admin, {user, "aleksey", "jabber.ru"}}.
\end{verbatim}
\item[\texttt{\{server, <server>\}}] Matches any JID from server
\texttt{<server>}. Example:
\begin{verbatim}
{acl, jabberorg, {server, "jabber.org"}}.
\end{verbatim}
\item[\texttt{\{user\_regexp, <regexp>\}}] Matches local user with name that
matches \texttt{<regexp>}. Example:
\begin{verbatim}
{acl, tests, {user, "^test[0-9]*$"}}.
\end{verbatim}
%$
\item[\texttt{\{user\_regexp, <regexp>, <server>\}}] Matches user with name
that matches \texttt{<regexp>} and from server \texttt{<server>}. Example:
\begin{verbatim}
{acl, tests, {user, "^test", "localhost"}}.
\end{verbatim}
\item[\texttt{\{server\_regexp, <regexp>\}}] Matches any JID from server that
matches \texttt{<regexp>}. Example:
\begin{verbatim}
{acl, icq, {server, "^icq\\."}}.
\end{verbatim}
\item[\texttt{\{node\_regexp, <user\_regexp>, <server\_regexp>\}}] Matches user
with name that matches \texttt{<user\_regexp>} and from server that matches
\texttt{<server\_regexp>}. Example:
\begin{verbatim}
{acl, aleksey, {node_regexp, "^aleksey", "^jabber.(ru|org)$"}}.
\end{verbatim}
%$
\item[\texttt{\{user\_glob, <glob>\}}]
\item[\texttt{\{user\_glob, <glob>, <server>\}}]
\item[\texttt{\{server\_glob, <glob>\}}]
\item[\texttt{\{node\_glob, <user\_glob>, <server\_glob>\}}] This is same as
above, but uses shell glob patterns instead of regexp. These patterns can
have following special characters:
\begin{description}
\item[\texttt{*}] matches any string including the null string.
\item[\texttt{?}] matches any single character.
\item[\texttt{[\ldots{}]}] matches any of the enclosed characters. Character
ranges are specified by a pair of characters separated by a \texttt{`-'}.
If the first character after \texttt{`['} is a \texttt{`!'}, then any
character not enclosed is matched.
\end{description}
\end{description}
The following ACLs pre-defined:
\begin{description}
\item[\texttt{all}] Matches all JIDs.
\item[\texttt{none}] Matches none JIDs.
\end{description}
An entry allowing or denying different services would look similar to this:
\begin{verbatim}
{access, <accessname>, [{allow, <aclname>},
{deny, <aclname>},
...
]}.
\end{verbatim}
When a JID is checked to have access to \texttt{<accessname>}, the server
sequentially checks if this JID mathes one of the ACLs that are second elements
in each tuple in list. If it is matched, then the first element of matched
tuple is returned else ``\texttt{deny}'' is returned.
Example:
\begin{verbatim}
{access, configure, [{allow, admin}]}.
{access, something, [{deny, badmans},
{allow, all}]}.
\end{verbatim}
Following access rules pre-defined:
\begin{description}
\item[\texttt{all}] Always return ``\texttt{allow}''
\item[\texttt{none}] Always return ``\texttt{deny}''
\end{description}
\subsubsection{Shapers Configuration}
\label{sec:configshaper}
With shapers is possible to bound connection traffic. The declarations of
shapers in config file have following syntax:
\begin{verbatim}
{shaper, <shapername>, <kind>}.
\end{verbatim}
Currently implemented only one kind of shaper: \texttt{maxrate}. It have
following syntax:
\begin{verbatim}
{maxrate, <rate>}
\end{verbatim}
where \texttt{<rate>} means maximum allowed incomig rate in bytes/second.
E.\,g.\ to define shaper with name ``\texttt{normal}'' and maximum allowed rate
1000\,bytes/s, add following line in config:
\begin{verbatim}
{shaper, normal, {maxrate, 1000}}.
\end{verbatim}
\subsubsection{Listened Sockets}
\label{sec:configlistened}
Option \texttt{listen} defines list of listened sockets and what services
runned on them. Each element of list is a tuple with following elements:
\begin{itemize}
\item Port number;
\item Module that serves this port;
\item Function in this module that starts connection (likely will be removed);
\item Options to this module.
\end{itemize}
Currently three modules are implemented:
\begin{description}
\item[\texttt{ejabberd\_c2s}] This module serves C2S connections.
Following options defined:
\begin{description}
\item[\texttt{\{access, <access rule>\}}] This option defines access of users
to this C2S port. Default value is ``\texttt{all}''.
\item[\texttt{\{shaper, <access rule>\}}] This option is like previous, but
use shapers instead of ``\texttt{allow}'' and ``\texttt{deny}''. Default
value is ``\texttt{none}''.
\end{description}
\item[\texttt{ejabberd\_s2s\_in}] This module serves incoming S2S connections.
\item[\texttt{ejabberd\_service}] This module serves connections to \Jabber{}
services (i.\,e.\ that use the \texttt{jabber:component:accept} namespace).
\end{description}
For example, the following configuration defines that C2S connections are
listened on port 5222 and denied for user ``\texttt{bad}'', S2S on port 5269
and that service \texttt{conference.jabber.org} must be connected to port 8888
with a password ``\texttt{secret}''. Also all users except admins have traffic
limit 1000\,b/s.
\begin{verbatim}
{acl, blocked, {user, "bad"}}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{shaper, normal, {maxrate, 1000}}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{listen, [{5222, ejabberd_c2s, start, [{access, c2s},
{shaper, c2s_shaper}]},
{5269, ejabberd_s2s_in, start, []},
{8888, ejabberd_service, start,
[{host, "conference.jabber.org", [{password, "secret"}]}]}
]}.
\end{verbatim}
\subsubsection{Modules}
\label{sec:configmodules}
Option \texttt{modules} defines the list of modules that will be loaded after
\ejabberd{} startup. Each list element is a tuple where first element is a
name of a module and second is list of options to this module. See
section~\ref{sec:modules} for detailed information on each module.
Example:
\begin{verbatim}
{modules, [
{mod_register, []},
{mod_roster, []},
{mod_configure, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_echo, [{host, "echo.localhost"}]},
{mod_private, []},
{mod_time, [{iqdisc, no_queue}]},
{mod_version, []}
]}.
\end{verbatim}
\subsection{Online Configuration and Monitoring}
\label{sec:onlineconfig}
To perform online reconfiguration of \ejabberd{} you will need to have
\modconfigure{} loaded (see section~\ref{sec:modconfigure}). It is also highly
recommended to load \moddisco{} as well (see section~\ref{sec:moddisco}),
because \modconfigure{} is highly integrated with it. Additionally it is
recommended to use a disco- and xdata-capable client such as
\footahref{http://www.jabber.ru/projects/tkabber/index\_en.html}{Tkabber}
(which was developed synchronously with \ejabberd{}, its CVS version
supports most of \ejabberd{} features).
On disco query \ejabberd{} returns following items:
\begin{itemize}
\item Identity of server.
\item List of features, including defined namespaces.
\item List of JIDs from route table.
\item List of disco-nodes described in following subsections.
\end{itemize}
\begin{figure}[htbp]
\centering
\insimg{disco.png}
\caption{Tkabber Discovery window}
\label{fig:disco}
\end{figure}
\subsubsection{Node \texttt{config}: Global Configuration}
Under this node the following nodes exists:
\paragraph{Node \texttt{config/hostname}}
Via \ns{jabber:x:data} queries to this node possible to change host name of
this \ejabberd{} server. (See figure~\ref{fig:hostname}) (Currently this works
correctly only after a restart)
\begin{figure}[htbp]
\centering
\insimg{confhostname.png}
\caption{Editing of hostname}
\label{fig:hostname}
\end{figure}
\paragraph{Node \texttt{config/acls}}
Via \ns{jabber:x:data} queries to this node it is possible to edit ACLs list.
(See figure~\ref{fig:acls})
\begin{figure}[htbp]
\centering
\insimg{confacls.png}
\caption{Editing of ACLs}
\label{fig:acls}
\end{figure}
\paragraph{Node \texttt{config/access}}
Via \ns{jabber:x:data} queries to this node it is possible to edit access
rules.
\paragraph{Node \texttt{config/remusers}}
Via \ns{jabber:x:data} queries to this node it is possible to remove users. If
removed user is online, then he will be disconnected. Also user-related data
(e.g. his roster) is removed (but appropriate module must be loaded).
\subsubsection{Node \texttt{online users}: List of Online Users}
\subsubsection{Node \texttt{all users}: List of Registered User}
\begin{figure}[htbp]
\centering
\insimg{discoallusers.png}
\caption{Discovery all users}
\label{fig:discoallusers}
\end{figure}
\subsubsection{Node \texttt{outgoing s2s}: List of Outgoing S2S connections}
\subsubsection{Node \texttt{running nodes}: List of Running \ejabberd{} Nodes}
\begin{figure}[htbp]
\centering
\insimg{discorunnodes.png}
\caption{Discovery running nodes}
\label{fig:discorunnodes}
\end{figure}
\subsubsection{Node \texttt{stopped nodes}: List of Stopped Nodes}
TBD
\section{Distribution}
\label{sec:distribution}
\subsection{How it works}
\label{sec:howitworks}
A \Jabber{} domain is served by one or more \ejabberd{} nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
\texttt{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc\ldots
Each \ejabberd{} node must run following modules:
\begin{itemize}
\item router;
\item local router.
\item session manager;
\item S2S manager;
\end{itemize}
\subsubsection{Router}
This module is the main router of \Jabber{} packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate \ejabberd{} node or
process. If itdoes not exists in either table, then it sent to the S2S
manager.
\subsubsection{Local Router}
This module routes packets which have a destination domain equal to this server
name. If destination JID has a node, then it routed to the session manager,
else it is processed depending on it's content.
\subsubsection{Session Manager}
This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.
\subsubsection{S2S Manager}
This module routes packets to other \Jabber{} servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.
\appendix{}
\section{Built-in Modules}
\label{sec:modules}
\subsection{Common Options}
\label{sec:modcommonopts}
Following options used by many modules, so they described in separate section.
\subsubsection{Option \texttt{iqdisc}}
Many modules define handlers for processing IQ queries of different namespaces
to this server or to user (e.\,g.\ to \texttt{myjabber.org} or to
\texttt{user@myjabber.org}). This option defines processing discipline of
these queries. Possible values are:
\begin{description}
\item[\texttt{no\_queue}] All queries of namespace with this processing
discipline processed immediately. This also means that no other packets can
be processed until finished this. Hence this discipline is not recommended
if processing of query can take relative many time.
\item[\texttt{one\_queue}] In this case created separate queue for processing
IQ queries of namespace with this discipline, and processing of this queue
done in parallel with processing of other packets. This discipline is most
recommended.
\item[\texttt{parallel}] In this case for all packets of namespace with this
discipline spawned separate Erlang process, so all this packets processed in
parallel. Although spawning of Erlang process have relative low cost, this
can broke server normal work, because Erlang have limit of 32000 processes.
\end{description}
Example:
\begin{verbatim}
{modules, [
...
{mod_time, [{iqdisc, no_queue}]},
...
]}.
\end{verbatim}
\subsubsection{Option \texttt{host}}
Some modules may act as services, and wants to have different domain name.
This option explicitly defines this name.
Example:
\begin{verbatim}
{modules, [
...
{mod_echo, [{host, "echo.myjabber.org"}]},
...
]}.
\end{verbatim}
\subsection{\modregister{}}
\label{sec:modregister}
\subsection{\modroster{}}
\label{sec:modroster}
\subsection{\modconfigure{}}
\label{sec:modconfigure}
\subsection{\moddisco{}}
\label{sec:moddisco}
\subsection{\modstats{}}
\label{sec:modstats}
This module adds support of
\footahref{http://www.jabber.org/jeps/jep-0039.html}{JEP-0039} (Statistics Gathering).
Options:
\begin{description}
\item[\texttt{iqdisc}] \ns{http://jabber.org/protocol/stats} IQ queries
processing discipline.
\end{description}
TBD about access.
\subsection{\modvcard{}}
\label{sec:modvcard}
\subsection{\modoffline{}}
\label{sec:modoffline}
\subsection{\modecho{}}
\label{sec:modecho}
\subsection{\modprivate{}}
\label{sec:modprivate}
This module adds support of
\footahref{http://www.jabber.org/jeps/jep-0049.html}{JEP-0049} (Private XML
Storage).
Options:
\begin{description}
\item[\texttt{iqdisc}] \ns{jabber:iq:private} IQ queries processing discipline.
\end{description}
\subsection{\modtime{}}
\label{sec:modtime}
This module answers UTC time on \ns{jabber:iq:time} queries.
Options:
\begin{description}
\item[\texttt{iqdisc}] \ns{jabber:iq:time} IQ queries processing discipline.
\end{description}
\subsection{\modversion{}}
\label{sec:modversion}
This module answers \ejabberd{} version on \ns{jabber:iq:version} queries.
Options:
\begin{description}
\item[\texttt{iqdisc}] \ns{jabber:iq:version} IQ queries processing discipline.
\end{description}
\section{I18n/L10n}
\label{sec:i18nl10n}
Many modules supports \texttt{xml:lang} attribute inside IQ queries. E.\,g.\
on figure~\ref{fig:discorus} (compare with figure~\ref{fig:disco}) showed reply
on following query:
\begin{verbatim}
<iq id='5'
to='e.localhost'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'
xml:lang='ru'/>
</iq>
\end{verbatim}
\begin{figure}[htbp]
\centering
\insimg{discorus.png}
\caption{Discovery result when \texttt{xml:lang='ru'}}
\label{fig:discorus}
\end{figure}
\end{document}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

-876
View File
@@ -1,876 +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/download/ejabberd/"/>
<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.13.2</xmpp:version>
<xmpp:since>0.5.0</xmpp:since>
<xmpp:status>complete</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>0.5.0</xmpp:since>
<xmpp:status>complete</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.3</xmpp:version>
<xmpp:since>16.02</xmpp:since>
<xmpp:status>complete</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.7</xmpp:version>
<xmpp:since>0.5.0</xmpp:since>
<xmpp:status>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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>0.7.5</xmpp:since>
<xmpp:status>complete</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.5.0</xmpp:version>
<xmpp:since>0.1.0</xmpp:since>
<xmpp:status>complete</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>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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.35.3</xmpp:version>
<xmpp:since>0.5.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_muc</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since>0.5.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_pubsub</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>0.1.0</xmpp:since>
<xmpp:status>complete</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.3.0</xmpp:version>
<xmpp:since>1.1.0</xmpp:since>
<xmpp:status>complete</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.3.0</xmpp:version>
<xmpp:since>0.1.0</xmpp:since>
<xmpp:status>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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>2.1.0</xmpp:since>
<xmpp:status>complete</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>0.5.0</xmpp:since>
<xmpp:status>partial</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.2</xmpp:version>
<xmpp:since>2.0.0</xmpp:since>
<xmpp:status>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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>17.03</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_legacy_auth</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0082.html"/>
<xmpp:version>1.1.1</xmpp:version>
<xmpp:since>2.1.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note></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>2.1.0</xmpp:since>
<xmpp:status>complete</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>0.5.0</xmpp:since>
<xmpp:status>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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.1</xmpp:version>
<xmpp:since>0.5.0</xmpp:since>
<xmpp:status>complete</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>0.1.0</xmpp:since>
<xmpp:status>complete</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.6.0</xmpp:version>
<xmpp:since>2.1.4</xmpp:since>
<xmpp:status>complete</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.2</xmpp:version>
<xmpp:since>16.12</xmpp:since>
<xmpp:status>complete</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.1</xmpp:version>
<xmpp:since>13.10</xmpp:since>
<xmpp:status>partial</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>1.1.0</xmpp:since>
<xmpp:status>complete</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.1</xmpp:version>
<xmpp:since>17.09</xmpp:since>
<xmpp:status>complete</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>complete</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.1.1</xmpp:version>
<xmpp:since>2.1.0</xmpp:since>
<xmpp:status>complete</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.1</xmpp:version>
<xmpp:since>2.1.0</xmpp:since>
<xmpp:status>complete</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.1</xmpp:version>
<xmpp:since>16.01</xmpp:since>
<xmpp:status>complete</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.2</xmpp:version>
<xmpp:since>2.0.0</xmpp:since>
<xmpp:status>complete</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>17.12</xmpp:since>
<xmpp:status>complete</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>1.1.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>ejabberd_auth_anonymous</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0178.html"/>
<xmpp:version>1.2</xmpp:version>
<xmpp:since>17.03</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note></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>17.03</xmpp:since>
<xmpp:status>complete</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.3</xmpp:version>
<xmpp:since>2.1.7</xmpp:since>
<xmpp:status>complete</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>complete</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.1</xmpp:version>
<xmpp:since>2.1.0</xmpp:since>
<xmpp:status>complete</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>2.1.0</xmpp:since>
<xmpp:status>complete</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>2.1.0</xmpp:since>
<xmpp:status>complete</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.2</xmpp:version>
<xmpp:since>1.1.2</xmpp:since>
<xmpp:status>complete</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>16.12</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>ejabberd_bosh</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0215.html"/>
<xmpp:version>1.0.0</xmpp:version>
<xmpp:since>20.04</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_stun_disco</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0220.html"/>
<xmpp:version>1.1.1</xmpp:version>
<xmpp:since>17.03</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_s2s_dialback</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0223.html"/>
<xmpp:version>1.1.1</xmpp:version>
<xmpp:since>2.0.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_pubsub</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>2.1.0</xmpp:since>
<xmpp:status>partial</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.1</xmpp:version>
<xmpp:since>2.1.0</xmpp:since>
<xmpp:status>complete</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>2.1.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_roster</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>2.1.0</xmpp:since>
<xmpp:status>complete</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>0.5.0</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_muc</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>2.1.3</xmpp:since>
<xmpp:status>complete</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>1.0.1</xmpp:version>
<xmpp:since>13.06</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_carboncopy</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0288.html"/>
<xmpp:version>1.0.1</xmpp:version>
<xmpp:since>24.10</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_s2s_bidi</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>complete</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.3.1</xmpp:version>
<xmpp:since>21.12</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_muc_room, 0.3.1 since 25.10</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>complete</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>1.0.0</xmpp:version>
<xmpp:since>16.01</xmpp:since>
<xmpp:status>complete</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>complete</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>complete</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.4.1</xmpp:version>
<xmpp:since>24.10</xmpp:since>
<xmpp:status>complete</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.4.1</xmpp:version>
<xmpp:since>17.08</xmpp:since>
<xmpp:status>complete</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.7.0</xmpp:version>
<xmpp:since>15.09</xmpp:since>
<xmpp:status>complete</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.3.0</xmpp:version>
<xmpp:since>15.10</xmpp:since>
<xmpp:status>complete</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>17.09</xmpp:since>
<xmpp:status>complete</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>complete</xmpp:status>
<xmpp:note>mod_mix</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0379.html"/>
<xmpp:version>0.3.3</xmpp:version>
<xmpp:since>26.01</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_invites</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html"/>
<xmpp:version>0.9.0</xmpp:version>
<xmpp:since>21.12</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>node_pep</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>complete</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>1.0.4</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status>complete</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>1.0.0</xmpp:version>
<xmpp:since>18.03</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_avatar</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0401.html"/>
<xmpp:version>0.5.0</xmpp:version>
<xmpp:since>26.01</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_invites</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0402.html"/>
<xmpp:version>1.2.0</xmpp:version>
<xmpp:since>23.10</xmpp:since>
<xmpp:status>complete</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>19.02</xmpp:since>
<xmpp:status>complete</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>complete</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>1.1.0</xmpp:version>
<xmpp:since>18.12</xmpp:since>
<xmpp:status>complete</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>1.0.1</xmpp:version>
<xmpp:since>23.10</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_muc</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
<xmpp:version>0.4.2</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status>partial</xmpp:status>
<xmpp:note>mod_mam, Tombstones not implemented</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0425.html"/>
<xmpp:version>0.3.0</xmpp:version>
<xmpp:since>24.06</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0431.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>24.12</xmpp:since>
<xmpp:status>complete</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>1.0.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status>complete</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>15.06</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_mam</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0445.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>26.01</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_invites</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0474.html"/>
<xmpp:version>0.5.0</xmpp:version>
<xmpp:since>24.02</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>, 0.4.0 since 25.03</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0480.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>24.10</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_scram_upgrade</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0484.html"/>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>24.12</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_auth_fast</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0485.html"/>
<xmpp:version>1.0.0</xmpp:version>
<xmpp:since>25.07</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_pubsub_serverinfo</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0486.html"/>
<xmpp:version>0.1.0</xmpp:version>
<xmpp:since>24.07</xmpp:since>
<xmpp:status>complete</xmpp:status>
<xmpp:note>mod_muc</xmpp:note>
</xmpp:SupportedXep>
</implements>
</Project>
</rdf:RDF>
-63
View File
@@ -1,63 +0,0 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: ejabberd
# Required-Start: $remote_fs $network $named $time
# Required-Stop: $remote_fs $network $named $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts ejabberd XMPP server
# Description: Starts ejabberd XMPP server, an XMPP
# compliant server written in Erlang.
### END INIT INFO
# chkconfig: 2345 90 10
# description: ejabberd XMPP server
set -o errexit
DIR=@ctlscriptpath@
CTL="$DIR"/ejabberdctl
USER=@installuser@
test -x "$CTL" || {
echo "ERROR: ejabberd not found: $DIR"
exit 1
}
getent passwd "$USER" >/dev/null || {
echo "ERROR: System user not found: $USER"
exit 2
}
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
case "$1" in
start)
test -x "$CTL" || exit 0
echo "Starting ejabberd..."
su - $USER -c "$CTL start"
su - $USER -c "$CTL started"
echo "done."
;;
stop)
test -x "$CTL" || exit 0
echo "Stopping ejabberd..."
su - $USER -c "$CTL stop"
su - $USER -c "$CTL stopped"
echo "done."
;;
status)
test -x "$CTL" || exit 0
echo "Getting ejabberd status..."
su - $USER -c "$CTL status"
;;
force-reload|restart)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
esac
exit 0
-21
View File
@@ -1,21 +0,0 @@
[Unit]
Description=XMPP Server
After=network.target
[Service]
Type=notify
User=@installuser@
Group=@installuser@
LimitNOFILE=65536
Restart=on-failure
RestartSec=5
ExecStart=@ctlscriptpath@/ejabberdctl foreground
ExecStop=/bin/sh -c '@ctlscriptpath@/ejabberdctl stop && @ctlscriptpath@/ejabberdctl stopped'
ExecReload=@ctlscriptpath@/ejabberdctl reload_config
NotifyAccess=all
PrivateDevices=true
AmbientCapabilities=CAP_NET_BIND_SERVICE
TimeoutSec=300
[Install]
WantedBy=multi-user.target
-250
View File
@@ -1,250 +0,0 @@
###
### ejabberd configuration file
###
### The parameters used in this configuration file are explained at
###
### https://docs.ejabberd.im/admin/configuration
###
### The configuration file is written in YAML.
### *******************************************************
### ******* !!! WARNING !!! *******
### ******* YAML IS INDENTATION SENSITIVE *******
### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******
### *******************************************************
### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.
###
hosts:
- localhost
loglevel: info
## If you already have certificates, list them here
# certfiles:
# - /etc/letsencrypt/live/domain.tld/fullchain.pem
# - /etc/letsencrypt/live/domain.tld/privkey.pem
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: true
-
port: 5223
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
-
port: 5478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
## The server's public IPv4 address:
# turn_ipv4_address: "203.0.113.3"
## The server's public IPv6 address:
# turn_ipv6_address: "2001:db8::3"
-
port: 1883
ip: "::"
module: mod_mqtt
backlog: 1000
s2s_use_starttls: optional
acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
api_permissions:
"console commands":
from: ejabberd_ctl
who: all
what: "*"
"webadmin commands":
from: ejabberd_web_admin
who: admin
what: "*"
"adhoc commands":
from: mod_adhoc_api
who: admin
what: "*"
"http access":
from: mod_http_api
who:
access:
allow:
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number
shaper:
normal:
rate: 3000
burst_size: 20000
fast: 100000
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
100: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
modules:
mod_adhoc: {}
mod_adhoc_api: {}
mod_admin_extra: {}
mod_announce:
access: announce
mod_avatar: {}
mod_blocking: {}
mod_bosh: {}
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_disco: {}
mod_fail2ban: {}
mod_http_api: {}
mod_http_upload:
put_url: https://@HOST_URL_ENCODE@:5443/upload
custom_headers:
"Access-Control-Allow-Origin": "https://@HOST@"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_last: {}
mod_mam:
## Mnesia is limited to 2GB, better to use an SQL backend
## For small servers SQLite is a good fit and is very easy
## to configure. Uncomment this when you have SQL configured:
## db_type: sql
assume_mam_usage: true
default: always
mod_mqtt: {}
mod_muc:
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
default_room_options:
mam: true
mod_muc_admin: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_proxy65:
access: local
max_connections: 5
mod_pubsub:
access_createnode: pubsub_createnode
plugins:
- flat
- pep
force_node_config:
## Avoid buggy clients to make their bookmarks public
storage:bookmarks:
access_model: whitelist
mod_push: {}
mod_push_keepalive: {}
mod_register:
## Only accept registration requests from the "trusted"
## network (see access_rules section above).
## Think twice before enabling registration from any
## address. See the Jabber SPAM Manifesto for details:
## https://github.com/ge0rg/jabber-spam-fighting-manifesto
ip_access: trusted_network
mod_roster:
versioning: true
mod_s2s_bidi: {}
mod_s2s_dialback: {}
mod_shared_roster: {}
mod_stream_mgmt:
resend_on_timeout: if_offline
mod_stun_disco: {}
mod_vcard: {}
mod_vcard_xupdate: {}
mod_version:
show_os: false
### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8
-214
View File
@@ -1,214 +0,0 @@
#
# In this file you can configure options that are passed by ejabberdctl
# to the erlang runtime system when starting ejabberd
#
#' POLL: Kernel polling ([true|false])
#
# The kernel polling option requires support in the kernel.
# Additionally, you need to enable this feature while compiling Erlang.
#
# Default: true
#
#POLL=true
#.
#' ERL_MAX_PORTS: Maximum number of simultaneously open Erlang ports
#
# ejabberd consumes two or three ports for every connection, either
# from a client or from another XMPP server. So take this into
# account when setting this limit.
#
# Default: 65536 (or 8196 on Windows)
# Maximum: 268435456
#
#ERL_MAX_PORTS=65536
#.
#' INET_DIST_INTERFACE: IP address where this Erlang node listens other nodes
#
# This communication is used by ejabberdctl command line tool,
# and in a cluster of several ejabberd nodes.
#
# Default: 0.0.0.0
#
#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
#.
#' FIREWALL_WINDOW: Range of allowed ports to pass through a firewall
#
# If ejabberd is configured to run in cluster, and a firewall is blocking ports,
# it's possible to make Erlang use a defined range of port (instead of dynamic
# ports) for node communication.
#
# Default: not defined
# Example: 4200-4210
#
#FIREWALL_WINDOW=
#.
#' 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
# will listen only on the specified address(es) and on the
# loopback address (which is implicitly added to the list if it
# has not been specified). The default behaviour is to listen on
# all available IP addresses.
#
# Default: 0.0.0.0
#
#ERL_EPMD_ADDRESS=127.0.0.1
#.
#' ERL_PROCESSES: Maximum number of Erlang processes
#
# Erlang consumes a lot of lightweight processes. If there is a lot of activity
# on ejabberd so that the maximum number of processes is reached, people will
# experience greater latency times. As these processes are implemented in
# Erlang, and therefore not related to the operating system processes, you do
# not have to worry about allowing a huge number of them.
#
# Default: 262144
# Maximum: 268435456
#
#ERL_PROCESSES=262144
#.
#' ERL_MAX_ETS_TABLES: Maximum number of ETS and Mnesia tables
#
# The number of concurrent ETS and Mnesia tables is limited. When the limit is
# reached, errors will appear in the logs:
# ** Too many db tables **
# You can safely increase this limit when starting ejabberd. It impacts memory
# consumption but the difference will be quite small.
#
# Default: 2053
#
#ERL_MAX_ETS_TABLES=2053
#.
#' 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.
#
# It might be useful to add "-pa /usr/local/lib/ejabberd/ebin" if you
# want to add local modules in this path.
#
# Default: ""
#
#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
#
# The next variable allows to explicitly specify erlang node for ejabberd
# It can be given in different formats:
# ERLANG_NODE=ejabberd
# Lets erlang add hostname to the node (ejabberd uses short name in this case)
# ERLANG_NODE=ejabberd@hostname
# Erlang uses node name as is (so make sure that hostname is a real
# machine hostname or you'll not be able to control ejabberd)
# ERLANG_NODE=ejabberd@hostname.domainname
# The same as previous, but erlang will use long hostname
# (see erl (1) manual for details)
#
# Default: ejabberd@localhost
#
#ERLANG_NODE=ejabberd@localhost
#.
#' EJABBERD_PID_PATH: ejabberd PID file
#
# Indicate the full path to the ejabberd Process identifier (PID) file.
# If this variable is defined, ejabberd writes the PID file when starts,
# and deletes it when stops.
# Remember to create the directory and grant write permission to ejabberd.
#
# Default: don't write PID file
#
#EJABBERD_PID_PATH=/var/run/ejabberd/ejabberd.pid
#.
#' EJABBERD_CONFIG_PATH: ejabberd configuration file
#
# Specify the full path to the ejabberd configuration file. If the file name has
# yml or yaml extension, it is parsed as a YAML file; otherwise, Erlang syntax is
# expected.
#
# Default: $ETC_DIR/ejabberd.yml
#
#EJABBERD_CONFIG_PATH=/etc/ejabberd/ejabberd.yml
#.
#' CONTRIB_MODULES_PATH: contributed ejabberd modules path
#
# Specify the full path to the contributed ejabberd modules. If the path is not
# defined, ejabberd will use ~/.ejabberd-modules in home of user running ejabberd.
#
# Default: $HOME/.ejabberd-modules
#
#CONTRIB_MODULES_PATH=/opt/ejabberd-modules
#.
#' CONTRIB_MODULES_CONF_DIR: configuration directory for contributed modules
#
# Specify the full path to the configuration directory for contributed ejabberd
# modules. In order to configure a module named mod_foo, a mod_foo.yml file can
# be created in this directory. This file will then be used instead of the
# default configuration file provided with the module.
#
# Default: $CONTRIB_MODULES_PATH/conf
#
#CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules
#.
#' CTL_OVER_HTTP: Path to ejabberdctl HTTP listener socket
#
# To speedup ejabberdctl execution time for ejabberd commands,
# you can setup an ejabberd_http listener with ejabberd_ctl handling requests,
# listening in a unix domain socket.
#
# Default: disabled
#
#CTL_OVER_HTTP=sockets/ctl_over_http.sock
#.
#'
# vim: foldmarker=#',#. foldmethod=marker:
-600
View File
@@ -1,600 +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}}"
INSTALLUSER="{{installuser}}"
# 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%@*}" ] && ERLANG_NODE="$ERLANG_NODE@$(hostname -s)"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# backward support for old mnesia spool dir path
: "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}"
[ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD"
# 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
# Only required for Erlang/OTP 25:
export ERL_FLAGS="$ERL_FLAGS -enable-feature maybe_expr"
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,$(uname -s) in
as_install_user,OpenBSD)
su -s /bin/sh "$INSTALLUSER" -c 'exec "$0" "$@"' "$@"
;;
as_install_user,NetBSD)
su "$INSTALLUSER" -c 'exec "$0" "$@"' -- "$@"
;;
as_install_user,*)
su -s /bin/sh -c 'exec "$0" "$@"' "$INSTALLUSER" -- "$@"
;;
as_current_user,*)
"$@"
;;
esac
}
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 stop ejabberd gracefully:"
echo " ejabberd:stop()."
echo "To quit erlang immediately, 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" ] && {
netstat -nl | grep ":$ERL_DIST_PORT" >/dev/null && {
echo ""
echo "NOTE: The file ejabberdctl.cfg has configured ERL_DIST_PORT=$ERL_DIST_PORT"
echo " and the port 5210 is already in use."
echo " If ejabberd fails to start with listen error eaddrinsuse,"
echo " try configuring in ejabberdctl.cfg a different"
echo " INET_DIST_INTERFACE, or different ERL_DIST_PORT"
echo ""
netstat -nlp 2>/dev/null | grep ":5210"
echo ""
}
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
}
}
# allow sync calls
wait_status()
{
wait_status_node "$ERLANG_NODE" $1 $2 $3
}
wait_status_node()
{
CONNECT_NODE=$1
shift
# 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
exec_erl "$(uid ctl)" -hidden -noinput \
-eval 'net_kernel:connect_node('"'$CONNECT_NODE'"')' \
-s ejabberd_ctl \
-extra "$CONNECT_NODE" $NO_TIMEOUT status > /dev/null
status="$?"
fi
done
[ $timeout -gt 0 ]
}
exec_other_command()
{
exec_other_command_node $ERLANG_NODE "$@"
}
exec_other_command_node()
{
CONNECT_NODE=$1
shift
if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
|| [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
|| [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
exec_erl "$(uid ctl)" -hidden -noinput \
-eval 'net_kernel:connect_node('"'$CONNECT_NODE'"')' \
-s ejabberd_ctl \
-extra "$CONNECT_NODE" $NO_TIMEOUT "$@"
result=$?
case $result in
3) help;;
*) :;;
esac
return $result
else
exec_ctl_over_http_socket "$@"
fi
}
exec_ctl_over_http_socket()
{
COMMAND=${1}
CARGS=""
while [ $# -gt 0 ]; do
[ -z "$CARGS" ] && CARGS="[" || CARGS="${CARGS}, "
CARGS="${CARGS}\"$1\""
shift
done
CARGS="${CARGS}]"
TEMPHEADERS=temp-headers.log
curl \
--unix-socket ${CTL_OVER_HTTP} \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "${CARGS}" \
--dump-header ${TEMPHEADERS} \
--no-progress-meter \
"http://localhost/ctl/${COMMAND}"
result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
rm ${TEMPHEADERS}
case $result in
2|3) exec_other_command help ${COMMAND};;
*) :;;
esac
exit $result
}
# ensure we can change current directory to SPOOL_DIR
[ -d "$SPOOL_DIR" ] || exec_cmd mkdir -p "$SPOOL_DIR"
cd "$SPOOL_DIR" || {
echo "ERROR: can not access directory $SPOOL_DIR"
exit 6
}
printe()
{
printf "\n"
printf "\e[1;40;32m==> %s\e[0m\n" "$1"
}
## Function copied from tools/make-installers
user_agrees()
{
question="$*"
if [ -t 0 ]
then
printe "$question (y/n) [n]"
read -r response
case "$response" in
[Yy]|[Yy][Ee][Ss])
return 0
;;
[Nn]|[Nn][Oo]|'')
return 1
;;
*)
echo 'Please respond with "yes" or "no".'
user_agrees "$question"
;;
esac
else # Assume 'yes' if not running interactively.
return 0
fi
}
mnesia_change()
{
ERLANG_NODE_OLD="$1"
[ "$ERLANG_NODE_OLD" = "" ] \
&& echo "Error: Please provide the old erlang node name, for example:" \
&& echo " ejabberdctl mnesia_change ejabberd@oldmachine" \
&& exit 1
SPOOL_DIR_BACKUP=$SPOOL_DIR/$ERLANG_NODE_OLD-backup/
OLDFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE_OLD.backup
NEWFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE.backup
printe "This changes your mnesia database from node name '$ERLANG_NODE_OLD' to '$ERLANG_NODE'"
[ -d "$SPOOL_DIR_BACKUP" ] && printe "WARNING! A backup of old node already exists in $SPOOL_DIR_BACKUP"
if ! user_agrees "Do you want to proceed?"
then
echo 'Operation aborted.'
exit 1
fi
printe "Starting ejabberd with old node name $ERLANG_NODE_OLD ..."
exec_erl "$ERLANG_NODE_OLD" $EJABBERD_OPTS -detached
wait_status_node $ERLANG_NODE_OLD 0 30 2
result=$?
case $result in
1) echo "There was a problem starting ejabberd with the old erlang node name. " \
&& echo "Check for log errors in $EJABBERD_LOG_PATH" \
&& exit $result;;
*) :;;
esac
exec_other_command_node $ERLANG_NODE_OLD "status"
printe "Making backup of old database to file $OLDFILE ..."
mkdir $SPOOL_DIR_BACKUP
exec_other_command_node $ERLANG_NODE_OLD backup "$OLDFILE"
printe "Changing node name in new backup file $NEWFILE ..."
exec_other_command_node $ERLANG_NODE_OLD mnesia_change_nodename "$ERLANG_NODE_OLD" "$ERLANG_NODE" "$OLDFILE" "$NEWFILE"
printe "Stopping old ejabberd..."
exec_other_command_node $ERLANG_NODE_OLD "stop"
wait_status_node $ERLANG_NODE_OLD 3 30 2 && stop_epmd
printe "Moving old mnesia spool files to backup subdirectory $SPOOL_DIR_BACKUP ..."
mv $SPOOL_DIR/*.DAT $SPOOL_DIR_BACKUP
mv $SPOOL_DIR/*.DCD $SPOOL_DIR_BACKUP
mv $SPOOL_DIR/*.LOG $SPOOL_DIR_BACKUP
printe "Starting ejabberd with new node name $ERLANG_NODE ..."
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached
wait_status 0 30 2
exec_other_command "status"
printe "Installing fallback of new mnesia..."
exec_other_command install_fallback "$NEWFILE"
printe "Stopping new ejabberd..."
exec_other_command "stop"
wait_status 3 30 2 && stop_epmd
printe "Finished, now you can start ejabberd normally"
}
# main
case $1 in
start)
check_start
exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached
;;
foreground)
check_start
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" -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'"')])' \
-eval 'halt(case net_adm:ping('"'$PEER'"') of pong -> 0; pang -> 1 end).' \
-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
;;
mnesia_change)
mnesia_change $2
;;
*)
set_dist_client
exec_other_command "$@"
;;
esac
-59
View File
@@ -1,59 +0,0 @@
[
{
elvis,
[
{config,
[#{dirs => ["src"],
filter => "*.erl",
ignore => ['ELDAPv3', eldap_filter_yecc],
ruleset => erl_files,
rules => [{elvis_text_style, line_length, #{limit => 1000, skip_comments => false}},
{elvis_text_style, no_tabs, disable},
{elvis_style, atom_naming_convention, disable},
{elvis_style, consistent_variable_casing, disable},
{elvis_style, dont_repeat_yourself, #{min_complexity => 70}},
{elvis_style, export_used_types, disable},
{elvis_style, function_naming_convention, disable},
{elvis_style, god_modules, #{limit => 300}},
{elvis_style, invalid_dynamic_call, disable},
{elvis_style, macro_names, disable},
{elvis_style, max_function_arity, disable}, % #{max_arity => 15}},
{elvis_style, nesting_level, disable},
{elvis_style, no_author, disable},
{elvis_style, no_boolean_in_comparison, disable},
{elvis_style, no_catch_expressions, disable},
{elvis_style, no_debug_call, disable},
{elvis_style, no_if_expression, disable},
{elvis_style, no_import, disable},
{elvis_style, no_nested_try_catch, disable},
{elvis_style, no_operation_on_same_value, disable},
{elvis_style, no_receive_without_timeout, disable},
{elvis_style, no_single_clause_case, disable},
{elvis_style, no_spec_with_records, disable},
{elvis_style, no_throw, disable},
{elvis_style, operator_spaces, disable},
{elvis_style, param_pattern_matching, disable},
{elvis_style, private_data_types, disable},
{elvis_style, variable_naming_convention, disable}
]
},
%#{dirs => ["include"],
% filter => "*.hrl",
% ruleset => hrl_files},
#{dirs => ["."],
filter => "Makefile.in",
ruleset => makefiles,
rules => [{elvis_text_style, line_length, #{limit => 400,
skip_comments => false}},
{elvis_style, dont_repeat_yourself, #{min_complexity => 20}}
]
}
]
}
]
}
].
%% vim: set filetype=erlang tabstop=8:
-29
View File
@@ -1,29 +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: OTP_BELOW_27
- 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
-81
View File
@@ -1,81 +0,0 @@
%% Generated by the Erlang ASN.1 compiler version:2.0.1
%% Purpose: Erlang record definitions for each named and unnamed
%% SEQUENCE and SET, and macro definitions for each value
%% definition,in module ELDAPv3
-record('LDAPMessage',{
messageID, protocolOp, controls = asn1_NOVALUE}).
-record('AttributeValueAssertion',{
attributeDesc, assertionValue}).
-record('Attribute',{
type, vals}).
-record('LDAPResult',{
resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE}).
-record('Control',{
controlType, criticality = asn1_DEFAULT, controlValue = asn1_NOVALUE}).
-record('BindRequest',{
version, name, authentication}).
-record('SaslCredentials',{
mechanism, credentials = asn1_NOVALUE}).
-record('BindResponse',{
resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, serverSaslCreds = asn1_NOVALUE}).
-record('SearchRequest',{
baseObject, scope, derefAliases, sizeLimit, timeLimit, typesOnly, filter, attributes}).
-record('SubstringFilter',{
type, substrings}).
-record('MatchingRuleAssertion',{
matchingRule = asn1_NOVALUE, type = asn1_NOVALUE, matchValue, dnAttributes = asn1_DEFAULT}).
-record('SearchResultEntry',{
objectName, attributes}).
-record('PartialAttributeList_SEQOF',{
type, vals}).
-record('ModifyRequest',{
object, modification}).
-record('ModifyRequest_modification_SEQOF',{
operation, modification}).
-record('AttributeTypeAndValues',{
type, vals}).
-record('AddRequest',{
entry, attributes}).
-record('AttributeList_SEQOF',{
type, vals}).
-record('ModifyDNRequest',{
entry, newrdn, deleteoldrdn, newSuperior = asn1_NOVALUE}).
-record('CompareRequest',{
entry, ava}).
-record('ExtendedRequest',{
requestName, requestValue = asn1_NOVALUE}).
-record('ExtendedResponse',{
resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, responseName = asn1_NOVALUE, response = asn1_NOVALUE}).
-record('PasswdModifyRequestValue',{
userIdentity = asn1_NOVALUE, oldPasswd = asn1_NOVALUE, newPasswd = asn1_NOVALUE}).
-record('PasswdModifyResponseValue',{
genPasswd = asn1_NOVALUE}).
-define('maxInt', 2147483647).
-define('passwdModifyOID', [49,46,51,46,54,46,49,46,52,46,49,46,52,50,48,51,46,49,46,49,49,46,49]).
-51
View File
@@ -1,51 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(CT_XML,
{<<"Content-Type">>, <<"text/xml; charset=utf-8">>}).
-define(CT_PLAIN,
{<<"Content-Type">>, <<"text/plain">>}).
-define(CT_JSON,
{<<"Content-Type">>, <<"application/json">>}).
-define(AC_ALLOW_ORIGIN,
{<<"Access-Control-Allow-Origin">>, <<"*">>}).
-define(AC_ALLOW_METHODS,
{<<"Access-Control-Allow-Methods">>,
<<"GET, POST, OPTIONS">>}).
-define(AC_ALLOW_HEADERS,
{<<"Access-Control-Allow-Headers">>,
<<"Content-Type">>}).
-define(AC_MAX_AGE,
{<<"Access-Control-Max-Age">>, <<"86400">>}).
-define(OPTIONS_HEADER,
[?CT_PLAIN, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_METHODS,
?AC_ALLOW_HEADERS, ?AC_MAX_AGE]).
-define(HEADER(CType),
[CType, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_HEADERS]).
-define(BOSH_CACHE, bosh_cache).
-22
View File
@@ -1,22 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | {binary(), binary(), atom()} | '$1',
password = <<"">> :: binary() | scram() | '_'}).
-111
View File
@@ -1,111 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-type aterm() :: {atom(), atype()}.
-type atype() :: integer | string | binary | any | atom |
{tuple, [aterm()]} | {list, aterm()}.
-type rterm() :: {atom(), rtype()}.
-type rtype() :: integer | string | atom | any |
{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.
%% When a command with tag 'async' is called by mod_adhoc_api,
%% it is spawned in a new process for the command execution,
%% and the command immediately returns success.
%% 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:
%% Two fields exist that are used to control access on a command from ReST API:
%% 1. Policy
%% If policy is:
%% - restricted: command is not exposed as OAuth Rest API.
%% - admin: Command is allowed for user that have Admin Rest command enabled by access rule: commands_admin_access
%% - user: Command might be called by any server user.
%% - open: Command can be called by anyone.
%%
%% Policy is just used to control who can call the command. A specific additional access rules can be performed, as
%% defined by access option.
%% Access option can be a list of:
%% - {Module, accessName, DefaultValue}: Reference and existing module access to limit who can use the command.
%% - AccessRule name: direct name of the access rule to check in config file.
%% TODO: Access option could be atom command (not a list). In the case, User performing the command, will be added as first parameter
%% to command, so that the command can perform additional check.
-record(ejabberd_commands,
{name :: atom(),
tags = [] :: [atom()] | '_' | '$2',
desc = "" :: string() | '_' | '$3',
longdesc = "" :: string() | '_',
version = 0 :: integer(),
note = "" :: string(),
weight = 1 :: integer(),
module :: atom() | '_',
function :: atom() | '_',
args = [] :: [aterm()] | '_' | '$1' | '$2',
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()] | '_',
result_desc = none :: none | string() | '_',
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()
}.
-27
View File
@@ -1,27 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(STATUS_SUCCESS, 0).
-define(STATUS_ERROR, 1).
-define(STATUS_USAGE, 2).
-define(STATUS_BADRPC, 3).
-70
View File
@@ -1,70 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(serialize_mam_v1, {
serverhost :: binary(),
username :: binary(),
timestamp :: integer(),
peer :: binary(),
type :: chat | groupchat,
nick :: binary(),
origin_id :: binary(),
packet :: binary()
}).
-record(serialize_mam_prefs_v1, {
serverhost :: binary(),
username :: binary(),
default :: atom(),
always :: term(),
never :: term()
}).
-record(serialize_roster_v1, {
serverhost :: binary(),
username :: binary(),
version :: binary() | undefined,
entries :: [{binary(),
binary(),
[binary()],
both | from | to | none,
boolean(),
subscribe | unsubscribe | both | in | out | none,
binary()}]
}).
-record(serialize_auth_v1, {
serverhost :: binary(),
username :: binary(),
passwords :: [binary() | {sha | sha256 | sha512, binary(), binary(), binary(), integer()}]
}).
-record(serialize_muc_room_v1, {
serverhost :: binary(),
name :: binary(),
host :: binary(),
options:: [{atom(), term()}]
}).
-record(serialize_muc_registrations_v1, {
serverhost :: binary(),
host :: binary(),
jid :: binary(),
nick :: binary()
}).
-55
View File
@@ -1,55 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(request,
{method :: method(),
path = [] :: [binary()],
raw_path :: binary(),
q = [] :: [{binary() | nokey, binary()}],
us = {<<>>, <<>>} :: {binary(), binary()},
auth :: {binary(), binary()} | {oauth, binary(), []} | undefined | invalid,
lang = <<"">> :: binary(),
data = <<"">> :: binary(),
ip :: {inet:ip_address(), inet:port_number()},
host = <<"">> :: binary(),
port = 5280 :: inet:port_number(),
opts = [] :: list(),
tp = http :: protocol(),
headers = [] :: [{atom() | binary(), binary()}],
length = 0 :: non_neg_integer(),
sockmod :: gen_tcp | fast_tls,
socket :: inet:socket() | fast_tls:tls_socket()}).
-record(ws,
{socket :: inet:socket() | fast_tls:tls_socket(),
sockmod = gen_tcp :: gen_tcp | fast_tls,
ip :: {inet:ip_address(), inet:port_number()},
host = <<"">> :: binary(),
port = 5280 :: inet:port_number(),
path = [] :: [binary()],
headers = [] :: [{atom() | binary(), binary()}],
local_path = [] :: [binary()],
q = [] :: [{binary() | nokey, binary()}],
buf :: binary(),
http_opts = [] :: list()}).
-type method() :: 'GET' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'PUT' | 'POST' | 'TRACE' | 'PATCH'.
-type protocol() :: http | https.
-type http_request() :: #request{}.
-33
View File
@@ -1,33 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(oauth_token, {
token = <<"">> :: binary() | '_',
us = {<<"">>, <<"">>} :: {binary(), binary()} | '_',
scope = [] :: [binary()] | '_',
expire :: integer() | '$1' | '_'
}).
-record(oauth_client, {
client_id = <<"">> :: binary() | '_',
client_name = <<"">> :: binary() | '_',
grant_type :: password | implicit | '_',
options :: [any()] | '_'
}).
-8
View File
@@ -1,8 +0,0 @@
-define(ROUTES_CACHE, routes_cache).
-type local_hint() :: integer() | {apply, atom(), atom()}.
-record(route, {domain :: binary(),
server_host :: binary(),
pid :: undefined | pid(),
local_hint :: local_hint() | undefined}).
-36
View File
@@ -1,36 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-ifndef(EJABBERD_SM_HRL).
-define(EJABBERD_SM_HRL, true).
-define(SM_CACHE, sm_cache).
-record(session, {sid, usr, us, priority, info = []}).
-record(session_counter, {vhost, count}).
-type sid() :: {erlang:timestamp(), pid()}.
-type ip() :: {inet:ip_address(), inet:port_number()} | undefined.
-type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()}
| {oor, boolean()} | {auth_module, atom()}
| {num_stanzas_in, non_neg_integer()}
| {atom(), term()}].
-type prio() :: undefined | integer().
-endif.
-70
View File
@@ -1,70 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(SQL_MARK, sql__mark_).
-define(SQL(SQL), ?SQL_MARK(SQL)).
-define(SQL_UPSERT_MARK, sql_upsert__mark_).
-define(SQL_UPSERT(Host, Table, Fields),
ejabberd_sql:sql_query(Host, ?SQL_UPSERT_MARK(Table, Fields))).
-define(SQL_UPSERT_T(Table, Fields),
ejabberd_sql:sql_query_t(?SQL_UPSERT_MARK(Table, Fields))).
-define(SQL_INSERT_MARK, sql_insert__mark_).
-define(SQL_INSERT(Table, Fields), ?SQL_INSERT_MARK(Table, Fields)).
-record(sql_query, {hash :: binary(),
format_query :: fun(),
format_res :: fun(),
args :: fun(),
flags :: non_neg_integer(),
loc :: {module(), {pos_integer(), pos_integer()}}}).
-record(sql_escape, {
string :: fun((binary()) -> binary() | atom()),
integer :: fun((integer()) -> binary() | atom()),
boolean :: fun((boolean()) -> binary() | atom()),
timestamp :: fun((calendar:datetime()) -> binary() | atom()),
in_array_string :: fun((binary()) -> binary() | atom()),
like_escape :: fun(() -> binary() | atom())
}).
-record(sql_index, {columns,
unique = false :: boolean(),
meta = #{}}).
-record(sql_column, {name :: binary(),
type,
nullable = false,
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(),
multihost_schema = true :: boolean()}).
-21
View File
@@ -1,21 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-compile([{parse_transform, ejabberd_sql_pt}]).
-include("ejabberd_sql.hrl").
-126
View File
@@ -1,126 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(X(Name),
#xmlel{name = Name, attrs = [], children = []}).
-define(XA(Name, Attrs),
#xmlel{name = Name, attrs = Attrs, children = []}).
-define(XE(Name, Els),
#xmlel{name = Name, attrs = [], children = Els}).
-define(XAE(Name, Attrs, Els),
#xmlel{name = Name, attrs = Attrs, children = Els}).
-define(C(Text), {xmlcdata, Text}).
-define(XC(Name, Text), ?XE(Name, [?C(Text)])).
-define(XAC(Name, Attrs, Text),
?XAE(Name, Attrs, [?C(Text)])).
-define(CT(Text), ?C((translate:translate(Lang, Text)))).
-define(XCT(Name, Text), ?XC(Name, (translate:translate(Lang, Text)))).
-define(XACT(Name, Attrs, Text),
?XAC(Name, Attrs, (translate:translate(Lang, Text)))).
-define(LI(Els), ?XE(<<"li">>, Els)).
-define(A(URL, Els),
?XAE(<<"a">>, [{<<"href">>, URL}], Els)).
-define(AC(URL, Text), ?A(URL, [?C(Text)])).
-define(ACT(URL, Text), ?AC(URL, (translate:translate(Lang, Text)))).
-define(P, ?X(<<"p">>)).
-define(BR, ?X(<<"br">>)).
-define(INPUT(Type, Name, Value),
?XA(<<"input">>,
[{<<"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)))).
-define(INPUTD(Type, Name, Value),
?XA(<<"input">>,
[{<<"type">>, Type}, {<<"name">>, Name},
{<<"class">>, <<"btn-danger">>}, {<<"value">>, Value}])).
-define(INPUTTD(Type, Name, Value),
?INPUTD(Type, Name, (translate:translate(Lang, Value)))).
-define(INPUTS(Type, Name, Value, Size),
?XA(<<"input">>,
[{<<"type">>, Type}, {<<"name">>, Name},
{<<"value">>, Value}, {<<"size">>, Size}])).
-define(INPUTST(Type, Name, Value, Size),
?INPUT(Type, Name, (translate:translate(Lang, Value)), Size)).
-define(ACLINPUT(Text),
?XE(<<"td">>,
[?INPUT(<<"text">>, <<"value", ID/binary>>, Text)])).
-define(TEXTAREA(Name, Rows, Cols, Value),
?XAC(<<"textarea">>,
[{<<"name">>, Name}, {<<"rows">>, Rows},
{<<"cols">>, Cols}],
Value)).
%% Build an xmlelement for result
-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>>},
{<<"target">>, <<"_blank">>}],
[?C(<<"docs: ", Title/binary>>)])])).
%% h1 with a Guide Link
-define(H1GLraw(Name, Ref, Title),
[?XC(<<"h1">>, Name), ?GL(Ref, Title), ?BR, ?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(unicode:characters_to_binary(""))])])).
-79
View File
@@ -1,79 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(LDAP_PORT, 389).
-define(LDAPS_PORT, 636).
-type scope() :: baseObject | singleLevel | wholeSubtree.
-record(eldap_search,
{scope = wholeSubtree :: scope(),
base = <<"">> :: binary(),
filter :: eldap:filter() | undefined,
limit = 0 :: non_neg_integer(),
attributes = [] :: [binary()],
types_only = false :: boolean(),
deref_aliases = neverDerefAliases :: neverDerefAliases |
derefInSearching |
derefFindingBaseObj |
derefAlways,
timeout = 0 :: non_neg_integer()}).
-record(eldap_search_result, {entries = [] :: [eldap_entry()],
referrals = [] :: list()}).
-record(eldap_entry, {object_name = <<>> :: binary(),
attributes = [] :: [{binary(), [binary()]}]}).
-type tlsopts() :: [{encrypt, tls | starttls | none} |
{tls_certfile, binary() | undefined} |
{tls_cacertfile, binary() | undefined} |
{tls_depth, non_neg_integer() | undefined} |
{tls_verify, hard | soft | false}].
-record(eldap_config, {servers = [] :: [binary()],
backups = [] :: [binary()],
tls_options = [] :: tlsopts(),
port = ?LDAP_PORT :: inet:port_number(),
dn = <<"">> :: binary(),
password = <<"">> :: binary(),
base = <<"">> :: binary(),
deref_aliases = never :: never | searching |
finding | always}).
-type eldap_config() :: #eldap_config{}.
-type eldap_search() :: #eldap_search{}.
-type eldap_entry() :: #eldap_entry{}.
-define(eldap_config(M, H),
#eldap_config{
servers = M:ldap_servers(H),
backups = M:ldap_backups(H),
tls_options = [{encrypt, M:ldap_encrypt(H)},
{tls_verify, M:ldap_tls_verify(H)},
{tls_certfile, M:ldap_tls_certfile(H)},
{tls_cacertfile, M:ldap_tls_cacertfile(H)},
{tls_depth, M:ldap_tls_depth(H)}],
port = M:ldap_port(H),
dn = M:ldap_rootdn(H),
password = M:ldap_password(H),
base = M:ldap_base(H),
deref_aliases = M:ldap_deref_aliases(H)}).
-49
View File
@@ -1,49 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(CT_XML,
{<<"Content-Type">>, <<"text/xml; charset=utf-8">>}).
-define(CT_PLAIN,
{<<"Content-Type">>, <<"text/plain">>}).
-define(AC_ALLOW_ORIGIN,
{<<"Access-Control-Allow-Origin">>, <<"*">>}).
-define(AC_ALLOW_METHODS,
{<<"Access-Control-Allow-Methods">>,
<<"GET, POST, OPTIONS">>}).
-define(AC_ALLOW_HEADERS,
{<<"Access-Control-Allow-Headers">>,
<<"Content-Type">>}).
-define(AC_MAX_AGE,
{<<"Access-Control-Max-Age">>, <<"86400">>}).
-define(NO_CACHE,
{<<"Cache-Control">>, <<"max-age=0, no-cache, no-store">>}).
-define(OPTIONS_HEADER,
[?CT_PLAIN, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_METHODS,
?AC_ALLOW_HEADERS, ?AC_MAX_AGE]).
-define(HEADER,
[?CT_XML, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_HEADERS, ?NO_CACHE]).
-73
View File
@@ -1,73 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(PRINT(Format, Args), io:format(Format, Args)).
-include_lib("kernel/include/logger.hrl").
-define(CLEAD, "\e[1"). % bold
-define(CMID, "\e[0"). % normal
-define(CCLEAN, "\e[0m"). % clean
-define(CDEFAULT, ";49;95m"). % light magenta
-define(CDEBUG, ";49;90m"). % dark gray
-define(CINFO, ";49;92m"). % green
-define(CWARNING, ";49;93m"). % light yellow
-define(CERROR, ";49;91m"). % light magenta
-define(CCRITICAL,";49;31m"). % light red
-define(DEBUG(Format, Args),
begin ?LOG_DEBUG(Format, Args,
#{clevel => ?CLEAD ++ ?CDEBUG,
ctext => ?CMID ++ ?CDEBUG}),
ok end).
-define(INFO_MSG(Format, Args),
begin ?LOG_INFO(Format, Args,
#{clevel => ?CLEAD ++ ?CINFO,
ctext => ?CCLEAN}),
ok end).
-define(WARNING_MSG(Format, Args),
begin ?LOG_WARNING(Format, Args,
#{clevel => ?CLEAD ++ ?CWARNING,
ctext => ?CMID ++ ?CWARNING}),
ok end).
-define(ERROR_MSG(Format, Args),
begin ?LOG_ERROR(Format, Args,
#{clevel => ?CLEAD ++ ?CERROR,
ctext => ?CMID ++ ?CERROR}),
ok end).
-define(CRITICAL_MSG(Format, Args),
begin ?LOG_CRITICAL(Format, Args,
#{clevel => ?CLEAD++ ?CCRITICAL,
ctext => ?CMID ++ ?CCRITICAL}),
ok end).
%% Use only when trying to troubleshoot test problem with ExUnit
-define(EXUNIT_LOG(Format, Args),
case lists:keyfind(logger, 1, application:loaded_applications()) of
false -> ok;
_ -> 'Elixir.Logger':bare_log(error, io_lib:format(Format, Args), [?MODULE])
end).
%% Uncomment if you want to debug p1_fsm/gen_fsm
%%-define(DBGFSM, true).
-25
View File
@@ -1,25 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(motd, {server = <<"">> :: binary(),
packet = #xmlel{} :: xmlel()}).
-record(motd_users, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1',
dummy = [] :: [] | '_'}).
-36
View File
@@ -1,36 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(MODULE_ANTISPAM, mod_antispam).
-type url() :: binary().
-type filename() :: binary() | none | false.
-type jid_set() :: sets:set(ljid()).
-type url_set() :: sets:set(url()).
-define(DEFAULT_RTBL_DOMAINS_NODE, <<"spam_source_domains">>).
-record(rtbl_service,
{host = none :: binary() | none,
node = ?DEFAULT_RTBL_DOMAINS_NODE :: binary(),
subscribed = false :: boolean(),
retry_timer = undefined :: reference() | undefined}).
-type rtbl_service() :: #rtbl_service{}.
-24
View File
@@ -1,24 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(caps_features,
{node_pair = {<<"">>, <<"">>} :: {binary(), binary()},
features = [] :: [binary()] | pos_integer()
}).
-23
View File
@@ -1,23 +0,0 @@
-define(INVITE_TOKEN_EXPIRE_SECONDS_DEFAULT, 5*86400).
-define(INVITE_TOKEN_LENGTH_DEFAULT, 24).
-define(NS_INVITE_INVITE, <<"urn:xmpp:invite#invite">>).
-define(NS_INVITE_CREATE_ACCOUNT, <<"urn:xmpp:invite#create-account">>).
-define(OVERUSE_LIMIT, 1000).
-define(SPEEDY_GOAT_LEVELS, 2).
-define(SPEEDY_GOAT_SECONDS, 300).
-record(invite_token, {token :: binary(),
inviter :: {binary(), binary()},
%% A non-empty value if `invitee` indicates the invite has been used.
invitee = <<>> :: binary(),
created_at = calendar:now_to_datetime(erlang:timestamp()) :: calendar:datetime(),
expires = calendar:gregorian_seconds_to_datetime(calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(erlang:timestamp())) + ?INVITE_TOKEN_EXPIRE_SECONDS_DEFAULT) :: calendar:datetime(),
type = roster_only :: roster_only | account_only | account_subscription,
%% If type is 'roster_only' then we indicate a token has been used to create
%% an account (if allowed) by setting `account_name` to the name of the user
%% (which should match `invitee`).
account_name = <<>> :: binary()
}).
-23
View File
@@ -1,23 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(last_activity, {us = {<<"">>, <<"">>} :: {binary(), binary()},
timestamp = 0 :: non_neg_integer(),
status = <<"">> :: binary()}).
-36
View File
@@ -1,36 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(archive_msg,
{us = {<<"">>, <<"">>} :: {binary(), binary()},
id = <<>> :: binary(),
timestamp = erlang:timestamp() :: erlang:timestamp(),
peer = {<<"">>, <<"">>, <<"">>} :: ljid() | undefined,
bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid(),
packet = #xmlel{} :: xmlel() | message(),
nick = <<"">> :: binary(),
type = chat :: chat | groupchat,
origin_id = <<"">> :: binary()}).
-record(archive_prefs,
{us = {<<"">>, <<"">>} :: {binary(), binary()},
default = never :: never | always | roster,
always = [] :: [ljid()],
never = [] :: [ljid()]}).
-36
View File
@@ -1,36 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(room_version,
{id :: binary(),
%% use the same field names as in Synapse
enforce_key_validity :: boolean(),
special_case_aliases_auth :: boolean(),
strict_canonicaljson :: boolean(),
limit_notifications_power_levels :: boolean(),
knock_join_rule :: boolean(),
restricted_join_rule :: boolean(),
restricted_join_rule_fix :: boolean(),
knock_restricted_join_rule :: boolean(),
enforce_int_power_levels :: boolean(),
implicit_room_creator :: boolean(),
updated_redaction_rules :: boolean(),
hydra :: boolean()
}).
-37
View File
@@ -1,37 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(muc_room, {name_host = {<<"">>, <<"">>} :: {binary(), binary()} |
{'_', binary()},
opts = [] :: list() | '_'}).
-record(muc_registered,
{us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary() | '$1', binary() | '$2'},
binary() | '_'} | '$1',
nick = <<"">> :: binary() | '$3'}).
-record(muc_online_room,
{name_host :: {binary(), binary()} | '$1' | {'_', binary()} | '_',
pid :: pid() | '$2' | '_' | '$1'}).
-record(muc_online_users, {us :: {binary(), binary()},
resource :: binary() | '_',
room :: binary() | '_' | '$1',
host :: binary() | '_' | '$2'}).
-144
View File
@@ -1,144 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
-define(MAX_USERS_DEFAULT, 200).
-define(SETS, gb_sets).
-record(lqueue,
{
queue = p1_queue:new() :: p1_queue:queue(lqueue_elem()),
max = 0 :: integer()
}).
-type lqueue() :: #lqueue{}.
-type lqueue_elem() :: {binary(), message(), boolean(),
erlang:timestamp(), non_neg_integer()}.
-record(config,
{
title = <<"">> :: binary(),
description = <<"">> :: binary(),
allow_change_subj = true :: boolean(),
allow_query_users = true :: boolean(),
allowpm = anyone :: anyone | participants | moderators | none,
allow_private_messages_from_visitors = anyone :: anyone | moderators | nobody ,
allow_visitor_status = true :: boolean(),
allow_visitor_nickchange = true :: boolean(),
public = true :: boolean(),
public_list = true :: boolean(),
persistent = false :: boolean() | {destroying, boolean()},
moderated = true :: boolean(),
captcha_protected = false :: boolean(),
members_by_default = true :: boolean(),
members_only = false :: boolean(),
allow_user_invites = false :: boolean(),
allow_subscription = false :: boolean(),
password_protected = false :: boolean(),
password = <<"">> :: binary(),
anonymous = true :: boolean(),
presence_broadcast = [moderator, participant, visitor] ::
[moderator | participant | visitor],
allow_voice_requests = true :: boolean(),
voice_request_min_interval = 1800 :: non_neg_integer(),
max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none,
logging = false :: boolean(),
vcard = <<"">> :: binary(),
vcard_xupdate = undefined :: undefined | external | binary(),
captcha_whitelist = (?SETS):empty() :: gb_sets:set(),
mam = false :: boolean(),
pubsub = <<"">> :: binary(),
enable_hats = true :: boolean(),
lang = ejabberd_option:language() :: binary()
}).
-type config() :: #config{}.
-type role() :: moderator | participant | visitor | none.
-type affiliation() :: admin | member | outcast | owner | none.
-record(user,
{
jid :: jid(),
nick :: binary(),
role :: role(),
%%is_subscriber = false :: boolean(),
%%subscriptions = [] :: [binary()],
last_presence :: presence() | undefined,
occupant_id :: binary()
}).
-record(subscriber, {jid :: jid(),
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(),
presence_time = 0 :: integer(),
message_shaper = none :: ejabberd_shaper:shaper(),
presence_shaper = none :: ejabberd_shaper:shaper(),
message :: message() | undefined,
presence :: {binary(), presence()} | undefined
}).
-record(state,
{
room = <<"">> :: binary(),
host = <<"">> :: binary(),
server_host = <<"">> :: binary(),
access = {none,none,none,none,none} :: {atom(), atom(), atom(), atom(), atom()},
jid = #jid{} :: jid(),
config = #config{} :: config(),
users = #{} :: users(),
muc_subscribers = #muc_subscribers{} :: #muc_subscribers{},
last_voice_request_time = treap:empty() :: treap:treap(),
robots = #{} :: robots(),
nicks = #{} :: nicks(),
affiliations = #{} :: affiliations(),
roles = #{} :: roles(),
history = #lqueue{} :: lqueue(),
subject = [] :: [text()],
subject_author = {<<"">>, #jid{}} :: {binary(), jid()},
hats_defs = #{} :: #{binary() => {binary(), binary()}},
hats_users = #{} :: #{ljid() => [binary()]},
just_created = erlang:system_time(microsecond) :: true | integer(),
activity = treap:empty() :: treap:treap(),
room_shaper = none :: ejabberd_shaper:shaper(),
room_queue :: p1_queue:queue({message | presence, jid()}) | undefined,
hibernate_timer = none :: reference() | none | hibernating,
salt = <<>> :: binary()
}).
-type users() :: #{ljid() => #user{}}.
-type robots() :: #{jid() => {binary(), stanza()}}.
-type nicks() :: #{binary() => [ljid()]}.
-type affiliations() :: #{ljid() => affiliation() | {affiliation(), binary()}}.
-type roles() :: #{ljid() => role() | {role(), binary()}}.
-31
View File
@@ -1,31 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(offline_msg,
{us = {<<"">>, <<"">>} :: {binary(), binary()},
timestamp :: erlang:timestamp() | '_' | undefined,
expire :: erlang:timestamp() | never | undefined | '_',
from = #jid{} :: jid() | '_',
to = #jid{} :: jid() | '_',
packet = #xmlel{} :: xmlel() | message() | '_'}).
-record(state,
{host = <<"">> :: binary(),
access_max_offline_messages}).
-40
View File
@@ -1,40 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(privacy, {us = {<<"">>, <<"">>} :: {binary(), binary()},
default = none :: none | binary(),
lists = [] :: [{binary(), [listitem()]}]}).
-type privacy() :: #privacy{}.
-record(listitem, {type = none :: listitem_type(),
value = none :: listitem_value(),
action = allow :: listitem_action(),
order = 0 :: integer(),
match_all = false :: boolean(),
match_iq = false :: boolean(),
match_message = false :: boolean(),
match_presence_in = false :: boolean(),
match_presence_out = false :: boolean()}).
-type listitem() :: #listitem{}.
-type listitem_type() :: none | jid | group | subscription.
-type listitem_value() :: none | both | from | to | jid:ljid() | binary().
-type listitem_action() :: allow | deny.
-24
View File
@@ -1,24 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(private_storage,
{usns = {<<"">>, <<"">>, <<"">>} :: {binary() | '$1' | '_', binary(), binary() |
'$1' | '_'},
xml = #xmlel{} :: xmlel() | '_' | '$1'}).
-73
View File
@@ -1,73 +0,0 @@
%%%----------------------------------------------------------------------
%%% RFC 1928 constants.
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
%% Version
-define(VERSION_5, 5).
%% Authentication methods
-define(AUTH_ANONYMOUS, 0).
-define(AUTH_GSSAPI, 1).
-define(AUTH_PLAIN, 2).
%% Address Type
-define(AUTH_NO_METHODS, 255).
-define(ATYP_IPV4, 1).
-define(ATYP_DOMAINNAME, 3).
-define(ATYP_IPV6, 4).
%% Commands
-define(CMD_CONNECT, 1).
-define(CMD_BIND, 2).
-define(CMD_UDP, 3).
%% RFC 1928 replies
-define(SUCCESS, 0).
-define(ERR_GENERAL_FAILURE, 1).
-define(ERR_NOT_ALLOWED, 2).
-define(ERR_NETWORK_UNREACHABLE, 3).
-define(ERR_HOST_UNREACHABLE, 4).
-define(ERR_CONNECTION_REFUSED, 5).
-define(ERR_TTL_EXPIRED, 6).
-define(ERR_COMMAND_NOT_SUPPORTED, 7).
-define(ERR_ADDRESS_TYPE_NOT_SUPPORTED, 8).
%% RFC 1928 defined timeout.
-define(SOCKS5_REPLY_TIMEOUT, 10000).
-record(s5_request, {rsv = 0 :: integer(),
cmd = connect :: connect | udp,
sha1 = <<"">> :: binary()}).
-24
View File
@@ -1,24 +0,0 @@
%%%----------------------------------------------------------------------
%%% ejabberd, Copyright (C) 2017-2026 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(push_session,
{us = {<<"">>, <<"">>} :: {binary(), binary()},
timestamp = erlang:timestamp() :: erlang:timestamp(),
service = {<<"">>, <<"">>, <<"">>} :: ljid(),
node = <<"">> :: binary(),
xml :: undefined | xmlel()}).
-42
View File
@@ -1,42 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(roster,
{
usj = {<<>>, <<>>, {<<>>, <<>>, <<>>}} :: {binary(), binary(), jid:ljid()} | '_',
us = {<<>>, <<>>} :: {binary(), binary()} | '_',
jid = {<<>>, <<>>, <<>>} :: jid:ljid(),
name = <<>> :: binary() | '_',
subscription = none :: subscription() | '_',
approved = false :: boolean() | '_',
ask = none :: ask() | '_',
groups = [] :: [binary()] | '_',
askmessage = <<"">> :: binary() | '_',
xs = [] :: [fxml:xmlel()] | '_'
}).
-record(roster_version,
{
us = {<<>>, <<>>} :: {binary(), binary()},
version = <<>> :: binary()
}).
-type ask() :: none | in | out | both | subscribe | unsubscribe.
-type subscription() :: none | both | from | to | remove.
-25
View File
@@ -1,25 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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(sr_group, {group_host = {<<"">>, <<"">>} :: {'$1' | binary(), '$2' | binary()},
opts = [] :: list() | '_' | '$2'}).
-record(sr_user, {us = {<<"">>, <<"">>} :: {binary(), binary()},
group_host = {<<"">>, <<"">>} :: {binary(), binary()}}).
-28
View File
@@ -1,28 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-record(vcard_search,
{us, user, luser, fn, lfn, family, lfamily, given,
lgiven, middle, lmiddle, nickname, lnickname, bday,
lbday, ctry, lctry, locality, llocality, email, lemail,
orgname, lorgname, orgunit, lorgunit}).
-record(vcard, {us = {<<"">>, <<"">>} :: {binary(), binary()} | binary(),
vcard = #xmlel{} :: xmlel()}).
-209
View File
@@ -1,209 +0,0 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2002-2026 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.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
%%%
%%%-------------------------------------------------------------------
-define(MQTT_VERSION_4, 4).
-define(MQTT_VERSION_5, 5).
-record(connect, {proto_level = 4 :: non_neg_integer(),
will :: undefined | publish(),
clean_start = true :: boolean(),
keep_alive = 0 :: non_neg_integer(),
client_id = <<>> :: binary(),
username = <<>> :: binary(),
password = <<>> :: binary(),
will_properties = #{} :: properties(),
properties = #{} :: properties()}).
-record(connack, {session_present = false :: boolean(),
code = success :: reason_code(),
properties = #{} :: properties()}).
-record(publish, {id :: undefined | non_neg_integer(),
dup = false :: boolean(),
qos = 0 :: qos(),
retain = false :: boolean(),
topic :: binary(),
payload :: binary(),
properties = #{} :: properties(),
meta = #{} :: map()}).
-record(puback, {id :: non_neg_integer(),
code = success :: reason_code(),
properties = #{} :: properties()}).
-record(pubrec, {id :: non_neg_integer(),
code = success :: reason_code(),
properties = #{} :: properties()}).
-record(pubrel, {id :: non_neg_integer(),
code = success :: reason_code(),
properties = #{} :: properties(),
meta = #{} :: map()}).
-record(pubcomp, {id :: non_neg_integer(),
code = success :: reason_code(),
properties = #{} :: properties()}).
-record(subscribe, {id :: non_neg_integer(),
filters :: [{binary(), sub_opts()}],
properties = #{} :: properties(),
meta = #{} :: map()}).
-record(suback, {id :: non_neg_integer(),
codes = [] :: [char() | reason_code()],
properties = #{} :: properties()}).
-record(unsubscribe, {id :: non_neg_integer(),
filters :: [binary()],
properties = #{} :: properties(),
meta = #{} :: map()}).
-record(unsuback, {id :: non_neg_integer(),
codes = [] :: [reason_code()],
properties = #{} :: properties()}).
-record(pingreq, {meta = #{} :: map()}).
-record(pingresp, {}).
-record(disconnect, {code = 'normal-disconnection' :: reason_code(),
properties = #{} :: properties()}).
-record(auth, {code = success :: reason_code(),
properties = #{} :: properties()}).
-record(sub_opts, {qos = 0 :: qos(),
no_local = false :: boolean(),
retain_as_published = false :: boolean(),
retain_handling = 0 :: 0..2}).
-type qos() :: 0|1|2.
-type sub_opts() :: #sub_opts{}.
-type utf8_pair() :: {binary(), binary()}.
-type properties() :: #{assigned_client_identifier => binary(),
authentication_data => binary(),
authentication_method => binary(),
content_type => binary(),
correlation_data => binary(),
maximum_packet_size => pos_integer(),
maximum_qos => 0|1,
message_expiry_interval => non_neg_integer(),
payload_format_indicator => binary | utf8,
reason_string => binary(),
receive_maximum => pos_integer(),
request_problem_information => boolean(),
request_response_information => boolean(),
response_information => binary(),
response_topic => binary(),
retain_available => boolean(),
server_keep_alive => non_neg_integer(),
server_reference => binary(),
session_expiry_interval => non_neg_integer(),
shared_subscription_available => boolean(),
subscription_identifier => [non_neg_integer()] | non_neg_integer(),
subscription_identifiers_available => boolean(),
topic_alias => pos_integer(),
topic_alias_maximum => non_neg_integer(),
user_property => [utf8_pair()],
wildcard_subscription_available => boolean(),
will_delay_interval => non_neg_integer()}.
-type property() :: assigned_client_identifier |
authentication_data |
authentication_method |
content_type |
correlation_data |
maximum_packet_size |
maximum_qos |
message_expiry_interval |
payload_format_indicator |
reason_string |
receive_maximum |
request_problem_information |
request_response_information |
response_information |
response_topic |
retain_available |
server_keep_alive |
server_reference |
session_expiry_interval |
shared_subscription_available |
subscription_identifier |
subscription_identifiers_available |
topic_alias |
topic_alias_maximum |
user_property |
wildcard_subscription_available |
will_delay_interval.
-type reason_code() :: 'success' |
'normal-disconnection' |
'granted-qos-0' |
'granted-qos-1' |
'granted-qos-2' |
'disconnect-with-will-message' |
'no-matching-subscribers' |
'no-subscription-existed' |
'continue-authentication' |
're-authenticate' |
'unspecified-error' |
'malformed-packet' |
'protocol-error' |
'implementation-specific-error' |
'unsupported-protocol-version' |
'client-identifier-not-valid' |
'bad-user-name-or-password' |
'not-authorized' |
'server-unavailable' |
'server-busy' |
'banned' |
'server-shutting-down' |
'bad-authentication-method' |
'keep-alive-timeout' |
'session-taken-over' |
'topic-filter-invalid' |
'topic-name-invalid' |
'packet-identifier-in-use' |
'packet-identifier-not-found' |
'receive-maximum-exceeded' |
'topic-alias-invalid' |
'packet-too-large' |
'message-rate-too-high' |
'quota-exceeded' |
'administrative-action' |
'payload-format-invalid' |
'retain-not-supported' |
'qos-not-supported' |
'use-another-server' |
'server-moved' |
'shared-subscriptions-not-supported' |
'connection-rate-exceeded' |
'maximum-connect-time' |
'subscription-identifiers-not-supported' |
'wildcard-subscriptions-not-supported'.
-type connect() :: #connect{}.
-type connack() :: #connack{}.
-type publish() :: #publish{}.
-type puback() :: #puback{}.
-type pubrel() :: #pubrel{}.
-type pubrec() :: #pubrec{}.
-type pubcomp() :: #pubcomp{}.
-type subscribe() :: #subscribe{}.
-type suback() :: #suback{}.
-type unsubscribe() :: #unsubscribe{}.
-type unsuback() :: #unsuback{}.
-type pingreq() :: #pingreq{}.
-type pingresp() :: #pingresp{}.
-type disconnect() :: #disconnect{}.
-type auth() :: #auth{}.
-type mqtt_packet() :: connect() | connack() | publish() | puback() |
pubrel() | pubrec() | pubcomp() | subscribe() |
suback() | unsubscribe() | unsuback() | pingreq() |
pingresp() | disconnect() | auth().
-type mqtt_version() :: ?MQTT_VERSION_4 | ?MQTT_VERSION_5.
-172
View File
@@ -1,172 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2026 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.
%%%
%%%----------------------------------------------------------------------
%% -------------------------------
%% Pubsub constants
-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).
%% this is currently a hard limit.
%% Would be nice to have it configurable.
-define(MAX_PAYLOAD_SIZE, 250000).
%% -------------------------------
%% Pubsub types
-type(hostPubsub() :: binary()).
%% <p><tt>hostPubsub</tt> is the name of the PubSub service. For example, it can be
%% <tt>"pubsub.localhost"</tt>.</p>
-type(hostPEP() :: {binary(), binary(), <<>>}).
%% @type hostPEP() = {User, Server, Resource}
%% User = string()
%% Server = string()
%% Resource = [].
%% <p>For example, it can be :
%% ```{"bob", "example.org", []}'''.</p>
-type(host() :: hostPubsub() | hostPEP()).
%% @type host() = hostPubsub() | hostPEP().
-type(nodeId() :: binary()).
%% @type nodeId() = binary().
%% <p>A node is defined by a list of its ancestors. The last element is the name
%% of the current node. For example:
%% ```<<"/home/localhost/user">>'''</p>
-type(nodeIdx() :: pos_integer() | binary()).
%% @type nodeIdx() = integer() | binary().
%% note: pos_integer() should always be used, but we allow anything else coded
%% as binary, so one can have a custom implementation of nodetree with custom
%% indexing (see nodetree_virtual). this also allows to use any kind of key for
%% indexing nodes, as this can be useful with external backends such as sql.
-type(itemId() :: binary()).
%% @type itemId() = string().
-type(subId() :: binary()).
%% @type subId() = string().
-type(nodeOption() ::
{Option::atom(),
Value::atom() | [binary()] | boolean() | non_neg_integer()
}).
-type(nodeOptions() :: [mod_pubsub:nodeOption(),...]).
%% @type nodeOption() = {Option, Value}
%% Option = atom()
%% Value = term().
%% Example:
%% ```{deliver_payloads, true}'''
-type(subOption() ::
{Option::atom(),
Value::binary() | [binary()] | boolean()
}).
-type(subOptions() :: [mod_pubsub:subOption()]).
-type(pubOption() ::
{Option::binary(),
Values::[binary()]
}).
-type(pubOptions() :: [mod_pubsub:pubOption()]).
-type(affiliation() :: 'none'
| 'owner'
| 'publisher'
| 'publish_only'
| 'member'
| 'outcast'
).
%% @type affiliation() = 'none' | 'owner' | 'publisher' | 'publish-only' | 'member' | 'outcast'.
-type(accessModel() :: 'open'
| 'presence'
| 'roster'
| 'authorize'
| 'whitelist'
).
%% @type accessModel() = 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'.
-type(publishModel() :: 'publishers'
| 'subscribers'
| 'open'
).
%% @type publishModel() = 'publishers' | 'subscribers' | 'open'
-record(pubsub_index,
{
index :: atom(),
last :: mod_pubsub:nodeIdx(),
free :: [mod_pubsub:nodeIdx()]
}).
-record(pubsub_node,
{
nodeid ,% :: {mod_pubsub:host(), mod_pubsub:nodeId()},
id ,% :: mod_pubsub:nodeIdx(),
parents = [] ,% :: [mod_pubsub:nodeId(),...],
type = <<"flat">>,% :: binary(),
owners = [] ,% :: [jid:ljid(),...],
options = [] % :: mod_pubsub:nodeOptions()
}).
-record(pubsub_state,
{
stateid ,% :: {jid:ljid(), mod_pubsub:nodeIdx()},
nodeidx ,% :: mod_pubsub:nodeIdx(),
items = [] ,% :: [mod_pubsub:itemId(),...],
affiliation = 'none',% :: mod_pubsub:affiliation(),
subscriptions = [] % :: [{mod_pubsub:subscription(), mod_pubsub:subId()}]
}).
-record(pubsub_item,
{
itemid ,% :: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()},
nodeidx ,% :: mod_pubsub:nodeIdx(),
creation = {unknown, unknown},% :: {erlang:timestamp(), jid:ljid()},
modification = {unknown, unknown},% :: {erlang:timestamp(), jid:ljid()},
payload = [] % :: mod_pubsub:payload()
}).
-record(pubsub_subscription,
{
subid ,% :: mod_pubsub:subId(),
options = [] % :: mod_pubsub:subOptions()
}).
-record(pubsub_last_item,
{
nodeid ,% :: {binary(), mod_pubsub:nodeIdx()},
itemid ,% :: mod_pubsub:itemId(),
creation ,% :: {erlang:timestamp(), jid:ljid()},
payload % :: mod_pubsub:payload()
}).
-record(pubsub_orphan,
{
nodeid ,% :: mod_pubsub:nodeIdx(),
items = [] % :: list()
}).

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