Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23beaa9fad | |||
| 839229b5f0 | |||
| b89b0f140a | |||
| 09454e1658 | |||
| 828c0ad1e0 | |||
| 87bbd9cb02 | |||
| 70507a694c | |||
| 1b168e7d5c | |||
| d5935fd1ad | |||
| 2bcd2c38a9 | |||
| 042cddb768 | |||
| e0b7fd72af | |||
| 9c5e4454e4 | |||
| 7fe0b8d274 | |||
| 90ca689123 | |||
| db2825342c | |||
| bc1de531cc | |||
| 2ea5f7856c | |||
| e5b66aadaf | |||
| cff7c4c100 | |||
| e30592c050 | |||
| ff92dab49e | |||
| f652f8c8d6 | |||
| 80a502782b | |||
| 3bf7fbc117 | |||
| 0ff5b44d15 | |||
| 61926a44be | |||
| ec5f369d9d | |||
| dbebcd08c7 | |||
| 768460b518 | |||
| 515dfc002b | |||
| 16645a3c0a | |||
| 38949bdeea | |||
| 5f3457dbd6 | |||
| b9108c4650 | |||
| a54c667c80 | |||
| bcd2cd7e93 | |||
| 337ba42953 | |||
| 4f5c00a83d | |||
| c6bbdafe92 | |||
| f2e81ed2a0 | |||
| 7efc208b9e | |||
| 266691f929 | |||
| 482917348b | |||
| 945a5cd09c | |||
| 9ea51d3295 | |||
| 77308e6aff | |||
| b0c6caa60e | |||
| 3cfc5c9633 | |||
| cd336369a5 | |||
| c62956ab7b | |||
| 1d7e29765e | |||
| c0f7008e96 | |||
| 2ca5712507 | |||
| 7a37483307 | |||
| 21312c79aa | |||
| 56d00e427d | |||
| 7bb4da2fee | |||
| f19b975e8d | |||
| 83fa637569 | |||
| 858bfb4b80 | |||
| 42c82c9e72 | |||
| 8efdd439f1 | |||
| 70977cbb13 | |||
| ad31fbee1e | |||
| 6f54b6ae3b | |||
| e94b89a57d | |||
| 44528d3fef | |||
| 4580feaa3c | |||
| f3b8dc9c0b | |||
| 9d923e8e6d | |||
| c861fa6a6a | |||
| d7d8085d3b | |||
| 5e70a47f20 | |||
| e286bb23db | |||
| 2c42bd07c8 | |||
| 2001540143 | |||
| d88a32992a | |||
| 64c09c20eb | |||
| c990704418 | |||
| edf5b3c7f0 | |||
| e5a2d42484 | |||
| 51e45516a4 | |||
| 41b06cb79e | |||
| d8509aec12 | |||
| 5649e35a64 | |||
| 865074603c | |||
| 6d13120e69 | |||
| e6a3b1fa68 | |||
| df66fa6a48 | |||
| 5d499c7173 | |||
| b1e967eaf3 | |||
| 151fa2ec50 | |||
| e4de03f3df |
+6
-1
@@ -3,9 +3,14 @@ language: erlang
|
||||
otp_release:
|
||||
- 19.3
|
||||
- 22.3
|
||||
- 23.0
|
||||
|
||||
os: linux
|
||||
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
- redis
|
||||
- postgresql
|
||||
|
||||
before_install:
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
# Version 20.07
|
||||
|
||||
* Changes in this version
|
||||
- Add support for using unix sockets in listeners.
|
||||
- Make this version compatible with erlang R23
|
||||
- Make room permissions checks more strict for subscribers
|
||||
- Fix problem with muc rooms crashing when using muc logger
|
||||
with some locales
|
||||
- Limit stat calls that logger module issues
|
||||
- Don't throw errors when using user_regexp acl rule and
|
||||
having non-matching host
|
||||
- Fix problem with leaving old data when updating shared rosters
|
||||
- Fix edge case that caused failure of resuming old sessions with
|
||||
stream management.
|
||||
- Fix crash when room that was started with loging enabled was later
|
||||
changed to logging disabled
|
||||
- Increase default shaper limits (this should help with delays for
|
||||
clients that are using jingle)
|
||||
- Fix couple compatibility problems which prevented working on
|
||||
erlang R19
|
||||
- Fix sending presence unavailable when session terminates for
|
||||
clients that only send directed presences (helps with sometimes
|
||||
not leaving muc rooms on disconnect).
|
||||
- Prevent supervisor errors for sockets that were closed before
|
||||
they were passed to handler modules
|
||||
- Make stun module work better with ipv6 addresses
|
||||
|
||||
# Version 20.03
|
||||
|
||||
* Changes in this version
|
||||
|
||||
@@ -14,24 +14,24 @@ solutions very cost effectively.
|
||||
Key Features
|
||||
------------
|
||||
|
||||
- **Cross-platform**
|
||||
- **Cross-platform**
|
||||
ejabberd runs under Microsoft Windows and Unix-derived systems such as
|
||||
Linux, FreeBSD and NetBSD.
|
||||
|
||||
- **Distributed**
|
||||
- **Distributed**
|
||||
You can run ejabberd on a cluster of machines and all of them will serve the
|
||||
same XMPP domain(s). When you need more capacity you can simply add a new
|
||||
cheap node to your cluster. Accordingly, you do not need to buy an expensive
|
||||
high-end machine to support tens of thousands concurrent users.
|
||||
|
||||
- **Fault-tolerant**
|
||||
- **Fault-tolerant**
|
||||
You can deploy an ejabberd cluster so that all the information required for
|
||||
a properly working service will be replicated permanently on all nodes. This
|
||||
means that if one of the nodes crashes, the others will continue working
|
||||
without disruption. In addition, nodes also can be added or replaced ‘on
|
||||
the fly’.
|
||||
|
||||
- **Administrator-friendly**
|
||||
- **Administrator-friendly**
|
||||
ejabberd is built on top of the Open Source Erlang. As a result you do not
|
||||
need to install an external database, an external web server, amongst others
|
||||
because everything is already included, and ready to run out of the box.
|
||||
@@ -46,13 +46,13 @@ Key Features
|
||||
- Can integrate with existing authentication mechanisms.
|
||||
- Capability to send announce messages.
|
||||
|
||||
- **Internationalized**
|
||||
- **Internationalized**
|
||||
ejabberd leads in internationalization. Hence it is very well suited in a
|
||||
globalized world. Related features are:
|
||||
- Translated to 25 languages.
|
||||
- Support for IDNA.
|
||||
|
||||
- **Open Standards**
|
||||
- **Open Standards**
|
||||
ejabberd is the first Open Source Jabber server claiming to fully comply to
|
||||
the XMPP standard.
|
||||
- Fully XMPP-compliant.
|
||||
|
||||
+148
-147
@@ -35,18 +35,6 @@ AC_PATH_TOOL(EPMD, epmd, , [${extra_erl_path}$PATH])
|
||||
AC_ERLANG_NEED_ERL
|
||||
AC_ERLANG_NEED_ERLC
|
||||
|
||||
AC_ARG_ENABLE(erlang-version-check,
|
||||
[AC_HELP_STRING([--enable-erlang-version-check],
|
||||
[Check Erlang/OTP version @<:@default=yes@:>@])])
|
||||
case "$enable_erlang_version_check" in
|
||||
yes|'')
|
||||
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX])
|
||||
;;
|
||||
no)
|
||||
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX],[warn])
|
||||
;;
|
||||
esac
|
||||
|
||||
# Checks and sets ERLANG_ROOT_DIR and ERLANG_LIB_DIR variable
|
||||
AC_ERLANG_SUBST_ROOT_DIR
|
||||
# AC_ERLANG_SUBST_LIB_DIR
|
||||
@@ -68,45 +56,9 @@ fi
|
||||
# Change default prefix
|
||||
AC_PREFIX_DEFAULT(/usr/local)
|
||||
|
||||
AC_ARG_ENABLE(hipe,
|
||||
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) hipe=true ;;
|
||||
no) hipe=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-hipe) ;;
|
||||
esac],[hipe=false])
|
||||
|
||||
AC_ARG_ENABLE(roster_gateway_workaround,
|
||||
[AC_HELP_STRING([--enable-roster-gateway-workaround], [turn on workaround for processing gateway subscriptions (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) roster_gateway_workaround=true ;;
|
||||
no) roster_gateway_workaround=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;;
|
||||
esac],[roster_gateway_workaround=false])
|
||||
|
||||
AC_ARG_ENABLE(new_sql_schema,
|
||||
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) new_sql_schema=true ;;
|
||||
no) new_sql_schema=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
|
||||
esac],[new_sql_schema=false])
|
||||
|
||||
AC_ARG_ENABLE(full_xml,
|
||||
[AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
|
||||
[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])
|
||||
|
||||
AC_ARG_ENABLE(mssql,
|
||||
[AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
|
||||
[case "${enableval}" in
|
||||
yes) db_type=mssql; mssql=true ;;
|
||||
no) db_type=generic; mssql=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
|
||||
esac],[db_type=generic])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
vars.config
|
||||
src/ejabberd.app.src])
|
||||
|
||||
AC_ARG_ENABLE(all,
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-redis --enable-elixir --enable-stun --enable-sip --enable-debug --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
@@ -116,69 +68,13 @@ AC_ARG_ENABLE(all,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
|
||||
esac],[])
|
||||
|
||||
AC_ARG_ENABLE(tools,
|
||||
[AC_HELP_STRING([--enable-tools], [build development tools (default: no)])],
|
||||
AC_ARG_ENABLE(debug,
|
||||
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
|
||||
[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])
|
||||
|
||||
AC_ARG_ENABLE(odbc,
|
||||
[AC_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(mysql,
|
||||
[AC_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(pgsql,
|
||||
[AC_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(sqlite,
|
||||
[AC_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(pam,
|
||||
[AC_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(zlib,
|
||||
[AC_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])
|
||||
|
||||
AC_ARG_ENABLE(redis,
|
||||
[AC_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])
|
||||
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,
|
||||
[AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])],
|
||||
@@ -188,13 +84,47 @@ AC_ARG_ENABLE(elixir,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-elixir) ;;
|
||||
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(debug,
|
||||
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
|
||||
AC_ARG_ENABLE(erlang-version-check,
|
||||
[AC_HELP_STRING([--enable-erlang-version-check],
|
||||
[Check Erlang/OTP version (default: yes)])])
|
||||
case "$enable_erlang_version_check" in
|
||||
yes|'')
|
||||
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX])
|
||||
;;
|
||||
no)
|
||||
ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX],[warn])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(full_xml,
|
||||
[AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
|
||||
[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])
|
||||
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]]]]], [allow this system group to start ejabberd (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(hipe,
|
||||
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) hipe=true ;;
|
||||
no) hipe=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-hipe) ;;
|
||||
esac],[hipe=false])
|
||||
|
||||
AC_ARG_ENABLE(latest_deps,
|
||||
[AC_HELP_STRING([--enable-latest-deps], [makes rebar use latest commits for dependencies instead of tagged versions (default: no)])],
|
||||
@@ -204,21 +134,69 @@ AC_ARG_ENABLE(latest_deps,
|
||||
*) 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(system_deps,
|
||||
[AC_HELP_STRING([--enable-system-deps], [makes rebar use locally installed dependencies instead of downloading them (default: no)])],
|
||||
AC_ARG_ENABLE(mssql,
|
||||
[AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
|
||||
[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])
|
||||
yes) db_type=mssql; mssql=true ;;
|
||||
no) db_type=generic; mssql=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
|
||||
esac],[db_type=generic])
|
||||
|
||||
AC_ARG_ENABLE(stun,
|
||||
[AC_HELP_STRING([--enable-stun], [enable STUN/TURN support (default: yes)])],
|
||||
AC_ARG_ENABLE(mysql,
|
||||
[AC_HELP_STRING([--enable-mysql], [enable MySQL support (default: no)])],
|
||||
[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])
|
||||
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,
|
||||
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) new_sql_schema=true ;;
|
||||
no) new_sql_schema=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
|
||||
esac],[new_sql_schema=false])
|
||||
|
||||
AC_ARG_ENABLE(odbc,
|
||||
[AC_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,
|
||||
[AC_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,
|
||||
[AC_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,
|
||||
[AC_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,
|
||||
[AC_HELP_STRING([--enable-roster-gateway-workaround], [turn on workaround for processing gateway subscriptions (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) roster_gateway_workaround=true ;;
|
||||
no) roster_gateway_workaround=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;;
|
||||
esac],[roster_gateway_workaround=false])
|
||||
|
||||
AC_ARG_ENABLE(sip,
|
||||
[AC_HELP_STRING([--enable-sip], [enable SIP support (default: no)])],
|
||||
@@ -228,9 +206,37 @@ AC_ARG_ENABLE(sip,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-sip) ;;
|
||||
esac],[if test "x$sip" = "x"; then sip=false; fi])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
vars.config
|
||||
src/ejabberd.app.src])
|
||||
AC_ARG_ENABLE(sqlite,
|
||||
[AC_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,
|
||||
[AC_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,
|
||||
[AC_HELP_STRING([--enable-system-deps], [makes rebar use locally installed dependencies instead of downloading them (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) system_deps=true ;;
|
||||
no) system_deps=false ;;
|
||||
*) 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,
|
||||
[AC_HELP_STRING([--enable-tools], [build 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,
|
||||
@@ -245,19 +251,14 @@ if test "$ENABLEUSER" != ""; then
|
||||
echo "allow this system user to start ejabberd: $ENABLEUSER"
|
||||
AC_SUBST([INSTALLUSER], [$ENABLEUSER])
|
||||
fi
|
||||
ENABLEGROUP=""
|
||||
AC_ARG_ENABLE(group,
|
||||
[AS_HELP_STRING([--enable-group[[[[=GROUP]]]]], [allow this system group to start ejabberd (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) ENABLEGROUP=`groups |head -n 1` ;;
|
||||
no) ENABLEGROUP="" ;;
|
||||
*) ENABLEGROUP=$enableval
|
||||
esac],
|
||||
[])
|
||||
if test "$ENABLEGROUP" != ""; then
|
||||
echo "allow this system group to start ejabberd: $ENABLEGROUP"
|
||||
AC_SUBST([INSTALLGROUP], [$ENABLEGROUP])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(zlib,
|
||||
[AC_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])
|
||||
|
||||
if test "$sqlite" = "true"; then
|
||||
AX_LIB_SQLITE3([3.6.19])
|
||||
|
||||
+16
-7
@@ -59,11 +59,14 @@ listen:
|
||||
/.well-known/acme-challenge: ejabberd_acme
|
||||
-
|
||||
port: 3478
|
||||
ip: "::"
|
||||
transport: udp
|
||||
module: ejabberd_stun
|
||||
use_turn: true
|
||||
## The server's public IPv4 address:
|
||||
# turn_ip: 203.0.113.3
|
||||
# turn_ipv4_address: "203.0.113.3"
|
||||
## The server's public IPv6 address:
|
||||
# turn_ipv6_address: "2001:db8::3"
|
||||
-
|
||||
port: 1883
|
||||
ip: "::"
|
||||
@@ -107,14 +110,14 @@ api_permissions:
|
||||
who:
|
||||
access:
|
||||
allow:
|
||||
acl: loopback
|
||||
acl: admin
|
||||
- acl: loopback
|
||||
- acl: admin
|
||||
oauth:
|
||||
scope: "ejabberd:admin"
|
||||
access:
|
||||
allow:
|
||||
acl: loopback
|
||||
acl: admin
|
||||
- acl: loopback
|
||||
- acl: admin
|
||||
what:
|
||||
- "*"
|
||||
- "!stop"
|
||||
@@ -127,8 +130,10 @@ api_permissions:
|
||||
- connected_users_number
|
||||
|
||||
shaper:
|
||||
normal: 1000
|
||||
fast: 50000
|
||||
normal:
|
||||
rate: 3000
|
||||
burst_size: 20000
|
||||
fast: 100000
|
||||
|
||||
shaper_rules:
|
||||
max_user_sessions: 10
|
||||
@@ -157,6 +162,10 @@ modules:
|
||||
mod_http_api: {}
|
||||
mod_http_upload:
|
||||
put_url: https://@HOST@: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
|
||||
|
||||
@@ -63,8 +63,6 @@
|
||||
#.
|
||||
#' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections
|
||||
#
|
||||
# IMPORTANT: This option works only in Erlang/OTP R14B03 and newer.
|
||||
#
|
||||
# This environment variable may be set to a comma-separated
|
||||
# list of IP addresses, in which case the epmd daemon
|
||||
# will listen only on the specified address(es) and on the
|
||||
|
||||
@@ -60,6 +60,8 @@ done
|
||||
: "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}"
|
||||
: "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}"
|
||||
: "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}"
|
||||
# Allows passing extra Erlang command-line arguments in vm.args file
|
||||
: "${VMARGS:="$ETC_DIR/vm.args"}"
|
||||
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
|
||||
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
|
||||
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
|
||||
@@ -77,6 +79,8 @@ if [ -n "$INET_DIST_INTERFACE" ] ; then
|
||||
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
|
||||
fi
|
||||
fi
|
||||
# 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="$ETC_DIR"/inetrc
|
||||
@@ -126,6 +130,14 @@ exec_iex()
|
||||
# usage
|
||||
debugwarning()
|
||||
{
|
||||
if [ "$OSTYPE" != "cygwin" ] && [ "$OSTYPE" != "win32" ]; then
|
||||
if [ "a$TERM" == "a" ] || [ "$TERM" == "dumb" ] ; then
|
||||
echo "Terminal type not supported."
|
||||
echo "You may have to set the TERM environnement variable to fix this."
|
||||
exit 8
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo ""
|
||||
|
||||
+1178
-74
File diff suppressed because it is too large
Load Diff
@@ -90,7 +90,7 @@ defmodule Ejabberd.Mixfile do
|
||||
{:stringprep, "~> 1.0"},
|
||||
{:fast_yaml, "~> 1.0"},
|
||||
{:fast_tls, "~> 1.1"},
|
||||
{:stun, "~> 1.0"},
|
||||
{:stun, "~> 1.0.34"},
|
||||
{:esip, "~> 1.0.32"},
|
||||
{:p1_mysql, "~> 1.0"},
|
||||
{:mqtree, "~> 1.0"},
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
%{
|
||||
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm", "514586f4312ef3709a3ccbd8e55f69455add235c1729656687bb781d10d0afdb"},
|
||||
"artificery": {:hex, :artificery, "0.4.3", "0bc4260f988dcb9dda4b23f9fc3c6c8b99a6220a331534fdf5bf2fd0d4333b02", [:mix], [], "hexpm", "12e95333a30e20884e937abdbefa3e7f5e05609c2ba8cf37b33f000b9ffc0504"},
|
||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
|
||||
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "53ed75e7c289434953a4407eb0a40b8675c5046b057313f97cf10e196efd8d79"},
|
||||
"cache_tab": {:hex, :cache_tab, "1.0.25", "1e94d4d38ad18abd92f0d076bd4bab0f3b7189e28927c358beea0c5c2ea9d2ae", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "cd04c19ffa1b8ba34611668cea28b1a76536ec2246f5ffb77697a4a0111c70dc"},
|
||||
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
|
||||
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
|
||||
"eimp": {:hex, :eimp, "1.0.17", "3d62a8edf67b204a200c92b099125bada62fc4b2d348fe186e775014df31e6e5", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c241c79cf5149d477ba613114d4d95d346f145fade70bdd657b03fd5dc9fcdc5"},
|
||||
"epam": {:hex, :epam, "1.0.7", "55889bbfdc5ab9f2e785a710229f34e550784c5ead1960d7839ea77514aef44d", [:rebar3], [], "hexpm", "6b029ebd2b244bc339cbf5cb5908d0f2d50e43f33a6e7f70818912ea5d3fd596"},
|
||||
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm"},
|
||||
"esip": {:hex, :esip, "1.0.33", "d3c78bfb291f52e11d6955ecb29cb194a55eb0c4ce7ecf407619698005b815e3", [:rebar3], [{:fast_tls, "1.1.5", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.32", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "d09addd003dbe078832a2af6d72367b374a6c495f35fbe54b09bff338f4803be"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
|
||||
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm", "5634b9f7112837f9338a61da1993601f4ab81615de84ff0baddcdc5a3fe940dc"},
|
||||
"fast_tls": {:hex, :fast_tls, "1.1.5", "e1f60d8b415aa36cae1fc405e14c3f5ff069bb30f04f298287e8a8aa25efe01c", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "b4edad6a10b30827f819238cc10c1f82839797256f5791ab4b41bfe3e362f144"},
|
||||
"fast_xml": {:hex, :fast_xml, "1.1.40", "1e44357f9862d86cee4e0a9b9892463096092c0b8b5ee295822309fabbceb063", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "d74864613e479fd5b0e9ebf8cf17f745e3133aa5314dd722d5e617850f473ac6"},
|
||||
"fast_yaml": {:hex, :fast_yaml, "1.0.24", "d304799e6b961a21a509449830193154870b2b526cfc2e7046e9953ad413765f", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "71f4d5f868a2cfd4794e6bbd89495c4e4c54c45c6cb65b7f12d96271d6c02c84"},
|
||||
"esip": {:hex, :esip, "1.0.37", "eb26a0bceda2019c40fd6ac3935f8d7f76c1a36fdd89ed2e3356696d33503737", [:rebar3], [{:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.37", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "19bacbf089aaa2c11a59c1daffd7819d7917baf457a8ee67f969a99d76160714"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
|
||||
"ezlib": {:hex, :ezlib, "1.0.8", "9bd3a4d905c4694da5054aefe0113303c6ad56701f6625bde94b4bcc06e50dc9", [:rebar3], [], "hexpm", "852c2b2fe0166d5e7454fa7667cafcb0dadb9d6571b3808a93cf935c0a39e4ef"},
|
||||
"fast_tls": {:hex, :fast_tls, "1.1.8", "d8f78d433b7cfae0548c2bc00b9ca4f9644ba894834ae34a0d2b39c8c97a316b", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "6cca3c9b14c2bcacbeb271959adc9f655707b301b7a483438c77c20068121668"},
|
||||
"fast_xml": {:hex, :fast_xml, "1.1.43", "a3b1a14270bae7191e9fcd42628d5987642632a9b28604937c51b55094c387c1", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "78651c9eedb88322a0359a213a6e68b65d1c88d5738f37650030588599677a32"},
|
||||
"fast_yaml": {:hex, :fast_yaml, "1.0.27", "c6b2fda782d0987f0d5463f42c44a2f220ae88ac1d8eae98f75e260f6c8a9739", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "51177f885466546bea70eadd9775610f008930b3de61a18901ff223de6e70f30"},
|
||||
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"},
|
||||
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
|
||||
"jiffy": {:hex, :jiffy, "1.0.4", "72adeff75c52a2ff07de738f0813768abe7ce158026cc1115a170340259c0caa", [:rebar3], [], "hexpm", "113e5299ee4e6b9f40204256d7bbbd1caf646edeaef31ef0f7f5f842c0dad39e"},
|
||||
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm", "6429c4fee52b2dda7861ee19a4f09c8c1ffa213bee3a1ec187828fde95d447ed"},
|
||||
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "5d10499461826b79c5abee18bb594b3949cbdf76d9d9fd7e66d0a558137c21c9"},
|
||||
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm", "1bc011c7297e43aec762e53b17ecb15b0ff29f9546cd153110b343cf5b043f5f"},
|
||||
"makeup": {:hex, :makeup, "1.0.1", "82f332e461dc6c79dbd82fbe2a9c10d48ed07146f0a478286e590c83c52010b5", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49736fe5b66a08d8575bf5321d716bac5da20c8e6b97714fec2bcd6febcfa1f8"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
|
||||
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "317db0349a8d9695bc89ef7062e9654e93347cd9576f827739650e26482825bb"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
|
||||
"p1_acme": {:hex, :p1_acme, "1.0.5", "de54353100ed82d0c820fbc011b7a7ad54f65af052eb8112922ad8be8eadf8f1", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.4", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "cbecfc70ce11d37d679875117c685aa2a7bc2502bfa51722c8e619602c92a0c0"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.15", "d24ac3cc154012733801ff4f7781e7ab7843dc85cbad61e757fad601a5d0b511", [:rebar3], [], "hexpm", "4a97e0c93a8bd61acad9a6f7894a6cc31881309cb87540a4734e4c78be41df9c"},
|
||||
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm", "8a5fd16fc581a50e62176ab8b78b83b6e7cc6f76f7f59f75f58d713b7c1ca7b2"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm", "81aab8cff0203250dd3d9cc77a0232dc9f8e56c99fd742abbaedc51a0fd633a7"},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"},
|
||||
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm", "b86aed212afaf019ac97bf56857366e5f01c3003f38ee050af8ba16455e13719"},
|
||||
"makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
|
||||
"mqtree": {:hex, :mqtree, "1.0.10", "224c74694c3720da707eda6c0863dbb21a6a74dd56b606534e511b58dd6aba62", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "e8d2c37e0fa6c69ba168c0cb8130ae92d3042bafc363cee346cb5602ff17b2fa"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
|
||||
"p1_acme": {:hex, :p1_acme, "1.0.6", "0b007b776331e3d6effe700fa85d63236a98dc4e6e8c3abbbf816d1bec70df3f", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.5", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "7cc6528cbbe7a98929e954604ec670de56ca9f7a69a14d22166e8746fbe86f10"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.16", "ef063cd8cc85fd902568a82839b359fdf3d83b27cd13fbcc4fb3a3edcd728b6b", [:rebar3], [], "hexpm", "e68e861043dc311f35e2bf8b97812b654c3d91488cc4aa3084d45c7366fe1555"},
|
||||
"p1_oauth2": {:hex, :p1_oauth2, "0.6.7", "28a1c3ba36d6ccf5b054604ef4cde47358c835f93a260fb216e9b257ca1a478b", [:rebar3], [], "hexpm", "2768d7659f213b143279fa2c1ee07101df3d24b177eb79cf175afd9fcffd01e2"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.10", "e4b19c9768ef4047f9c56090a91bfefc7337abb3809a28aa4a6538eef6ad76b0", [:rebar3], [], "hexpm", "5458c0db9e47425f8cc1f592356a29359267c624785b316b34a46ad7439e9367"},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.20", "559313c0ea267a646317fd122cdfbb041db86b1ed00df91902fd273ce08d4a45", [:rebar3], [], "hexpm", "0b2c98edfe3e82dd49b287a70913f265e09eb630e40774bee88e0a9f06b0c061"},
|
||||
"pkix": {:hex, :pkix, "1.0.6", "f2b64118a25c5f80064b60a235eb299f44dd9b33a554e42df5369eae3d23c12f", [:rebar3], [], "hexpm", "9082d29e9abc965f763f1c7d7e90408dc6de91f5c1886228c3500fedf2ee183c"},
|
||||
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm", "cf9fa59c5b27de0d5d94a2ef464521379e23d8c6e9fa939abf8415c767f514bb"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "3f77edbcb530899faffe95d57b6e2bac704a5a6ea1ead5957387f9e4ed8c5f07"},
|
||||
"stun": {:hex, :stun, "1.0.32", "c1bf6c3ef4b6304c423541b2734adcfa46e265d96119b14f2a390da7119d0a42", [:rebar3], [{:fast_tls, "1.1.5", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "4178cf7514dd1df05502199b6d68ed8dc568d8cfa9dbad36a890843431190aac"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.22", "c6389cb635930044bc60973925d17abe9f259edba0a3dd155cccae2db79c0c52", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "956c5909016532d0445f1eb73bb15a1d81bf46ee452b92fdf67993becb5549cf"},
|
||||
"stun": {:hex, :stun, "1.0.37", "30c7012cd2a48de4177283aeb13719f84e8570f0b97b791c476bc384605a4c83", [:rebar3], [{:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "9f46745405f495446817908fe735fb1e2c38eb776021cbda44cc18cab0b16ede"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
|
||||
"xmpp": {:hex, :xmpp, "1.4.6", "99b24010ed9ba6423887c65a8686566f4e5408f0c7a75ef624aea1ac612034af", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.5", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.40", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "355d2d9eac87fc75c5290a94386a8c7b25b2874b3889e80e0b6af40bd0bb8adf"},
|
||||
"yconf": {:hex, :yconf, "1.0.4", "f08dcc2ad041f68580e98753f70453976d256f2c1a40a29a985465ab16d489a6", [:rebar3], [{:fast_yaml, "1.0.24", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "44570111ad224ee4eec6e2bffa1e7223ef4b76f91f9dd2f768eee214d2dcabe2"},
|
||||
"xmpp": {:hex, :xmpp, "1.4.9", "4b33ba41f9efc2eb2c4b89a9c3aac61aa0d2e5efafd681c37caa23a2bc2bc6ad", [:rebar3], [{:ezlib, "1.0.8", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.43", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.22", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "e4958505ff4e2e4cd0aa6a7cb18d19ace7bf4450be8c0b375522fb4ca623c529"},
|
||||
"yconf": {:hex, :yconf, "1.0.7", "941fa712f7c01f0e5649c5cf9b2787853802bc406dc3b6a80417475b1d63d209", [:rebar3], [{:fast_yaml, "1.0.27", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "8b09f5249b9197f0c542eb67a05b9d50e8f98df08c9dac11ce2c80fbabe05e5e"},
|
||||
}
|
||||
|
||||
+85
-79
@@ -18,67 +18,70 @@
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
|
||||
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.18"}}},
|
||||
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.22"}}},
|
||||
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.5"}}},
|
||||
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.19"}}},
|
||||
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.40"}}},
|
||||
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.6"}}},
|
||||
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.24"}}},
|
||||
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.4"}}},
|
||||
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.4"}}},
|
||||
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.6"}}},
|
||||
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.5"}}},
|
||||
{deps, [{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
|
||||
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.25"}}},
|
||||
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.17"}}},
|
||||
{if_var_true, elixir,
|
||||
{elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.4.4"}}}},
|
||||
{if_var_true, pam,
|
||||
{epam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.9"}}}},
|
||||
{if_var_true, redis,
|
||||
{eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}},
|
||||
{if_var_true, sip,
|
||||
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.37"}}}},
|
||||
{if_var_true, zlib,
|
||||
{ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.8"}}}},
|
||||
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.8"}}},
|
||||
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.43"}}},
|
||||
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.27"}}},
|
||||
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
|
||||
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.5"}}},
|
||||
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.9.0"}}},
|
||||
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.14"}}},
|
||||
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.7"}}},
|
||||
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.5"}}},
|
||||
{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
|
||||
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.32"}}}},
|
||||
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.33"}}}},
|
||||
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
|
||||
{tag, "1.0.15"}}}},
|
||||
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
|
||||
{tag, "1.1.9"}}}},
|
||||
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
|
||||
{tag, "1.1.6"}}}},
|
||||
{if_var_true, pam, {epam, ".*", {git, "https://github.com/processone/epam",
|
||||
{tag, "1.0.7"}}}},
|
||||
{if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib",
|
||||
{tag, "1.0.7"}}}},
|
||||
%% Elixir support, needed to run tests
|
||||
{if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir",
|
||||
{tag, {if_version_above, "17", "v1.4.4", "v1.1.1"}}}}},
|
||||
%% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin
|
||||
{if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*",
|
||||
{git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
|
||||
{if_var_true, tools, {luerl, ".*", {git, "https://github.com/rvirding/luerl",
|
||||
{tag, "v0.3"}}}},
|
||||
{if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis",
|
||||
{tag, "v1.0.8"}}}}]}.
|
||||
{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
|
||||
{if_var_true, tools,
|
||||
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "v0.3"}}}},
|
||||
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.10"}}},
|
||||
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.8"}}},
|
||||
{if_var_true, mysql,
|
||||
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.16"}}}},
|
||||
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.7"}}},
|
||||
{if_var_true, pgsql,
|
||||
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.10"}}}},
|
||||
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.20"}}},
|
||||
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.6"}}},
|
||||
{if_not_rebar3, %% Needed because modules are not fully migrated to new structure and mix
|
||||
{if_var_true, elixir,
|
||||
{rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
|
||||
{if_var_true, sqlite,
|
||||
{sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.8"}}}},
|
||||
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.22"}}},
|
||||
{if_var_true, stun,
|
||||
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.37"}}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.9"}}},
|
||||
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.7"}}}
|
||||
]}.
|
||||
|
||||
{if_var_true, latest_deps,
|
||||
{floating_deps, [cache_tab,
|
||||
fast_tls,
|
||||
stringprep,
|
||||
fast_xml,
|
||||
esip,
|
||||
stun,
|
||||
fast_yaml,
|
||||
xmpp,
|
||||
p1_utils,
|
||||
p1_mysql,
|
||||
p1_pgsql,
|
||||
p1_oauth2,
|
||||
epam,
|
||||
ezlib,
|
||||
eimp,
|
||||
epam,
|
||||
esip,
|
||||
ezlib,
|
||||
fast_tls,
|
||||
fast_xml,
|
||||
fast_yaml,
|
||||
mqtree,
|
||||
p1_acme,
|
||||
p1_mysql,
|
||||
p1_oauth2,
|
||||
p1_pgsql,
|
||||
p1_utils,
|
||||
pkix,
|
||||
yconf,
|
||||
p1_acme]}}.
|
||||
sqlite3,
|
||||
stringprep,
|
||||
stun,
|
||||
xmpp,
|
||||
yconf]}}.
|
||||
|
||||
{erl_first_files, ["src/ejabberd_sql_pt.erl", "src/ejabberd_config.erl",
|
||||
"src/gen_mod.erl", "src/mod_muc_room.erl",
|
||||
@@ -87,20 +90,23 @@
|
||||
{erl_opts, [nowarn_deprecated_function,
|
||||
{i, "include"},
|
||||
{i, "deps/fast_xml/include"},
|
||||
{i, "deps/xmpp/include"},
|
||||
{i, "deps/p1_utils/include"},
|
||||
{i, "deps/xmpp/include"},
|
||||
{if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}},
|
||||
{if_version_below, "21", {d, 'USE_OLD_HTTP_URI'}},
|
||||
{if_version_below, "22", {d, 'LAGER'}},
|
||||
{if_version_below, "23", {d, 'USE_OLD_CRYPTO_HMAC'}},
|
||||
{if_version_below, "23", {d, 'USE_OLD_PG2'}},
|
||||
{if_var_match, db_type, mssql, {d, 'mssql'}},
|
||||
{if_var_false, debug, no_debug_info},
|
||||
{if_var_true, debug, debug_info},
|
||||
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
|
||||
{if_var_true, hipe, native},
|
||||
{if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
|
||||
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
|
||||
{if_var_true, sip, {d, 'SIP'}},
|
||||
{if_var_true, stun, {d, 'STUN'}},
|
||||
{if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}},
|
||||
{if_version_below, "22", {d, 'LAGER'}},
|
||||
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
|
||||
{if_var_match, db_type, mssql, {d, 'mssql'}},
|
||||
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
|
||||
{if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
|
||||
{if_var_true, hipe, native},
|
||||
{if_have_fun, {erl_error, format_exception, 6}, {d, 'HAVE_ERL_ERROR'}},
|
||||
{if_have_fun, {erl_error, format_exception, 6}, {d, 'HAVE_ERL_ERROR'}},
|
||||
{src_dirs, [src,
|
||||
{if_var_true, tools, tools},
|
||||
{if_var_true, elixir, include}]}]}.
|
||||
@@ -130,20 +136,20 @@
|
||||
{xref_exclusions, [
|
||||
"(\"gen_transport\":_/_)",
|
||||
"(\"eprof\":_/_)",
|
||||
{if_var_false, mysql, "(\".*mysql.*\":_/_)"},
|
||||
{if_var_false, pgsql, "(\".*pgsql.*\":_/_)"},
|
||||
{if_var_false, pam, "(\"epam\":_/_)"},
|
||||
{if_var_false, zlib, "(\"ezlib\":_/_)"},
|
||||
{if_var_false, http, "(\"lhttpc\":_/_)"},
|
||||
{if_var_false, odbc, "(\"odbc\":_/_)"},
|
||||
{if_var_false, sqlite, "(\"sqlite3\":_/_)"},
|
||||
{if_var_false, elixir, "(\"Elixir.*\":_/_)"},
|
||||
{if_var_false, redis, "(\"eredis\":_/_)"}]}.
|
||||
{if_var_false, http, "(\"lhttpc\":_/_)"},
|
||||
{if_var_false, mysql, "(\".*mysql.*\":_/_)"},
|
||||
{if_var_false, odbc, "(\"odbc\":_/_)"},
|
||||
{if_var_false, pam, "(\"epam\":_/_)"},
|
||||
{if_var_false, pgsql, "(\".*pgsql.*\":_/_)"},
|
||||
{if_var_false, redis, "(\"eredis\":_/_)"},
|
||||
{if_var_false, sqlite, "(\"sqlite3\":_/_)"},
|
||||
{if_var_false, zlib, "(\"ezlib\":_/_)"}]}.
|
||||
|
||||
{eunit_compile_opts, [{i, "tools"},
|
||||
{i, "include"},
|
||||
{i, "deps/p1_utils/include"},
|
||||
{i, "deps/fast_xml/include"},
|
||||
{i, "deps/p1_utils/include"},
|
||||
{i, "deps/xmpp/include"}]}.
|
||||
|
||||
{cover_enabled, true}.
|
||||
@@ -153,14 +159,14 @@
|
||||
{overrides, [
|
||||
{del, [{erl_opts, [warnings_as_errors]}]}]}.
|
||||
|
||||
{post_hook_configure, [{"fast_tls", []},
|
||||
{"stringprep", []},
|
||||
{"fast_yaml", []},
|
||||
{"eimp", []},
|
||||
{if_var_true, sip, {"esip", []}},
|
||||
{"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]},
|
||||
{post_hook_configure, [{"eimp", []},
|
||||
{if_var_true, pam, {"epam", []}},
|
||||
{if_var_true, zlib, {"ezlib", []}}]}.
|
||||
{if_var_true, sip, {"esip", []}},
|
||||
{if_var_true, zlib, {"ezlib", []}},
|
||||
{"fast_tls", []},
|
||||
{"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]},
|
||||
{"fast_yaml", []},
|
||||
{"stringprep", []}]}.
|
||||
|
||||
%% Local Variables:
|
||||
%% mode: erlang
|
||||
|
||||
+4
-4
@@ -107,8 +107,8 @@ match_acl(_Host, {shared_group, {G, H}}, #{usr := {U, S, _}}) ->
|
||||
end;
|
||||
match_acl(Host, {shared_group, G}, Map) ->
|
||||
match_acl(Host, {shared_group, {G, Host}}, Map);
|
||||
match_acl(_Host, {user_regexp, {UR, S}}, #{usr := {U, S, _}}) ->
|
||||
match_regexp(U, UR);
|
||||
match_acl(_Host, {user_regexp, {UR, S1}}, #{usr := {U, S2, _}}) ->
|
||||
S1 == S2 andalso match_regexp(U, UR);
|
||||
match_acl(_Host, {user_regexp, UR}, #{usr := {U, S, _}}) ->
|
||||
ejabberd_router:is_my_host(S) andalso match_regexp(U, UR);
|
||||
match_acl(_Host, {server_regexp, SR}, #{usr := {_, S, _}}) ->
|
||||
@@ -117,8 +117,8 @@ match_acl(_Host, {resource_regexp, RR}, #{usr := {_, _, R}}) ->
|
||||
match_regexp(R, RR);
|
||||
match_acl(_Host, {node_regexp, {UR, SR}}, #{usr := {U, S, _}}) ->
|
||||
match_regexp(U, UR) andalso match_regexp(S, SR);
|
||||
match_acl(_Host, {user_glob, {UR, S}}, #{usr := {U, S, _}}) ->
|
||||
match_regexp(U, UR);
|
||||
match_acl(_Host, {user_glob, {UR, S1}}, #{usr := {U, S2, _}}) ->
|
||||
S1 == S2 andalso match_regexp(U, UR);
|
||||
match_acl(_Host, {user_glob, UR}, #{usr := {U, S, _}}) ->
|
||||
ejabberd_router:is_my_host(S) andalso match_regexp(U, UR);
|
||||
match_acl(_Host, {server_glob, SR}, #{usr := {_, S, _}}) ->
|
||||
|
||||
@@ -208,6 +208,9 @@ get_commands_spec() ->
|
||||
|
||||
#ejabberd_commands{name = join_cluster, tags = [cluster],
|
||||
desc = "Join this node into the cluster handled by Node",
|
||||
longdesc = "This command works only with ejabberdctl, "
|
||||
"not mod_http_api or other code that runs inside the "
|
||||
"same ejabberd node that will be joined.",
|
||||
module = ?MODULE, function = join_cluster,
|
||||
args_desc = ["Nodename of the node to join"],
|
||||
args_example = [<<"ejabberd1@machine7">>],
|
||||
@@ -215,8 +218,11 @@ get_commands_spec() ->
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = leave_cluster, tags = [cluster],
|
||||
desc = "Remove and shutdown Node from the running cluster",
|
||||
longdesc = "This command can be run from any running node of the cluster, "
|
||||
"even the node to be removed.",
|
||||
longdesc = "This command can be run from any running "
|
||||
"node of the cluster, even the node to be removed. "
|
||||
"In the removed node, this command works only when "
|
||||
"using ejabberdctl, not mod_http_api or other code that "
|
||||
"runs inside the same ejabberd node that will leave.",
|
||||
module = ?MODULE, function = leave_cluster,
|
||||
args_desc = ["Nodename of the node to kick from the cluster"],
|
||||
args_example = [<<"ejabberd1@machine8">>],
|
||||
|
||||
+41
-32
@@ -180,10 +180,9 @@ host_down(Host) ->
|
||||
%% Copies content of one c2s state to another.
|
||||
%% This is needed for session migration from one pid to another.
|
||||
-spec copy_state(state(), state()) -> state().
|
||||
copy_state(#{owner := Owner} = NewState,
|
||||
#{jid := JID, resource := Resource, sid := {Time, _},
|
||||
auth_module := AuthModule, lserver := LServer,
|
||||
pres_a := PresA} = OldState) ->
|
||||
copy_state(NewState,
|
||||
#{jid := JID, resource := Resource, auth_module := AuthModule,
|
||||
lserver := LServer, pres_a := PresA} = OldState) ->
|
||||
State1 = case OldState of
|
||||
#{pres_last := Pres, pres_timestamp := PresTS} ->
|
||||
NewState#{pres_last => Pres, pres_timestamp => PresTS};
|
||||
@@ -193,7 +192,6 @@ copy_state(#{owner := Owner} = NewState,
|
||||
Conn = get_conn_type(State1),
|
||||
State2 = State1#{jid => JID, resource => Resource,
|
||||
conn => Conn,
|
||||
sid => {Time, Owner},
|
||||
auth_module => AuthModule,
|
||||
pres_a => PresA},
|
||||
ejabberd_hooks:run_fold(c2s_copy_session, LServer, State2, [OldState]).
|
||||
@@ -293,17 +291,17 @@ process_terminated(#{sid := SID, socket := Socket,
|
||||
Status = format_reason(State, Reason),
|
||||
?INFO_MSG("(~ts) Closing c2s session for ~ts: ~ts",
|
||||
[xmpp_socket:pp(Socket), jid:encode(JID), Status]),
|
||||
Pres = #presence{type = unavailable,
|
||||
from = JID,
|
||||
to = jid:remove_resource(JID)},
|
||||
State1 = case maps:is_key(pres_last, State) of
|
||||
true ->
|
||||
Pres = #presence{type = unavailable,
|
||||
from = JID,
|
||||
to = jid:remove_resource(JID)},
|
||||
ejabberd_sm:close_session_unset_presence(SID, U, S, R,
|
||||
Status),
|
||||
broadcast_presence_unavailable(State, Pres);
|
||||
broadcast_presence_unavailable(State, Pres, true);
|
||||
false ->
|
||||
ejabberd_sm:close_session(SID, U, S, R),
|
||||
State
|
||||
broadcast_presence_unavailable(State, Pres, false)
|
||||
end,
|
||||
bounce_message_queue(SID, JID),
|
||||
State1;
|
||||
@@ -734,7 +732,7 @@ process_self_presence(#{lserver := LServer, sid := SID,
|
||||
_ = ejabberd_sm:unset_presence(SID, U, S, R, Status),
|
||||
{Pres1, State1} = ejabberd_hooks:run_fold(
|
||||
c2s_self_presence, LServer, {Pres, State}, []),
|
||||
State2 = broadcast_presence_unavailable(State1, Pres1),
|
||||
State2 = broadcast_presence_unavailable(State1, Pres1, true),
|
||||
maps:remove(pres_last, maps:remove(pres_timestamp, State2));
|
||||
process_self_presence(#{lserver := LServer} = State,
|
||||
#presence{type = available} = Pres) ->
|
||||
@@ -755,28 +753,39 @@ update_priority(#{sid := SID, user := U, server := S, resource := R},
|
||||
Priority = get_priority_from_presence(Pres),
|
||||
ejabberd_sm:set_presence(SID, U, S, R, Priority, Pres).
|
||||
|
||||
-spec broadcast_presence_unavailable(state(), presence()) -> state().
|
||||
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres) ->
|
||||
-spec broadcast_presence_unavailable(state(), presence(), boolean()) -> state().
|
||||
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres,
|
||||
BroadcastToRoster) ->
|
||||
#jid{luser = LUser, lserver = LServer} = JID,
|
||||
BareJID = jid:remove_resource(JID),
|
||||
Items1 = ejabberd_hooks:run_fold(roster_get, LServer,
|
||||
[], [{LUser, LServer}]),
|
||||
BareJID = jid:tolower(jid:remove_resource(JID)),
|
||||
Items1 = case BroadcastToRoster of
|
||||
true ->
|
||||
Roster = ejabberd_hooks:run_fold(roster_get, LServer,
|
||||
[], [{LUser, LServer}]),
|
||||
lists:foldl(
|
||||
fun(#roster{jid = LJID, subscription = Sub}, Acc)
|
||||
when Sub == both; Sub == from ->
|
||||
maps:put(LJID, 1, Acc);
|
||||
(_, Acc) ->
|
||||
Acc
|
||||
end, #{BareJID => 1}, Roster);
|
||||
_ ->
|
||||
#{BareJID => 1}
|
||||
end,
|
||||
Items2 = ?SETS:fold(
|
||||
fun(LJID, Items) ->
|
||||
[#roster{jid = LJID, subscription = from}|Items]
|
||||
end, Items1, PresA),
|
||||
JIDs = lists:foldl(
|
||||
fun(#roster{jid = LJID, subscription = Sub}, Tos)
|
||||
when Sub == both orelse Sub == from ->
|
||||
To = jid:make(LJID),
|
||||
P = xmpp:set_to(Pres, jid:make(LJID)),
|
||||
case privacy_check_packet(State, P, out) of
|
||||
allow -> [To|Tos];
|
||||
deny -> Tos
|
||||
end;
|
||||
(_, Tos) ->
|
||||
Tos
|
||||
end, [BareJID], Items2),
|
||||
fun(LJID, Acc) ->
|
||||
maps:put(LJID, 1, Acc)
|
||||
end, Items1, PresA),
|
||||
|
||||
JIDs = lists:filtermap(
|
||||
fun(LJid) ->
|
||||
To = jid:make(LJid),
|
||||
P = xmpp:set_to(Pres, To),
|
||||
case privacy_check_packet(State, P, out) of
|
||||
allow -> {true, To};
|
||||
deny -> false
|
||||
end
|
||||
end, maps:keys(Items2)),
|
||||
route_multiple(State, JIDs, Pres),
|
||||
State#{pres_a => ?SETS:new()}.
|
||||
|
||||
@@ -999,4 +1008,4 @@ listen_options() ->
|
||||
{tls_verify, false},
|
||||
{zlib, false},
|
||||
{max_stanza_size, infinity},
|
||||
{max_fsm_queue, 5000}].
|
||||
{max_fsm_queue, 10000}].
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 5 Jul 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
@@ -23,190 +23,6 @@
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
%%% @headerfile "ejabberd_commands.hrl"
|
||||
|
||||
%%% @doc Management of ejabberd commands.
|
||||
%%%
|
||||
%%% An ejabberd command is an abstract function identified by a name,
|
||||
%%% with a defined number and type of calling arguments and type of
|
||||
%%% result, that can be defined in any Erlang module and executed
|
||||
%%% using any valid frontend.
|
||||
%%%
|
||||
%%%
|
||||
%%% == Define a new ejabberd command ==
|
||||
%%%
|
||||
%%% ejabberd commands can be defined and registered in
|
||||
%%% any Erlang module.
|
||||
%%%
|
||||
%%% Some commands are procedures; and their purpose is to perform an
|
||||
%%% action in the server, so the command result is only some result
|
||||
%%% code or result tuple. Other commands are inspectors, and their
|
||||
%%% purpose is to gather some information about the server and return
|
||||
%%% a detailed response: it can be integer, string, atom, tuple, list
|
||||
%%% or a mix of those ones.
|
||||
%%%
|
||||
%%% The arguments and result of an ejabberd command are strictly
|
||||
%%% defined. The number and format of the arguments provided when
|
||||
%%% calling an ejabberd command must match the definition of that
|
||||
%%% command. The format of the result provided by an ejabberd command
|
||||
%%% must be exactly its definition. For example, if a command is said
|
||||
%%% to return an integer, it must always return an integer (except in
|
||||
%%% case of a crash).
|
||||
%%%
|
||||
%%% If you are developing an Erlang module that will run inside
|
||||
%%% ejabberd and you want to provide a new ejabberd command to
|
||||
%%% administer some task related to your module, you only need to:
|
||||
%%% implement a function, define the command, and register it.
|
||||
%%%
|
||||
%%%
|
||||
%%% === Define a new ejabberd command ===
|
||||
%%%
|
||||
%%% An ejabberd command is defined using the Erlang record
|
||||
%%% 'ejabberd_commands'. This record has several elements that you
|
||||
%%% must define. Note that 'tags', 'desc' and 'longdesc' are optional.
|
||||
%%%
|
||||
%%% For example let's define an ejabberd command 'pow' that gets the
|
||||
%%% integers 'base' and 'exponent'. Its result will be an integer
|
||||
%%% 'power':
|
||||
%%%
|
||||
%%% <pre>#ejabberd_commands{name = pow, tags = [test],
|
||||
%%% desc = "Return the power of base for exponent",
|
||||
%%% longdesc = "This is an example command. The formula is:\n"
|
||||
%%% " power = base ^ exponent",
|
||||
%%% module = ?MODULE, function = pow,
|
||||
%%% args = [{base, integer}, {exponent, integer}],
|
||||
%%% result = {power, integer}}</pre>
|
||||
%%%
|
||||
%%%
|
||||
%%% === Implement the function associated to the command ===
|
||||
%%%
|
||||
%%% Now implement a function in your module that matches the arguments
|
||||
%%% and result of the ejabberd command.
|
||||
%%%
|
||||
%%% For example the function calc_power gets two integers Base and
|
||||
%%% Exponent. It calculates the power and rounds to an integer:
|
||||
%%%
|
||||
%%% <pre>calc_power(Base, Exponent) ->
|
||||
%%% PowFloat = math:pow(Base, Exponent),
|
||||
%%% round(PowFloat).</pre>
|
||||
%%%
|
||||
%%% Since this function will be called by ejabberd_commands, it must
|
||||
%%% be exported.
|
||||
%%% Add to your module:
|
||||
%%% <pre>-export([calc_power/2]).</pre>
|
||||
%%%
|
||||
%%% Only some types of result formats are allowed.
|
||||
%%% If the format is defined as 'rescode', then your function must return:
|
||||
%%% ok | true | atom()
|
||||
%%% where the atoms ok and true as considered positive answers,
|
||||
%%% and any other response atom is considered negative.
|
||||
%%%
|
||||
%%% If the format is defined as 'restuple', then the command must return:
|
||||
%%% {rescode(), string()}
|
||||
%%%
|
||||
%%% If the format is defined as '{list, something()}', then the command
|
||||
%%% must return a list of something().
|
||||
%%%
|
||||
%%%
|
||||
%%% === Register the command ===
|
||||
%%%
|
||||
%%% Define this function and put inside the #ejabberd_command you
|
||||
%%% defined in the beginning:
|
||||
%%%
|
||||
%%% <pre>commands() ->
|
||||
%%% [
|
||||
%%%
|
||||
%%% ].</pre>
|
||||
%%%
|
||||
%%% You need to include this header file in order to use the record:
|
||||
%%%
|
||||
%%% <pre>-include("ejabberd_commands.hrl").</pre>
|
||||
%%%
|
||||
%%% When your module is initialized or started, register your commands:
|
||||
%%%
|
||||
%%% <pre>ejabberd_commands:register_commands(commands()),</pre>
|
||||
%%%
|
||||
%%% And when your module is stopped, unregister your commands:
|
||||
%%%
|
||||
%%% <pre>ejabberd_commands:unregister_commands(commands()),</pre>
|
||||
%%%
|
||||
%%% That's all! Now when your module is started, the command will be
|
||||
%%% registered and any frontend can access it. For example:
|
||||
%%%
|
||||
%%% <pre>$ ejabberdctl help pow
|
||||
%%%
|
||||
%%% Command Name: pow
|
||||
%%%
|
||||
%%% Arguments: base::integer
|
||||
%%% exponent::integer
|
||||
%%%
|
||||
%%% Returns: power::integer
|
||||
%%%
|
||||
%%% Tags: test
|
||||
%%%
|
||||
%%% Description: Return the power of base for exponent
|
||||
%%%
|
||||
%%% This is an example command. The formula is:
|
||||
%%% power = base ^ exponent
|
||||
%%%
|
||||
%%% $ ejabberdctl pow 3 4
|
||||
%%% 81
|
||||
%%% </pre>
|
||||
%%%
|
||||
%%%
|
||||
%%% == Execute an ejabberd command ==
|
||||
%%%
|
||||
%%% ejabberd commands are mean to be executed using any valid
|
||||
%%% frontend. An ejabberd commands is implemented in a regular Erlang
|
||||
%%% function, so it is also possible to execute this function in any
|
||||
%%% Erlang module, without dealing with the associated ejabberd
|
||||
%%% commands.
|
||||
%%%
|
||||
%%%
|
||||
%%% == Frontend to ejabberd commands ==
|
||||
%%%
|
||||
%%% Currently there are two frontends to ejabberd commands: the shell
|
||||
%%% script {@link ejabberd_ctl. ejabberdctl}, and the XML-RPC server
|
||||
%%% ejabberd_xmlrpc.
|
||||
%%%
|
||||
%%%
|
||||
%%% === ejabberdctl as a frontend to ejabberd commands ===
|
||||
%%%
|
||||
%%% It is possible to use ejabberdctl to get documentation of any
|
||||
%%% command. But ejabberdctl does not support all the argument types
|
||||
%%% allowed in ejabberd commands, so there are some ejabberd commands
|
||||
%%% that cannot be executed using ejabberdctl.
|
||||
%%%
|
||||
%%% Also note that the ejabberdctl shell administration script also
|
||||
%%% manages ejabberdctl commands, which are unrelated to ejabberd
|
||||
%%% commands and can only be executed using ejabberdctl.
|
||||
%%%
|
||||
%%%
|
||||
%%% === ejabberd_xmlrpc as a frontend to ejabberd commands ===
|
||||
%%%
|
||||
%%% ejabberd_xmlrpc provides an XML-RPC server to execute ejabberd commands.
|
||||
%%% ejabberd_xmlrpc is a contributed module published in ejabberd-modules SVN.
|
||||
%%%
|
||||
%%% Since ejabberd_xmlrpc does not provide any method to get documentation
|
||||
%%% of the ejabberd commands, please use ejabberdctl to know which
|
||||
%%% commands are available, and their usage.
|
||||
%%%
|
||||
%%% The number and format of the arguments provided when calling an
|
||||
%%% ejabberd command must match the definition of that command. Please
|
||||
%%% make sure the XML-RPC call provides the required arguments, with
|
||||
%%% the specified format. The order of the arguments in an XML-RPC
|
||||
%%% call is not important, because all the data is tagged and will be
|
||||
%%% correctly prepared by ejabberd_xmlrpc before executing the ejabberd
|
||||
%%% command.
|
||||
|
||||
%%% TODO: consider this feature:
|
||||
%%% All commands are caught. If an error happens, return the restuple:
|
||||
%%% {error, flattened error string}
|
||||
%%% This means that ecomm call APIs (ejabberd_ctl, ejabberd_xmlrpc)
|
||||
%%% need to allows this. And ejabberd_xmlrpc must be prepared to
|
||||
%%% handle such an unexpected response.
|
||||
|
||||
|
||||
-module(ejabberd_commands).
|
||||
-author('badlop@process-one.net').
|
||||
|
||||
@@ -312,11 +128,6 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
|
||||
-spec register_commands([ejabberd_commands()]) -> ok.
|
||||
|
||||
%% @doc Register ejabberd commands.
|
||||
%% If a command is already registered, a warning is printed and the
|
||||
%% old command is preserved.
|
||||
%% A registered command is not directly available to be called through
|
||||
%% ejabberd ReST API. It need to be exposed to be available through API.
|
||||
register_commands(Commands) ->
|
||||
lists:foreach(
|
||||
fun(Command) ->
|
||||
@@ -330,7 +141,6 @@ register_commands(Commands) ->
|
||||
|
||||
-spec unregister_commands([ejabberd_commands()]) -> ok.
|
||||
|
||||
%% @doc Unregister ejabberd commands.
|
||||
unregister_commands(Commands) ->
|
||||
lists:foreach(
|
||||
fun(Command) ->
|
||||
@@ -341,14 +151,11 @@ unregister_commands(Commands) ->
|
||||
|
||||
-spec list_commands() -> [{atom(), [aterm()], string()}].
|
||||
|
||||
%% @doc Get a list of all the available commands, arguments and description.
|
||||
list_commands() ->
|
||||
list_commands(?DEFAULT_VERSION).
|
||||
|
||||
-spec list_commands(integer()) -> [{atom(), [aterm()], string()}].
|
||||
|
||||
%% @doc Get a list of all the available commands, arguments and
|
||||
%% description in a given API version.
|
||||
list_commands(Version) ->
|
||||
Commands = get_commands_definition(Version),
|
||||
[{Name, Args, Desc} || #ejabberd_commands{name = Name,
|
||||
@@ -357,7 +164,6 @@ list_commands(Version) ->
|
||||
|
||||
-spec get_command_format(atom()) -> {[aterm()], [{atom(),atom()}], rterm()}.
|
||||
|
||||
%% @doc Get the format of arguments and result of a command.
|
||||
get_command_format(Name) ->
|
||||
get_command_format(Name, noauth, ?DEFAULT_VERSION).
|
||||
get_command_format(Name, Version) when is_integer(Version) ->
|
||||
@@ -383,13 +189,11 @@ get_command_format(Name, Auth, Version) ->
|
||||
|
||||
-spec get_command_definition(atom()) -> ejabberd_commands().
|
||||
|
||||
%% @doc Get the definition record of a command.
|
||||
get_command_definition(Name) ->
|
||||
get_command_definition(Name, ?DEFAULT_VERSION).
|
||||
|
||||
-spec get_command_definition(atom(), integer()) -> ejabberd_commands().
|
||||
|
||||
%% @doc Get the definition record of a command in a given API version.
|
||||
get_command_definition(Name, Version) ->
|
||||
case lists:reverse(
|
||||
lists:sort(
|
||||
@@ -409,7 +213,6 @@ get_commands_definition() ->
|
||||
|
||||
-spec get_commands_definition(integer()) -> [ejabberd_commands()].
|
||||
|
||||
% @doc Returns all commands for a given API version
|
||||
get_commands_definition(Version) ->
|
||||
L = lists:reverse(
|
||||
lists:sort(
|
||||
@@ -450,15 +253,11 @@ do_execute_command(Command, Arguments) ->
|
||||
|
||||
-spec get_tags_commands() -> [{string(), [string()]}].
|
||||
|
||||
%% @spec () -> [{Tag::string(), [CommandName::string()]}]
|
||||
%% @doc Get all the tags and associated commands.
|
||||
get_tags_commands() ->
|
||||
get_tags_commands(?DEFAULT_VERSION).
|
||||
|
||||
-spec get_tags_commands(integer()) -> [{string(), [string()]}].
|
||||
|
||||
%% @spec (integer) -> [{Tag::string(), [CommandName::string()]}]
|
||||
%% @doc Get all the tags and associated commands in a given API version
|
||||
get_tags_commands(Version) ->
|
||||
CommandTags = [{Name, Tags} ||
|
||||
#ejabberd_commands{name = Name, tags = Tags}
|
||||
|
||||
@@ -461,7 +461,7 @@ generate_md_output(File, RegExp, Languages) ->
|
||||
Langs = binary:split(Languages, <<",">>, [global]),
|
||||
Header = <<"---\ntitle: Administration API reference\ntoc: true\nmenu: Administration API\norder: 40\n"
|
||||
"// Autogenerated with 'ejabberdctl gen_markdown_doc_for_commands'\n---\n\n"
|
||||
"This page documents API of ejabberd version ", (ejabberd_option:version())/binary>>,
|
||||
"This section describes API of ejabberd version ", (ejabberd_option:version())/binary>>,
|
||||
Out = lists:map(fun(C) -> gen_doc(C, false, Langs) end, Cmds4),
|
||||
{ok, Fh} = file:open(File, [write]),
|
||||
io:format(Fh, "~ts~ts", [Header, Out]),
|
||||
|
||||
@@ -102,8 +102,8 @@ transform(_Host, certfiles, CertFiles1, Acc) ->
|
||||
transform(_Host, acme, ACME, Acc) ->
|
||||
ACME1 = lists:map(
|
||||
fun({ca_url, URL} = Opt) ->
|
||||
case http_uri:parse(binary_to_list(URL)) of
|
||||
{ok, {_, _, "acme-v01.api.letsencrypt.org", _, _, _}} ->
|
||||
case misc:uri_parse(URL) of
|
||||
{ok, _, "acme-v01.api.letsencrypt.org", _, _} ->
|
||||
NewURL = ejabberd_acme:default_directory_url(),
|
||||
?WARNING_MSG("ACME directory URL ~ts defined in "
|
||||
"option acme->ca_url is deprecated "
|
||||
@@ -245,8 +245,9 @@ filter(_, _, _, _) ->
|
||||
%%%===================================================================
|
||||
transform_listener(Opts, Acc) ->
|
||||
Opts1 = transform_request_handlers(Opts),
|
||||
Opts2 = remove_inet_options(Opts1),
|
||||
collect_listener_certfiles(Opts2, Acc).
|
||||
Opts2 = transform_turn_ip(Opts1),
|
||||
Opts3 = remove_inet_options(Opts2),
|
||||
collect_listener_certfiles(Opts3, Acc).
|
||||
|
||||
transform_request_handlers(Opts) ->
|
||||
case lists:keyfind(module, 1, Opts) of
|
||||
@@ -258,6 +259,14 @@ transform_request_handlers(Opts) ->
|
||||
Opts
|
||||
end.
|
||||
|
||||
transform_turn_ip(Opts) ->
|
||||
case lists:keyfind(module, 1, Opts) of
|
||||
{_, ejabberd_stun} ->
|
||||
replace_turn_ip(Opts);
|
||||
_ ->
|
||||
Opts
|
||||
end.
|
||||
|
||||
replace_request_handlers(Opts) ->
|
||||
Handlers = proplists:get_value(request_handlers, Opts, []),
|
||||
Handlers1 =
|
||||
@@ -322,6 +331,15 @@ remove_xmlrpc_access_commands(Opts) ->
|
||||
true
|
||||
end, Opts).
|
||||
|
||||
replace_turn_ip(Opts) ->
|
||||
lists:filtermap(
|
||||
fun({turn_ip, Val}) ->
|
||||
warn_replaced_option(turn_ip, turn_ipv4_address),
|
||||
{true, {turn_ipv4_address, Val}};
|
||||
(_) ->
|
||||
true
|
||||
end, Opts).
|
||||
|
||||
remove_inet_options(Opts) ->
|
||||
lists:filter(
|
||||
fun({Opt, _}) when Opt == inet; Opt == inet6 ->
|
||||
|
||||
@@ -254,7 +254,7 @@ process2(Args, AccessCommands, Auth, Version) ->
|
||||
%% Command calling
|
||||
%%-----------------------------
|
||||
|
||||
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()}
|
||||
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()}
|
||||
try_run_ctp(Args, Auth, AccessCommands, Version) ->
|
||||
try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of
|
||||
false when Args /= [] ->
|
||||
@@ -275,7 +275,7 @@ try_run_ctp(Args, Auth, AccessCommands, Version) ->
|
||||
{io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE}
|
||||
end.
|
||||
|
||||
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()}
|
||||
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()}
|
||||
try_call_command(Args, Auth, AccessCommands, Version) ->
|
||||
try call_command(Args, Auth, AccessCommands, Version) of
|
||||
{Reason, wrong_command_arguments} ->
|
||||
@@ -299,7 +299,7 @@ try_call_command(Args, Auth, AccessCommands, Version) ->
|
||||
?STATUS_ERROR}
|
||||
end.
|
||||
|
||||
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType}
|
||||
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()} | {error, ErrorType}
|
||||
call_command([CmdString | Args], Auth, _AccessCommands, Version) ->
|
||||
CmdStringU = ejabberd_regexp:greplace(
|
||||
list_to_binary(CmdString), <<"-">>, <<"_">>),
|
||||
@@ -695,7 +695,7 @@ print_usage_help(MaxC, ShCode) ->
|
||||
%% Print usage command
|
||||
%%-----------------------------
|
||||
|
||||
%% @spec (CmdSubString::string(), MaxC::integer(), ShCode::boolean()) -> ok
|
||||
%% @spec (CmdSubString::string(), MaxC::integer(), ShCode::boolean(), Version) -> ok
|
||||
print_usage_commands2(CmdSubString, MaxC, ShCode, Version) ->
|
||||
%% Get which command names match this substring
|
||||
AllCommandsNames = [atom_to_list(Name) || {Name, _, _} <- ejabberd_commands:list_commands(Version)],
|
||||
@@ -738,7 +738,7 @@ filter_commands_regexp(All, Glob) ->
|
||||
end,
|
||||
All).
|
||||
|
||||
%% @spec (Cmd::string(), MaxC::integer(), ShCode::boolean()) -> ok
|
||||
%% @spec (Cmd::string(), MaxC::integer(), ShCode::boolean(), Version) -> ok
|
||||
print_usage_command(Cmd, MaxC, ShCode, Version) ->
|
||||
Name = list_to_atom(Cmd),
|
||||
C = ejabberd_commands:get_command_definition(Name, Version),
|
||||
|
||||
@@ -193,6 +193,9 @@ receive_headers(#state{trail = Trail} = State) ->
|
||||
Socket = State#state.socket,
|
||||
Data = SockMod:recv(Socket, 0, 300000),
|
||||
case Data of
|
||||
{error, closed} when State#state.request_method == undefined ->
|
||||
% socket closed without receiving anything in it
|
||||
ok;
|
||||
{error, Error} ->
|
||||
?DEBUG("Error when retrieving http headers ~p: ~p",
|
||||
[State#state.sockmod, Error]),
|
||||
|
||||
+41
-12
@@ -105,10 +105,18 @@ init({_, _, Transport} = EndPoint, Module, AllOpts) ->
|
||||
|
||||
-spec init(endpoint(), module(), opts(), [gen_tcp:option()]) -> ok.
|
||||
init({Port, _, udp} = EndPoint, Module, Opts, SockOpts) ->
|
||||
case gen_udp:open(Port, [binary,
|
||||
{Port2, ExtraOpts} = case Port of
|
||||
<<"unix:", Path/binary>> ->
|
||||
SO = lists:keydelete(ip, 1, SockOpts),
|
||||
file:delete(Path),
|
||||
{0, [{ip, {local, Path}} | SO]};
|
||||
_ ->
|
||||
{Port, SockOpts}
|
||||
end,
|
||||
case gen_udp:open(Port2, [binary,
|
||||
{active, false},
|
||||
{reuseaddr, true} |
|
||||
SockOpts]) of
|
||||
ExtraOpts]) of
|
||||
{ok, Socket} ->
|
||||
case inet:sockname(Socket) of
|
||||
{ok, {Addr, Port1}} ->
|
||||
@@ -174,15 +182,22 @@ init({Port, _, tcp} = EndPoint, Module, Opts, SockOpts) ->
|
||||
-spec listen_tcp(inet:port_number(), [gen_tcp:option()]) ->
|
||||
{ok, inet:socket()} | {error, system_limit | inet:posix()}.
|
||||
listen_tcp(Port, SockOpts) ->
|
||||
Res = gen_tcp:listen(Port, [binary,
|
||||
{Port2, ExtraOpts} = case Port of
|
||||
<<"unix:", Path/binary>> ->
|
||||
SO = lists:keydelete(ip, 1, SockOpts),
|
||||
file:delete(Path),
|
||||
{0, [{ip, {local, Path}} | SO]};
|
||||
_ ->
|
||||
{Port, SockOpts}
|
||||
end,
|
||||
Res = gen_tcp:listen(Port2, [binary,
|
||||
{packet, 0},
|
||||
{active, false},
|
||||
{reuseaddr, true},
|
||||
{nodelay, true},
|
||||
{send_timeout, ?TCP_SEND_TIMEOUT},
|
||||
{send_timeout_close, true},
|
||||
{keepalive, true} |
|
||||
SockOpts]),
|
||||
{keepalive, true} | ExtraOpts]),
|
||||
case Res of
|
||||
{ok, ListenSocket} ->
|
||||
{ok, ListenSocket};
|
||||
@@ -226,6 +241,8 @@ accept(ListenSocket, Module, State, Sup, Interval, Proxy, Arity) ->
|
||||
?ERROR_MSG("(~w) Proxy protocol parsing failed: ~ts",
|
||||
[ListenSocket, format_error(Err)]),
|
||||
gen_tcp:close(Socket);
|
||||
{undefined, undefined} ->
|
||||
gen_tcp:close(Socket);
|
||||
{{Addr, Port}, {PAddr, PPort}} = SP ->
|
||||
%% THIS IS WRONG
|
||||
State2 = [{sock_peer_name, SP} | State],
|
||||
@@ -307,7 +324,12 @@ start_connection(Module, Arity, Socket, State, Sup) ->
|
||||
Module:accept(Pid),
|
||||
{ok, Pid};
|
||||
Err ->
|
||||
exit(Pid, kill),
|
||||
case Sup of
|
||||
undefined ->
|
||||
exit(Pid, kill);
|
||||
_ ->
|
||||
supervisor:terminate_child(Sup, Pid)
|
||||
end,
|
||||
Err
|
||||
end;
|
||||
Err ->
|
||||
@@ -459,11 +481,16 @@ format_error(Reason) ->
|
||||
|
||||
-spec format_endpoint(endpoint()) -> string().
|
||||
format_endpoint({Port, IP, _Transport}) ->
|
||||
IPStr = case tuple_size(IP) of
|
||||
4 -> inet:ntoa(IP);
|
||||
8 -> "[" ++ inet:ntoa(IP) ++ "]"
|
||||
end,
|
||||
IPStr ++ ":" ++ integer_to_list(Port).
|
||||
case Port of
|
||||
Unix when is_binary(Unix) ->
|
||||
<<"unix:", Unix/binary>>;
|
||||
_ ->
|
||||
IPStr = case tuple_size(IP) of
|
||||
4 -> inet:ntoa(IP);
|
||||
8 -> "[" ++ inet:ntoa(IP) ++ "]"
|
||||
end,
|
||||
IPStr ++ ":" ++ integer_to_list(Port)
|
||||
end.
|
||||
|
||||
-spec format_transport(transport(), opts()) -> string().
|
||||
format_transport(Transport, Opts) ->
|
||||
@@ -618,7 +645,9 @@ partition(Fun, Opts) ->
|
||||
|
||||
-spec listen_opt_type(atom()) -> econf:validator().
|
||||
listen_opt_type(port) ->
|
||||
econf:int(0, 65535);
|
||||
econf:either(
|
||||
econf:int(0, 65535),
|
||||
econf:binary("^unix:.*"));
|
||||
listen_opt_type(module) ->
|
||||
econf:beam([[{start, 3}, {start, 2}],
|
||||
[{start_link, 3}, {start_link, 2}],
|
||||
|
||||
+13
-7
@@ -47,13 +47,6 @@
|
||||
|
||||
-export_type([loglevel/0]).
|
||||
|
||||
-spec restart() -> ok.
|
||||
-spec reopen_log() -> ok.
|
||||
-spec rotate_log() -> ok.
|
||||
-spec get() -> loglevel().
|
||||
-spec set(0..5 | loglevel()) -> ok.
|
||||
-spec flush() -> ok.
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
@@ -173,14 +166,17 @@ do_start(Level) ->
|
||||
lager:set_loghwm(Handler, LogRateLimit)
|
||||
end, gen_event:which_handlers(lager_event)).
|
||||
|
||||
-spec restart() -> ok.
|
||||
restart() ->
|
||||
Level = ejabberd_option:loglevel(),
|
||||
application:stop(lager),
|
||||
start(Level).
|
||||
|
||||
-spec reopen_log() -> ok.
|
||||
reopen_log() ->
|
||||
ok.
|
||||
|
||||
-spec rotate_log() -> ok.
|
||||
rotate_log() ->
|
||||
catch lager_crash_log ! rotate,
|
||||
lists:foreach(
|
||||
@@ -190,6 +186,7 @@ rotate_log() ->
|
||||
ok
|
||||
end, gen_event:which_handlers(lager_event)).
|
||||
|
||||
-spec get() -> loglevel().
|
||||
get() ->
|
||||
Handlers = get_lager_handlers(),
|
||||
lists:foldl(fun(lager_console_backend, _Acc) ->
|
||||
@@ -201,6 +198,7 @@ get() ->
|
||||
end,
|
||||
none, Handlers).
|
||||
|
||||
-spec set(0..5 | loglevel()) -> ok.
|
||||
set(N) when is_integer(N), N>=0, N=<5 ->
|
||||
set(convert_loglevel(N));
|
||||
set(Level) when ?is_loglevel(Level) ->
|
||||
@@ -241,6 +239,7 @@ get_lager_version() ->
|
||||
false -> "0.0.0"
|
||||
end.
|
||||
|
||||
-spec flush() -> ok.
|
||||
flush() ->
|
||||
application:stop(lager),
|
||||
application:stop(sasl).
|
||||
@@ -261,6 +260,7 @@ start(Level) ->
|
||||
Config = #{max_no_bytes => LogRotateSize,
|
||||
max_no_files => LogRotateCount,
|
||||
filesync_repeat_interval => no_repeat,
|
||||
file_check => 1000,
|
||||
sync_mode_qlen => 1000,
|
||||
drop_mode_qlen => 1000,
|
||||
flush_qlen => 5000},
|
||||
@@ -297,6 +297,7 @@ start(Level) ->
|
||||
Err
|
||||
end.
|
||||
|
||||
-spec restart() -> ok.
|
||||
restart() ->
|
||||
ok.
|
||||
|
||||
@@ -321,16 +322,20 @@ msg() ->
|
||||
[{logger_formatter, [[logger_formatter, title], ":", io_lib:nl()], []},
|
||||
msg, io_lib:nl()].
|
||||
|
||||
-spec reopen_log() -> ok.
|
||||
reopen_log() ->
|
||||
ok.
|
||||
|
||||
-spec rotate_log() -> ok.
|
||||
rotate_log() ->
|
||||
ok.
|
||||
|
||||
-spec get() -> loglevel().
|
||||
get() ->
|
||||
#{level := Level} = logger:get_primary_config(),
|
||||
Level.
|
||||
|
||||
-spec set(0..5 | loglevel()) -> ok.
|
||||
set(N) when is_integer(N), N>=0, N=<5 ->
|
||||
set(convert_loglevel(N));
|
||||
set(Level) when ?is_loglevel(Level) ->
|
||||
@@ -346,6 +351,7 @@ set(Level) when ?is_loglevel(Level) ->
|
||||
end
|
||||
end.
|
||||
|
||||
-spec flush() -> ok.
|
||||
flush() ->
|
||||
lists:foreach(
|
||||
fun(#{id := HandlerId, module := logger_std_h}) ->
|
||||
|
||||
@@ -110,7 +110,7 @@ doc() ->
|
||||
"Modules and other components (e.g. authentication) "
|
||||
"may have its own value. The default value is 'mnesia'.")}},
|
||||
{default_ram_db,
|
||||
#{value => "mnesia | sql | redis",
|
||||
#{value => "mnesia | redis | sql",
|
||||
desc =>
|
||||
?T("Default volatile (in-memory) storage for ejabberd. "
|
||||
"Modules and other components (e.g. session management) "
|
||||
@@ -253,7 +253,7 @@ doc() ->
|
||||
{acme,
|
||||
#{value => ?T("Options"),
|
||||
desc =>
|
||||
?T("ACME configuration. ACME is used to automatically "
|
||||
?T("http://../basic/#acme[ACME] configuration, to automatically "
|
||||
"obtain SSL certificates for the domains served by ejabberd, "
|
||||
"which means that certificate requests and renewals are "
|
||||
"performed to some CA server (aka \"ACME server\") in a fully "
|
||||
@@ -1022,7 +1022,7 @@ doc() ->
|
||||
?T("Same as 'cache_size', but applied to routing table cache "
|
||||
"only. If not set, the value from 'cache_size' will be used.")}},
|
||||
{router_db_type,
|
||||
#{value => "mnesia | sql | redis",
|
||||
#{value => "mnesia | redis | sql",
|
||||
desc =>
|
||||
?T("Database backend to use for routing information. "
|
||||
"The default value is picked from 'default_ram_db' option, or "
|
||||
@@ -1182,7 +1182,7 @@ doc() ->
|
||||
?T("Same as 'cache_size', but applied to client sessions table cache "
|
||||
"only. If not set, the value from 'cache_size' will be used.")}},
|
||||
{sm_db_type,
|
||||
#{value => "mnesia | sql | redis",
|
||||
#{value => "mnesia | redis | sql",
|
||||
desc =>
|
||||
?T("Database backend to use for client sessions information. "
|
||||
"The default value is picked from 'default_ram_db' option, or "
|
||||
@@ -1193,7 +1193,7 @@ doc() ->
|
||||
?T("Same as 'use_cache', but applied to client sessions table cache "
|
||||
"only. If not set, the value from 'use_cache' will be used.")}},
|
||||
{sql_type,
|
||||
#{value => "mysql | pgsql | sqlite | mssql | odbc",
|
||||
#{value => "mssql | mysql | odbc | pgsql | sqlite",
|
||||
desc =>
|
||||
?T("The type of an SQL connection. The default is 'odbc'.")}},
|
||||
{sql_connect_timeout,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 4 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 6 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
+6
-45
@@ -1,7 +1,7 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_regexp.erl
|
||||
%%% Author : Badlop
|
||||
%%% Purpose : Frontend to Re and Regexp OTP modules
|
||||
%%% Purpose : Frontend to Re OTP module
|
||||
%%% Created : 8 Dec 2011 by Badlop
|
||||
%%%
|
||||
%%%
|
||||
@@ -25,66 +25,27 @@
|
||||
|
||||
-module(ejabberd_regexp).
|
||||
|
||||
-export([exec/2, run/2, split/2, replace/3, greplace/3, sh_to_awk/1]).
|
||||
|
||||
exec({ReM, ReF, ReA}, {RgM, RgF, RgA}) ->
|
||||
try apply(ReM, ReF, ReA) catch
|
||||
error:undef -> apply(RgM, RgF, RgA);
|
||||
A:B -> {error, {A, B}}
|
||||
end.
|
||||
-export([run/2, split/2, replace/3, greplace/3, sh_to_awk/1]).
|
||||
|
||||
-spec run(binary(), binary()) -> match | nomatch | {error, any()}.
|
||||
|
||||
run(String, Regexp) ->
|
||||
case exec({re, run, [String, Regexp, [{capture, none}, unicode]]},
|
||||
{regexp, first_match, [binary_to_list(String),
|
||||
binary_to_list(Regexp)]})
|
||||
of
|
||||
{match, _, _} -> match;
|
||||
{match, _} -> match;
|
||||
match -> match;
|
||||
nomatch -> nomatch;
|
||||
{error, Error} -> {error, Error}
|
||||
end.
|
||||
re:run(String, Regexp, [{capture, none}, unicode]).
|
||||
|
||||
-spec split(binary(), binary()) -> [binary()].
|
||||
|
||||
split(String, Regexp) ->
|
||||
case exec({re, split, [String, Regexp, [{return, binary}]]},
|
||||
{regexp, split, [binary_to_list(String),
|
||||
binary_to_list(Regexp)]})
|
||||
of
|
||||
{ok, FieldList} -> [iolist_to_binary(F) || F <- FieldList];
|
||||
{error, Error} -> throw(Error);
|
||||
A -> A
|
||||
end.
|
||||
re:split(String, Regexp, [{return, binary}]).
|
||||
|
||||
-spec replace(binary(), binary(), binary()) -> binary().
|
||||
|
||||
replace(String, Regexp, New) ->
|
||||
case exec({re, replace, [String, Regexp, New, [{return, binary}]]},
|
||||
{regexp, sub, [binary_to_list(String),
|
||||
binary_to_list(Regexp),
|
||||
binary_to_list(New)]})
|
||||
of
|
||||
{ok, NewString, _RepCount} -> iolist_to_binary(NewString);
|
||||
{error, Error} -> throw(Error);
|
||||
A -> A
|
||||
end.
|
||||
re:replace(String, Regexp, New, [{return, binary}]).
|
||||
|
||||
-spec greplace(binary(), binary(), binary()) -> binary().
|
||||
|
||||
greplace(String, Regexp, New) ->
|
||||
case exec({re, replace, [String, Regexp, New, [global, {return, binary}]]},
|
||||
{regexp, sub, [binary_to_list(String),
|
||||
binary_to_list(Regexp),
|
||||
binary_to_list(New)]})
|
||||
of
|
||||
{ok, NewString, _RepCount} -> iolist_to_binary(NewString);
|
||||
{error, Error} -> throw(Error);
|
||||
A -> A
|
||||
end.
|
||||
|
||||
re:replace(String, Regexp, New, [global, {return, binary}]).
|
||||
|
||||
%% This code was copied and adapted from xmerl_regexp.erl
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
@@ -351,4 +351,4 @@ listen_options() ->
|
||||
{tls, false},
|
||||
{tls_compression, false},
|
||||
{max_stanza_size, infinity},
|
||||
{max_fsm_queue, 5000}].
|
||||
{max_fsm_queue, 10000}].
|
||||
|
||||
@@ -302,7 +302,7 @@ listen_options() ->
|
||||
{tls, false},
|
||||
{tls_compression, false},
|
||||
{max_stanza_size, infinity},
|
||||
{max_fsm_queue, 5000},
|
||||
{max_fsm_queue, 10000},
|
||||
{password, undefined},
|
||||
{hosts, []},
|
||||
{check_from, true},
|
||||
|
||||
+51
-11
@@ -50,16 +50,22 @@ start_link(_, _, _) ->
|
||||
get_password/2]).
|
||||
|
||||
-include("logger.hrl").
|
||||
-ifndef(LAGER).
|
||||
-export([stun_filter/2]).
|
||||
-define(STUN_MAX_LOG_LEVEL, notice). % Drop STUN/TURN info/debug messages.
|
||||
-endif.
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
tcp_init(Socket, Opts) ->
|
||||
init_logger(),
|
||||
ejabberd:start_app(stun),
|
||||
stun:tcp_init(Socket, prepare_turn_opts(Opts)).
|
||||
|
||||
-dialyzer({nowarn_function, udp_init/2}).
|
||||
udp_init(Socket, Opts) ->
|
||||
init_logger(),
|
||||
ejabberd:start_app(stun),
|
||||
stun:udp_init(Socket, prepare_turn_opts(Opts)).
|
||||
|
||||
@@ -101,20 +107,20 @@ prepare_turn_opts(Opts, _UseTurn = false) ->
|
||||
set_certfile(Opts);
|
||||
prepare_turn_opts(Opts, _UseTurn = true) ->
|
||||
NumberOfMyHosts = length(ejabberd_option:hosts()),
|
||||
TurnIP = case proplists:get_value(turn_ip, Opts) of
|
||||
TurnIP = case proplists:get_value(turn_ipv4_address, Opts) of
|
||||
undefined ->
|
||||
MyIP = misc:get_my_ip(),
|
||||
MyIP = misc:get_my_ipv4_address(),
|
||||
case MyIP of
|
||||
{127, _, _, _} ->
|
||||
?WARNING_MSG("Option 'turn_ip' is undefined and "
|
||||
"the server's hostname doesn't "
|
||||
"resolve to a public IPv4 address, "
|
||||
"most likely the TURN relay won't be "
|
||||
"working properly", []);
|
||||
?WARNING_MSG("Option 'turn_ipv4_address' is "
|
||||
"undefined and the server's hostname "
|
||||
"doesn't resolve to a public IPv4 "
|
||||
"address, most likely the TURN relay "
|
||||
"won't be working properly", []);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
[{turn_ip, MyIP}];
|
||||
[{turn_ipv4_address, MyIP}];
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
@@ -160,9 +166,11 @@ set_certfile(Opts) ->
|
||||
listen_opt_type(use_turn) ->
|
||||
econf:bool();
|
||||
listen_opt_type(ip) ->
|
||||
econf:ip();
|
||||
listen_opt_type(turn_ipv4_address) ->
|
||||
econf:ipv4();
|
||||
listen_opt_type(turn_ip) ->
|
||||
econf:ipv4();
|
||||
listen_opt_type(turn_ipv6_address) ->
|
||||
econf:ipv6();
|
||||
listen_opt_type(auth_type) ->
|
||||
econf:enum([anonymous, user]);
|
||||
listen_opt_type(auth_realm) ->
|
||||
@@ -175,6 +183,8 @@ listen_opt_type(turn_max_allocations) ->
|
||||
econf:pos_int(infinity);
|
||||
listen_opt_type(turn_max_permissions) ->
|
||||
econf:pos_int(infinity);
|
||||
listen_opt_type(turn_blacklist) ->
|
||||
econf:list_or_single(econf:ip_mask());
|
||||
listen_opt_type(server_name) ->
|
||||
econf:binary();
|
||||
listen_opt_type(certfile) ->
|
||||
@@ -183,7 +193,8 @@ listen_opt_type(certfile) ->
|
||||
listen_options() ->
|
||||
[{shaper, none},
|
||||
{use_turn, false},
|
||||
{turn_ip, undefined},
|
||||
{turn_ipv4_address, undefined},
|
||||
{turn_ipv6_address, undefined},
|
||||
{auth_type, user},
|
||||
{auth_realm, undefined},
|
||||
{tls, false},
|
||||
@@ -192,5 +203,34 @@ listen_options() ->
|
||||
{turn_max_port, 65535},
|
||||
{turn_max_allocations, 10},
|
||||
{turn_max_permissions, 10},
|
||||
{turn_blacklist, [<<"2001::/32">>, <<"2002::/16">>]}, % Teredo, 6to4.
|
||||
{server_name, <<"ejabberd">>}].
|
||||
|
||||
-spec init_logger() -> ok.
|
||||
-ifdef(LAGER).
|
||||
init_logger() ->
|
||||
ok.
|
||||
-else.
|
||||
init_logger() ->
|
||||
case logger:add_primary_filter(stun, {fun ?MODULE:stun_filter/2,
|
||||
?STUN_MAX_LOG_LEVEL}) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, {already_exist, _}} ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec stun_filter(logger:log_event(), logger:level() | term())
|
||||
-> logger:filter_return().
|
||||
stun_filter(#{meta := #{domain := [stun | _]}, level := Level}, MaxLevel) ->
|
||||
case logger:compare_levels(Level, MaxLevel) of
|
||||
lt ->
|
||||
stop;
|
||||
_ ->
|
||||
ignore
|
||||
end;
|
||||
stun_filter(Event, _Extra) ->
|
||||
Event.
|
||||
-endif.
|
||||
|
||||
-endif.
|
||||
|
||||
@@ -283,7 +283,7 @@ get_auth_account2(HostOfRule, AccessRule, User, Server,
|
||||
make_xhtml(Els, Host, Lang, JID, Level) ->
|
||||
make_xhtml(Els, Host, cluster, Lang, JID, Level).
|
||||
|
||||
%% @spec (Els, Host, Node, Lang, JID) -> {200, [html], xmlelement()}
|
||||
%% @spec (Els, Host, Node, Lang, JID, Level::integer()) -> {200, [html], xmlelement()}
|
||||
%% where Host = global | string()
|
||||
%% Node = cluster | atom()
|
||||
%% JID = jid()
|
||||
@@ -340,6 +340,7 @@ make_xhtml(Els, Host, Node, Lang, JID, Level) ->
|
||||
[?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}],
|
||||
[?XE(<<"p">>,
|
||||
[?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>),
|
||||
?C(<<" ">>), ?C(ejabberd_option:version()),
|
||||
?C(<<" (c) 2002-2020 ">>),
|
||||
?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)]
|
||||
)])])])]}}.
|
||||
@@ -1742,12 +1743,12 @@ pretty_string_int(String) when is_binary(String) ->
|
||||
%%%==================================
|
||||
%%%% navigation menu
|
||||
|
||||
%% @spec (Host, Node, Lang, JID::jid()) -> [LI]
|
||||
%% @spec (Host, Node, Lang, JID::jid(), Level::integer()) -> [LI]
|
||||
make_navigation(Host, Node, Lang, JID, Level) ->
|
||||
Menu = make_navigation_menu(Host, Node, Lang, JID, Level),
|
||||
make_menu_items(Lang, Menu).
|
||||
|
||||
%% @spec (Host, Node, Lang, JID::jid()) -> Menu
|
||||
%% @spec (Host, Node, Lang, JID::jid(), Level::integer()) -> Menu
|
||||
%% where Host = global | string()
|
||||
%% Node = cluster | string()
|
||||
%% Lang = string()
|
||||
|
||||
+15
-14
@@ -42,8 +42,7 @@
|
||||
-include("xmpp.hrl").
|
||||
|
||||
-record(state,
|
||||
{access_commands = [] :: list(),
|
||||
auth = noauth :: noauth | map(),
|
||||
{auth = noauth :: noauth | map(),
|
||||
get_auth = true :: boolean(),
|
||||
ip :: inet:ip_address()}).
|
||||
|
||||
@@ -66,10 +65,9 @@ accept(Pid) ->
|
||||
%% HTTP interface
|
||||
%% -----------------------------
|
||||
|
||||
process(_, #request{method = 'POST', data = Data, opts = Opts, ip = {IP, _}}) ->
|
||||
AccessCommands = proplists:get_value(access_commands, Opts, []),
|
||||
process(_, #request{method = 'POST', data = Data, ip = {IP, _}}) ->
|
||||
GetAuth = true,
|
||||
State = #state{access_commands = AccessCommands, get_auth = GetAuth, ip = IP},
|
||||
State = #state{get_auth = GetAuth, ip = IP},
|
||||
case fxml_stream:parse_element(Data) of
|
||||
{error, _} ->
|
||||
{400, [],
|
||||
@@ -190,8 +188,7 @@ handler(State, {call, Command, []}) ->
|
||||
handler(State,
|
||||
{call, Command, [{struct, AttrL}]}) ->
|
||||
{ArgsF, ArgsR, ResultF} = ejabberd_commands:get_command_format(Command, State#state.auth),
|
||||
try_do_command(State#state.access_commands,
|
||||
State#state.auth, Command, AttrL, ArgsF, ArgsR, ResultF);
|
||||
try_do_command(State#state.auth, Command, AttrL, ArgsF, ArgsR, ResultF);
|
||||
handler(_State, Payload) ->
|
||||
build_fault_response(-112, "Unknown call: ~p",
|
||||
[Payload]).
|
||||
@@ -200,10 +197,8 @@ handler(_State, Payload) ->
|
||||
%% Command
|
||||
%% -----------------------------
|
||||
|
||||
try_do_command(AccessCommands, Auth, Command, AttrL,
|
||||
ArgsF, ArgsR, ResultF) ->
|
||||
try do_command(AccessCommands, Auth, Command, AttrL,
|
||||
ArgsF, ArgsR, ResultF)
|
||||
try_do_command(Auth, Command, AttrL, ArgsF, ArgsR, ResultF) ->
|
||||
try do_command(Auth, Command, AttrL, ArgsF, ArgsR, ResultF)
|
||||
of
|
||||
{command_result, ResultFormatted} ->
|
||||
{false, {response, [ResultFormatted]}}
|
||||
@@ -238,11 +233,10 @@ build_fault_response(Code, ParseString, ParseArgs) ->
|
||||
?WARNING_MSG(FaultString, []),
|
||||
{false, {response, {fault, Code, list_to_binary(FaultString)}}}.
|
||||
|
||||
do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ArgsR,
|
||||
do_command(Auth, Command, AttrL, ArgsF, ArgsR,
|
||||
ResultF) ->
|
||||
ArgsFormatted = format_args(rename_old_args(AttrL, ArgsR), ArgsF),
|
||||
Auth2 = Auth#{extra_permissions => AccessCommands},
|
||||
Result = ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth2),
|
||||
Result = ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth),
|
||||
ResultFormatted = format_result(Result, ResultF),
|
||||
{command_result, ResultFormatted}.
|
||||
|
||||
@@ -401,4 +395,11 @@ make_status(error) -> 1;
|
||||
make_status(_) -> 1.
|
||||
|
||||
listen_options() ->
|
||||
?WARNING_MSG("It is deprecated defining ejabberd_xmlrpc as a listen module "
|
||||
"in the ejabberd configuration. Support for that configuration"
|
||||
" method may be removed in a future ejabberd release. You are "
|
||||
"encouraged to define ejabberd_xmlrpc inside request_handlers "
|
||||
"option of ejabberd_http listen module. See the ejabberd "
|
||||
"documentation for details: https://docs.ejabberd.im/admin/"
|
||||
"configuration/listen/#ejabberd-xmlrpc", []),
|
||||
[].
|
||||
|
||||
+21
-3
@@ -33,6 +33,24 @@
|
||||
|
||||
-include("logger.hrl").
|
||||
|
||||
-ifdef(USE_OLD_PG2).
|
||||
pg_create(PoolName) -> pg2:create(PoolName).
|
||||
pg_join(PoolName, Pid) -> pg2:join(PoolName, Pid).
|
||||
pg_get_closest_pid(Name) -> pg2:get_closest_pid(Name).
|
||||
-else.
|
||||
pg_create(_) -> pg:start_link().
|
||||
pg_join(PoolName, Pid) -> pg:join(PoolName, Pid).
|
||||
pg_get_closest_pid(Group) ->
|
||||
case pg:get_local_members(Group) of
|
||||
[] ->
|
||||
case pg:get_members(Group) of
|
||||
[] -> {error, {no_process, Group}};
|
||||
[Pid | _] -> Pid
|
||||
end;
|
||||
[Pid | _] -> Pid
|
||||
end.
|
||||
-endif.
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
@@ -48,14 +66,14 @@ modify_passwd(PoolName, DN, Passwd) ->
|
||||
start_link(Name, Hosts, Backups, Port, Rootdn, Passwd,
|
||||
Opts) ->
|
||||
PoolName = make_id(Name),
|
||||
pg2:create(PoolName),
|
||||
pg_create(PoolName),
|
||||
lists:foreach(fun (Host) ->
|
||||
ID = list_to_binary(erlang:ref_to_list(make_ref())),
|
||||
case catch eldap:start_link(ID, [Host | Backups],
|
||||
Port, Rootdn, Passwd,
|
||||
Opts)
|
||||
of
|
||||
{ok, Pid} -> pg2:join(PoolName, Pid);
|
||||
{ok, Pid} -> pg_join(PoolName, Pid);
|
||||
Err ->
|
||||
?ERROR_MSG("Err = ~p", [Err]),
|
||||
error
|
||||
@@ -67,7 +85,7 @@ start_link(Name, Hosts, Backups, Port, Rootdn, Passwd,
|
||||
%% Internal functions
|
||||
%%====================================================================
|
||||
do_request(Name, {F, Args}) ->
|
||||
case pg2:get_closest_pid(make_id(Name)) of
|
||||
case pg_get_closest_pid(make_id(Name)) of
|
||||
Pid when is_pid(Pid) ->
|
||||
case catch apply(eldap, F, [Pid | Args]) of
|
||||
{'EXIT', {timeout, _}} ->
|
||||
|
||||
+43
-29
@@ -37,11 +37,12 @@
|
||||
now_to_usec/1, usec_to_now/1, encode_pid/1, decode_pid/2,
|
||||
compile_exprs/2, join_atoms/2, try_read_file/1, get_descr/2,
|
||||
css_dir/0, img_dir/0, js_dir/0, msgs_dir/0, sql_dir/0, lua_dir/0,
|
||||
read_css/1, read_img/1, read_js/1, read_lua/1, try_url/1,
|
||||
read_css/1, read_img/1, read_js/1, read_lua/1,
|
||||
intersection/2, format_val/1, cancel_timer/1, unique_timestamp/0,
|
||||
is_mucsub_message/1, best_match/2, pmap/2, peach/2, format_exception/4,
|
||||
get_my_ip/0, parse_ip_mask/1, match_ip_mask/3, format_hosts_list/1,
|
||||
format_cycle/1, delete_dir/1]).
|
||||
get_my_ipv4_address/0, get_my_ipv6_address/0, parse_ip_mask/1,
|
||||
crypto_hmac/3, crypto_hmac/4, uri_parse/1,
|
||||
match_ip_mask/3, format_hosts_list/1, format_cycle/1, delete_dir/1]).
|
||||
|
||||
%% Deprecated functions
|
||||
-export([decode_base64/1, encode_base64/1]).
|
||||
@@ -54,6 +55,34 @@
|
||||
|
||||
-type distance_cache() :: #{{string(), string()} => non_neg_integer()}.
|
||||
|
||||
-ifdef(USE_OLD_HTTP_URI).
|
||||
uri_parse(URL) when is_binary(URL) ->
|
||||
uri_parse(binary_to_list(URL));
|
||||
uri_parse(URL) ->
|
||||
{ok, {Scheme, _UserInfo, Host, Port, Path, _Query}} = http_uri:parse(URL),
|
||||
{ok, Scheme, Host, Port, Path}.
|
||||
-else.
|
||||
uri_parse(URL) when is_binary(URL) ->
|
||||
uri_parse(binary_to_list(URL));
|
||||
uri_parse(URL) ->
|
||||
case uri_string:parse(URL) of
|
||||
#{scheme := Scheme, host := Host, port := Port, path := Path} ->
|
||||
{ok, Scheme, Host, Port, Path};
|
||||
#{scheme := "https", host := Host, path := Path} ->
|
||||
{ok, "https", Host, 443, Path};
|
||||
#{scheme := "http", host := Host, path := Path} ->
|
||||
{ok, "http", Host, 80, Path}
|
||||
end.
|
||||
-endif.
|
||||
|
||||
-ifdef(USE_OLD_CRYPTO_HMAC).
|
||||
crypto_hmac(Type, Key, Data) -> crypto:hmac(Type, Key, Data).
|
||||
crypto_hmac(Type, Key, Data, MacL) -> crypto:hmac(Type, Key, Data, MacL).
|
||||
-else.
|
||||
crypto_hmac(Type, Key, Data) -> crypto:mac(hmac, Type, Key, Data).
|
||||
crypto_hmac(Type, Key, Data, MacL) -> crypto:macN(hmac, Type, Key, Data, MacL).
|
||||
-endif.
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
@@ -306,7 +335,7 @@ join_atoms(Atoms, Sep) ->
|
||||
str:join([io_lib:format("~p", [A]) || A <- lists:sort(Atoms)], Sep).
|
||||
|
||||
%% @doc Checks if the file is readable and converts its name to binary.
|
||||
%% Fails with `badarg` otherwise. The function is intended for usage
|
||||
%% Fails with `badarg' otherwise. The function is intended for usage
|
||||
%% in configuration validators only.
|
||||
-spec try_read_file(file:filename_all()) -> binary().
|
||||
try_read_file(Path) ->
|
||||
@@ -319,29 +348,6 @@ try_read_file(Path) ->
|
||||
erlang:error(badarg)
|
||||
end.
|
||||
|
||||
%% @doc Checks if the URL is valid HTTP(S) URL and converts its name to binary.
|
||||
%% Fails with `badarg` otherwise. The function is intended for usage
|
||||
%% in configuration validators only.
|
||||
-spec try_url(binary() | string()) -> binary().
|
||||
try_url(URL0) ->
|
||||
URL = case URL0 of
|
||||
V when is_binary(V) -> binary_to_list(V);
|
||||
_ -> URL0
|
||||
end,
|
||||
case http_uri:parse(URL) of
|
||||
{ok, {Scheme, _, _, _, _, _}} when Scheme /= http, Scheme /= https ->
|
||||
?ERROR_MSG("Unsupported URI scheme: ~ts", [URL]),
|
||||
erlang:error(badarg);
|
||||
{ok, {_, _, Host, _, _, _}} when Host == ""; Host == <<"">> ->
|
||||
?ERROR_MSG("Invalid URL: ~ts", [URL]),
|
||||
erlang:error(badarg);
|
||||
{ok, _} ->
|
||||
iolist_to_binary(URL);
|
||||
{error, _} ->
|
||||
?ERROR_MSG("Invalid URL: ~ts", [URL]),
|
||||
erlang:error(badarg)
|
||||
end.
|
||||
|
||||
-spec css_dir() -> file:filename().
|
||||
css_dir() ->
|
||||
get_dir("css").
|
||||
@@ -509,14 +515,22 @@ format_exception(Level, Class, Reason, Stacktrace) ->
|
||||
end).
|
||||
-endif.
|
||||
|
||||
-spec get_my_ip() -> inet:ip_address().
|
||||
get_my_ip() ->
|
||||
-spec get_my_ipv4_address() -> inet:ip4_address().
|
||||
get_my_ipv4_address() ->
|
||||
{ok, MyHostName} = inet:gethostname(),
|
||||
case inet:getaddr(MyHostName, inet) of
|
||||
{ok, Addr} -> Addr;
|
||||
{error, _} -> {127, 0, 0, 1}
|
||||
end.
|
||||
|
||||
-spec get_my_ipv6_address() -> inet:ip6_address().
|
||||
get_my_ipv6_address() ->
|
||||
{ok, MyHostName} = inet:gethostname(),
|
||||
case inet:getaddr(MyHostName, inet6) of
|
||||
{ok, Addr} -> Addr;
|
||||
{error, _} -> {0, 0, 0, 0, 0, 0, 0, 1}
|
||||
end.
|
||||
|
||||
-spec parse_ip_mask(binary()) -> {ok, {inet:ip4_address(), 0..32}} |
|
||||
{ok, {inet:ip6_address(), 0..128}} |
|
||||
error.
|
||||
|
||||
+26
-26
@@ -113,26 +113,26 @@ depends(_Host, _Opts) ->
|
||||
%%%
|
||||
|
||||
get_commands_spec() ->
|
||||
Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n"
|
||||
" FN - Full Name\n"
|
||||
" NICKNAME - Nickname\n"
|
||||
" BDAY - Birthday\n"
|
||||
" TITLE - Work: Position\n"
|
||||
" ROLE - Work: Role",
|
||||
Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n\n"
|
||||
"* FN - Full Name\n"
|
||||
"* NICKNAME - Nickname\n"
|
||||
"* BDAY - Birthday\n"
|
||||
"* TITLE - Work: Position\n"
|
||||
"* ROLE - Work: Role\n",
|
||||
|
||||
Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n"
|
||||
" N FAMILY - Family name\n"
|
||||
" N GIVEN - Given name\n"
|
||||
" N MIDDLE - Middle name\n"
|
||||
" ADR CTRY - Address: Country\n"
|
||||
" ADR LOCALITY - Address: City\n"
|
||||
" TEL HOME - Telephone: Home\n"
|
||||
" TEL CELL - Telephone: Cellphone\n"
|
||||
" TEL WORK - Telephone: Work\n"
|
||||
" TEL VOICE - Telephone: Voice\n"
|
||||
" EMAIL USERID - E-Mail Address\n"
|
||||
" ORG ORGNAME - Work: Company\n"
|
||||
" ORG ORGUNIT - Work: Department",
|
||||
Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n\n"
|
||||
"* N FAMILY - Family name\n"
|
||||
"* N GIVEN - Given name\n"
|
||||
"* N MIDDLE - Middle name\n"
|
||||
"* ADR CTRY - Address: Country\n"
|
||||
"* ADR LOCALITY - Address: City\n"
|
||||
"* TEL HOME - Telephone: Home\n"
|
||||
"* TEL CELL - Telephone: Cellphone\n"
|
||||
"* TEL WORK - Telephone: Work\n"
|
||||
"* TEL VOICE - Telephone: Voice\n"
|
||||
"* EMAIL USERID - E-Mail Address\n"
|
||||
"* ORG ORGNAME - Work: Company\n"
|
||||
"* ORG ORGUNIT - Work: Department\n",
|
||||
|
||||
VcardXEP = "For a full list of vCard fields check XEP-0054: vcard-temp at "
|
||||
"http://www.xmpp.org/extensions/xep-0054.html",
|
||||
@@ -435,7 +435,7 @@ get_commands_spec() ->
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = get_vcard, tags = [vcard],
|
||||
desc = "Get content from a vCard field",
|
||||
longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
|
||||
longdesc = Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = get_vcard,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}],
|
||||
args_example = [<<"user1">>,<<"myserver.com">>,<<"NICKNAME">>],
|
||||
@@ -445,7 +445,7 @@ get_commands_spec() ->
|
||||
result = {content, string}},
|
||||
#ejabberd_commands{name = get_vcard2, tags = [vcard],
|
||||
desc = "Get content from a vCard subfield",
|
||||
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = get_vcard,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
|
||||
args_example = [<<"user1">>,<<"myserver.com">>,<<"N">>, <<"FAMILY">>],
|
||||
@@ -455,14 +455,14 @@ get_commands_spec() ->
|
||||
result = {content, string}},
|
||||
#ejabberd_commands{name = get_vcard2_multi, tags = [vcard],
|
||||
desc = "Get multiple contents from a vCard field",
|
||||
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = get_vcard_multi,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
|
||||
result = {contents, {list, {value, string}}}},
|
||||
|
||||
#ejabberd_commands{name = set_vcard, tags = [vcard],
|
||||
desc = "Set content in a vCard field",
|
||||
longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
|
||||
longdesc = Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = set_vcard,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}, {content, binary}],
|
||||
args_example = [<<"user1">>,<<"myserver.com">>, <<"URL">>, <<"www.example.com">>],
|
||||
@@ -470,7 +470,7 @@ get_commands_spec() ->
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = set_vcard2, tags = [vcard],
|
||||
desc = "Set content in a vCard subfield",
|
||||
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = set_vcard,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {content, binary}],
|
||||
args_example = [<<"user1">>,<<"myserver.com">>,<<"TEL">>, <<"NUMBER">>, <<"123456">>],
|
||||
@@ -478,7 +478,7 @@ get_commands_spec() ->
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = set_vcard2_multi, tags = [vcard],
|
||||
desc = "Set multiple contents in a vCard subfield",
|
||||
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
|
||||
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
|
||||
module = ?MODULE, function = set_vcard,
|
||||
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, {value, binary}}}],
|
||||
result = {res, rescode}},
|
||||
@@ -1605,7 +1605,7 @@ mod_doc() ->
|
||||
"administrator changes their password again. It is possible to "
|
||||
"define the reason of the ban. The new password also includes "
|
||||
"the reason and the date and time of the ban. See an example below."),
|
||||
?T("- 'pushroster' (and 'pushroster-all'):"),
|
||||
?T("- 'pushroster': (and 'pushroster-all')"),
|
||||
?T("The roster file must be placed, if using Windows, on the "
|
||||
"directory where you installed ejabberd: "
|
||||
"C:/Program Files/ejabberd or similar. If you use other "
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 13 Sep 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
+14
-1
@@ -260,7 +260,20 @@ mod_doc() ->
|
||||
{cache_life_time,
|
||||
#{value => "timeout()",
|
||||
desc =>
|
||||
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}]}.
|
||||
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}],
|
||||
example =>
|
||||
["listen:",
|
||||
" -",
|
||||
" port: 5222",
|
||||
" module: ejabberd_c2s",
|
||||
" -",
|
||||
" port: 5443",
|
||||
" module: ejabberd_http",
|
||||
" request_handlers:",
|
||||
" /bosh: mod_bosh",
|
||||
"",
|
||||
"modules:",
|
||||
" mod_bosh: {}"]}.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Cache stuff
|
||||
|
||||
@@ -711,8 +711,8 @@ get_proc_name(ServerHost, ModuleName) ->
|
||||
-spec get_proc_name(binary(), atom(), binary()) -> atom().
|
||||
get_proc_name(ServerHost, ModuleName, PutURL) ->
|
||||
%% Once we depend on OTP >= 20.0, we can use binaries with http_uri.
|
||||
{ok, {_Scheme, _UserInfo, Host0, _Port, Path0, _Query}} =
|
||||
http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))),
|
||||
{ok, _Scheme, Host0, _Port, Path0} =
|
||||
misc:uri_parse(expand_host(PutURL, ServerHost)),
|
||||
Host = jid:nameprep(iolist_to_binary(Host0)),
|
||||
Path = str:strip(iolist_to_binary(Path0), right, $/),
|
||||
ProcPrefix = <<Host/binary, Path/binary>>,
|
||||
@@ -934,7 +934,7 @@ make_query_string(Slot, Size, #state{external_secret = Key}) when Key /= <<>> ->
|
||||
UrlPath = str:join(Slot, <<$/>>),
|
||||
SizeStr = integer_to_binary(Size),
|
||||
Data = <<UrlPath/binary, " ", SizeStr/binary>>,
|
||||
HMAC = str:to_hexlist(crypto:hmac(sha256, Key, Data)),
|
||||
HMAC = str:to_hexlist(misc:crypto_hmac(sha256, Key, Data)),
|
||||
<<"?v=", HMAC/binary>>;
|
||||
make_query_string(_Slot, _Size, _State) ->
|
||||
<<>>.
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ notify_participant_left(Mod, LServer, To, ID) ->
|
||||
-spec make_id(jid(), binary()) -> binary().
|
||||
make_id(JID, Key) ->
|
||||
Data = jid:encode(jid:tolower(jid:remove_resource(JID))),
|
||||
xmpp_util:hex(crypto:hmac(sha256, Data, Key, 10)).
|
||||
xmpp_util:hex(misc:crypto_hmac(sha256, Data, Key, 10)).
|
||||
|
||||
%%%===================================================================
|
||||
%%% Error generators
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ listen_opt_type(max_payload_size) ->
|
||||
econf:pos_int(infinity).
|
||||
|
||||
listen_options() ->
|
||||
[{max_fsm_queue, 5000},
|
||||
[{max_fsm_queue, 10000},
|
||||
{max_payload_size, infinity},
|
||||
{tls, false},
|
||||
{tls_verify, false}].
|
||||
|
||||
@@ -494,8 +494,8 @@ get_sort_query(Q) ->
|
||||
end.
|
||||
|
||||
get_sort_query2(Q) ->
|
||||
{value, {_, String}} = lists:keysearch(<<"sort">>, 1, Q),
|
||||
Integer = binary_to_integer(String),
|
||||
{value, {_, Binary}} = lists:keysearch(<<"sort">>, 1, Q),
|
||||
Integer = list_to_integer(string:strip(binary_to_list(Binary), right, $/)),
|
||||
case Integer >= 0 of
|
||||
true -> {ok, {normal, Integer}};
|
||||
false -> {ok, {reverse, abs(Integer)}}
|
||||
@@ -627,9 +627,10 @@ justcreated_to_binary(J) when is_atom(J) ->
|
||||
create_room(Name1, Host1, ServerHost) ->
|
||||
create_room_with_opts(Name1, Host1, ServerHost, []).
|
||||
|
||||
create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) ->
|
||||
create_room_with_opts(Name1, Host1, ServerHost1, CustomRoomOpts) ->
|
||||
true = (error /= (Name = jid:nodeprep(Name1))),
|
||||
true = (error /= (Host = jid:nodeprep(Host1))),
|
||||
true = (error /= (ServerHost = jid:nodeprep(ServerHost1))),
|
||||
|
||||
%% Get the default room options from the muc configuration
|
||||
DefRoomOpts = mod_muc_opt:default_room_options(ServerHost),
|
||||
@@ -988,7 +989,7 @@ send_direct_invitation(FromJid, UserJid, Msg) ->
|
||||
%% the option to change (for example title or max_users),
|
||||
%% and the value to assign to the new option.
|
||||
%% For example:
|
||||
%% change_room_option(<<"testroom">>, <<"conference.localhost">>, <<"title">>, <<"Test Room">>)
|
||||
%% `change_room_option(<<"testroom">>, <<"conference.localhost">>, <<"title">>, <<"Test Room">>)'
|
||||
change_room_option(Name, Service, OptionString, ValueString) ->
|
||||
case get_room_pid(Name, Service) of
|
||||
room_not_found ->
|
||||
|
||||
+5
-2
@@ -92,7 +92,7 @@ check_access_log(Host, From) ->
|
||||
|
||||
-spec get_url(#state{}) -> {ok, binary()} | error.
|
||||
get_url(#state{room = Room, host = Host, server_host = ServerHost}) ->
|
||||
case mod_muc_log_opt:url(ServerHost) of
|
||||
try mod_muc_log_opt:url(ServerHost) of
|
||||
undefined -> error;
|
||||
URL ->
|
||||
case mod_muc_log_opt:dirname(ServerHost) of
|
||||
@@ -101,6 +101,9 @@ get_url(#state{room = Room, host = Host, server_host = ServerHost}) ->
|
||||
room_name ->
|
||||
{ok, <<URL/binary, $/, Room/binary>>}
|
||||
end
|
||||
catch
|
||||
error:{module_not_loaded, _, _} ->
|
||||
error
|
||||
end.
|
||||
|
||||
depends(_Host, _Opts) ->
|
||||
@@ -485,7 +488,7 @@ get_dateweek(Date, Lang) ->
|
||||
11 -> tr(Lang, ?T("November"));
|
||||
12 -> tr(Lang, ?T("December"))
|
||||
end,
|
||||
list_to_binary(
|
||||
unicode:characters_to_binary(
|
||||
case Lang of
|
||||
<<"en">> ->
|
||||
io_lib:format("~ts, ~ts ~w, ~w", [Weekday, Month, D, Y]);
|
||||
|
||||
@@ -935,7 +935,8 @@ process_groupchat_message(#message{from = From, lang = Lang} = Packet, StateData
|
||||
of
|
||||
true ->
|
||||
{FromNick, Role} = get_participant_data(From, StateData),
|
||||
if (Role == moderator) or (Role == participant) or IsSubscriber or
|
||||
if (Role == moderator) or (Role == participant) or
|
||||
(IsSubscriber andalso ((StateData#state.config)#config.members_by_default == true)) or
|
||||
((StateData#state.config)#config.moderated == false) ->
|
||||
Subject = check_subject(Packet),
|
||||
{NewStateData1, IsAllowed} = case Subject of
|
||||
|
||||
@@ -1188,19 +1188,19 @@ mod_doc() ->
|
||||
desc =>
|
||||
[?T("Specify a list of custom limits which override the "
|
||||
"default ones defined in XEP-0033. Limits are defined "
|
||||
"per sender type and stanza type, where:"),
|
||||
?T("- The sender type can be: 'local' or 'remote'."), "",
|
||||
?T("- The stanza type can be: 'message' or 'presence'."), "",
|
||||
?T("- The number can be a positive integer or the key word 'infinite'.")],
|
||||
"per sender type and stanza type, where:"), "",
|
||||
?T("- 'sender' can be: 'local' or 'remote'."),
|
||||
?T("- 'stanza' can be: 'message' or 'presence'."),
|
||||
?T("- 'number' can be a positive integer or 'infinite'.")],
|
||||
example =>
|
||||
[{?T("Default values:"),
|
||||
["local:",
|
||||
["# Default values:",
|
||||
"local:",
|
||||
" message: 100",
|
||||
" presence: 100",
|
||||
"remote:",
|
||||
" message: 20",
|
||||
" presence: 20"]}
|
||||
]}},
|
||||
" presence: 20"]
|
||||
}},
|
||||
{name,
|
||||
#{desc => ?T("Service name to provide in the Info query to the "
|
||||
"Service Discovery. Default is '\"Multicast\"'.")}},
|
||||
|
||||
+8
-1
@@ -184,7 +184,14 @@ user_online(_SID, JID, _Info) ->
|
||||
|
||||
-spec user_offline(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok.
|
||||
user_offline(_SID, JID, _Info) ->
|
||||
stop_ping(JID#jid.lserver, JID).
|
||||
case ejabberd_sm:get_session_pid(JID#jid.luser,
|
||||
JID#jid.lserver,
|
||||
JID#jid.lresource) of
|
||||
none ->
|
||||
stop_ping(JID#jid.lserver, JID);
|
||||
_ ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec user_send({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}.
|
||||
user_send({Packet, #{jid := JID} = C2SState}) ->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 31 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
@@ -266,7 +266,7 @@ get_streamhost(Host, ServerHost) ->
|
||||
get_endpoint(Host) ->
|
||||
Port = mod_proxy65_opt:port(Host),
|
||||
IP = case mod_proxy65_opt:ip(Host) of
|
||||
undefined -> misc:get_my_ip();
|
||||
undefined -> misc:get_my_ipv4_address();
|
||||
Addr -> Addr
|
||||
end,
|
||||
{Port, IP, tcp}.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Created : 30 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
|
||||
+4
-4
@@ -4303,17 +4303,17 @@ mod_doc() ->
|
||||
#{value => "List of Key:Value",
|
||||
desc =>
|
||||
?T("This allows to define a list of key-value to choose "
|
||||
"defined node plugins on given PEP namespace."),
|
||||
"defined node plugins on given PEP namespace. "
|
||||
"The following example will use 'node_tune' instead of "
|
||||
"'node_pep' for every PEP node with the tune namespace:"),
|
||||
example =>
|
||||
[{?T("The following example will use 'node_tune' instead of "
|
||||
"'node_pep' for every PEP node with the tune namespace:"),
|
||||
["modules:",
|
||||
" ...",
|
||||
" mod_pubsub:",
|
||||
" pep_mapping:",
|
||||
" http://jabber.org/protocol/tune: tune",
|
||||
" ..."]
|
||||
}]}},
|
||||
}},
|
||||
{plugins,
|
||||
#{value => "[Plugin, ...]",
|
||||
desc => [?T("To specify which pubsub node plugins to use. "
|
||||
|
||||
@@ -202,7 +202,7 @@ index_page(Lang) ->
|
||||
?XCT(<<"title">>,
|
||||
?T("Jabber Account Registration")),
|
||||
?XA(<<"link">>,
|
||||
[{<<"href">>, <<"/register/register.css">>},
|
||||
[{<<"href">>, <<"register.css">>},
|
||||
{<<"type">>, <<"text/css">>},
|
||||
{<<"rel">>, <<"stylesheet">>}])],
|
||||
Els = [?XACT(<<"h1">>,
|
||||
@@ -211,11 +211,11 @@ index_page(Lang) ->
|
||||
?T("Jabber Account Registration")),
|
||||
?XE(<<"ul">>,
|
||||
[?XE(<<"li">>,
|
||||
[?ACT(<<"new">>, ?T("Register a Jabber account"))]),
|
||||
[?ACT(<<"new/">>, ?T("Register a Jabber account"))]),
|
||||
?XE(<<"li">>,
|
||||
[?ACT(<<"change_password">>, ?T("Change Password"))]),
|
||||
[?ACT(<<"change_password/">>, ?T("Change Password"))]),
|
||||
?XE(<<"li">>,
|
||||
[?ACT(<<"delete">>,
|
||||
[?ACT(<<"delete/">>,
|
||||
?T("Unregister a Jabber account"))])])],
|
||||
{200,
|
||||
[{<<"Server">>, <<"ejabberd">>},
|
||||
@@ -241,7 +241,7 @@ form_new_get2(Host, Lang, CaptchaEls) ->
|
||||
?XCT(<<"title">>,
|
||||
?T("Register a Jabber account")),
|
||||
?XA(<<"link">>,
|
||||
[{<<"href">>, <<"/register/register.css">>},
|
||||
[{<<"href">>, <<"../register.css">>},
|
||||
{<<"type">>, <<"text/css">>},
|
||||
{<<"rel">>, <<"stylesheet">>}])],
|
||||
Els = [?XACT(<<"h1">>,
|
||||
@@ -388,7 +388,7 @@ form_changepass_get(Host, Lang) ->
|
||||
HeadEls = [meta(),
|
||||
?XCT(<<"title">>, ?T("Change Password")),
|
||||
?XA(<<"link">>,
|
||||
[{<<"href">>, <<"/register/register.css">>},
|
||||
[{<<"href">>, <<"../register.css">>},
|
||||
{<<"type">>, <<"text/css">>},
|
||||
{<<"rel">>, <<"stylesheet">>}])],
|
||||
Els = [?XACT(<<"h1">>,
|
||||
@@ -496,7 +496,7 @@ form_del_get(Host, Lang) ->
|
||||
?XCT(<<"title">>,
|
||||
?T("Unregister a Jabber account")),
|
||||
?XA(<<"link">>,
|
||||
[{<<"href">>, <<"/register/register.css">>},
|
||||
[{<<"href">>, <<"../register.css">>},
|
||||
{<<"type">>, <<"text/css">>},
|
||||
{<<"rel">>, <<"stylesheet">>}])],
|
||||
Els = [?XACT(<<"h1">>,
|
||||
|
||||
@@ -305,7 +305,7 @@ s2s_out_tls_verify(_, #{server_host := ServerHost, remote_server := RServer}) ->
|
||||
make_key(From, To, StreamID) ->
|
||||
Secret = ejabberd_config:get_shared_key(),
|
||||
str:to_hexlist(
|
||||
crypto:hmac(sha256, str:to_hexlist(crypto:hash(sha256, Secret)),
|
||||
misc:crypto_hmac(sha256, str:to_hexlist(crypto:hash(sha256, Secret)),
|
||||
[To, " ", From, " ", StreamID])).
|
||||
|
||||
-spec send_verify_request(ejabberd_s2s_out:state()) -> ejabberd_s2s_out:state().
|
||||
|
||||
@@ -448,7 +448,7 @@ delete_group(Host, Group) ->
|
||||
get_group_opts(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
Res = case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?GROUP_OPTS_CACHE, {Host, Group},
|
||||
@@ -460,12 +460,17 @@ get_group_opts(Host1, Group1) ->
|
||||
end);
|
||||
false ->
|
||||
Mod:get_group_opts(Host, Group)
|
||||
end,
|
||||
case Res of
|
||||
{ok, Opts} -> Opts;
|
||||
error -> error
|
||||
end.
|
||||
|
||||
set_group_opts(Host, Group, Opts) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:delete(?GROUP_OPTS_CACHE, {Host, Group}, cache_nodes(Mod, Host)),
|
||||
ets_cache:insert(?GROUP_OPTS_CACHE, {Host, Group}, Opts, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
|
||||
_ ->
|
||||
|
||||
@@ -87,7 +87,7 @@ delete_group(Host, Group) ->
|
||||
|
||||
get_group_opts(Host, Group) ->
|
||||
case catch mnesia:dirty_read(sr_group, {Group, Host}) of
|
||||
[#sr_group{opts = Opts}] -> Opts;
|
||||
[#sr_group{opts = Opts}] -> {ok, Opts};
|
||||
_ -> error
|
||||
end.
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ get_group_opts(Host, Group) ->
|
||||
?SQL("select @(opts)s from sr_group"
|
||||
" where name=%(Group)s and %(Host)H")) of
|
||||
{selected, [{SOpts}]} ->
|
||||
mod_shared_roster:opts_to_binary(ejabberd_sql:decode_term(SOpts));
|
||||
{ok, mod_shared_roster:opts_to_binary(ejabberd_sql:decode_term(SOpts))};
|
||||
_ -> error
|
||||
end.
|
||||
|
||||
|
||||
+5
-5
@@ -357,8 +357,8 @@ mod_opt_type(via) ->
|
||||
(econf:and_then(
|
||||
econf:url([tls, tcp, udp]),
|
||||
fun(URI) ->
|
||||
{ok, {Type, _, Host, Port, _, _}} =
|
||||
http_uri:parse(binary_to_list(URI)),
|
||||
{ok, Type, Host, Port, _} =
|
||||
misc:uri_parse(URI),
|
||||
{Type, {unicode:characters_to_binary(Host), Port}}
|
||||
end))(U)
|
||||
end, [unique]).
|
||||
@@ -382,9 +382,9 @@ mod_doc() ->
|
||||
"for the corresponding virtual host."), "",
|
||||
?T("NOTE: It is not enough to just load this module. "
|
||||
"You should also configure listeners and DNS records "
|
||||
"properly. See section "
|
||||
"https://docs.ejabberd.im/admin/configuration/#sip[SIP] "
|
||||
"of the Configuration Guide for details.")],
|
||||
"properly. For details see the section about the "
|
||||
"http://../listen/#ejabberd-sip[ejabberd_sip] listen module "
|
||||
"in the ejabberd Documentation.")],
|
||||
opts =>
|
||||
[{always_record_route,
|
||||
#{value => "true | false",
|
||||
|
||||
+51
-35
@@ -52,6 +52,7 @@
|
||||
|
||||
-type state() :: ejabberd_c2s:state().
|
||||
-type queue() :: p1_queue:queue({non_neg_integer(), erlang:timestamp(), xmpp_element() | xmlel()}).
|
||||
-type id() :: binary().
|
||||
-type error_reason() :: session_not_found | session_timed_out |
|
||||
session_is_dead | session_has_exited |
|
||||
session_was_killed | session_copy_timed_out |
|
||||
@@ -228,8 +229,8 @@ c2s_handle_send(#{mgmt_state := MgmtState, mod := Mod,
|
||||
c2s_handle_send(State, _Pkt, _Result) ->
|
||||
State.
|
||||
|
||||
c2s_handle_call(#{sid := {Time, _}, mod := Mod, mgmt_queue := Queue} = State,
|
||||
{resume_session, Time}, From) ->
|
||||
c2s_handle_call(#{mgmt_id := MgmtID, mgmt_queue := Queue, mod := Mod} = State,
|
||||
{resume_session, MgmtID}, From) ->
|
||||
State1 = State#{mgmt_queue => p1_queue:file_to_ram(Queue)},
|
||||
Mod:reply(From, {resume, State1}),
|
||||
{stop, State#{mgmt_state => resumed, mgmt_queue => p1_queue:clear(Queue)}};
|
||||
@@ -288,10 +289,10 @@ c2s_terminated(#{mgmt_state := resumed, sid := SID, jid := JID} = State, _Reason
|
||||
ejabberd_c2s:bounce_message_queue(SID, JID),
|
||||
{stop, State};
|
||||
c2s_terminated(#{mgmt_state := MgmtState, mgmt_stanzas_in := In,
|
||||
sid := {Time, _}, jid := JID} = State, _Reason) ->
|
||||
mgmt_id := MgmtID, jid := JID} = State, _Reason) ->
|
||||
case MgmtState of
|
||||
timeout ->
|
||||
store_stanzas_in(jid:tolower(JID), Time, In);
|
||||
store_stanzas_in(jid:tolower(JID), MgmtID, In);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
@@ -377,6 +378,7 @@ handle_enable(#{mgmt_timeout := DefaultTimeout,
|
||||
mgmt_max_timeout := MaxTimeout,
|
||||
mgmt_xmlns := Xmlns, jid := JID} = State,
|
||||
#sm_enable{resume = Resume, max = Max}) ->
|
||||
State1 = State#{mgmt_id => make_id()},
|
||||
Timeout = if Resume == false ->
|
||||
0;
|
||||
Max /= undefined, Max > 0, Max*1000 =< MaxTimeout ->
|
||||
@@ -388,7 +390,7 @@ handle_enable(#{mgmt_timeout := DefaultTimeout,
|
||||
?DEBUG("Stream management with resumption enabled for ~ts",
|
||||
[jid:encode(JID)]),
|
||||
#sm_enabled{xmlns = Xmlns,
|
||||
id = make_resume_id(State),
|
||||
id = encode_id(State1),
|
||||
resume = true,
|
||||
max = Timeout div 1000};
|
||||
true ->
|
||||
@@ -396,10 +398,10 @@ handle_enable(#{mgmt_timeout := DefaultTimeout,
|
||||
[jid:encode(JID)]),
|
||||
#sm_enabled{xmlns = Xmlns}
|
||||
end,
|
||||
State1 = State#{mgmt_state => active,
|
||||
mgmt_queue => p1_queue:new(QueueType),
|
||||
mgmt_timeout => Timeout},
|
||||
send(State1, Res).
|
||||
State2 = State1#{mgmt_state => active,
|
||||
mgmt_queue => p1_queue:new(QueueType),
|
||||
mgmt_timeout => Timeout},
|
||||
send(State2, Res).
|
||||
|
||||
-spec handle_r(state()) -> state().
|
||||
handle_r(#{mgmt_xmlns := Xmlns, mgmt_stanzas_in := H} = State) ->
|
||||
@@ -431,10 +433,9 @@ handle_resume(#{user := User, lserver := LServer,
|
||||
{ok, #{jid := JID} = ResumedState, NumHandled} ->
|
||||
State1 = check_h_attribute(ResumedState, NumHandled),
|
||||
#{mgmt_xmlns := AttrXmlns, mgmt_stanzas_in := AttrH} = State1,
|
||||
AttrId = make_resume_id(State1),
|
||||
State2 = send(State1, #sm_resumed{xmlns = AttrXmlns,
|
||||
h = AttrH,
|
||||
previd = AttrId}),
|
||||
previd = PrevID}),
|
||||
State3 = resend_unacked_stanzas(State2),
|
||||
State4 = send(State3, #sm_r{xmlns = AttrXmlns}),
|
||||
State5 = ejabberd_hooks:run_fold(c2s_session_resumed, LServer, State4, []),
|
||||
@@ -649,20 +650,19 @@ route_unacked_stanzas(_State) ->
|
||||
{error, error_reason()} |
|
||||
{error, error_reason(), non_neg_integer()}.
|
||||
inherit_session_state(#{user := U, server := S,
|
||||
mgmt_queue_type := QueueType} = State, ResumeID) ->
|
||||
case misc:base64_to_term(ResumeID) of
|
||||
{term, {R, Time}} ->
|
||||
case ejabberd_sm:get_session_pid(U, S, R) of
|
||||
mgmt_queue_type := QueueType} = State, PrevID) ->
|
||||
case decode_id(PrevID) of
|
||||
{ok, {R, MgmtID}} ->
|
||||
case ejabberd_sm:get_session_sid(U, S, R) of
|
||||
none ->
|
||||
case pop_stanzas_in({U, S, R}, Time) of
|
||||
case pop_stanzas_in({U, S, R}, MgmtID) of
|
||||
error ->
|
||||
{error, session_not_found};
|
||||
{ok, H} ->
|
||||
{error, session_timed_out, H}
|
||||
end;
|
||||
OldPID ->
|
||||
OldSID = {Time, OldPID},
|
||||
try resume_session(OldSID, State) of
|
||||
{_, OldPID} = OldSID ->
|
||||
try resume_session(OldPID, MgmtID, State) of
|
||||
{resume, #{mgmt_xmlns := Xmlns,
|
||||
mgmt_queue := Queue,
|
||||
mgmt_timeout := Timeout,
|
||||
@@ -673,7 +673,9 @@ inherit_session_state(#{user := U, server := S,
|
||||
ram -> Queue;
|
||||
_ -> p1_queue:ram_to_file(Queue)
|
||||
end,
|
||||
State2 = State1#{mgmt_xmlns => Xmlns,
|
||||
State2 = State1#{sid => ejabberd_sm:make_sid(),
|
||||
mgmt_id => MgmtID,
|
||||
mgmt_xmlns => Xmlns,
|
||||
mgmt_queue => Queue1,
|
||||
mgmt_timeout => Timeout,
|
||||
mgmt_stanzas_in => NumStanzasIn,
|
||||
@@ -698,18 +700,14 @@ inherit_session_state(#{user := U, server := S,
|
||||
{error, session_copy_timed_out}
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
error ->
|
||||
{error, invalid_previd}
|
||||
end.
|
||||
|
||||
-spec resume_session({erlang:timestamp(), pid()}, state()) -> {resume, state()} |
|
||||
{error, error_reason()}.
|
||||
resume_session({Time, Pid}, _State) ->
|
||||
ejabberd_c2s:call(Pid, {resume_session, Time}, timer:seconds(15)).
|
||||
|
||||
-spec make_resume_id(state()) -> binary().
|
||||
make_resume_id(#{sid := {Time, _}, resource := Resource}) ->
|
||||
misc:term_to_base64({Resource, Time}).
|
||||
-spec resume_session(pid(), id(), state()) -> {resume, state()} |
|
||||
{error, error_reason()}.
|
||||
resume_session(PID, MgmtID, _State) ->
|
||||
ejabberd_c2s:call(PID, {resume_session, MgmtID}, timer:seconds(15)).
|
||||
|
||||
-spec add_resent_delay_info(state(), stanza(), erlang:timestamp()) -> stanza();
|
||||
(state(), xmlel(), erlang:timestamp()) -> xmlel().
|
||||
@@ -756,6 +754,24 @@ need_to_enqueue(#{mgmt_force_enqueue := true} = State, #xmlel{}) ->
|
||||
need_to_enqueue(State, _) ->
|
||||
{false, State}.
|
||||
|
||||
-spec make_id() -> id().
|
||||
make_id() ->
|
||||
p1_rand:bytes(8).
|
||||
|
||||
-spec encode_id(state()) -> binary().
|
||||
encode_id(#{mgmt_id := MgmtID, resource := Resource}) ->
|
||||
misc:term_to_base64({Resource, MgmtID}).
|
||||
|
||||
-spec decode_id(binary()) -> {ok, {binary(), id()}} | error.
|
||||
decode_id(Encoded) ->
|
||||
case misc:base64_to_term(Encoded) of
|
||||
{term, {Resource, MgmtID}} when is_binary(Resource),
|
||||
is_binary(MgmtID) ->
|
||||
{ok, {Resource, MgmtID}};
|
||||
_ ->
|
||||
error
|
||||
end.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Formatters and Logging
|
||||
%%%===================================================================
|
||||
@@ -803,14 +819,14 @@ cache_opts(Opts) ->
|
||||
{life_time, mod_stream_mgmt_opt:cache_life_time(Opts)},
|
||||
{type, ordered_set}].
|
||||
|
||||
-spec store_stanzas_in(ljid(), erlang:timestamp(), non_neg_integer()) -> boolean().
|
||||
store_stanzas_in(LJID, Time, Num) ->
|
||||
ets_cache:insert(?STREAM_MGMT_CACHE, {LJID, Time}, Num,
|
||||
-spec store_stanzas_in(ljid(), id(), non_neg_integer()) -> boolean().
|
||||
store_stanzas_in(LJID, MgmtID, Num) ->
|
||||
ets_cache:insert(?STREAM_MGMT_CACHE, {LJID, MgmtID}, Num,
|
||||
ejabberd_cluster:get_nodes()).
|
||||
|
||||
-spec pop_stanzas_in(ljid(), erlang:timestamp()) -> {ok, non_neg_integer()} | error.
|
||||
pop_stanzas_in(LJID, Time) ->
|
||||
case ets_cache:lookup(?STREAM_MGMT_CACHE, {LJID, Time}) of
|
||||
-spec pop_stanzas_in(ljid(), id()) -> {ok, non_neg_integer()} | error.
|
||||
pop_stanzas_in(LJID, MgmtID) ->
|
||||
case ets_cache:lookup(?STREAM_MGMT_CACHE, {LJID, MgmtID}) of
|
||||
{ok, Val} ->
|
||||
ets_cache:match_delete(?STREAM_MGMT_CACHE, {LJID, '_'},
|
||||
ejabberd_cluster:get_nodes()),
|
||||
|
||||
+107
-66
@@ -149,7 +149,7 @@ mod_opt_type(services) ->
|
||||
-spec mod_options(binary()) -> [{services, [tuple()]} | {atom(), any()}].
|
||||
mod_options(_Host) ->
|
||||
[{access, local},
|
||||
{credentials_lifetime, timer:minutes(10)},
|
||||
{credentials_lifetime, timer:hours(12)},
|
||||
{offer_local_services, true},
|
||||
{secret, undefined},
|
||||
{services, []}].
|
||||
@@ -171,10 +171,14 @@ mod_doc() ->
|
||||
{credentials_lifetime,
|
||||
#{value => "timeout()",
|
||||
desc =>
|
||||
?T("The lifetime of temporary credentails offered to "
|
||||
"clients. If a lifetime longer than the default value of "
|
||||
"'10' minutes is specified, it's strongly recommended to "
|
||||
"also specify a 'secret' (see below).")}},
|
||||
?T("The lifetime of temporary credentials offered to "
|
||||
"clients. If ejabberd's built-in TURN service is used, "
|
||||
"TURN relays allocated using temporary credentials will "
|
||||
"be terminated shortly after the credentials expired. The "
|
||||
"default value is '12' hours. Note that restarting the "
|
||||
"ejabberd node invalidates any temporary credentials "
|
||||
"offered before the restart unless a 'secret' is "
|
||||
"specified (see below).")}},
|
||||
{offer_local_services,
|
||||
#{value => "true | false",
|
||||
desc =>
|
||||
@@ -191,14 +195,15 @@ mod_doc() ->
|
||||
desc =>
|
||||
?T("The secret used for generating temporary credentials. If "
|
||||
"this option isn't specified, a secret will be "
|
||||
"auto-generated. However, a secret must be specified if "
|
||||
"non-anonymous TURN services running on other ejabberd "
|
||||
"nodes and/or external TURN 'services' are configured. "
|
||||
"Also note that auto-generated secrets are lost when the "
|
||||
"node is restarted, which invalidates any credentials "
|
||||
"offered before the restart. Therefore, the "
|
||||
"'credentials_lifetime' should not exceed a few minutes "
|
||||
"if no 'secret' is specified.")}},
|
||||
"auto-generated. However, a secret must be specified "
|
||||
"explicitly if non-anonymous TURN services running on "
|
||||
"other ejabberd nodes and/or external TURN 'services' are "
|
||||
"configured. Also note that auto-generated secrets are "
|
||||
"lost when the node is restarted, which invalidates any "
|
||||
"credentials offered before the restart. Therefore, it's "
|
||||
"recommended to explicitly specify a secret if clients "
|
||||
"cache retrieved credentials (for later use) across "
|
||||
"service restarts.")}},
|
||||
{services,
|
||||
#{value => "[Service, ...]",
|
||||
example =>
|
||||
@@ -216,26 +221,20 @@ mod_doc() ->
|
||||
" transport: udp",
|
||||
" restricted: true",
|
||||
" -",
|
||||
" host: 203.0.113.3",
|
||||
" host: 2001:db8::3",
|
||||
" port: 3478",
|
||||
" type: stun",
|
||||
" transport: tcp",
|
||||
" transport: udp",
|
||||
" restricted: false",
|
||||
" -",
|
||||
" host: 203.0.113.3",
|
||||
" host: 2001:db8::3",
|
||||
" port: 3478",
|
||||
" type: turn",
|
||||
" transport: tcp",
|
||||
" transport: udp",
|
||||
" restricted: true",
|
||||
" -",
|
||||
" host: server.example.com",
|
||||
" port: 5349",
|
||||
" type: stuns",
|
||||
" transport: tcp",
|
||||
" restricted: false",
|
||||
" -",
|
||||
" host: server.example.com",
|
||||
" port: 5349",
|
||||
" type: turns",
|
||||
" transport: tcp",
|
||||
" restricted: true"],
|
||||
@@ -256,12 +255,12 @@ mod_doc() ->
|
||||
[{host,
|
||||
#{value => ?T("Host"),
|
||||
desc =>
|
||||
?T("The host name or IPv4 address the STUN/TURN service is "
|
||||
?T("The hostname or IP address the STUN/TURN service is "
|
||||
"listening on. For non-TLS services, it's recommended "
|
||||
"to specify an IPv4 address (to avoid additional DNS "
|
||||
"to specify an IP address (to avoid additional DNS "
|
||||
"lookup latency on the client side). For TLS services, "
|
||||
"the host name (or possible IPv4 address) should match "
|
||||
"the certificate. Specifying the 'host' option is "
|
||||
"the hostname (or IP address) should match the "
|
||||
"certificate. Specifying the 'host' option is "
|
||||
"mandatory.")}},
|
||||
{port,
|
||||
#{value => "1..65535",
|
||||
@@ -348,7 +347,7 @@ handle_cast({reload, NewOpts, _OldOpts}, #state{host = Host} = State) ->
|
||||
TTL = get_configured_ttl(NewOpts),
|
||||
{noreply, State#state{services = Services, secret = Secret, ttl = TTL}};
|
||||
handle_cast(Request, State) ->
|
||||
?ERROR_MSG("Got unexpected request from: ~p", [Request]),
|
||||
?ERROR_MSG("Got unexpected request: ~p", [Request]),
|
||||
{noreply, State}.
|
||||
|
||||
-spec handle_info(term(), state()) -> {noreply, state()}.
|
||||
@@ -556,7 +555,7 @@ make_username(ExpireAt, Hash) ->
|
||||
|
||||
-spec make_password(binary(), binary()) -> binary().
|
||||
make_password(Username, Secret) ->
|
||||
base64:encode(crypto:hmac(sha, Secret, Username)).
|
||||
base64:encode(misc:crypto_hmac(sha, Secret, Username)).
|
||||
|
||||
-spec get_password(binary(), binary()) -> binary().
|
||||
get_password(Username, HostHash) ->
|
||||
@@ -594,52 +593,88 @@ parse_listener({_EndPoint, ?STUN_MODULE, #{tls := true}}) ->
|
||||
?DEBUG("Ignoring TLS-enabled STUN/TURN listener", []),
|
||||
[]; % Avoid certificate hostname issues.
|
||||
parse_listener({{Port, _Addr, Transport}, ?STUN_MODULE, Opts}) ->
|
||||
case get_listener_ip(Opts) of
|
||||
{127, _, _, _} = Addr ->
|
||||
?INFO_MSG("Won't auto-announce STUN/TURN service with loopback "
|
||||
"address: ~s:~B (~s), please specify a public 'turn_ip'",
|
||||
[misc:ip_to_list(Addr), Port, Transport]),
|
||||
case get_listener_ips(Opts) of
|
||||
{undefined, undefined} ->
|
||||
?INFO_MSG("Won't auto-announce STUN/TURN service on port ~B (~s) "
|
||||
"without public IP address, please specify "
|
||||
"'turn_ipv4_address' and optionally 'turn_ipv6_address'",
|
||||
[Port, Transport]),
|
||||
[];
|
||||
Addr ->
|
||||
StunService = #service{host = Addr,
|
||||
port = Port,
|
||||
transport = Transport,
|
||||
restricted = false,
|
||||
type = stun},
|
||||
case Opts of
|
||||
#{use_turn := true} ->
|
||||
?DEBUG("Found STUN/TURN listener: ~s:~B (~s)",
|
||||
[misc:ip_to_list(Addr), Port, Transport]),
|
||||
[StunService, #service{host = Addr,
|
||||
port = Port,
|
||||
transport = Transport,
|
||||
restricted = is_restricted(Opts),
|
||||
type = turn}];
|
||||
#{use_turn := false} ->
|
||||
?DEBUG("Found STUN listener: ~s:~B (~s)",
|
||||
[misc:ip_to_list(Addr), Port, Transport]),
|
||||
[StunService]
|
||||
end
|
||||
{IPv4Addr, IPv6Addr} ->
|
||||
lists:flatmap(
|
||||
fun(undefined) ->
|
||||
[];
|
||||
(Addr) ->
|
||||
StunService = #service{host = Addr,
|
||||
port = Port,
|
||||
transport = Transport,
|
||||
restricted = false,
|
||||
type = stun},
|
||||
case Opts of
|
||||
#{use_turn := true} ->
|
||||
?INFO_MSG("Going to offer STUN/TURN service: "
|
||||
"~s (~s)",
|
||||
[addr_to_str(Addr, Port), Transport]),
|
||||
[StunService,
|
||||
#service{host = Addr,
|
||||
port = Port,
|
||||
transport = Transport,
|
||||
restricted = is_restricted(Opts),
|
||||
type = turn}];
|
||||
#{use_turn := false} ->
|
||||
?INFO_MSG("Going to offer STUN service: "
|
||||
"~s (~s)",
|
||||
[addr_to_str(Addr, Port), Transport]),
|
||||
[StunService]
|
||||
end
|
||||
end, [IPv4Addr, IPv6Addr])
|
||||
end;
|
||||
parse_listener({_EndPoint, Module, _Opts}) ->
|
||||
?DEBUG("Ignoring ~s listener", [Module]),
|
||||
[].
|
||||
|
||||
-spec get_listener_ip(map()) -> inet:ip_address().
|
||||
get_listener_ip(#{ip := { 0, 0, 0, 0}} = Opts) -> get_turn_ip(Opts);
|
||||
get_listener_ip(#{ip := {127, _, _, _}} = Opts) -> get_turn_ip(Opts);
|
||||
get_listener_ip(#{ip := { 10, _, _, _}} = Opts) -> get_turn_ip(Opts);
|
||||
get_listener_ip(#{ip := {172, 16, _, _}} = Opts) -> get_turn_ip(Opts);
|
||||
get_listener_ip(#{ip := {192, 168, _, _}} = Opts) -> get_turn_ip(Opts);
|
||||
get_listener_ip(#{ip := IP}) -> IP.
|
||||
-spec get_listener_ips(map()) -> {inet:ip4_address() | undefined,
|
||||
inet:ip6_address() | undefined}.
|
||||
get_listener_ips(#{ip := {0, 0, 0, 0}} = Opts) ->
|
||||
{get_turn_ipv4_addr(Opts), undefined};
|
||||
get_listener_ips(#{ip := {0, 0, 0, 0, 0, 0, 0, 0}} = Opts) ->
|
||||
{get_turn_ipv4_addr(Opts), get_turn_ipv6_addr(Opts)}; % Assume dual-stack.
|
||||
get_listener_ips(#{ip := {127, _, _, _}} = Opts) ->
|
||||
{get_turn_ipv4_addr(Opts), undefined};
|
||||
get_listener_ips(#{ip := {0, 0, 0, 0, 0, 0, 0, 1}} = Opts) ->
|
||||
{undefined, get_turn_ipv6_addr(Opts)};
|
||||
get_listener_ips(#{ip := {_, _, _, _} = IP}) ->
|
||||
{IP, undefined};
|
||||
get_listener_ips(#{ip := {_, _, _, _, _,_, _, _, _} = IP}) ->
|
||||
{undefined, IP}.
|
||||
|
||||
-spec get_turn_ip(map()) -> inet:ip_address().
|
||||
get_turn_ip(#{turn_ip := {_, _, _, _} = TurnIP}) -> TurnIP;
|
||||
get_turn_ip(#{turn_ip := undefined}) -> misc:get_my_ip().
|
||||
-spec get_turn_ipv4_addr(map()) -> inet:ip4_address() | undefined.
|
||||
get_turn_ipv4_addr(#{turn_ipv4_address := {_, _, _, _} = TurnIP}) ->
|
||||
TurnIP;
|
||||
get_turn_ipv4_addr(#{turn_ipv4_address := undefined}) ->
|
||||
case misc:get_my_ipv4_address() of
|
||||
{127, _, _, _} ->
|
||||
undefined;
|
||||
IP ->
|
||||
IP
|
||||
end.
|
||||
|
||||
-spec get_turn_ipv6_addr(map()) -> inet:ip6_address() | undefined.
|
||||
get_turn_ipv6_addr(#{turn_ipv6_address := {_, _, _, _, _, _, _, _} = TurnIP}) ->
|
||||
TurnIP;
|
||||
get_turn_ipv6_addr(#{turn_ipv6_address := undefined}) ->
|
||||
case misc:get_my_ipv6_address() of
|
||||
{0, 0, 0, 0, 0, 0, 0, 1} ->
|
||||
undefined;
|
||||
IP ->
|
||||
IP
|
||||
end.
|
||||
|
||||
-spec is_restricted(map()) -> boolean().
|
||||
is_restricted(#{auth_type := user}) -> true;
|
||||
is_restricted(#{auth_type := anonymous}) -> false.
|
||||
is_restricted(#{auth_type := user}) ->
|
||||
true;
|
||||
is_restricted(#{auth_type := anonymous}) ->
|
||||
false.
|
||||
|
||||
-spec call(host_or_hash(), term()) -> term().
|
||||
call(Host, Request) ->
|
||||
@@ -668,3 +703,9 @@ dedup([H | T]) -> [H | [E || E <- dedup(T), E /= H]].
|
||||
-spec seconds_to_timestamp(non_neg_integer()) -> erlang:timestamp().
|
||||
seconds_to_timestamp(Seconds) ->
|
||||
{Seconds div 1000000, Seconds rem 1000000, 0}.
|
||||
|
||||
-spec addr_to_str(inet:ip_address(), 0..65535) -> iolist().
|
||||
addr_to_str({_, _, _, _, _, _, _, _} = Addr, Port) ->
|
||||
[$[, inet_parse:ntoa(Addr), $], $:, integer_to_list(Port)];
|
||||
addr_to_str({_, _, _, _} = Addr, Port) ->
|
||||
[inet_parse:ntoa(Addr), $:, integer_to_list(Port)].
|
||||
|
||||
@@ -897,12 +897,12 @@ select_affiliation_subscriptions(Nidx, GenKey, SubKey) ->
|
||||
GJ = encode_jid(GenKey),
|
||||
SJ = encode_jid(SubKey),
|
||||
case catch ejabberd_sql:sql_query_t(
|
||||
?SQL("select jid = %(GJ)s as @(G)b, @(affiliation)s, @(subscriptions)s from "
|
||||
?SQL("select @(jid)s, @(affiliation)s, @(subscriptions)s from "
|
||||
" pubsub_state where nodeid=%(Nidx)d and jid in (%(GJ)s, %(SJ)s)"))
|
||||
of
|
||||
{selected, Res} ->
|
||||
lists:foldr(
|
||||
fun({true, A, S}, {_, Subs}) ->
|
||||
fun({Jid, A, S}, {_, Subs}) when Jid == GJ ->
|
||||
{decode_affiliation(A), Subs ++ decode_subscriptions(S)};
|
||||
({_, _, S}, {Aff, Subs}) ->
|
||||
{Aff, Subs ++ decode_subscriptions(S)}
|
||||
|
||||
@@ -35,9 +35,7 @@
|
||||
delete_subscription/1, update_subscription/1]).
|
||||
-export([export/1]).
|
||||
|
||||
%% TODO: Those -spec lines produce errors in old Erlang versions.
|
||||
%% They can be enabled again in ejabberd 3.0 because it uses R12B or higher.
|
||||
%% -spec read_subscription(SubID :: string()) -> {ok, #pubsub_subscription{}} | notfound.
|
||||
-spec read_subscription(SubID :: string()) -> {ok, #pubsub_subscription{}} | notfound.
|
||||
read_subscription(SubID) ->
|
||||
case
|
||||
ejabberd_sql:sql_query_t(
|
||||
@@ -51,19 +49,18 @@ read_subscription(SubID) ->
|
||||
options = lists:map(fun subscription_opt_from_sql/1, Options)}}
|
||||
end.
|
||||
|
||||
%% -spec delete_subscription(SubID :: string()) -> ok.
|
||||
-spec delete_subscription(SubID :: string()) -> ok.
|
||||
delete_subscription(SubID) ->
|
||||
%% -spec update_subscription(#pubsub_subscription{}) -> ok .
|
||||
%% -spec add_subscription(#pubsub_subscription{}) -> ok.
|
||||
%% -------------- Internal utilities -----------------------
|
||||
ejabberd_sql:sql_query_t(
|
||||
?SQL("delete from pubsub_subscription_opt "
|
||||
"where subid = %(SubID)s")),
|
||||
ok.
|
||||
|
||||
-spec update_subscription(#pubsub_subscription{}) -> ok .
|
||||
update_subscription(#pubsub_subscription{subid = SubId} = Sub) ->
|
||||
delete_subscription(SubId), add_subscription(Sub).
|
||||
|
||||
-spec add_subscription(#pubsub_subscription{}) -> ok.
|
||||
add_subscription(#pubsub_subscription{subid = SubId, options = Opts}) ->
|
||||
lists:foreach(
|
||||
fun(Opt) ->
|
||||
|
||||
@@ -98,7 +98,7 @@ listen:
|
||||
module: ejabberd_stun
|
||||
transport: udp
|
||||
use_turn: true
|
||||
turn_ip: "203.0.113.3"
|
||||
turn_ipv4_address: "203.0.113.3"
|
||||
-
|
||||
port: COMPONENT_PORT
|
||||
module: ejabberd_service
|
||||
@@ -148,7 +148,6 @@ Welcome to this XMPP server."
|
||||
max_size: 10000
|
||||
vcard: VCARD
|
||||
registration_timeout: infinity
|
||||
route_subdomains: s2s
|
||||
s2s_use_starttls: false
|
||||
ca_file: CAFILE
|
||||
c2s_cafile: CAFILE
|
||||
|
||||
+3
-4
@@ -4,8 +4,7 @@
|
||||
main(Paths) ->
|
||||
Dict = fold_erls(
|
||||
fun(File, Tokens, Acc) ->
|
||||
File1 = filename:rootname(filename:basename(File)),
|
||||
extract_tr(File1, Tokens, Acc)
|
||||
extract_tr(File, Tokens, Acc)
|
||||
end, dict:new(), Paths),
|
||||
generate_pot(Dict).
|
||||
|
||||
@@ -114,7 +113,7 @@ format_location_list(L) ->
|
||||
"#: " ++ string:join(
|
||||
lists:map(
|
||||
fun({File, Pos}) ->
|
||||
io_lib:format("~s.erl:~B", [File, Pos])
|
||||
io_lib:format("~s:~B", [File, Pos])
|
||||
end, L),
|
||||
" ") ++ io_lib:nl().
|
||||
|
||||
@@ -137,7 +136,7 @@ pot_header() ->
|
||||
"\"MIME-Version: 1.0\\n\"",
|
||||
"\"Content-Type: text/plain; charset=UTF-8\\n\"",
|
||||
"\"Content-Transfer-Encoding: 8bit\\n\"",
|
||||
"\"X-Poedit-Basepath: ../../src\\n\"",
|
||||
"\"X-Poedit-Basepath: ../..\\n\"",
|
||||
"\"X-Poedit-SearchPath-0: .\\n\""],
|
||||
io_lib:nl()).
|
||||
|
||||
|
||||
@@ -301,6 +301,10 @@ is_exported(Mod, Fun, Arity, Exports) ->
|
||||
catch _:{badkey, _} -> false
|
||||
end.
|
||||
|
||||
warn_type({var, _, 'Type'}, #state{module = mod_delegation}, "not an atom") ->
|
||||
ok;
|
||||
warn_type({var, _, 'NS'}, #state{module = mod_delegation}, "not a binary") ->
|
||||
ok;
|
||||
warn_type(Form, State, Warning) ->
|
||||
log("~s:~p: Warning: " ++ Warning ++ ": ~s~n",
|
||||
[State#state.file,
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
extract_lang_src2pot ()
|
||||
{
|
||||
./tools/extract-tr.sh src > priv/msgs/ejabberd.pot
|
||||
./tools/extract-tr.sh src deps/xmpp/src > priv/msgs/ejabberd.pot
|
||||
}
|
||||
|
||||
extract_lang_popot2po ()
|
||||
|
||||
Reference in New Issue
Block a user