Compare commits
236 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72f35a6dc6 | |||
| 83cce468a5 | |||
| 6631078884 | |||
| fc0754c609 | |||
| 73a0fb418c | |||
| 4dc23a5d81 | |||
| 36a96ae3f5 | |||
| d528457ba5 | |||
| e5a98b100d | |||
| 1cf2dfe63a | |||
| 3c47a5bb75 | |||
| e608274243 | |||
| 2110b929bc | |||
| dcf5aefea0 | |||
| 357ff6c8f7 | |||
| c04053cfae | |||
| fe10c6f6f2 | |||
| 7206bff4a4 | |||
| 6c712b6caa | |||
| faa4851dbf | |||
| 6f48f22c71 | |||
| 9a9633dbc5 | |||
| c1119b1f39 | |||
| ab196b4b02 | |||
| 730fd55ec9 | |||
| 0ae9ef2b41 | |||
| 83faff37e5 | |||
| 4ed6a3d78f | |||
| 0de7864880 | |||
| 157ff4d093 | |||
| fb6267f38e | |||
| 9a802185ad | |||
| a9f7d9481f | |||
| ea7de2097f | |||
| 48213b09ce | |||
| 22d9011c0c | |||
| 100827ec6e | |||
| a291e7d4e6 | |||
| 6cba7bf834 | |||
| e8ffbbb0b4 | |||
| 6a9c9616d0 | |||
| d0443bb714 | |||
| 5585fb1ecf | |||
| b83c07251c | |||
| b2f98099bb | |||
| 9574e71e8d | |||
| 3af507cc43 | |||
| e54e556e01 | |||
| 90225a4744 | |||
| 0d322d8dab | |||
| be6ac85f31 | |||
| b07cb1ed84 | |||
| 0c725b5fac | |||
| 3b24923458 | |||
| b04f3a4c93 | |||
| 3188941af2 | |||
| fcdb519770 | |||
| 8985a47468 | |||
| 05011e6918 | |||
| da68b9a572 | |||
| 889459b45c | |||
| 1854b5e411 | |||
| 3b267eaa61 | |||
| fba13a0b93 | |||
| 8bb994dbca | |||
| dfbef8be8f | |||
| 2af659b737 | |||
| 16532dd643 | |||
| 555c1736b7 | |||
| e66b45d886 | |||
| 0800a9733c | |||
| f5c9dfbc93 | |||
| 084d0c4efe | |||
| 61afd668c2 | |||
| de7ff536b2 | |||
| 5dbe7a3c6c | |||
| 6efce7f706 | |||
| 42c7205739 | |||
| dbcfd38c18 | |||
| 09f5565ca0 | |||
| d885435552 | |||
| eca3b46ee1 | |||
| f817762cc4 | |||
| 25beb46391 | |||
| 7ab6c4b4fd | |||
| b0b004b26e | |||
| f7d9bb7ce4 | |||
| b0b3870b2e | |||
| 7297b23508 | |||
| 6eab111d05 | |||
| fa99519f8b | |||
| 96c62acb1b | |||
| 77e57afae1 | |||
| 60fe008268 | |||
| 6987e85602 | |||
| 7492ecae52 | |||
| 4440b03b89 | |||
| 01718a4e42 | |||
| 6f99775115 | |||
| bd43385415 | |||
| 987e337c66 | |||
| dc449687a0 | |||
| 0edba763fb | |||
| 50f35f1b07 | |||
| 9c85cb5f25 | |||
| 23aa8598ab | |||
| 38dd44e18f | |||
| df3afafb48 | |||
| 2e194bd997 | |||
| 43f2064daa | |||
| e280de8452 | |||
| 6e4d6caebf | |||
| cf37f3977a | |||
| 61f80396da | |||
| cbd45974e2 | |||
| 747d25b4ad | |||
| e0563e3918 | |||
| 63926efd20 | |||
| 28090a3958 | |||
| ed79a61752 | |||
| 94936b261e | |||
| fd54181435 | |||
| e8576c23c5 | |||
| c2e6ce0f04 | |||
| 837706e9d9 | |||
| aa36742a40 | |||
| c01940f33c | |||
| afdc269825 | |||
| b447839592 | |||
| 01b3defb86 | |||
| d624753410 | |||
| a5adaf5798 | |||
| 63d6d68979 | |||
| 31c5775025 | |||
| ba69c469b5 | |||
| a1f81057ca | |||
| e408276283 | |||
| b67af5e036 | |||
| 25449a076f | |||
| b9fdcc3985 | |||
| e8701802ee | |||
| 2797fa16a6 | |||
| 8732817c3c | |||
| f129c6530c | |||
| 32b60d4250 | |||
| 7a89dda816 | |||
| 9b4942890d | |||
| 0cf8d1fa6e | |||
| fb0e82f743 | |||
| 675c428f21 | |||
| bdedcf8d8a | |||
| 2a3a2d9804 | |||
| 5a820aca40 | |||
| c3280e9dad | |||
| 0fd4984c23 | |||
| b81b0d0be9 | |||
| c140f98276 | |||
| f981a53f9a | |||
| 2a94c68724 | |||
| 81b0643036 | |||
| 64978b3d9c | |||
| 34f8f6d868 | |||
| cc247c5510 | |||
| 1106afb2f6 | |||
| cf83a75ceb | |||
| 69bff82301 | |||
| 47537aa901 | |||
| 0cd77ab942 | |||
| ea8db9967f | |||
| 7d3b2cad26 | |||
| cf40daf663 | |||
| 1fa73fd33f | |||
| 94761ff31e | |||
| 088c5c4672 | |||
| b580da3547 | |||
| cf3b4dbc7b | |||
| 305b281c15 | |||
| 821039b7d5 | |||
| fb1fd50df5 | |||
| 4af15df546 | |||
| 15af88a09a | |||
| 176114d28e | |||
| 9c96d30719 | |||
| a8f2cbac75 | |||
| 30dc82a98a | |||
| 8707c0b045 | |||
| 10dfd182f6 | |||
| 9b3dda105d | |||
| 392772977f | |||
| fbb6b65192 | |||
| 0c30beb93d | |||
| c9393bc4f4 | |||
| 5103ed1c3b | |||
| 88cd8c7b12 | |||
| 00fe68ed06 | |||
| 09dd288ac0 | |||
| 2186c03a9c | |||
| 441d48f080 | |||
| c3afc3c7c0 | |||
| 9a64bfe605 | |||
| ca25d44c8b | |||
| 4e9b4cbc11 | |||
| 46b33b51b4 | |||
| 3eebf100f9 | |||
| 5c0a1dde1c | |||
| 949705b04a | |||
| f682dfe3a6 | |||
| 14a3662ca4 | |||
| ffea2bf350 | |||
| f314da7b1f | |||
| d72c739630 | |||
| 57035b383c | |||
| 2746e358b3 | |||
| d66f40d94f | |||
| e6a9c5ccee | |||
| f0cf90c11e | |||
| de26af3fdb | |||
| d9ad26b4ec | |||
| f40e6a0421 | |||
| 1b1878409f | |||
| 8f9a2d6df8 | |||
| bc008d4041 | |||
| 33c9f21171 | |||
| 27a4d783a5 | |||
| 736710cc9c | |||
| 8f46ca48c1 | |||
| b6999b126a | |||
| 31e356c126 | |||
| a5d6044448 | |||
| 477d27a3dc | |||
| 8b23727cc6 | |||
| 5135e30633 | |||
| 5ae01e8bb4 | |||
| 2a15453d98 | |||
| b81250d667 | |||
| eb52c118d0 |
@@ -4,6 +4,8 @@
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
.edts
|
||||
*.dump
|
||||
/Makefile
|
||||
/config.log
|
||||
/config.status
|
||||
@@ -28,7 +30,7 @@
|
||||
/ebin/
|
||||
/ejabberd.init
|
||||
/ejabberdctl.example
|
||||
/include/XmppAddr.hrl
|
||||
XmppAddr.hrl
|
||||
/rel/ejabberd/
|
||||
/src/XmppAddr.asn1db
|
||||
/src/XmppAddr.erl
|
||||
@@ -38,3 +40,5 @@
|
||||
/dialyzer/
|
||||
/test/*.beam
|
||||
/logs/
|
||||
/priv/sql
|
||||
mix.exs
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
language: erlang
|
||||
|
||||
otp_release:
|
||||
- 17.4
|
||||
- R16B03
|
||||
- R15B01
|
||||
|
||||
services:
|
||||
- riak
|
||||
@@ -11,7 +11,7 @@ before_install:
|
||||
- sudo apt-get -qq update
|
||||
|
||||
install:
|
||||
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev
|
||||
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev
|
||||
|
||||
before_script:
|
||||
- mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';"
|
||||
|
||||
@@ -43,6 +43,9 @@ SODIR = $(PRIVDIR)/lib
|
||||
# /usr/lib/ejabberd/priv/msgs
|
||||
MSGSDIR = $(PRIVDIR)/msgs
|
||||
|
||||
# /usr/lib/ejabberd/priv/sql
|
||||
SQLDIR = $(PRIVDIR)/sql
|
||||
|
||||
# /var/lib/ejabberd/
|
||||
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
|
||||
|
||||
@@ -98,10 +101,6 @@ xref: all
|
||||
translations:
|
||||
contrib/extract_translations/prepare-translation.sh -updateall
|
||||
|
||||
doc:
|
||||
echo making $$target in doc; \
|
||||
(cd doc && $(MAKE) $$target) || exit 1
|
||||
|
||||
edoc:
|
||||
$(ERL) -noinput +B -eval \
|
||||
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
|
||||
@@ -176,11 +175,16 @@ install: all
|
||||
$(INSTALL) -d $(SODIR)
|
||||
$(INSTALL) -m 644 $(DLLs) $(SODIR)
|
||||
-[ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true)
|
||||
-[ -f $(SODIR)/sqlite3_drv.so ] && (cd $(PRIVDIR); ln -s lib/sqlite3_drv.so; true)
|
||||
#
|
||||
# Translated strings
|
||||
$(INSTALL) -d $(MSGSDIR)
|
||||
$(INSTALL) -m 644 priv/msgs/*.msg $(MSGSDIR)
|
||||
#
|
||||
# Copy lite.sql
|
||||
-[ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR)
|
||||
-[ -d deps/sqlite3 ] && $(INSTALL) -m 644 sql/lite.sql $(SQLDIR)
|
||||
#
|
||||
# Spool directory
|
||||
$(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR)
|
||||
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
|
||||
@@ -199,16 +203,9 @@ install: all
|
||||
#
|
||||
# Documentation
|
||||
$(INSTALL) -d $(DOCDIR)
|
||||
[ -f doc/dev.html ] \
|
||||
&& $(INSTALL) -m 644 doc/dev.html $(DOCDIR) \
|
||||
|| echo "No doc/dev.html was built"
|
||||
[ -f doc/guide.html ] \
|
||||
&& $(INSTALL) -m 644 doc/guide.html $(DOCDIR) \
|
||||
|| echo "No doc/guide.html was built"
|
||||
[ -f doc/guide.pdf ] \
|
||||
&& $(INSTALL) -m 644 doc/guide.pdf $(DOCDIR) \
|
||||
|| echo "No doc/guide.pdf was built"
|
||||
$(INSTALL) -m 644 doc/*.png $(DOCDIR)
|
||||
|| echo "Documentation not included in sources"
|
||||
$(INSTALL) -m 644 COPYING $(DOCDIR)
|
||||
|
||||
uninstall: uninstall-binary
|
||||
@@ -229,6 +226,8 @@ uninstall-binary:
|
||||
rm -fr $(SODIR)
|
||||
rm -f $(MSGSDIR)/*.msgs
|
||||
rm -fr $(MSGSDIR)
|
||||
rm -f $(SQLDIR)/*.sql
|
||||
rm -fr $(SQLDIR)
|
||||
rm -fr $(PRIVDIR)
|
||||
rm -fr $(EJABBERDDIR)
|
||||
|
||||
@@ -310,11 +309,12 @@ test:
|
||||
@echo "************************** NOTICE ***************************************"
|
||||
@cat test/README
|
||||
@echo "*************************************************************************"
|
||||
@cd priv && ln -sf ../sql
|
||||
$(REBAR) skip_deps=true ct
|
||||
|
||||
quicktest:
|
||||
$(REBAR) skip_deps=true ct suites=elixir
|
||||
|
||||
.PHONY: src doc edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
|
||||
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
|
||||
install uninstall uninstall-binary uninstall-all translations deps test spec \
|
||||
quicktest erlang_plt deps_plt ejabberd_plt
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
|
||||
include Makefile.inc
|
||||
|
||||
ALL : build
|
||||
|
||||
REL=..\release
|
||||
EREL=$(REL)\ejabberd-$(EJABBERD_VERSION)
|
||||
EBIN_DIR=$(EREL)\ebin
|
||||
SRC_DIR=$(EREL)\src
|
||||
PRIV_DIR=$(EREL)\priv
|
||||
SO_DIR=$(EREL)
|
||||
MSGS_DIR=$(EREL)\msgs
|
||||
WIN32_DIR=$(EREL)\win32
|
||||
DOC_DIR=$(EREL)\doc
|
||||
|
||||
NSIS_SCRIPT=win32\ejabberd.nsi
|
||||
NSIS_HEADER=win32\ejabberd.nsh
|
||||
|
||||
installer : $(NSIS_SCRIPT) $(NSIS_HEADER)
|
||||
makensis $(NSIS_SCRIPT)
|
||||
|
||||
$(NSIS_HEADER) : Makefile.inc
|
||||
echo !define OUTFILEDIR "..\$(REL)" >$(NSIS_HEADER)
|
||||
echo !define TESTDIR "..\$(REL)\ejabberd-$(EJABBERD_VERSION)" >>$(NSIS_HEADER)
|
||||
echo !define VERSION "$(EJABBERD_VERSION)" >>$(NSIS_HEADER)
|
||||
|
||||
release_clean :
|
||||
if exist $(REL) rd /s /q $(REL)
|
||||
|
||||
|
||||
release : build release_clean
|
||||
mkdir $(REL)
|
||||
mkdir $(EREL)
|
||||
mkdir $(EBIN_DIR)
|
||||
copy *.beam $(EBIN_DIR)
|
||||
@erase $(EBIN_DIR)\configure.beam
|
||||
copy *.app $(EBIN_DIR)
|
||||
copy *.dll $(SO_DIR)
|
||||
mkdir $(MSGS_DIR)
|
||||
copy msgs\*.msg $(MSGS_DIR)
|
||||
mkdir $(WIN32_DIR)
|
||||
copy win32\ejabberd.cfg $(EREL)
|
||||
copy win32\inetrc $(EREL)
|
||||
copy $(SYSTEMROOT)\system32\libeay32.dll $(EREL)
|
||||
copy $(SYSTEMROOT)\system32\ssleay32.dll $(EREL)
|
||||
copy win32\ejabberd.ico $(WIN32_DIR)
|
||||
mkdir $(SRC_DIR)
|
||||
copy *.app $(SRC_DIR)
|
||||
copy *.erl $(SRC_DIR)
|
||||
copy *.hrl $(SRC_DIR)
|
||||
copy *.c $(SRC_DIR)
|
||||
mkdir $(SRC_DIR)\eldap
|
||||
copy eldap\eldap.* $(SRC_DIR)\eldap
|
||||
copy eldap\ELDAPv3.asn $(SRC_DIR)\eldap
|
||||
mkdir $(SRC_DIR)\mod_irc
|
||||
copy mod_irc\*.erl $(SRC_DIR)\mod_irc
|
||||
copy mod_irc\*.c $(SRC_DIR)\mod_irc
|
||||
mkdir $(SRC_DIR)\mod_muc
|
||||
copy mod_muc\*.erl $(SRC_DIR)\mod_muc
|
||||
mkdir $(SRC_DIR)\mod_pubsub
|
||||
copy mod_pubsub\*.erl $(SRC_DIR)\mod_pubsub
|
||||
mkdir $(SRC_DIR)\mod_proxy65
|
||||
copy mod_proxy65\*.erl $(SRC_DIR)\mod_proxy65
|
||||
copy mod_proxy65\*.hrl $(SRC_DIR)\mod_proxy65
|
||||
mkdir $(SRC_DIR)\stringprep
|
||||
copy stringprep\*.erl $(SRC_DIR)\stringprep
|
||||
copy stringprep\*.c $(SRC_DIR)\stringprep
|
||||
copy stringprep\*.tcl $(SRC_DIR)\stringprep
|
||||
mkdir $(SRC_DIR)\stun
|
||||
copy stun\*.erl $(SRC_DIR)\stun
|
||||
copy stun\*.hrl $(SRC_DIR)\stun
|
||||
mkdir $(SRC_DIR)\tls
|
||||
copy tls\*.erl $(SRC_DIR)\tls
|
||||
copy tls\*.c $(SRC_DIR)\tls
|
||||
mkdir $(SRC_DIR)\ejabberd_zlib
|
||||
copy ejabberd_zlib\*.erl $(SRC_DIR)\ejabberd_zlib
|
||||
copy ejabberd_zlib\*.c $(SRC_DIR)\ejabberd_zlib
|
||||
mkdir $(SRC_DIR)\web
|
||||
copy web\*.erl $(SRC_DIR)\web
|
||||
mkdir $(SRC_DIR)\odbc
|
||||
copy odbc\*.erl $(SRC_DIR)\odbc
|
||||
copy odbc\*.sql $(EREL)
|
||||
mkdir $(DOC_DIR)
|
||||
copy ..\doc\*.txt $(DOC_DIR)
|
||||
copy ..\doc\*.html $(DOC_DIR)
|
||||
copy ..\doc\*.png $(DOC_DIR)
|
||||
|
||||
SOURCE = expat_erl.c
|
||||
OBJECT = expat_erl.o
|
||||
DLL = expat_erl.dll
|
||||
|
||||
build : $(DLL) compile-beam all-recursive
|
||||
|
||||
all-recursive :
|
||||
cd eldap
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\mod_irc
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\mod_muc
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\mod_pubsub
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\mod_proxy65
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\stringprep
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\stun
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\tls
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\ejabberd_zlib
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\web
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..\odbc
|
||||
nmake -nologo -f Makefile.win32
|
||||
cd ..
|
||||
|
||||
compile-beam : XmppAddr.hrl
|
||||
erl -s make all report -noinput -s erlang halt
|
||||
|
||||
XmppAddr.hrl : XmppAddr.asn1
|
||||
erlc -bber_bin +der +compact_bit_string +optimize +noobj XmppAddr.asn1
|
||||
|
||||
CLEAN : clean-recursive clean-local
|
||||
|
||||
clean-local :
|
||||
-@erase $(OBJECT)
|
||||
-@erase $(DLL)
|
||||
-@erase expat_erl.exp
|
||||
-@erase expat_erl.lib
|
||||
-@erase *.beam
|
||||
-@erase XmppAddr.asn1db
|
||||
-@erase XmppAddr.erl
|
||||
-@erase XmppAddr.hrl
|
||||
|
||||
clean-recursive :
|
||||
cd eldap
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\mod_irc
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\mod_muc
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\mod_pubsub
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\mod_proxy65
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\stringprep
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\stun
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\tls
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\ejabberd_zlib
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\web
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..\odbc
|
||||
nmake -nologo -f Makefile.win32 clean
|
||||
cd ..
|
||||
|
||||
distclean : release_clean clean
|
||||
-@erase $(NSIS_HEADER)
|
||||
-@erase Makefile.inc
|
||||
|
||||
CC=cl.exe
|
||||
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT $(EXPAT_FLAG) -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(EXPAT_DIR)\source\lib"
|
||||
|
||||
LD=link.exe
|
||||
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(EXPAT_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
|
||||
|
||||
$(DLL) : $(OBJECT)
|
||||
$(LD) $(LD_FLAGS) -out:$@ $<
|
||||
|
||||
$(OBJECT) : $(SOURCE)
|
||||
$(CC) $(CC_FLAGS) -c -Fo$@ $<
|
||||
@@ -106,7 +106,7 @@ To compile ejabberd you need:
|
||||
- GCC.
|
||||
- Libexpat 1.95 or higher.
|
||||
- Libyaml 0.1.4 or higher.
|
||||
- Erlang/OTP R15B or higher.
|
||||
- Erlang/OTP R16B03 or higher.
|
||||
- OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
|
||||
- Zlib 1.2.3 or higher, for Stream Compression support (XEP-0138). Optional.
|
||||
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
|
||||
@@ -152,6 +152,14 @@ Operation Guide available online and in the `doc` directory of the source
|
||||
tarball.
|
||||
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
In order to assist in the development of ejabberd, and particularly the
|
||||
execution of the test suite, a Vagrant environment is available at
|
||||
https://github.com/processone/ejabberd-vagrant-dev.
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
|
||||
@@ -106,10 +106,10 @@ AC_ARG_ENABLE(mssql,
|
||||
esac],[db_type=generic])
|
||||
|
||||
AC_ARG_ENABLE(all,
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) nif=true odbc=true mysql=true pgsql=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false pam=false zlib=false riak=false redis=false json=false elixir=false iconv=false debug=false lager=false tools=false ;;
|
||||
yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false json=false elixir=false iconv=false debug=false lager=false tools=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
|
||||
esac],[])
|
||||
|
||||
@@ -153,6 +153,14 @@ AC_ARG_ENABLE(pgsql,
|
||||
*) 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
|
||||
@@ -227,7 +235,8 @@ esac],[if test "x$lager" = "x"; then lager=true; fi])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
vars.config
|
||||
src/ejabberd.app.src])
|
||||
src/ejabberd.app.src
|
||||
mix.exs])
|
||||
|
||||
ENABLEUSER=""
|
||||
AC_ARG_ENABLE(user,
|
||||
@@ -245,6 +254,13 @@ fi
|
||||
|
||||
ERLANG_DEPRECATED_TYPES_CHECK
|
||||
|
||||
if test "$sqlite" = "true"; then
|
||||
AX_LIB_SQLITE3([3.6.19])
|
||||
if test "x$SQLITE3_VERSION" = "x"; then
|
||||
AC_MSG_ERROR(SQLite3 library >= 3.6.19 was not found)
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(hipe)
|
||||
AC_SUBST(roster_gateway_workaround)
|
||||
AC_SUBST(transient_supervisors)
|
||||
@@ -254,6 +270,7 @@ AC_SUBST(db_type)
|
||||
AC_SUBST(odbc)
|
||||
AC_SUBST(mysql)
|
||||
AC_SUBST(pgsql)
|
||||
AC_SUBST(sqlite)
|
||||
AC_SUBST(pam)
|
||||
AC_SUBST(zlib)
|
||||
AC_SUBST(riak)
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
CONTRIBUTED_MODULES = ""
|
||||
#ifeq ($(shell ls mod_http_bind.tex),mod_http_bind.tex)
|
||||
# CONTRIBUTED_MODULES += "\\n\\setboolean{modhttpbind}{true}"
|
||||
#endif
|
||||
|
||||
|
||||
all: release pdf html
|
||||
|
||||
release:
|
||||
@printf '%s\n' "Notes for the releaser:"
|
||||
@printf '%s\n' "* Do not forget to add a link to the release notes in guide.tex"
|
||||
@printf '%s\n' "* Do not forget to update the version number in ebin/ejabberd.app!"
|
||||
@printf '%s\n' "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)."
|
||||
@printf '%s\n' "Press any key to continue"
|
||||
##@read foo
|
||||
@printf '%s\n' "% ejabberd version (automatically generated)." > version.tex
|
||||
@printf '%s\n' "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../ebin/ejabberd.app`"}" >> version.tex
|
||||
@printf '%s' "% Contributed modules (automatically generated)." > contributed_modules.tex
|
||||
@printf '%b\n' "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex
|
||||
|
||||
html: guide.html dev.html features.html
|
||||
|
||||
pdf: guide.pdf features.pdf
|
||||
|
||||
clean:
|
||||
rm -f *.aux
|
||||
rm -f *.haux
|
||||
rm -f *.htoc
|
||||
rm -f *.idx
|
||||
rm -f *.ilg
|
||||
rm -f *.ind
|
||||
rm -f *.log
|
||||
rm -f *.out
|
||||
rm -f *.pdf
|
||||
rm -f *.toc
|
||||
[ ! -f contributed_modules.tex ] || rm contributed_modules.tex
|
||||
|
||||
distclean: clean
|
||||
rm -f *.html
|
||||
|
||||
guide.html: guide.tex
|
||||
hevea -fix -pedantic guide.tex
|
||||
|
||||
dev.html: dev.tex
|
||||
hevea -fix -pedantic dev.tex
|
||||
|
||||
features.html: features.tex
|
||||
hevea -fix -pedantic features.tex
|
||||
|
||||
guide.pdf: guide.tex
|
||||
pdflatex guide.tex
|
||||
pdflatex guide.tex
|
||||
pdflatex guide.tex
|
||||
makeindex guide.idx
|
||||
pdflatex guide.tex
|
||||
|
||||
features.pdf: features.tex
|
||||
pdflatex features.tex
|
||||
@@ -1,18 +0,0 @@
|
||||
APPNAME = ejabberd
|
||||
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../../src/ejabberd.app)
|
||||
|
||||
DOCDIR=.
|
||||
SRCDIR=../../src
|
||||
|
||||
.PHONY = all
|
||||
|
||||
all: docs
|
||||
|
||||
clean:
|
||||
rm -f *.html
|
||||
rm edoc-info
|
||||
rm erlang.png
|
||||
|
||||
docs:
|
||||
erl -noshell -run edoc_run application \
|
||||
"'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop
|
||||
@@ -1,10 +0,0 @@
|
||||
@author Mickael Remond <mickael.remond@process-one.net>
|
||||
[http://www.process-one.net/]
|
||||
@copyright 2013 ProcessOne
|
||||
@version {@vsn}, {@date} {@time}
|
||||
@title ejabberd Development API Documentation
|
||||
|
||||
@doc
|
||||
== Introduction ==
|
||||
|
||||
TODO: Insert content from Jerome documentation.
|
||||
@@ -1,92 +0,0 @@
|
||||
html, body {
|
||||
font-family: Verdana, sans-serif;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #4a5389;
|
||||
border-bottom: solid 1px #000;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
text-align: right;
|
||||
color: #4a5389;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
color: #900;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a[href] {
|
||||
color: #4a5389;
|
||||
}
|
||||
|
||||
a[href]:hover {
|
||||
background-color: #ecefff;
|
||||
}
|
||||
|
||||
p, li, dd {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
li:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
caption {
|
||||
font-style: italic;
|
||||
color: #009;
|
||||
text-align: left;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
table[border="1"] {
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
table[border="1"] td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
pre, tt, code {
|
||||
color: #461b7e;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin:1ex 2ex;
|
||||
border:1px dashed lightgrey;
|
||||
background-color:#f9f9f9;
|
||||
padding:0.5ex;
|
||||
}
|
||||
|
||||
pre em {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dt {
|
||||
margin:0ex 2ex;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin:0ex 0ex 1ex 4ex;
|
||||
}
|
||||
@@ -1,437 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<meta name="generator" content="hevea 2.09">
|
||||
<style type="text/css">
|
||||
.li-itemize{margin:1ex 0ex;}
|
||||
.li-enumerate{margin:1ex 0ex;}
|
||||
.dd-description{margin:0ex 0ex 1ex 4ex;}
|
||||
.dt-description{margin:0ex;}
|
||||
.toc{list-style:none;}
|
||||
.footnotetext{margin:0ex; padding:0ex;}
|
||||
div.footnotetext P{margin:0px; text-indent:1em;}
|
||||
.thefootnotes{text-align:left;margin:0ex;}
|
||||
.dt-thefootnotes{margin:0em;}
|
||||
.dd-thefootnotes{margin:0em 0em 0em 2em;}
|
||||
.footnoterule{margin:1em auto 1em 0px;width:50%;}
|
||||
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
|
||||
.title{margin:2ex auto;text-align:center}
|
||||
.titlemain{margin:1ex 2ex 2ex 1ex;}
|
||||
.titlerest{margin:0ex 2ex;}
|
||||
.center{text-align:center;margin-left:auto;margin-right:auto;}
|
||||
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
|
||||
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
|
||||
td table{margin:auto;}
|
||||
table{border-collapse:collapse;}
|
||||
td{padding:0;}
|
||||
.cellpadding0 tr td{padding:0;}
|
||||
.cellpadding1 tr td{padding:1px;}
|
||||
pre{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
blockquote{margin-left:4ex;margin-right:4ex;text-align:left;}
|
||||
td p{margin:0px;}
|
||||
.boxed{border:1px solid black}
|
||||
.textboxed{border:1px solid black}
|
||||
.vbar{border:none;width:2px;background-color:black;}
|
||||
.hbar{border:none;height:2px;width:100%;background-color:black;}
|
||||
.hfill{border:none;height:1px;width:200%;background-color:black;}
|
||||
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
|
||||
.vdcell{white-space:nowrap;padding:0px; border:2px solid green;}
|
||||
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
|
||||
.dcell{white-space:nowrap;padding:0px; border:none;}
|
||||
.dcenter{margin:0ex auto;}
|
||||
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
|
||||
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
|
||||
.marginpar{border:solid thin black; width:20%; text-align:left;}
|
||||
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
|
||||
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
|
||||
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
|
||||
.part{margin:2ex auto;text-align:center}
|
||||
</style>
|
||||
<title>Ejabberd community 14.05-120-gedfb5fc Developers Guide
|
||||
</title>
|
||||
</head>
|
||||
<body >
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex -->
|
||||
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
|
||||
|
||||
</p><table class="title"><tr><td style="padding:1ex"><h1 class="titlemain">Ejabberd community 14.05-120-gedfb5fc Developers Guide</h1><h3 class="titlerest">Alexey Shchepin <br>
|
||||
<a href="mailto:alexey@sevcom.net"><span style="font-family:monospace">mailto:alexey@sevcom.net</span></a> <br>
|
||||
<a href="xmpp:aleksey@jabber.ru"><span style="font-family:monospace">xmpp:aleksey@jabber.ru</span></a></h3></td></tr>
|
||||
</table><div class="center">
|
||||
|
||||
<img src="logo.png" alt="logo.png">
|
||||
|
||||
|
||||
</div><blockquote class="quotation"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup –
|
||||
Kevin Smith, Current maintainer of the Psi project</span></blockquote><!--TOC section id="intro" Contents-->
|
||||
<h2 id="intro" class="section">Contents</h2><!--SEC END --><ul class="toc"><li class="li-toc">
|
||||
<a href="#sec2">1  Key Features</a>
|
||||
</li><li class="li-toc"><a href="#sec3">2  Additional Features</a>
|
||||
</li><li class="li-toc"><a href="#sec4">3  How it Works</a>
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec5">3.1  Router</a>
|
||||
</li><li class="li-toc"><a href="#sec6">3.2  Local Router</a>
|
||||
</li><li class="li-toc"><a href="#sec7">3.3  Session Manager</a>
|
||||
</li><li class="li-toc"><a href="#sec8">3.4  S2S Manager</a>
|
||||
</li></ul>
|
||||
</li><li class="li-toc"><a href="#sec9">4  Authentication</a>
|
||||
<ul class="toc">
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec10">4.0.1  External</a>
|
||||
</li></ul>
|
||||
</ul>
|
||||
</li><li class="li-toc"><a href="#sec11">5  XML Representation</a>
|
||||
</li><li class="li-toc"><a href="#sec12">6  Module <span style="font-family:monospace">xml</span></a>
|
||||
</li><li class="li-toc"><a href="#sec13">7  Module <span style="font-family:monospace">xml_stream</span></a>
|
||||
</li><li class="li-toc"><a href="#sec14">8  Modules</a>
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec15">8.1  Module gen_iq_handler</a>
|
||||
</li><li class="li-toc"><a href="#sec16">8.2  Services</a>
|
||||
</li></ul>
|
||||
</li></ul><p>Introduction
|
||||
</p><p><span style="font-family:monospace">ejabberd</span> is a free and open source instant messaging server written in <a href="http://www.erlang.org/">Erlang/OTP</a>.</p><p><span style="font-family:monospace">ejabberd</span> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</p><p><span style="font-family:monospace">ejabberd</span> is designed to be a rock-solid and feature rich XMPP server.</p><p><span style="font-family:monospace">ejabberd</span> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</p>
|
||||
<!--TOC section id="sec2" Key Features-->
|
||||
<h2 id="sec2" class="section">1  Key Features</h2><!--SEC END --><p>
|
||||
<a id="keyfeatures"></a>
|
||||
</p><p><span style="font-family:monospace">ejabberd</span> is:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
Cross-platform: <span style="font-family:monospace">ejabberd</span> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</li><li class="li-itemize">Distributed: You can run <span style="font-family:monospace">ejabberd</span> on a cluster of machines and all of them will serve the same Jabber 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.</li><li class="li-itemize">Fault-tolerant: You can deploy an <span style="font-family:monospace">ejabberd</span> 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’.</li><li class="li-itemize">Administrator Friendly: <span style="font-family:monospace">ejabberd</span> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Comprehensive documentation.
|
||||
</li><li class="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </li><li class="li-itemize">Web Administration.
|
||||
</li><li class="li-itemize">Shared Roster Groups.
|
||||
</li><li class="li-itemize">Command line administration tool. </li><li class="li-itemize">Can integrate with existing authentication mechanisms.
|
||||
</li><li class="li-itemize">Capability to send announce messages.
|
||||
</li></ul></li><li class="li-itemize">Internationalized: <span style="font-family:monospace">ejabberd</span> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Translated to 25 languages. </li><li class="li-itemize">Support for <a href="http://www.ietf.org/rfc/rfc3490.txt">IDNA</a>.
|
||||
</li></ul></li><li class="li-itemize">Open Standards: <span style="font-family:monospace">ejabberd</span> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Fully XMPP compliant.
|
||||
</li><li class="li-itemize">XML-based protocol.
|
||||
</li><li class="li-itemize"><a href="http://www.ejabberd.im/protocols">Many protocols supported</a>.
|
||||
</li></ul></li></ul>
|
||||
<!--TOC section id="sec3" Additional Features-->
|
||||
<h2 id="sec3" class="section">2  Additional Features</h2><!--SEC END --><p>
|
||||
<a id="addfeatures"></a>
|
||||
</p><p>Moreover, <span style="font-family:monospace">ejabberd</span> comes with a wide range of other state-of-the-art features:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
Modular
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Load only the modules you want.
|
||||
</li><li class="li-itemize">Extend <span style="font-family:monospace">ejabberd</span> with your own custom modules.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Security
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
SASL and STARTTLS for c2s and s2s connections.
|
||||
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
|
||||
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Databases
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal database for fast deployment (Mnesia).
|
||||
</li><li class="li-itemize">Native MySQL support.
|
||||
</li><li class="li-itemize">Native PostgreSQL support.
|
||||
</li><li class="li-itemize">ODBC data storage support.
|
||||
</li><li class="li-itemize">Microsoft SQL Server support. </li><li class="li-itemize">Riak NoSQL database support.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Authentication
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal Authentication.
|
||||
</li><li class="li-itemize">PAM, LDAP, ODBC and Riak. </li><li class="li-itemize">External Authentication script.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Others
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Support for virtual hosting.
|
||||
</li><li class="li-itemize">Compressing XML streams with Stream Compression (<a href="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</a>).
|
||||
</li><li class="li-itemize">Statistics via Statistics Gathering (<a href="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</a>).
|
||||
</li><li class="li-itemize">IPv6 support both for c2s and s2s connections.
|
||||
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</a> module with support for clustering and HTML logging. </li><li class="li-itemize">Users Directory based on users vCards.
|
||||
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</a> component with support for <a href="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</a>.
|
||||
</li><li class="li-itemize">Support for web clients: <a href="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</a> and <a href="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</a> services.
|
||||
</li><li class="li-itemize">IRC transport.
|
||||
</li><li class="li-itemize">SIP support.
|
||||
</li><li class="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
</li></ul>
|
||||
</li></ul>
|
||||
<!--TOC section id="sec4" How it Works-->
|
||||
<h2 id="sec4" class="section">3  How it Works</h2><!--SEC END --><p>
|
||||
<a id="howitworks"></a></p><p>A XMPP domain is served by one or more <span style="font-family:monospace">ejabberd</span> nodes. These nodes can
|
||||
be run on different machines that are connected via a network. They all must
|
||||
have the ability to connect to port 4369 of all another nodes, and must have
|
||||
the same magic cookie (see Erlang/OTP documentation, in other words the file
|
||||
<span style="font-family:monospace">~ejabberd/.erlang.cookie</span> must be the same on all nodes). This is
|
||||
needed because all nodes exchange information about connected users, S2S
|
||||
connections, registered services, etc…</p><p>Each <span style="font-family:monospace">ejabberd</span> node have following modules:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
router;
|
||||
</li><li class="li-itemize">local router.
|
||||
</li><li class="li-itemize">session manager;
|
||||
</li><li class="li-itemize">S2S manager;
|
||||
</li></ul>
|
||||
<!--TOC subsection id="sec5" Router-->
|
||||
<h3 id="sec5" class="subsection">3.1  Router</h3><!--SEC END --><p>This module is the main router of XMPP packets on each node. It routes
|
||||
them based on their destinations domains. It has two tables: local and global
|
||||
routes. First, domain of packet destination searched in local table, and if it
|
||||
found, then the packet is routed to appropriate process. If no, then it
|
||||
searches in global table, and is routed to the appropriate <span style="font-family:monospace">ejabberd</span> node or
|
||||
process. If it does not exists in either tables, then it sent to the S2S
|
||||
manager.</p>
|
||||
<!--TOC subsection id="sec6" Local Router-->
|
||||
<h3 id="sec6" class="subsection">3.2  Local Router</h3><!--SEC END --><p>This module routes packets which have a destination domain equal to this server
|
||||
name. If destination JID has a non-empty user part, then it routed to the
|
||||
session manager, else it is processed depending on it’s content.</p>
|
||||
<!--TOC subsection id="sec7" Session Manager-->
|
||||
<h3 id="sec7" class="subsection">3.3  Session Manager</h3><!--SEC END --><p>This module routes packets to local users. It searches for what user resource
|
||||
packet must be sent via presence table. If this resource is connected to
|
||||
this node, it is routed to C2S process, if it connected via another node, then
|
||||
the packet is sent to session manager on that node.</p>
|
||||
<!--TOC subsection id="sec8" S2S Manager-->
|
||||
<h3 id="sec8" class="subsection">3.4  S2S Manager</h3><!--SEC END --><p>This module routes packets to other XMPP servers. First, it checks if an
|
||||
open S2S connection from the domain of the packet source to the domain of
|
||||
packet destination already exists. If it is open on another node, then it
|
||||
routes the packet to S2S manager on that node, if it is open on this node, then
|
||||
it is routed to the process that serves this connection, and if a connection
|
||||
does not exist, then it is opened and registered.</p>
|
||||
<!--TOC section id="sec9" Authentication-->
|
||||
<h2 id="sec9" class="section">4  Authentication</h2><!--SEC END -->
|
||||
<!--TOC subsubsection id="sec10" External-->
|
||||
<h4 id="sec10" class="subsubsection">4.0.1  External</h4><!--SEC END --><p>
|
||||
<a id="externalauth"></a>
|
||||
</p><p>The external authentication script follows
|
||||
<a href="http://www.erlang.org/doc/tutorial/c_portdriver.html">the erlang port driver API</a>.</p><p>That script is supposed to do theses actions, in an infinite loop:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
read from stdin: AABBBBBBBBB.....
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
A: 2 bytes of length data (a short in network byte order)
|
||||
</li><li class="li-itemize">B: a string of length found in A that contains operation in plain text
|
||||
operation are as follows:
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
auth:User:Server:Password (check if a username/password pair is correct)
|
||||
</li><li class="li-itemize">isuser:User:Server (check if it’s a valid user)
|
||||
</li><li class="li-itemize">setpass:User:Server:Password (set user’s password)
|
||||
</li><li class="li-itemize">tryregister:User:Server:Password (try to register an account)
|
||||
</li><li class="li-itemize">removeuser:User:Server (remove this account)
|
||||
</li><li class="li-itemize">removeuser3:User:Server:Password (remove this account if the password is correct)
|
||||
</li></ul>
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">write to stdout: AABB
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
A: the number 2 (coded as a short, which is bytes length of following result)
|
||||
</li><li class="li-itemize">B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
|
||||
</li></ul>
|
||||
</li></ul><p>Example python script
|
||||
</p><pre class="verbatim">#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from struct import *
|
||||
|
||||
def from_ejabberd():
|
||||
input_length = sys.stdin.read(2)
|
||||
(size,) = unpack('>h', input_length)
|
||||
return sys.stdin.read(size).split(':')
|
||||
|
||||
def to_ejabberd(bool):
|
||||
answer = 0
|
||||
if bool:
|
||||
answer = 1
|
||||
token = pack('>hh', 2, answer)
|
||||
sys.stdout.write(token)
|
||||
sys.stdout.flush()
|
||||
|
||||
def auth(username, server, password):
|
||||
return True
|
||||
|
||||
def isuser(username, server):
|
||||
return True
|
||||
|
||||
def setpass(username, server, password):
|
||||
return True
|
||||
|
||||
while True:
|
||||
data = from_ejabberd()
|
||||
success = False
|
||||
if data[0] == "auth":
|
||||
success = auth(data[1], data[2], data[3])
|
||||
elif data[0] == "isuser":
|
||||
success = isuser(data[1], data[2])
|
||||
elif data[0] == "setpass":
|
||||
success = setpass(data[1], data[2], data[3])
|
||||
to_ejabberd(success)
|
||||
</pre>
|
||||
<!--TOC section id="sec11" XML Representation-->
|
||||
<h2 id="sec11" class="section">5  XML Representation</h2><!--SEC END --><p>
|
||||
<a id="xmlrepr"></a></p><p>Each XML stanza is represented as the following tuple:
|
||||
</p><pre class="verbatim">XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
|
||||
Name = string()
|
||||
Attrs = [Attr]
|
||||
Attr = {Key, Val}
|
||||
Key = string()
|
||||
Val = string()
|
||||
ElementOrCDATA = XMLElement | CDATA
|
||||
CDATA = {xmlcdata, string()}
|
||||
</pre><p>E. g. this stanza:
|
||||
</p><pre class="verbatim"><message to='test@conference.example.org' type='groupchat'>
|
||||
<body>test</body>
|
||||
</message>
|
||||
</pre><p>is represented as the following structure:
|
||||
</p><pre class="verbatim">{xmlelement, "message",
|
||||
[{"to", "test@conference.example.org"},
|
||||
{"type", "groupchat"}],
|
||||
[{xmlelement, "body",
|
||||
[],
|
||||
[{xmlcdata, "test"}]}]}}
|
||||
</pre>
|
||||
<!--TOC section id="sec12" Module <span style="font-family:monospace">xml</span>-->
|
||||
<h2 id="sec12" class="section">6  Module <span style="font-family:monospace">xml</span></h2><!--SEC END --><p>
|
||||
<a id="xmlmod"></a></p><dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>element_to_string(El) -> string()</code>
|
||||
<pre class="verbatim">El = XMLElement
|
||||
</pre>Returns string representation of XML stanza <span style="font-family:monospace">El</span>.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>crypt(S) -> string()</code>
|
||||
<pre class="verbatim">S = string()
|
||||
</pre>Returns string which correspond to <span style="font-family:monospace">S</span> with encoded XML special
|
||||
characters.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>remove_cdata(ECList) -> EList</code>
|
||||
<pre class="verbatim">ECList = [ElementOrCDATA]
|
||||
EList = [XMLElement]
|
||||
</pre><span style="font-family:monospace">EList</span> is a list of all non-CDATA elements of ECList.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>get_path_s(El, Path) -> Res</code>
|
||||
<pre class="verbatim">El = XMLElement
|
||||
Path = [PathItem]
|
||||
PathItem = PathElem | PathAttr | PathCDATA
|
||||
PathElem = {elem, Name}
|
||||
PathAttr = {attr, Name}
|
||||
PathCDATA = cdata
|
||||
Name = string()
|
||||
Res = string() | XMLElement
|
||||
</pre>If <span style="font-family:monospace">Path</span> is empty, then returns <span style="font-family:monospace">El</span>. Else sequentially
|
||||
consider elements of <span style="font-family:monospace">Path</span>. Each element is one of:
|
||||
<dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>{elem, Name}</code> <span style="font-family:monospace">Name</span> is name of subelement of
|
||||
<span style="font-family:monospace">El</span>, if such element exists, then this element considered in
|
||||
following steps, else returns empty string.
|
||||
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>{attr, Name}</code> If <span style="font-family:monospace">El</span> have attribute <span style="font-family:monospace">Name</span>, then
|
||||
returns value of this attribute, else returns empty string.
|
||||
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>cdata</code> Returns CDATA of <span style="font-family:monospace">El</span>.
|
||||
</dd></dl></dd><dt class="dt-description"></dt><dd class="dd-description">TODO:
|
||||
<pre class="verbatim"> get_cdata/1, get_tag_cdata/1
|
||||
get_attr/2, get_attr_s/2
|
||||
get_tag_attr/2, get_tag_attr_s/2
|
||||
get_subtag/2
|
||||
</pre></dd></dl>
|
||||
<!--TOC section id="sec13" Module <span style="font-family:monospace">xml_stream</span>-->
|
||||
<h2 id="sec13" class="section">7  Module <span style="font-family:monospace">xml_stream</span></h2><!--SEC END --><p>
|
||||
<a id="xmlstreammod"></a></p><dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>parse_element(Str) -> XMLElement | {error, Err}</code>
|
||||
<pre class="verbatim">Str = string()
|
||||
Err = term()
|
||||
</pre>Parses <span style="font-family:monospace">Str</span> using XML parser, returns either parsed element or error
|
||||
tuple.
|
||||
</dd></dl>
|
||||
<!--TOC section id="sec14" Modules-->
|
||||
<h2 id="sec14" class="section">8  Modules</h2><!--SEC END --><p>
|
||||
<a id="emods"></a></p>
|
||||
<!--TOC subsection id="sec15" Module gen_iq_handler-->
|
||||
<h3 id="sec15" class="subsection">8.1  Module gen_iq_handler</h3><!--SEC END --><p>
|
||||
<a id="geniqhandl"></a></p><p>The module <code>gen_iq_handler</code> allows to easily write handlers for IQ packets
|
||||
of particular XML namespaces that addressed to server or to users bare JIDs.</p><p>In this module the following functions are defined:
|
||||
</p><dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>add_iq_handler(Component, Host, NS, Module, Function, Type)</code>
|
||||
<pre class="verbatim">Component = Module = Function = atom()
|
||||
Host = NS = string()
|
||||
Type = no_queue | one_queue | parallel
|
||||
</pre>Registers function <code>Module:Function</code> as handler for IQ packets on
|
||||
virtual host <code>Host</code> that contain child of namespace <code>NS</code> in
|
||||
<code>Component</code>. Queueing discipline is <code>Type</code>. There are at least
|
||||
two components defined:
|
||||
<dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>ejabberd_local</code> Handles packets that addressed to server JID;
|
||||
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>ejabberd_sm</code> Handles packets that addressed to users bare JIDs.
|
||||
</dd></dl>
|
||||
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>remove_iq_handler(Component, Host, NS)</code>
|
||||
<pre class="verbatim">Component = atom()
|
||||
Host = NS = string()
|
||||
</pre>Removes IQ handler on virtual host <code>Host</code> for namespace <code>NS</code> from
|
||||
<code>Component</code>.
|
||||
</dd></dl><p>Handler function must have the following type:
|
||||
</p><dl class="description"><dt class="dt-description">
|
||||
</dt><dd class="dd-description"><code>Module:Function(From, To, IQ)</code>
|
||||
<pre class="verbatim">From = To = jid()
|
||||
</pre></dd></dl><pre class="verbatim">-module(mod_cputime).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2,
|
||||
stop/1,
|
||||
process_local_iq/3]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
-define(NS_CPUTIME, "ejabberd:cputime").
|
||||
|
||||
start(Host, Opts) ->
|
||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
|
||||
?MODULE, process_local_iq, IQDisc).
|
||||
|
||||
stop(Host) ->
|
||||
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
|
||||
|
||||
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||
case Type of
|
||||
set ->
|
||||
{iq, ID, error, XMLNS,
|
||||
[SubEl, ?ERR_NOT_ALLOWED]};
|
||||
get ->
|
||||
CPUTime = element(1, erlang:statistics(runtime))/1000,
|
||||
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
|
||||
{iq, ID, result, XMLNS,
|
||||
[{xmlelement, "query",
|
||||
[{"xmlns", ?NS_CPUTIME}],
|
||||
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
|
||||
end.
|
||||
</pre>
|
||||
<!--TOC subsection id="sec16" Services-->
|
||||
<h3 id="sec16" class="subsection">8.2  Services</h3><!--SEC END --><p>
|
||||
<a id="services"></a></p><pre class="verbatim">-module(mod_echo).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2, init/1, stop/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
start(Host, Opts) ->
|
||||
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
|
||||
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
spawn(?MODULE, init, [MyHost])).
|
||||
|
||||
init(Host) ->
|
||||
ejabberd_router:register_local_route(Host),
|
||||
loop(Host).
|
||||
|
||||
loop(Host) ->
|
||||
receive
|
||||
{route, From, To, Packet} ->
|
||||
ejabberd_router:route(To, From, Packet),
|
||||
loop(Host);
|
||||
stop ->
|
||||
ejabberd_router:unregister_route(Host),
|
||||
ok;
|
||||
_ ->
|
||||
loop(Host)
|
||||
end.
|
||||
|
||||
stop(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
Proc ! stop,
|
||||
{wait, Proc}.
|
||||
</pre><!--CUT END -->
|
||||
<!--HTMLFOOT-->
|
||||
<!--ENDHTML-->
|
||||
<!--FOOTER-->
|
||||
<hr style="height:2"><blockquote class="quote"><em>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</em><a href="http://hevea.inria.fr/index.html"><em>H</em><em><span style="font-size:small"><sup>E</sup></span></em><em>V</em><em><span style="font-size:small"><sup>E</sup></span></em><em>A</em></a><em>.</em></blockquote></body>
|
||||
</html>
|
||||
@@ -1,470 +0,0 @@
|
||||
\documentclass[a4paper,10pt]{article}
|
||||
|
||||
%% Packages
|
||||
\usepackage{graphics}
|
||||
\usepackage{hevea}
|
||||
\usepackage{makeidx}
|
||||
\usepackage{verbatim}
|
||||
|
||||
%% Index
|
||||
\makeindex
|
||||
% Remove the index anchors from the HTML version to save size and bandwith.
|
||||
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
|
||||
|
||||
%% Images
|
||||
\newcommand{\logoscale}{0.7}
|
||||
\newcommand{\imgscale}{0.58}
|
||||
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
|
||||
\newcommand{\insscaleimg}[2]{
|
||||
\imgsrc{#2}{}
|
||||
\begin{latexonly}
|
||||
\scalebox{#1}{\includegraphics{#2}}
|
||||
\end{latexonly}
|
||||
}
|
||||
|
||||
%% Various
|
||||
\newcommand{\ns}[1]{\texttt{#1}}
|
||||
\newcommand{\ejabberd}{\texttt{ejabberd}}
|
||||
\newcommand{\Jabber}{Jabber}
|
||||
\newcommand{\XMPP}{XMPP}
|
||||
|
||||
%% Modules
|
||||
\newcommand{\module}[1]{\texttt{#1}}
|
||||
\newcommand{\modadhoc}{\module{mod\_adhoc}}
|
||||
\newcommand{\modannounce}{\module{mod\_announce}}
|
||||
\newcommand{\modconfigure}{\module{mod\_configure}}
|
||||
\newcommand{\moddisco}{\module{mod\_disco}}
|
||||
\newcommand{\modecho}{\module{mod\_echo}}
|
||||
\newcommand{\modirc}{\module{mod\_irc}}
|
||||
\newcommand{\modlast}{\module{mod\_last}}
|
||||
\newcommand{\modlastodbc}{\module{mod\_last\_odbc}}
|
||||
\newcommand{\modmuc}{\module{mod\_muc}}
|
||||
\newcommand{\modmuclog}{\module{mod\_muc\_log}}
|
||||
\newcommand{\modoffline}{\module{mod\_offline}}
|
||||
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
|
||||
\newcommand{\modprivacy}{\module{mod\_privacy}}
|
||||
\newcommand{\modprivate}{\module{mod\_private}}
|
||||
\newcommand{\modpubsub}{\module{mod\_pubsub}}
|
||||
\newcommand{\modregister}{\module{mod\_register}}
|
||||
\newcommand{\modroster}{\module{mod\_roster}}
|
||||
\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
|
||||
\newcommand{\modservicelog}{\module{mod\_service\_log}}
|
||||
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
|
||||
\newcommand{\modstats}{\module{mod\_stats}}
|
||||
\newcommand{\modtime}{\module{mod\_time}}
|
||||
\newcommand{\modvcard}{\module{mod\_vcard}}
|
||||
\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
|
||||
\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}}
|
||||
\newcommand{\modversion}{\module{mod\_version}}
|
||||
|
||||
%% Title page
|
||||
\include{version}
|
||||
\title{Ejabberd \version\ Developers Guide}
|
||||
\author{Alexey Shchepin \\
|
||||
\ahrefurl{mailto:alexey@sevcom.net} \\
|
||||
\ahrefurl{xmpp:aleksey@jabber.ru}}
|
||||
|
||||
%% Options
|
||||
\newcommand{\marking}[1]{#1} % Marking disabled
|
||||
\newcommand{\quoting}[2][yozhik]{} % Quotes disabled
|
||||
\newcommand{\new}{\begin{latexonly}\marginpar{\textsc{new}}\end{latexonly}} % Highlight new features
|
||||
\newcommand{\improved}{\begin{latexonly}\marginpar{\textsc{improved}}\end{latexonly}} % Highlight improved features
|
||||
\newcommand{\moreinfo}[1]{} % Hide details
|
||||
|
||||
%% Footnotes
|
||||
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
|
||||
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\label{titlepage}
|
||||
\begin{titlepage}
|
||||
\maketitle{}
|
||||
|
||||
\begin{center}
|
||||
{\insscaleimg{\logoscale}{logo.png}
|
||||
\par
|
||||
}
|
||||
\end{center}
|
||||
|
||||
\begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup --
|
||||
Kevin Smith, Current maintainer of the Psi project}\end{quotation}
|
||||
|
||||
\end{titlepage}
|
||||
|
||||
\tableofcontents{}
|
||||
|
||||
% Input introduction.tex
|
||||
\input{introduction}
|
||||
|
||||
\section{How it Works}
|
||||
\label{howitworks}
|
||||
|
||||
|
||||
A \XMPP{} domain is served by one or more \ejabberd{} nodes. These nodes can
|
||||
be run on different machines that are connected via a network. They all must
|
||||
have the ability to connect to port 4369 of all another nodes, and must have
|
||||
the same magic cookie (see Erlang/OTP documentation, in other words the file
|
||||
\texttt{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is
|
||||
needed because all nodes exchange information about connected users, S2S
|
||||
connections, registered services, etc\ldots
|
||||
|
||||
|
||||
|
||||
Each \ejabberd{} node have following modules:
|
||||
\begin{itemize}
|
||||
\item router;
|
||||
\item local router.
|
||||
\item session manager;
|
||||
\item S2S manager;
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\subsection{Router}
|
||||
|
||||
This module is the main router of \XMPP{} packets on each node. It routes
|
||||
them based on their destinations domains. It has two tables: local and global
|
||||
routes. First, domain of packet destination searched in local table, and if it
|
||||
found, then the packet is routed to appropriate process. If no, then it
|
||||
searches in global table, and is routed to the appropriate \ejabberd{} node or
|
||||
process. If it does not exists in either tables, then it sent to the S2S
|
||||
manager.
|
||||
|
||||
|
||||
\subsection{Local Router}
|
||||
|
||||
This module routes packets which have a destination domain equal to this server
|
||||
name. If destination JID has a non-empty user part, then it routed to the
|
||||
session manager, else it is processed depending on it's content.
|
||||
|
||||
|
||||
\subsection{Session Manager}
|
||||
|
||||
This module routes packets to local users. It searches for what user resource
|
||||
packet must be sent via presence table. If this resource is connected to
|
||||
this node, it is routed to C2S process, if it connected via another node, then
|
||||
the packet is sent to session manager on that node.
|
||||
|
||||
|
||||
\subsection{S2S Manager}
|
||||
|
||||
This module routes packets to other \XMPP{} servers. First, it checks if an
|
||||
open S2S connection from the domain of the packet source to the domain of
|
||||
packet destination already exists. If it is open on another node, then it
|
||||
routes the packet to S2S manager on that node, if it is open on this node, then
|
||||
it is routed to the process that serves this connection, and if a connection
|
||||
does not exist, then it is opened and registered.
|
||||
|
||||
|
||||
\section{Authentication}
|
||||
|
||||
\subsubsection{External}
|
||||
\label{externalauth}
|
||||
\ind{external authentication}
|
||||
|
||||
The external authentication script follows
|
||||
\footahref{http://www.erlang.org/doc/tutorial/c_portdriver.html}{the erlang port driver API}.
|
||||
|
||||
That script is supposed to do theses actions, in an infinite loop:
|
||||
\begin{itemize}
|
||||
\item read from stdin: AABBBBBBBBB.....
|
||||
\begin{itemize}
|
||||
\item A: 2 bytes of length data (a short in network byte order)
|
||||
\item B: a string of length found in A that contains operation in plain text
|
||||
operation are as follows:
|
||||
\begin{itemize}
|
||||
\item auth:User:Server:Password (check if a username/password pair is correct)
|
||||
\item isuser:User:Server (check if it's a valid user)
|
||||
\item setpass:User:Server:Password (set user's password)
|
||||
\item tryregister:User:Server:Password (try to register an account)
|
||||
\item removeuser:User:Server (remove this account)
|
||||
\item removeuser3:User:Server:Password (remove this account if the password is correct)
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item write to stdout: AABB
|
||||
\begin{itemize}
|
||||
\item A: the number 2 (coded as a short, which is bytes length of following result)
|
||||
\item B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
||||
Example python script
|
||||
\begin{verbatim}
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from struct import *
|
||||
|
||||
def from_ejabberd():
|
||||
input_length = sys.stdin.read(2)
|
||||
(size,) = unpack('>h', input_length)
|
||||
return sys.stdin.read(size).split(':')
|
||||
|
||||
def to_ejabberd(bool):
|
||||
answer = 0
|
||||
if bool:
|
||||
answer = 1
|
||||
token = pack('>hh', 2, answer)
|
||||
sys.stdout.write(token)
|
||||
sys.stdout.flush()
|
||||
|
||||
def auth(username, server, password):
|
||||
return True
|
||||
|
||||
def isuser(username, server):
|
||||
return True
|
||||
|
||||
def setpass(username, server, password):
|
||||
return True
|
||||
|
||||
while True:
|
||||
data = from_ejabberd()
|
||||
success = False
|
||||
if data[0] == "auth":
|
||||
success = auth(data[1], data[2], data[3])
|
||||
elif data[0] == "isuser":
|
||||
success = isuser(data[1], data[2])
|
||||
elif data[0] == "setpass":
|
||||
success = setpass(data[1], data[2], data[3])
|
||||
to_ejabberd(success)
|
||||
\end{verbatim}
|
||||
|
||||
\section{XML Representation}
|
||||
\label{xmlrepr}
|
||||
|
||||
Each XML stanza is represented as the following tuple:
|
||||
\begin{verbatim}
|
||||
XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
|
||||
Name = string()
|
||||
Attrs = [Attr]
|
||||
Attr = {Key, Val}
|
||||
Key = string()
|
||||
Val = string()
|
||||
ElementOrCDATA = XMLElement | CDATA
|
||||
CDATA = {xmlcdata, string()}
|
||||
\end{verbatim}
|
||||
E.\,g. this stanza:
|
||||
\begin{verbatim}
|
||||
<message to='test@conference.example.org' type='groupchat'>
|
||||
<body>test</body>
|
||||
</message>
|
||||
\end{verbatim}
|
||||
is represented as the following structure:
|
||||
\begin{verbatim}
|
||||
{xmlelement, "message",
|
||||
[{"to", "test@conference.example.org"},
|
||||
{"type", "groupchat"}],
|
||||
[{xmlelement, "body",
|
||||
[],
|
||||
[{xmlcdata, "test"}]}]}}
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
|
||||
\section{Module \texttt{xml}}
|
||||
\label{xmlmod}
|
||||
|
||||
\begin{description}
|
||||
\item{\verb|element_to_string(El) -> string()|}
|
||||
\begin{verbatim}
|
||||
El = XMLElement
|
||||
\end{verbatim}
|
||||
Returns string representation of XML stanza \texttt{El}.
|
||||
|
||||
\item{\verb|crypt(S) -> string()|}
|
||||
\begin{verbatim}
|
||||
S = string()
|
||||
\end{verbatim}
|
||||
Returns string which correspond to \texttt{S} with encoded XML special
|
||||
characters.
|
||||
|
||||
\item{\verb|remove_cdata(ECList) -> EList|}
|
||||
\begin{verbatim}
|
||||
ECList = [ElementOrCDATA]
|
||||
EList = [XMLElement]
|
||||
\end{verbatim}
|
||||
\texttt{EList} is a list of all non-CDATA elements of ECList.
|
||||
|
||||
|
||||
|
||||
\item{\verb|get_path_s(El, Path) -> Res|}
|
||||
\begin{verbatim}
|
||||
El = XMLElement
|
||||
Path = [PathItem]
|
||||
PathItem = PathElem | PathAttr | PathCDATA
|
||||
PathElem = {elem, Name}
|
||||
PathAttr = {attr, Name}
|
||||
PathCDATA = cdata
|
||||
Name = string()
|
||||
Res = string() | XMLElement
|
||||
\end{verbatim}
|
||||
If \texttt{Path} is empty, then returns \texttt{El}. Else sequentially
|
||||
consider elements of \texttt{Path}. Each element is one of:
|
||||
\begin{description}
|
||||
\item{\verb|{elem, Name}|} \texttt{Name} is name of subelement of
|
||||
\texttt{El}, if such element exists, then this element considered in
|
||||
following steps, else returns empty string.
|
||||
\item{\verb|{attr, Name}|} If \texttt{El} have attribute \texttt{Name}, then
|
||||
returns value of this attribute, else returns empty string.
|
||||
\item{\verb|cdata|} Returns CDATA of \texttt{El}.
|
||||
\end{description}
|
||||
|
||||
\item{TODO:}
|
||||
\begin{verbatim}
|
||||
get_cdata/1, get_tag_cdata/1
|
||||
get_attr/2, get_attr_s/2
|
||||
get_tag_attr/2, get_tag_attr_s/2
|
||||
get_subtag/2
|
||||
\end{verbatim}
|
||||
\end{description}
|
||||
|
||||
|
||||
\section{Module \texttt{xml\_stream}}
|
||||
\label{xmlstreammod}
|
||||
|
||||
\begin{description}
|
||||
\item{\verb!parse_element(Str) -> XMLElement | {error, Err}!}
|
||||
\begin{verbatim}
|
||||
Str = string()
|
||||
Err = term()
|
||||
\end{verbatim}
|
||||
Parses \texttt{Str} using XML parser, returns either parsed element or error
|
||||
tuple.
|
||||
\end{description}
|
||||
|
||||
|
||||
\section{Modules}
|
||||
\label{emods}
|
||||
|
||||
|
||||
%\subsection{gen\_mod behaviour}
|
||||
%\label{genmod}
|
||||
|
||||
%TBD
|
||||
|
||||
\subsection{Module gen\_iq\_handler}
|
||||
\label{geniqhandl}
|
||||
|
||||
The module \verb|gen_iq_handler| allows to easily write handlers for IQ packets
|
||||
of particular XML namespaces that addressed to server or to users bare JIDs.
|
||||
|
||||
In this module the following functions are defined:
|
||||
\begin{description}
|
||||
\item{\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|}
|
||||
\begin{verbatim}
|
||||
Component = Module = Function = atom()
|
||||
Host = NS = string()
|
||||
Type = no_queue | one_queue | parallel
|
||||
\end{verbatim}
|
||||
Registers function \verb|Module:Function| as handler for IQ packets on
|
||||
virtual host \verb|Host| that contain child of namespace \verb|NS| in
|
||||
\verb|Component|. Queueing discipline is \verb|Type|. There are at least
|
||||
two components defined:
|
||||
\begin{description}
|
||||
\item{\verb|ejabberd_local|} Handles packets that addressed to server JID;
|
||||
\item{\verb|ejabberd_sm|} Handles packets that addressed to users bare JIDs.
|
||||
\end{description}
|
||||
\item{\verb|remove_iq_handler(Component, Host, NS)|}
|
||||
\begin{verbatim}
|
||||
Component = atom()
|
||||
Host = NS = string()
|
||||
\end{verbatim}
|
||||
Removes IQ handler on virtual host \verb|Host| for namespace \verb|NS| from
|
||||
\verb|Component|.
|
||||
\end{description}
|
||||
|
||||
Handler function must have the following type:
|
||||
\begin{description}
|
||||
\item{\verb|Module:Function(From, To, IQ)|}
|
||||
\begin{verbatim}
|
||||
From = To = jid()
|
||||
\end{verbatim}
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
\begin{verbatim}
|
||||
-module(mod_cputime).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2,
|
||||
stop/1,
|
||||
process_local_iq/3]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
-define(NS_CPUTIME, "ejabberd:cputime").
|
||||
|
||||
start(Host, Opts) ->
|
||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
|
||||
?MODULE, process_local_iq, IQDisc).
|
||||
|
||||
stop(Host) ->
|
||||
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
|
||||
|
||||
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||
case Type of
|
||||
set ->
|
||||
{iq, ID, error, XMLNS,
|
||||
[SubEl, ?ERR_NOT_ALLOWED]};
|
||||
get ->
|
||||
CPUTime = element(1, erlang:statistics(runtime))/1000,
|
||||
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
|
||||
{iq, ID, result, XMLNS,
|
||||
[{xmlelement, "query",
|
||||
[{"xmlns", ?NS_CPUTIME}],
|
||||
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
|
||||
end.
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\subsection{Services}
|
||||
\label{services}
|
||||
|
||||
%TBD
|
||||
|
||||
|
||||
%TODO: use \verb|proc_lib|
|
||||
\begin{verbatim}
|
||||
-module(mod_echo).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2, init/1, stop/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
start(Host, Opts) ->
|
||||
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
|
||||
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
spawn(?MODULE, init, [MyHost])).
|
||||
|
||||
init(Host) ->
|
||||
ejabberd_router:register_local_route(Host),
|
||||
loop(Host).
|
||||
|
||||
loop(Host) ->
|
||||
receive
|
||||
{route, From, To, Packet} ->
|
||||
ejabberd_router:route(To, From, Packet),
|
||||
loop(Host);
|
||||
stop ->
|
||||
ejabberd_router:unregister_route(Host),
|
||||
ok;
|
||||
_ ->
|
||||
loop(Host)
|
||||
end.
|
||||
|
||||
stop(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
Proc ! stop,
|
||||
{wait, Proc}.
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
|
||||
\end{document}
|
||||
|
Before Width: | Height: | Size: 9.8 KiB |
@@ -1,143 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<meta name="generator" content="hevea 2.09">
|
||||
<style type="text/css">
|
||||
.li-itemize{margin:1ex 0ex;}
|
||||
.li-enumerate{margin:1ex 0ex;}
|
||||
.dd-description{margin:0ex 0ex 1ex 4ex;}
|
||||
.dt-description{margin:0ex;}
|
||||
.toc{list-style:none;}
|
||||
.footnotetext{margin:0ex; padding:0ex;}
|
||||
div.footnotetext P{margin:0px; text-indent:1em;}
|
||||
.thefootnotes{text-align:left;margin:0ex;}
|
||||
.dt-thefootnotes{margin:0em;}
|
||||
.dd-thefootnotes{margin:0em 0em 0em 2em;}
|
||||
.footnoterule{margin:1em auto 1em 0px;width:50%;}
|
||||
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
|
||||
.title{margin:2ex auto;text-align:center}
|
||||
.titlemain{margin:1ex 2ex 2ex 1ex;}
|
||||
.titlerest{margin:0ex 2ex;}
|
||||
.center{text-align:center;margin-left:auto;margin-right:auto;}
|
||||
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
|
||||
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
|
||||
td table{margin:auto;}
|
||||
table{border-collapse:collapse;}
|
||||
td{padding:0;}
|
||||
.cellpadding0 tr td{padding:0;}
|
||||
.cellpadding1 tr td{padding:1px;}
|
||||
pre{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
blockquote{margin-left:4ex;margin-right:4ex;text-align:left;}
|
||||
td p{margin:0px;}
|
||||
.boxed{border:1px solid black}
|
||||
.textboxed{border:1px solid black}
|
||||
.vbar{border:none;width:2px;background-color:black;}
|
||||
.hbar{border:none;height:2px;width:100%;background-color:black;}
|
||||
.hfill{border:none;height:1px;width:200%;background-color:black;}
|
||||
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
|
||||
.vdcell{white-space:nowrap;padding:0px; border:2px solid green;}
|
||||
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
|
||||
.dcell{white-space:nowrap;padding:0px; border:none;}
|
||||
.dcenter{margin:0ex auto;}
|
||||
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
|
||||
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
|
||||
.marginpar{border:solid thin black; width:20%; text-align:left;}
|
||||
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
|
||||
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
|
||||
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
|
||||
.part{margin:2ex auto;text-align:center}
|
||||
SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
|
||||
</style>
|
||||
<title>Ejabberd community 14.05-120-gedfb5fc Feature Sheet
|
||||
</title>
|
||||
</head>
|
||||
<body >
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex -->
|
||||
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
|
||||
|
||||
</p><table class="title"><tr><td style="padding:1ex"><h1 class="titlemain">Ejabberd community 14.05-120-gedfb5fc Feature Sheet</h1><h3 class="titlerest">Sander Devrieze <br>
|
||||
<a href="mailto:s.devrieze@pandora.be"><span style="font-family:monospace">mailto:s.devrieze@pandora.be</span></a> <br>
|
||||
<a href="xmpp:sander@devrieze.dyndns.org"><span style="font-family:monospace">xmpp:sander@devrieze.dyndns.org</span></a></h3></td></tr>
|
||||
</table><div class="center">
|
||||
|
||||
<img src="logo.png" alt="logo.png">
|
||||
|
||||
|
||||
</div><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup –
|
||||
Kevin Smith, Current maintainer of the Psi project</span></span></blockquote><p>Introduction
|
||||
<a id="intro"></a></p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. —
|
||||
Joeri</span></span></blockquote><p><span style="font-family:monospace">ejabberd</span> is a <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">free and open source</span></span></span> instant messaging server written in <a href="http://www.erlang.org/">Erlang/OTP</a>.</p><p><span style="font-family:monospace">ejabberd</span> is <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">cross-platform</span></span></span>, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</p><p><span style="font-family:monospace">ejabberd</span> is designed to be a <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">rock-solid and feature rich</span></span></span> XMPP server.</p><p><span style="font-family:monospace">ejabberd</span> is suitable for small deployments, whether they need to be <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">scalable</span></span></span> or not, as well as extremely big deployments.</p>
|
||||
<!--TOC section id="sec1" Key Features-->
|
||||
<h2 id="sec1" class="section">Key Features</h2><!--SEC END --><p>
|
||||
<a id="keyfeatures"></a>
|
||||
</p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">Erlang seems to be tailor-made for writing stable, robust servers. —
|
||||
Peter Saint-André, Executive Director of the Jabber Software Foundation</span></span></blockquote><p><span style="font-family:monospace">ejabberd</span> is:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
<span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Cross-platform:</span></span></span> <span style="font-family:monospace">ejabberd</span> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Distributed:</span></span></span> You can run <span style="font-family:monospace">ejabberd</span> on a cluster of machines and all of them will serve the same Jabber 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.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Fault-tolerant:</span></span></span> You can deploy an <span style="font-family:monospace">ejabberd</span> 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’.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Administrator Friendly:</span></span></span> <span style="font-family:monospace">ejabberd</span> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Comprehensive documentation.
|
||||
</li><li class="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </li><li class="li-itemize">Web Administration.
|
||||
</li><li class="li-itemize">Shared Roster Groups.
|
||||
</li><li class="li-itemize">Command line administration tool. </li><li class="li-itemize">Can integrate with existing authentication mechanisms.
|
||||
</li><li class="li-itemize">Capability to send announce messages.
|
||||
</li></ul></li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Internationalized:</span></span></span> <span style="font-family:monospace">ejabberd</span> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Translated to 25 languages. </li><li class="li-itemize">Support for <a href="http://www.ietf.org/rfc/rfc3490.txt">IDNA</a>.
|
||||
</li></ul></li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Open Standards:</span></span></span> <span style="font-family:monospace">ejabberd</span> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Fully XMPP compliant.
|
||||
</li><li class="li-itemize">XML-based protocol.
|
||||
</li><li class="li-itemize"><a href="http://www.ejabberd.im/protocols">Many protocols supported</a>.
|
||||
</li></ul></li></ul>
|
||||
<!--TOC section id="sec2" Additional Features-->
|
||||
<h2 id="sec2" class="section">Additional Features</h2><!--SEC END --><p>
|
||||
<a id="addfeatures"></a>
|
||||
</p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">ejabberd is making inroads to solving the "buggy incomplete server" problem —
|
||||
Justin Karneges, Founder of the Psi and the Delta projects</span></span></blockquote><p>Moreover, <span style="font-family:monospace">ejabberd</span> comes with a wide range of other state-of-the-art features:
|
||||
</p><ul class="itemize"><li class="li-itemize">
|
||||
Modular
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Load only the modules you want.
|
||||
</li><li class="li-itemize">Extend <span style="font-family:monospace">ejabberd</span> with your own custom modules.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Security
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
SASL and STARTTLS for c2s and s2s connections.
|
||||
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
|
||||
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Databases
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal database for fast deployment (Mnesia).
|
||||
</li><li class="li-itemize">Native MySQL support.
|
||||
</li><li class="li-itemize">Native PostgreSQL support.
|
||||
</li><li class="li-itemize">ODBC data storage support.
|
||||
</li><li class="li-itemize">Microsoft SQL Server support. </li><li class="li-itemize">Riak NoSQL database support.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Authentication
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal Authentication.
|
||||
</li><li class="li-itemize">PAM, LDAP, ODBC and Riak. </li><li class="li-itemize">External Authentication script.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Others
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Support for virtual hosting.
|
||||
</li><li class="li-itemize">Compressing XML streams with Stream Compression (<a href="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</a>).
|
||||
</li><li class="li-itemize">Statistics via Statistics Gathering (<a href="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</a>).
|
||||
</li><li class="li-itemize">IPv6 support both for c2s and s2s connections.
|
||||
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</a> module with support for clustering and HTML logging. </li><li class="li-itemize">Users Directory based on users vCards.
|
||||
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</a> component with support for <a href="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</a>.
|
||||
</li><li class="li-itemize">Support for web clients: <a href="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</a> and <a href="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</a> services.
|
||||
</li><li class="li-itemize">IRC transport.
|
||||
</li><li class="li-itemize">SIP support.
|
||||
</li><li class="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
</li></ul>
|
||||
</li></ul><!--CUT END -->
|
||||
<!--HTMLFOOT-->
|
||||
<!--ENDHTML-->
|
||||
<!--FOOTER-->
|
||||
<hr style="height:2"><blockquote class="quote"><em>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</em><a href="http://hevea.inria.fr/index.html"><em>H</em><em><span style="font-size:small"><sup>E</sup></span></em><em>V</em><em><span style="font-size:small"><sup>E</sup></span></em><em>A</em></a><em>.</em></blockquote></body>
|
||||
</html>
|
||||
@@ -1,136 +0,0 @@
|
||||
\documentclass[a4paper,10pt]{article}
|
||||
|
||||
%% Packages
|
||||
\usepackage{epsfig}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{graphics}
|
||||
\usepackage{hevea}
|
||||
\usepackage[pdftex,colorlinks,unicode,urlcolor=blue,linkcolor=blue,pdftitle=Ejabberd\
|
||||
Feature\ Sheet,pdfauthor=Sander\
|
||||
Devrieze,pdfsubject=ejabberd,pdfkeywords=ejabberd]{hyperref}
|
||||
\usepackage{verbatim}
|
||||
\usepackage{color}
|
||||
|
||||
%% Index
|
||||
% Remove the index anchors from the HTML version to save size and bandwith.
|
||||
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
|
||||
|
||||
%% Images
|
||||
\newcommand{\logoscale}{0.7}
|
||||
\newcommand{\imgscale}{0.58}
|
||||
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
|
||||
\newcommand{\insscaleimg}[2]{
|
||||
\imgsrc{#2}{}
|
||||
\begin{latexonly}
|
||||
\scalebox{#1}{\includegraphics{#2}}
|
||||
\end{latexonly}
|
||||
}
|
||||
|
||||
%% Various
|
||||
\newcommand{\bracehack}{\def\{{\char"7B}\def\}{\char"7D}}
|
||||
\newcommand{\titem}[1]{\item[\bracehack\texttt{#1}]}
|
||||
\newcommand{\ns}[1]{\texttt{#1}}
|
||||
\newcommand{\jid}[1]{\texttt{#1}}
|
||||
\newcommand{\option}[1]{\texttt{#1}}
|
||||
\newcommand{\poption}[1]{{\bracehack\texttt{#1}}}
|
||||
\newcommand{\node}[1]{\texttt{#1}}
|
||||
\newcommand{\term}[1]{\texttt{#1}}
|
||||
\newcommand{\shell}[1]{\texttt{#1}}
|
||||
\newcommand{\ejabberd}{\texttt{ejabberd}}
|
||||
\newcommand{\Jabber}{Jabber}
|
||||
|
||||
%% Title page
|
||||
\include{version}
|
||||
\title{Ejabberd \version\ Feature Sheet}
|
||||
\author{Sander Devrieze \\
|
||||
\ahrefurl{mailto:s.devrieze@pandora.be} \\
|
||||
\ahrefurl{xmpp:sander@devrieze.dyndns.org}}
|
||||
|
||||
% Options
|
||||
\newcommand{\marking}[1]{\textbf{\begin{large}\textcolor{ejblue}{#1}\end{large}}} % Marking enabled
|
||||
\newcommand{\quoting}[2][yozhik]{\begin{quotation}\textcolor{#1}{\textit{#2}}\end{quotation}} % Quotes enabled
|
||||
\newcommand{\new}{\marginpar{\textcolor{red}{\textsc{new}}}} % Highlight new features
|
||||
\newcommand{\improved}{\marginpar{\textcolor{orange}{\textsc{improved}}}} % Highlight improved features
|
||||
\setcounter{secnumdepth}{-1} % Disable section numbering
|
||||
|
||||
%% To by-pass errors in the HTML version.
|
||||
\newstyle{SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;}
|
||||
\definecolor{orange} {cmyk}{0.000,0.333,1.000,0.000}
|
||||
|
||||
%% Footnotes
|
||||
\begin{latexonly}
|
||||
\global\parskip=9pt plus 3pt minus 1pt
|
||||
\global\parindent=0pt
|
||||
\gdef\ahrefurl#1{\href{#1}{\texttt{#1}}}
|
||||
\gdef\footahref#1#2{#2\footnote{\href{#1}{\texttt{#1}}}}
|
||||
\end{latexonly}
|
||||
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
|
||||
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
|
||||
|
||||
%% Fancy header
|
||||
\fancyhf{}
|
||||
\pagestyle{fancy}
|
||||
\rhead{\textcolor{ejblue}{The Expandable Jabber/XMPP Daemon.}}
|
||||
\renewcommand{\headrule}{{\color{ejblue}%
|
||||
\hrule width\headwidth height\headrulewidth \vskip-\headrulewidth}}
|
||||
\lhead{\setlength{\unitlength}{-6mm}
|
||||
\begin{picture}(0,0)
|
||||
\put(5.8,3.25){\includegraphics[width=1.3\textwidth]{yozhikheader.png}}
|
||||
\end{picture}}
|
||||
|
||||
% Official ejabberd colours
|
||||
\definecolor{ejblue} {cmyk}{1.000,0.831,0.000,0.537} %RGB: 0,0,118 HTML: 000076
|
||||
\definecolor{ejgreenyellow}{cmyk}{0.079,0.000,0.275,0.102} %RGB: 209,229,159 HTML: d1e59f
|
||||
\definecolor{ejgreendark} {cmyk}{0.131,0.000,0.146,0.220} %RGB: 166,199,162 HTML: a6c7a2
|
||||
\definecolor{ejgreen} {cmyk}{0.077,0.000,0.081,0.078} %RGB: 216,236,215 HTML: d8ecd7
|
||||
\definecolor{ejgreenwhite} {cmyk}{0.044,0.000,0.048,0.020} %RGB: 239,250,238 HTML: effaee
|
||||
\definecolor{yozhik} {cmyk}{0.000,0.837,1.000,0.424} %RGB: 147,0,0 HTML: 930000
|
||||
|
||||
\begin{document}
|
||||
|
||||
\label{titlepage}
|
||||
\begin{titlepage}
|
||||
\maketitle{}
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\begin{center}
|
||||
{\insscaleimg{\logoscale}{logo.png}
|
||||
\par
|
||||
}
|
||||
\end{center}
|
||||
\quoting{I can thoroughly recommend ejabberd for ease of setup --
|
||||
Kevin Smith, Current maintainer of the Psi project}
|
||||
|
||||
\end{titlepage}
|
||||
|
||||
\newpage
|
||||
% Set the page counter to 2 so that the titlepage and the second page do not
|
||||
% have the same page number. This fixes the PDFLaTeX warning "destination with
|
||||
% the same identifier".
|
||||
\begin{latexonly}
|
||||
\setcounter{page}{2}
|
||||
\pagecolor{ejgreenwhite}
|
||||
\end{latexonly}
|
||||
|
||||
% Input introduction.tex
|
||||
\input{introduction}
|
||||
|
||||
\end{document}
|
||||
|
||||
%% TODO
|
||||
% * illustrations (e.g. screenshot from web interface)
|
||||
% * commented parts
|
||||
% * slides, guide and html version
|
||||
% * cleaning and improving LaTeX code
|
||||
% * key features: something like this (shorter)? (more focussed on Erlang now): "To reach the goal of high
|
||||
% availability, performance and clustering, ejabberd is written in Erlang, a programming language perfectly
|
||||
% suited for this. Besides that, some parts are written in C to also incude the advantages of this language. In
|
||||
% short, ejabberd is a perfect mix of mainly Erlang code, peppered with some C code to get the final touch!"
|
||||
% <picture of a cocktail>
|
||||
% * key features: saying that ejabberd the only XMPP server is that can do real clustering:
|
||||
% http://www.jivesoftware.org/forums/thread.jspa?threadID=14602
|
||||
% "What I find interesting is that *no* XMPP servers truly provide clustering. This includes all the commercial
|
||||
% servers. The one partial exception appears to be ejabberd, which can cluster certain data such as sessions,
|
||||
% but not all services such as MUC."
|
||||
% * try it today: links to migration tutorials
|
||||
@@ -1,105 +0,0 @@
|
||||
digraph messages {
|
||||
//concentrate=true;
|
||||
subgraph clusterclients {
|
||||
client1 [shape = box];
|
||||
client2 [shape = box];
|
||||
client3 [shape = box];
|
||||
|
||||
style = dashed;
|
||||
label = "Clients";
|
||||
}
|
||||
|
||||
subgraph clusternode1 {
|
||||
subgraph clusterc2s1 {
|
||||
c2s11;
|
||||
c2s12;
|
||||
style = invis;
|
||||
}
|
||||
subgraph clusterservices1 {
|
||||
service11;
|
||||
service12;
|
||||
service13;
|
||||
style = invis;
|
||||
}
|
||||
//subgraph clusters2s1 {
|
||||
//s2s11;
|
||||
//s2s12;
|
||||
//style = invis;
|
||||
//}
|
||||
c2s11 -> auth1;
|
||||
c2s12 -> auth1;
|
||||
auth1 -> c2s11;
|
||||
auth1 -> c2s12;
|
||||
c2s11 -> sm1;
|
||||
c2s11 -> router1;
|
||||
c2s12 -> sm1;
|
||||
c2s12 -> router1;
|
||||
router1 -> local1;
|
||||
router1 -> service11;
|
||||
router1 -> service12;
|
||||
router1 -> service13;
|
||||
router1 -> s2s11;
|
||||
router1 -> s2s12;
|
||||
service11 -> router1;
|
||||
service12 -> router1;
|
||||
service13 -> router1;
|
||||
s2s11 -> router1;
|
||||
s2s12 -> router1;
|
||||
local1 -> sm1;
|
||||
sm1 -> c2s11;
|
||||
sm1 -> c2s12;
|
||||
|
||||
style = dashed;
|
||||
label = "Node1";
|
||||
}
|
||||
|
||||
subgraph clusternode2 {
|
||||
c2s2 -> auth2;
|
||||
auth2 -> c2s2;
|
||||
c2s2 -> sm2;
|
||||
c2s2 -> router2;
|
||||
router2 -> local2;
|
||||
router2 -> service21;
|
||||
router2 -> s2s21;
|
||||
service21 -> router2;
|
||||
s2s21 -> router2;
|
||||
local2 -> sm2;
|
||||
sm2 -> c2s2;
|
||||
|
||||
style = dashed;
|
||||
label = "Node2";
|
||||
}
|
||||
|
||||
|
||||
|
||||
subgraph clusterservers {
|
||||
server1 [shape = box];
|
||||
server2 [shape = box];
|
||||
server3 [shape = box];
|
||||
|
||||
style = dashed;
|
||||
label = "Servers";
|
||||
}
|
||||
|
||||
|
||||
client1 -> c2s11;
|
||||
client2 -> c2s12;
|
||||
client3 -> c2s2;
|
||||
c2s11 -> client1 [constraint=false];
|
||||
c2s12 -> client2 [constraint=false];
|
||||
c2s2 -> client3 [constraint=false];
|
||||
|
||||
s2s11 -> server1 [minlen = 2];
|
||||
s2s12 -> server2 [minlen = 2];
|
||||
s2s21 -> server3 [minlen = 2];
|
||||
server1 -> s2s11 [constraint=false];
|
||||
server2 -> s2s12 [constraint=false];
|
||||
server3 -> s2s21 [constraint=false];
|
||||
|
||||
router1 -> router2;
|
||||
router2 -> router1;
|
||||
sm1 -> sm2;
|
||||
sm2 -> sm1;
|
||||
|
||||
label = "Data Flows";
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
\chapter{Introduction}
|
||||
\label{intro}
|
||||
|
||||
%% TODO: improve the feature sheet with a nice table to highlight new features.
|
||||
|
||||
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. ---
|
||||
Joeri}
|
||||
|
||||
%ejabberd is a free and open source instant messaging server written in Erlang. ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication (Jabber/XMPP).
|
||||
|
||||
\ejabberd{} is a \marking{free and open source} instant messaging server written in \footahref{http://www.erlang.org/}{Erlang/OTP}.
|
||||
|
||||
\ejabberd{} is \marking{cross-platform}, distributed, fault-tolerant, and based on open standards to achieve real-time communication.
|
||||
|
||||
\ejabberd{} is designed to be a \marking{rock-solid and feature rich} XMPP server.
|
||||
|
||||
\ejabberd{} is suitable for small deployments, whether they need to be \marking{scalable} or not, as well as extremely big deployments.
|
||||
|
||||
%\subsection{Layout with example deployment (title needs a better name)}
|
||||
%\label{layout}
|
||||
|
||||
%In this section there will be a graphical overview like these:\\
|
||||
%\verb|http://www.tipic.com/var/timp/timp_dep.gif| \\
|
||||
%\verb|http://www.jabber.com/images/jabber_Com_Platform.jpg| \\
|
||||
%\verb|http://www.antepo.com/files/OPN45systemdatasheet.pdf| \\
|
||||
|
||||
%A page full with names of Jabber client that are known to work with ejabberd. \begin{tiny}tiny font\end{tiny}
|
||||
|
||||
%\subsection{Try It Today}
|
||||
%\label{trytoday}
|
||||
|
||||
%(Not sure if I will include/finish this section for the next version.)
|
||||
|
||||
%\begin{itemize}
|
||||
%\item Erlang REPOS
|
||||
%\item Packages in distributions
|
||||
%\item Windows binary
|
||||
%\item source tar.gz
|
||||
%\item Migration from Jabberd14 (and so also Jabberd2 because you can migrate from version 2 back to 14) and Jabber Inc. XCP possible.
|
||||
%\end{itemize}
|
||||
|
||||
\newpage
|
||||
\section{Key Features}
|
||||
\label{keyfeatures}
|
||||
\ind{features!key features}
|
||||
|
||||
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. ---
|
||||
Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
|
||||
|
||||
\ejabberd{} is:
|
||||
\begin{itemize}
|
||||
\item \marking{Cross-platform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
|
||||
|
||||
\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve the same \Jabber{} 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.
|
||||
|
||||
\item \marking{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'.
|
||||
|
||||
\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
|
||||
\begin{itemize}
|
||||
\item Comprehensive documentation.
|
||||
\item Straightforward installers for Linux, Mac OS X, and Windows. %%\improved{}
|
||||
\item Web Administration.
|
||||
\item Shared Roster Groups.
|
||||
\item Command line administration tool. %%\improved{}
|
||||
\item Can integrate with existing authentication mechanisms.
|
||||
\item Capability to send announce messages.
|
||||
\end{itemize}
|
||||
|
||||
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
\begin{itemize}
|
||||
\item Translated to 25 languages. %%\improved{}
|
||||
\item Support for \footahref{http://tools.ietf.org/html/rfc3490}{IDNA}.
|
||||
\end{itemize}
|
||||
|
||||
\item \marking{Open Standards:} \ejabberd{} is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
|
||||
\begin{itemize}
|
||||
\item Fully XMPP compliant.
|
||||
\item XML-based protocol.
|
||||
\item \footahref{http://www.ejabberd.im/protocols}{Many protocols supported}.
|
||||
\end{itemize}
|
||||
|
||||
\end{itemize}
|
||||
|
||||
\newpage
|
||||
|
||||
\section{Additional Features}
|
||||
\label{addfeatures}
|
||||
\ind{features!additional features}
|
||||
|
||||
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem ---
|
||||
Justin Karneges, Founder of the Psi and the Delta projects}
|
||||
|
||||
Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features:
|
||||
\begin{itemize}
|
||||
\item Modular
|
||||
\begin{itemize}
|
||||
\item Load only the modules you want.
|
||||
\item Extend \ejabberd{} with your own custom modules.
|
||||
\end{itemize}
|
||||
\item Security
|
||||
\begin{itemize}
|
||||
\item SASL and STARTTLS for c2s and s2s connections.
|
||||
\item STARTTLS and Dialback s2s connections.
|
||||
\item Web Admin accessible via HTTPS secure access.
|
||||
\end{itemize}
|
||||
\item Databases
|
||||
\begin{itemize}
|
||||
\item Internal database for fast deployment (Mnesia).
|
||||
\item Native MySQL support.
|
||||
\item Native PostgreSQL support.
|
||||
\item ODBC data storage support.
|
||||
\item Microsoft SQL Server support. %%\new{}
|
||||
\item Riak NoSQL database support.
|
||||
\end{itemize}
|
||||
\item Authentication
|
||||
\begin{itemize}
|
||||
\item Internal Authentication.
|
||||
\item PAM, LDAP, ODBC and Riak. %%\improved{}
|
||||
\item External Authentication script.
|
||||
\end{itemize}
|
||||
\item Others
|
||||
\begin{itemize}
|
||||
\item Support for virtual hosting.
|
||||
\item Compressing XML streams with Stream Compression (\xepref{0138}).
|
||||
\item Statistics via Statistics Gathering (\xepref{0039}).
|
||||
\item IPv6 support both for c2s and s2s connections.
|
||||
\item \txepref{0045}{Multi-User Chat} module with support for clustering and HTML logging. %%\improved{}
|
||||
\item Users Directory based on users vCards.
|
||||
\item \txepref{0060}{Publish-Subscribe} component with support for \txepref{0163}{Personal Eventing via Pubsub}.
|
||||
\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services.
|
||||
\item IRC transport.
|
||||
\item SIP support.
|
||||
\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,62 +0,0 @@
|
||||
Release notes
|
||||
ejabberd 0.9.1
|
||||
|
||||
This document describes the main changes from [25]ejabberd 0.9.
|
||||
|
||||
The code can be downloaded from the [26]download page.
|
||||
|
||||
For more detailed information, please refer to ejabberd [27]User Guide.
|
||||
|
||||
|
||||
Groupchat (Multi-user chat and IRC) improvements
|
||||
|
||||
The multi-user chat code has been improved to comply with the latest version
|
||||
of Jabber Enhancement Proposal 0045.
|
||||
|
||||
The IRC (Internet Relay Chat) features now support WHOIS and USERINFO
|
||||
requests.
|
||||
|
||||
|
||||
Web interface
|
||||
|
||||
ejabberd modules management features have been added to the web interface.
|
||||
They now allow to start or stop extension module without restarting the
|
||||
ejabberd server.
|
||||
|
||||
|
||||
Publish and subscribe
|
||||
|
||||
It is now possible to a subscribe node with a JabberID that includes a
|
||||
resource.
|
||||
|
||||
|
||||
Translations
|
||||
|
||||
A new script has been included to help translate ejabberd into new languages
|
||||
and maintain existing translations.
|
||||
|
||||
As a result, ejabberd is now translating into 10 languages:
|
||||
* Dutch
|
||||
* English
|
||||
* French
|
||||
* German
|
||||
* Polish
|
||||
* Portuguese
|
||||
* Russian
|
||||
* Spanish
|
||||
* Swedish
|
||||
* Ukrainian
|
||||
|
||||
|
||||
Migration
|
||||
|
||||
No changes have been made to the database. No particular conversion steps
|
||||
are needed. However, you should backup your database before upgrading to a
|
||||
new ejabberd version.
|
||||
|
||||
|
||||
Bugfixes
|
||||
|
||||
This release contains several bugfixes and architectural changes. Please
|
||||
refer to the Changelog file supplied with this release for details of all
|
||||
improvements in the ejabberd code.
|
||||
@@ -1,99 +0,0 @@
|
||||
Release notes
|
||||
ejabberd 0.9.8
|
||||
2005-08-01
|
||||
|
||||
This document describes the main changes in ejabberd 0.9.8. This
|
||||
version prepares the way for the release of ejabberd 1.0, which
|
||||
is due later this year.
|
||||
|
||||
The code can be downloaded from the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
For more detailed information, please refer to ejabberd User Guide
|
||||
on the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs.html
|
||||
|
||||
|
||||
Recent changes include....
|
||||
|
||||
|
||||
Enhanced virtual hosting
|
||||
|
||||
Virtual hosting applies to many more setting options and
|
||||
features and is transparent. Virtual hosting accepts different
|
||||
parameters for different virtual hosts regarding the following
|
||||
features: authentication method, access control lists and access
|
||||
rules, users management, statistics, and shared roster. The web
|
||||
interface gives access to each virtual host's parameters.
|
||||
|
||||
|
||||
Enhanced Publish-Subscribe module
|
||||
|
||||
ejabberd's Publish-Subscribe module integrates enhancements
|
||||
coming from J-EAI, an XMPP-based integration server built on
|
||||
ejabberd. ejabberd thus supports Publish-Subscribe node
|
||||
configuration. It is possible to define nodes that should be
|
||||
persistent, and the number of items to persist. Besides that, it
|
||||
is also possible to define various notification parameters, such
|
||||
as the delivery of the payload with the notifications, and the
|
||||
notification of subscribers when some changes occur on items.
|
||||
Other examples are: the maximum size of the items payload, the
|
||||
subscription approvers, the limitation of the notification to
|
||||
online users only, etc.
|
||||
|
||||
|
||||
Code reorganisation and update
|
||||
|
||||
- The mod_register module has been cleaned up.
|
||||
- ODBC support has been updated and several bugs have been fixed.
|
||||
|
||||
|
||||
Development API
|
||||
|
||||
To ease the work of Jabber/XMPP developers, a filter_packet hook
|
||||
has been added. As a result it is possible to develop plugins to
|
||||
filter or modify packets flowing through ejabberd.
|
||||
|
||||
|
||||
Translations
|
||||
|
||||
- Translations have been updated to support the new Publish-Subscribe features.
|
||||
- A new Brazilian Portuguese translation has been contributed.
|
||||
|
||||
|
||||
Web interface
|
||||
|
||||
- The CSS stylesheet from the web interface is W3C compliant.
|
||||
|
||||
|
||||
Installers
|
||||
|
||||
Installers are provided for Microsoft Windows and Linux/x86. The
|
||||
Linux installer includes Erlang ASN.1 modules for LDAP
|
||||
authentication support.
|
||||
|
||||
|
||||
Bugfixes
|
||||
|
||||
- This release contains several bugfixes and architectural
|
||||
changes. Among other bugfixes include improvements in LDAP
|
||||
authentication. Please refer to the ChangeLog file supplied
|
||||
with this release regarding all improvements in ejabberd.
|
||||
|
||||
|
||||
References
|
||||
|
||||
The ejabberd feature sheet helps comparing with other Jabber/XMPP
|
||||
servers:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs/features.pdf
|
||||
|
||||
Contributed tutorials of interest are:
|
||||
- Migration from Jabberd1.4 to ejabberd:
|
||||
http://ejabberd.jabber.ru/jabberd1-to-ejabberd
|
||||
- Migration from Jabberd2 to ejabberd:
|
||||
http://ejabberd.jabber.ru/jabberd2-to-ejabberd
|
||||
- Transport configuration for connecting to other networks:
|
||||
http://ejabberd.jabber.ru/tutorials-transports
|
||||
|
||||
END
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
Release notes
|
||||
ejabberd 0.9
|
||||
|
||||
This document describes the major new features of and changes to
|
||||
ejabberd 0.9, compared to latest public release ejabber 0.7.5.
|
||||
|
||||
For more detailed information, please refer to ejabberd User
|
||||
Guide.
|
||||
|
||||
|
||||
Virtual Hosting
|
||||
|
||||
ejabberd now can host several domain on the same instance.
|
||||
This option is enabled by using:
|
||||
|
||||
{hosts, ["erlang-projects.org", "erlang-fr.org"]}.
|
||||
|
||||
instead of the previous host directive.
|
||||
|
||||
Note that you are now using a list of hosts. The main one should
|
||||
be the first listed. See migration section further in this release
|
||||
note for details.
|
||||
|
||||
|
||||
Shared Roster
|
||||
|
||||
Shared roster is a new feature that allow the ejabberd
|
||||
administrator to add jabber user that will be present in the
|
||||
roster of every users on the server.
|
||||
Shared roster are enabled by adding:
|
||||
|
||||
{mod_shared_roster, []}
|
||||
|
||||
at the end of your module list in your ejabberd.cfg file.
|
||||
|
||||
|
||||
PostgreSQL (ODBC) support
|
||||
|
||||
This feature is experimental and not yet properly documented. This
|
||||
feature is released for testing purpose.
|
||||
|
||||
You need to have Erlang/OTP R10 to compile with ODBC on various
|
||||
flavour of *nix. You should use Erlang/OTP R10B-4, as this task
|
||||
has became easier with this release. It comes already build in
|
||||
Erlang/OTP Microsoft Windows binary.
|
||||
|
||||
PostgreSQL support is enabled by using the following module in
|
||||
ejabberd.cfg instead of their standard counterpart:
|
||||
|
||||
mod_last_odbc.erl
|
||||
mod_offline_odbc.erl
|
||||
mod_roster_odbc.erl
|
||||
|
||||
The database schema is located in the src/odbc/pq.sql file.
|
||||
|
||||
Look at the src/ejabberd.cfg.example file for more information on
|
||||
how to configure ejabberd with odbc support. You can get support
|
||||
on how to configure ejabberd with a relational database.
|
||||
|
||||
|
||||
Migration from ejabberd 0.7.5
|
||||
|
||||
Migration is pretty straightforward as Mnesia database schema
|
||||
conversions is handled automatically. Remember however that you
|
||||
must backup your ejabberd database before migration.
|
||||
|
||||
Here are the following steps to proceed:
|
||||
|
||||
1. Stop your instance of ejabberd.
|
||||
|
||||
2. In ejabberd.cfg, define the host lists. Change the host
|
||||
directive to the hosts one:
|
||||
Before:
|
||||
{host, "erlang-projects.org"}.
|
||||
After:
|
||||
{hosts, ["erlang-projects.org", "erlang-fr.org"]}.
|
||||
Note that when you restart the server the existing users will be
|
||||
affected to the first virtual host, so the order is important. You
|
||||
should keep the previous hostname as the first virtual host.
|
||||
|
||||
3. Restart ejabberd.
|
||||
|
||||
|
||||
Bugfixes
|
||||
|
||||
This release contains several bugfixes and architectural changes.
|
||||
Please refer to the Changelog file supplied with this release for
|
||||
details of all improvements in the ejabberd code.
|
||||
@@ -1,120 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.0.0
|
||||
14 December 2005
|
||||
|
||||
This document describes the main changes in ejabberd 1.0.0. Unique in this
|
||||
version is the compliancy with the XMPP (eXtensible Messaging and Presence
|
||||
Protocol) standard. ejabberd is the first Open Source Jabber server claiming
|
||||
to fully comply to the XMPP standard.
|
||||
|
||||
ejabberd can be downloaded from the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
Detailed information can be found in the ejabberd Feature Sheet and User
|
||||
Guide which are available on the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs.html
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
|
||||
Server-to-server Encryption for Enhanced Security
|
||||
|
||||
- Support for STARTTLS and SASL EXTERNAL to secure server-to-server traffic
|
||||
has been added.
|
||||
- Also, STARTTLS and Dialback has been implemented for server-to-server (s2s)
|
||||
connections. Detailed information about these new features can be found on
|
||||
http://ejabberd.jabber.ru/s2s-encryption
|
||||
- commonName and dNSName fields matching were introduced to ease the process
|
||||
of retrieving certificates.
|
||||
- Different certificates can be defined for each virtual host.
|
||||
|
||||
ODBC Support
|
||||
|
||||
- ODBC support has been improved to allow production use of ejabberd with
|
||||
relational databases.
|
||||
- Support for vCard storage in ODBC has been added.
|
||||
- ejd2odbc.erl is a tool to convert an installation from Erlang's database
|
||||
Mnesia to an ODBC compatible relational database.
|
||||
|
||||
Native PostgreSQL Support
|
||||
|
||||
- Native PostgreSQL support gives you a better performance when you use
|
||||
PostgreSQL.
|
||||
|
||||
Shared Roster groups
|
||||
|
||||
- Shared Roster groups support has been enhanced. New is the ability to add
|
||||
all registered users to everyone's roster. Detailed information about this
|
||||
new feature can be found on http://ejabberd.jabber.ru/shared-roster-all
|
||||
|
||||
Web Interface
|
||||
|
||||
- The web interface internal code has been modified for better integration
|
||||
and compliancy with J-EAI, an ejabberd-based Enterprise Application
|
||||
Integration platform.
|
||||
- More XHTML 1.0 Transitional compliancy work was done.
|
||||
|
||||
Transports
|
||||
|
||||
- A transport workaround can be enabled during compilation. To do this, you
|
||||
can pass the "--enable-roster-gateway-workaround" option to the configure
|
||||
script. (./configure --enable-roster-gateway-workaround)
|
||||
This option allows transports to add items with subscription "to" in the
|
||||
roster by sending <presence type='subscribed'/> stanza to user. This option
|
||||
is only needed for JIT ICQ transport.
|
||||
Warning: by enabling this option, ejabberd will not be fully XMPP compliant
|
||||
anymore.
|
||||
|
||||
Documentation and Internationalization
|
||||
|
||||
- Documentation has been extended to cover more topics.
|
||||
- Translations have been updated.
|
||||
|
||||
Bugfixes
|
||||
|
||||
- This release contains several bugfixes.
|
||||
- Among other bugfixes include improvements to the client-to-server (c2s)
|
||||
connection management module.
|
||||
- Please refer to the ChangeLog file supplied
|
||||
with this release regarding all improvements in ejabberd.
|
||||
|
||||
|
||||
Installation Notes
|
||||
|
||||
|
||||
Supported Erlang Version
|
||||
|
||||
- You need at least Erlang/OTP R9C to run ejabberd 1.0.0.
|
||||
|
||||
Installation
|
||||
|
||||
Installers are provided for Microsoft Windows and Linux/x86.
|
||||
Installers can be retrieved from:
|
||||
http://www.process-one.net/en/projects/ejabberd/download.html
|
||||
|
||||
Migration Notes
|
||||
|
||||
- Before any migration, ejabberd system and database must be properly
|
||||
backed up.
|
||||
- When upgrading an ODBC-based installation, you will need to change the
|
||||
relational database schema. The following SQL commands must be run on the
|
||||
database:
|
||||
CREATE SEQUENCE spool_seq_seq;
|
||||
ALTER TABLE spool ADD COLUMN seq integer;
|
||||
ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
|
||||
UPDATE spool SET seq = DEFAULT;
|
||||
ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
|
||||
|
||||
References
|
||||
|
||||
Contributed tutorials of interest are:
|
||||
- Migration from Jabberd1.4 to ejabberd:
|
||||
http://ejabberd.jabber.ru/jabberd1-to-ejabberd
|
||||
- Migration from Jabberd2 to ejabberd:
|
||||
http://ejabberd.jabber.ru/jabberd2-to-ejabberd
|
||||
- Transport configuration for connecting to other networks:
|
||||
http://ejabberd.jabber.ru/tutorials-transports
|
||||
|
||||
END
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.1.0
|
||||
24 April 2006
|
||||
|
||||
This document describes the main changes in ejabberd 1.1.0. This version
|
||||
introduce new features including support for new Jabber Enhancement
|
||||
Proposals and several performance improvements enabling deployments on an
|
||||
even larger scale than already possible.
|
||||
|
||||
ejabberd can be downloaded from the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
Detailed information can be found in the ejabberd Feature Sheet and User
|
||||
Guide which are available on the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs.html
|
||||
|
||||
A complete list of changes is available from:
|
||||
http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
|
||||
New Jabber Enhancement Proposal support:
|
||||
|
||||
- JEP-0050: Ad-Hoc Commands.
|
||||
- JEP-0138: Stream Compression.
|
||||
- JEP-0175: SASL anonymous.
|
||||
|
||||
Anonymous login
|
||||
|
||||
- SASL anonymous.
|
||||
- Anonymous login for clients that do not yet support SASL Anonymous.
|
||||
|
||||
Relational database Support
|
||||
|
||||
- MySQL is now fully supported through ODBC and in native mode.
|
||||
- Various improvements to the native database interfaces.
|
||||
- The migration tool can use relational databases.
|
||||
|
||||
Multi-User Chat improvements
|
||||
|
||||
- Logging of room discussion to text file is now supported.
|
||||
- Better reconfiguration support.
|
||||
- Security oriented fixes.
|
||||
- Several improvements and updates to latest JEP-0045.
|
||||
|
||||
Performance scalability improvements for large clusters
|
||||
|
||||
- Improved session synchronisation management between cluster nodes.
|
||||
- Internal architecture has been reworked to use generalize Erlang/OTP
|
||||
framework usage.
|
||||
- Speed improvement on logger.
|
||||
- TCP/IP packet reception change for better network throttling and
|
||||
regulation.
|
||||
As a result, these improvements will reduce load on large scale deployments.
|
||||
|
||||
XMPP Protocol related improvements
|
||||
|
||||
- XML stanza size can be limited.
|
||||
- Messages are send to all resources with the same highest priority.
|
||||
|
||||
Documentation and Internationalization
|
||||
|
||||
- Documentation has been extended to cover more topics.
|
||||
- Translations have been updated.
|
||||
|
||||
Web interface
|
||||
|
||||
- XHTML 1.0 compliance.
|
||||
|
||||
Bugfixes
|
||||
|
||||
- This release contains many bugfixes on various areas such as Publish-Subscribe, build
|
||||
chain, installers, IRC gateway, ejabberdctl, amongst others.
|
||||
- Please refer to the ChangeLog file supplied with this release regarding
|
||||
all improvements in ejabberd.
|
||||
|
||||
|
||||
|
||||
Installation Notes
|
||||
|
||||
Supported Erlang Version
|
||||
|
||||
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0.
|
||||
|
||||
Installation
|
||||
|
||||
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
|
||||
Installers can be retrieved from:
|
||||
http://www.process-one.net/en/projects/ejabberd/download.html
|
||||
|
||||
Migration Notes
|
||||
|
||||
- Before any migration, ejabberd system and database must be properly
|
||||
backed up.
|
||||
- The database schema has not been changed comparing to version 1.0.0 and
|
||||
consequently it does not require any migration.
|
||||
|
||||
|
||||
References
|
||||
|
||||
Contributed tutorials and documents of interest are:
|
||||
- Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd:
|
||||
http://ejabberd.jabber.ru/migrate-to-ejabberd
|
||||
- Transport configuration for connecting to other networks:
|
||||
http://ejabberd.jabber.ru/tutorials-transports
|
||||
- Using ejabberd with MySQL native driver:
|
||||
http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver
|
||||
- Anonymous User Support:
|
||||
http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support
|
||||
- Frequently Asked Questions:
|
||||
http://ejabberd.jabber.ru/faq
|
||||
|
||||
END
|
||||
@@ -1,119 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.1.1
|
||||
28 April 2006
|
||||
|
||||
This document describes the main changes in ejabberd 1.1.x. This version
|
||||
introduce new features including support for new Jabber Enhancement
|
||||
Proposals and several performance improvements enabling deployments on an
|
||||
even larger scale than already possible.
|
||||
|
||||
This release fix a security issue introduced in ejabberd 1.1.0. In SASL
|
||||
mode, anonymous login was enabled as a default. Upgrading ejabberd 1.1.0 to
|
||||
ejabberd 1.1.1 is highly recommended.
|
||||
|
||||
ejabberd can be downloaded from the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
Detailed information can be found in the ejabberd Feature Sheet and User
|
||||
Guide which are available on the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs.html
|
||||
|
||||
A complete list of changes is available from:
|
||||
http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
|
||||
New Jabber Enhancement Proposal support:
|
||||
|
||||
- JEP-0050: Ad-Hoc Commands.
|
||||
- JEP-0138: Stream Compression.
|
||||
- JEP-0175: SASL anonymous.
|
||||
|
||||
Anonymous login
|
||||
|
||||
- SASL anonymous.
|
||||
- Anonymous login for clients that do not yet support SASL Anonymous.
|
||||
|
||||
Relational database Support
|
||||
|
||||
- MySQL is now fully supported through ODBC and in native mode.
|
||||
- Various improvements to the native database interfaces.
|
||||
- The migration tool can use relational databases.
|
||||
|
||||
Multi-User Chat improvements
|
||||
|
||||
- Logging of room discussion to text file is now supported.
|
||||
- Better reconfiguration support.
|
||||
- Security oriented fixes.
|
||||
- Several improvements and updates to latest JEP-0045.
|
||||
|
||||
Performance scalability improvements for large clusters
|
||||
|
||||
- Improved session synchronisation management between cluster nodes.
|
||||
- Internal architecture has been reworked to use generalize Erlang/OTP
|
||||
framework usage.
|
||||
- Speed improvement on logger.
|
||||
- TCP/IP packet reception change for better network throttling and
|
||||
regulation.
|
||||
As a result, these improvements will reduce load on large scale deployments.
|
||||
|
||||
XMPP Protocol related improvements
|
||||
|
||||
- XML stanza size can be limited.
|
||||
- Messages are send to all resources with the same highest priority.
|
||||
|
||||
Documentation and Internationalization
|
||||
|
||||
- Documentation has been extended to cover more topics.
|
||||
- Translations have been updated.
|
||||
|
||||
Web interface
|
||||
|
||||
- XHTML 1.0 compliance.
|
||||
|
||||
Bugfixes
|
||||
|
||||
- This release contains many bugfixes on various areas such as Publish-Subscribe, build
|
||||
chain, installers, IRC gateway, ejabberdctl, amongst others.
|
||||
- Please refer to the ChangeLog file supplied with this release regarding
|
||||
all improvements in ejabberd.
|
||||
|
||||
|
||||
|
||||
Installation Notes
|
||||
|
||||
Supported Erlang Version
|
||||
|
||||
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0.
|
||||
|
||||
Installation
|
||||
|
||||
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
|
||||
Installers can be retrieved from:
|
||||
http://www.process-one.net/en/projects/ejabberd/download.html
|
||||
|
||||
Migration Notes
|
||||
|
||||
- Before any migration, ejabberd system and database must be properly
|
||||
backed up.
|
||||
- The database schema has not been changed comparing to version 1.0.0 and
|
||||
consequently it does not require any migration.
|
||||
|
||||
|
||||
References
|
||||
|
||||
Contributed tutorials and documents of interest are:
|
||||
- Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd:
|
||||
http://ejabberd.jabber.ru/migrate-to-ejabberd
|
||||
- Transport configuration for connecting to other networks:
|
||||
http://ejabberd.jabber.ru/tutorials-transports
|
||||
- Using ejabberd with MySQL native driver:
|
||||
http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver
|
||||
- Anonymous User Support:
|
||||
http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support
|
||||
- Frequently Asked Questions:
|
||||
http://ejabberd.jabber.ru/faq
|
||||
|
||||
END
|
||||
@@ -1,119 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.1.2
|
||||
27 September 2006
|
||||
|
||||
This document describes the main changes in ejabberd 1.1.2.
|
||||
|
||||
This version is a major improvement over ejabberd 1.1.1, improving the
|
||||
overall behaviour of the server in many areas. Users of ejabberd 1.1.1
|
||||
should upgrade to this new release for improved robustness and compliance.
|
||||
|
||||
ejabberd can be downloaded from the Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
Detailed information can be found in the Feature Sheet and in the
|
||||
Installation and Operation Guide which are both available on the
|
||||
Process-one website:
|
||||
http://www.process-one.net/en/projects/ejabberd/docs.html
|
||||
|
||||
ejabberd includes 44 improvements. A complete list of changes can be
|
||||
retrieved from:
|
||||
http://redir.process-one.net/ejabberd-1.1.2
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
LDAP Improvements
|
||||
|
||||
- Major improvements have been made on the LDAP module. It is now more
|
||||
flexible and more robust.
|
||||
|
||||
HTTP Polling Fixes
|
||||
|
||||
- The HTTP polling modules have been fixed and improved: the connections are
|
||||
closed properly and polled messages cannot be lost anymore.
|
||||
|
||||
Roster Management Improvement
|
||||
|
||||
- Roster management improvements increase reliability, especially in cases
|
||||
where users are on different servers.
|
||||
- Shared rosters are more reliable.
|
||||
|
||||
Improved Robustness
|
||||
|
||||
- It is now possible to limit the number of opened connections for a single
|
||||
user.
|
||||
|
||||
Relational databases
|
||||
|
||||
- Database support: Microsoft SQL Server is now officially supported in ODBC
|
||||
mode.
|
||||
|
||||
Publish-Subscribe Improvement
|
||||
|
||||
- Restricting node creation with a dedicated ACL rule is now possible.
|
||||
|
||||
Localization
|
||||
|
||||
- A Czech translation has been added.
|
||||
- Translations have been updated.
|
||||
|
||||
Binary Installer
|
||||
|
||||
- New binary installer for Windows including all requirements.
|
||||
- Improved installers for Linux and MacOSX (PowerPC)
|
||||
|
||||
XMPP Compliancy
|
||||
|
||||
- Some protocol compliance fix have been added, after the Portland XMPP
|
||||
Interop Meeting in July.
|
||||
|
||||
Miscelanous
|
||||
|
||||
- MUC have been improved (logging rendering).
|
||||
- The command line tool ejabberdctl has been improved.
|
||||
- The build chain has been improved, including MacOSX support.
|
||||
- The documentation has been improved and updated to describe the new
|
||||
features.
|
||||
|
||||
Bugfixes
|
||||
|
||||
- Anonymous login bugfixes.
|
||||
- Please refer to the ChangeLog file supplied with this release regarding
|
||||
all improvements in ejabberd.
|
||||
|
||||
|
||||
Installation Notes
|
||||
|
||||
Supported Erlang Version
|
||||
|
||||
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.2.
|
||||
- The recommanded version is Erlang/OTP R10B-10.
|
||||
- Erlang/OTP R11B has not yet been fully certified for ejabberd.
|
||||
|
||||
Installation
|
||||
|
||||
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
|
||||
They can be retrieved from:
|
||||
http://www.process-one.net/en/projects/ejabberd/download.html
|
||||
|
||||
Migration Notes
|
||||
|
||||
- Before any migration, ejabberd system and database must be properly
|
||||
backed up.
|
||||
- The relational database schema has changed between version 1.1.1 and
|
||||
1.1.2. An "askmessage" column needs to be added in the "rosterusers" table
|
||||
to perform the migration.
|
||||
|
||||
|
||||
References
|
||||
|
||||
Contributed tutorials and documents of interest are:
|
||||
- Migration from other XMPP servers to ejabberd:
|
||||
http://ejabberd.jabber.ru/migrate-to-ejabberd
|
||||
- Transport configuration for connecting to other networks:
|
||||
http://ejabberd.jabber.ru/tutorials-transports
|
||||
- Frequently Asked Questions:
|
||||
http://ejabberd.jabber.ru/faq
|
||||
|
||||
END
|
||||
@@ -1,14 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.1.3
|
||||
2 February 2007
|
||||
|
||||
ejabberd 1.1.3 is a security fix release for ejabberd roster ODBC
|
||||
module.
|
||||
|
||||
The upgrade is only necessary if you are using ejabberd with the
|
||||
mod_roster_odbc.
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
END
|
||||
@@ -1,31 +0,0 @@
|
||||
Release Notes
|
||||
ejabberd 1.1.4
|
||||
3 september 2007
|
||||
|
||||
ejabberd 1.1.4 is a bugfix release for ejabberd 1.1.x branch.
|
||||
|
||||
ejabberd 1.1.4 includes 10 improvements. A complete list of changes
|
||||
can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-1.1.4
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
- Better LDAP support.
|
||||
- Support for UTF-8 with MySQL 5.
|
||||
- Roster migration script bugfixes.
|
||||
- Performance improvements on user removal.
|
||||
- Traffic shapers bugfix.
|
||||
- Configuration: host value is now case insensitive.
|
||||
- Build: ejabberd.cfg file is not overwritten with 'make install' command.
|
||||
|
||||
|
||||
Bugs report
|
||||
|
||||
You can officially report bugs on Process-one support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,208 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.0
|
||||
21 February 2008
|
||||
|
||||
ejabberd 2.0.0 is a major new version for ejabberd adding plenty of
|
||||
new features, performance and scalability improvements and
|
||||
architectural changes.
|
||||
|
||||
ejabberd 2.0.0 includes more than 200 improvements over ejabberd
|
||||
1.1.x. A complete list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.0
|
||||
|
||||
The new code can be downloaded from ejabberd downloads page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
|
||||
* Clustering and Architecture
|
||||
|
||||
- New front-end and back-end cluster architecture for better
|
||||
scalability and robustness. Back-end nodes are able to run a fully
|
||||
fault-tolerant XMPP router and services, but you can now deploy
|
||||
many front-end nodes to share the load without needing to synchronize
|
||||
any state with the back-ends.
|
||||
- All components now run in cluster mode (For example, Multi-User chat
|
||||
service and file transfer proxy).
|
||||
- New load balancing algorithm to support Multi-User chat and gateways
|
||||
clustering. More generally it supports any external component load
|
||||
balancing.
|
||||
- ejabberd watchdog to receive warning on suspicious resources consumption.
|
||||
- Traffic shapers are now supported on components. This protect
|
||||
ejabberd from components and gateways abuses.
|
||||
|
||||
|
||||
* Publish and Subscribe
|
||||
|
||||
- Complete rewrite of the PubSub module. The new PubSub module is
|
||||
plugin-based, allowing developers to create new nodes type. Any
|
||||
application can be plugged to ejabberd and can provide rich presence
|
||||
as a pubsub plugin.
|
||||
- Personal Eventing via Pubsub support (XEP-0163). This module is
|
||||
implemented as a PubSub service. It supports user mood (XEP-107),
|
||||
User Tune (XEP-118), user location (XEP-0080) or user avatar
|
||||
(XEP-0084) for example.
|
||||
|
||||
|
||||
* Server to Server (s2s)
|
||||
|
||||
- More robust code with connection timeout implementation.
|
||||
- Support for multiple s2s connections per domain.
|
||||
- s2s whitelist and blacklist support.
|
||||
- s2s retrial interval.
|
||||
|
||||
|
||||
* LDAP
|
||||
|
||||
- Many enterprise-class enhancements such as better behaviour under
|
||||
heavy load.
|
||||
- Support for LDAP servers pool.
|
||||
- Simplified use of virtual hosting with LDAP with domain substitution
|
||||
in config.
|
||||
- Ability to match on several userid attributes.
|
||||
|
||||
|
||||
* Multi-User Chat
|
||||
|
||||
- Clustering and load balancing support.
|
||||
- Ability to define default room configuration in ejabberd config file.
|
||||
- Many anti abuse features have been added:
|
||||
. New ACL to limit the creation of persistent room to authorized users.
|
||||
. Ability to define the maximum number of users per room.
|
||||
. Limitation of the rate of message and presence packets.
|
||||
. Limitation of the maximum number of room a user can join at the same time.
|
||||
|
||||
|
||||
* File Transfer
|
||||
|
||||
- XEP-0065 - Proxy65 file transfer proxy. The proxy can run in
|
||||
cluster mode.
|
||||
|
||||
|
||||
* Authentication
|
||||
|
||||
- PAM (Pluggable Authentication Modules) support on *nix systems.
|
||||
- External Authentication protocol is now fully documented.
|
||||
|
||||
|
||||
* Web Client Support
|
||||
|
||||
- XEP-0124 - BOSH support: BOSH (Bidirectional-streams Over
|
||||
Synchronous HTTP) was formerly known as "HTTP binding". It provides
|
||||
an efficient alternative to HTTP polling for scalable Web based chat
|
||||
solutions.
|
||||
- HTTP module can now serve static documents (with
|
||||
mod_http_fileserver). It is needed for high-performance Web 2.0 chat
|
||||
/ IM application. System administrators can now avoid using a proxy
|
||||
(like Apache) that handles much less simultaneous than ejabberd HTTP
|
||||
module.
|
||||
- Added limitations enforcement on HTTP poll and HTTP bind modules
|
||||
(bandwidth, packet size).
|
||||
|
||||
|
||||
* System Administration
|
||||
|
||||
- XEP-0133 - Service administration support. System administrators can
|
||||
now perform lot of ejabberd related admin tasks from their XMPP
|
||||
client, through adhoc commands.
|
||||
- Dynamic log levels: Improved logging with more log levels. You can
|
||||
now change the loglevel at run time. No performance penalty is
|
||||
involved when less verbose levels are used.
|
||||
- The ejabberdctl command-line administration script now can start
|
||||
and stop ejabberd. It also includes other useful options.
|
||||
|
||||
|
||||
* Localization
|
||||
|
||||
- ejabberd is now translated to 24 languages: Catalan, Chinese, Czech,
|
||||
Dutch, English, Esperanto, French, Galician, German, Italian, Japanese,
|
||||
Norwegian, Polish, Portuguese, Portuguese (Brazil), Russian, Slovak,
|
||||
Spanish, Swedish, Thai, Turkish, Ukrainian, Vietnamese, Walloon.
|
||||
|
||||
|
||||
* Build and Installer
|
||||
|
||||
- Many launch script improvements.
|
||||
- New translations. The binary installer is now available in Chinese,
|
||||
Dutch, English, French, German, Spanish, Russian.
|
||||
- Makefile now implements uninstall command.
|
||||
- Full MacOSX compliance in Makefile.
|
||||
- Configure script is clever at finding libraries in unusual places.
|
||||
|
||||
|
||||
* Development API
|
||||
|
||||
- Several hooks have been added for module developers (most notably
|
||||
presence related hooks).
|
||||
- HTTP request handler to write HTTP based plugins.
|
||||
- Manage connections IP address.
|
||||
|
||||
|
||||
* Bugfixes
|
||||
|
||||
- ejabberd 2.0.0 also fixes numerous small bugs :) Read the full
|
||||
changelog for details.
|
||||
|
||||
|
||||
|
||||
Important Note:
|
||||
|
||||
- Since this release, ejabberd requires Erlang R10B-5 or higher.
|
||||
R11B-5 is the recommended version. R12 is not yet officially
|
||||
supported, and is not recommended for production servers.
|
||||
|
||||
|
||||
|
||||
Upgrading From ejabberd 1.x:
|
||||
|
||||
- If you upgrade from a version older than 1.1.4, please check the
|
||||
Release Notes of the intermediate versions for additional
|
||||
information about database or configuration changes.
|
||||
|
||||
- The database schemas didn't change since ejabberd 1.1.4. Of course,
|
||||
you are encouraged to make a database backup of your SQL database,
|
||||
or your Mnesia spool directory before upgrading ejabberd.
|
||||
|
||||
- The ejabberdctl command line administration script is improved in
|
||||
ejabberd 2.0.0, and now it can start and stop ejabberd. If you
|
||||
already wrote your own start script for ejabberd 1.x, you can
|
||||
continue using it, or try ejabberdctl. For your convenience, the
|
||||
ejabberd Guide describes all the ejabberd and Erlang options used by
|
||||
ejabberdctl.
|
||||
|
||||
- The example ejabberd.cfg file has been reorganized, but its format
|
||||
and syntax rules are the same. So, you can continue using your
|
||||
ejabberd.cfg file from 1.x if you want. The most important changes
|
||||
are described now.
|
||||
|
||||
- The 'ssl' option is no longer available in the listening ports. For
|
||||
legacy SSL encryption use the option 'tls'. For STARTTLS encryption
|
||||
as defined in RFC 3920 XMPP-CORE use the option 'starttls'. Check
|
||||
the ejabberd Guide for more information about configuring listening
|
||||
ports.
|
||||
|
||||
- The options 'welcome_message' and 'registration_watchers' are now
|
||||
options of the module mod_register. Check in the ejabberd Guide how
|
||||
to configure that module.
|
||||
|
||||
- To enable PEP support in mod_pubsub, you need to enable it in the
|
||||
mod_pubsub configuration, and also enable the new module
|
||||
mod_caps. Check the section about mod_pubsub in the ejabberd Guide.
|
||||
|
||||
- Other new features and improvements also require changes in the
|
||||
ejabberd.cfg, like mod_http_bind, mod_http_fileserver, mod_proxy65,
|
||||
loglevel, pam_service, and watchdog_admins. Search for those words
|
||||
in the ejabberd Guide and the example ejabberd.cfg.
|
||||
|
||||
|
||||
|
||||
Bug Reports
|
||||
|
||||
You can officially report bugs on Process-one support site:
|
||||
https://support.process-one.net/
|
||||
|
||||
|
||||
END
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.1
|
||||
20 May 2008
|
||||
|
||||
ejabberd 2.0.1 is a bugfix release for ejabberd 2.0.x branch.
|
||||
|
||||
ejabberd 2.0.1 includes 10 improvements and 32 bugfixes.
|
||||
A complete list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.1
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/projects/ejabberd/
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
- Erlang R12 support.
|
||||
- Better LDAP handling.
|
||||
- PubSub bugfixes.
|
||||
- Documentation improvements.
|
||||
- inband registration limitation per IP.
|
||||
- s2s improvements.
|
||||
|
||||
Bugs report
|
||||
|
||||
You can officially report bugs on Process-one support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.2
|
||||
28 August 2008
|
||||
|
||||
ejabberd 2.0.2 is the second bug fix release for ejabberd 2.0.x branch.
|
||||
|
||||
ejabberd 2.0.2 includes many bugfixes and a few improvements.
|
||||
A complete list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.2
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
- Anti-abuse feature: client blacklist support by IP.
|
||||
- Guide: new section Securing ejabberd; improved usability.
|
||||
- LDAP filter optimisation: ability to filter user in ejabberd and not LDAP.
|
||||
- MUC improvements: room options to restrict visitors; broadcast reasons.
|
||||
- Privacy rules: fix MySQL storage.
|
||||
- Pub/Sub and PEP: many improvements in implementation and protocol compliance.
|
||||
- Proxy65: send valid SOCKS5 reply (removed support for Psi < 0.10).
|
||||
- Web server embedded: better support for HTTPS.
|
||||
- Binary installers: SMP on Windows; don't remove config when uninstalling.
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.3
|
||||
14 January 2009
|
||||
|
||||
ejabberd 2.0.3 is the third bugfix release for ejabberd 2.0.x branch.
|
||||
|
||||
ejabberd 2.0.3 includes several bugfixes and a few improvements.
|
||||
A complete list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.3
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
Recent changes include:
|
||||
|
||||
- Do not ask certificate for client (c2s)
|
||||
- Check digest-uri in SASL digest authentication
|
||||
- Use send timeout to avoid locking on gen_tcp:send
|
||||
- Fix ejabberd reconnection to database
|
||||
- HTTP-Bind: handle wrong order of packets
|
||||
- MUC: Improve traffic regulation management
|
||||
- PubSub: Several bugfixes and improvements for best coverage of XEP-0060 v1.12
|
||||
- Shared Roster Groups: push immediately membership changes
|
||||
- Rotate also sasl.log on "reopen-log" command
|
||||
- Binary Windows installer: better detect "Error running Post Install Script"
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.4
|
||||
|
||||
ejabberd 2.0.4 is the fourth bugfix release for ejabberd 2.0.x branch.
|
||||
|
||||
ejabberd 2.0.4 includes several bugfixes.
|
||||
A detailed list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.4
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
- Ensure ID attribute in roster push is unique
|
||||
- Authentication: Fix Anonymous auth when enabled with broken ODBC
|
||||
- Authentication: Unquote correctly backslash in DIGEST-MD5 SASL responses
|
||||
- Authentication: Cancel presence subscriptions on account deletion
|
||||
- LDAP: Close a connection on tcp_error
|
||||
- LDAP: Implemented queue for pending queries
|
||||
- LDAP: On failure of LDAP connection, waiting is done on pending queue
|
||||
- MUC: Owner of a password protected room must also provide the password
|
||||
- MUC: Prevent XSS in MUC logs by linkifying only a few known protocols
|
||||
- Privacy rules: Items are now processed in the specified order
|
||||
- Privacy rules: Fix to correctly block subscription requests
|
||||
- Proxy65: If ip option is not defined, take an IP address of a local hostname
|
||||
- PubSub: Add roster subscription handling; send PEP events to all resources
|
||||
- PubSub: Allow node creation without configure item
|
||||
- PubSub: Requesting items on a node which exists, but empty returns an error
|
||||
- PEP: Fix sending notifications to other domains and s2s
|
||||
- S2S: Fix problem with encrypted connection to Gtalk and recent Openfire
|
||||
- S2S: Workaround to get DNS SRV lookup to work on Windows machine
|
||||
- Shared Roster Groups: Fix to not resend authorization request
|
||||
- WebAdmin: Fix encryption problem for ejabberd_http after timeout
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.0.5
|
||||
|
||||
ejabberd 2.0.5 is the fifth bugfix release in ejabberd 2.0.x branch.
|
||||
|
||||
ejabberd 2.0.5 includes three bugfixes.
|
||||
More details of those fixes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.0.5
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
- Fix two problems introduced in ejabberd 2.0.4: subscription request
|
||||
produced many authorization requests with some clients and
|
||||
transports; and subscription requests were not stored for later
|
||||
delivery when receiver was offline.
|
||||
|
||||
- Fix warning in expat_erl.c about implicit declaration of x_fix_buff
|
||||
|
||||
- HTTP-Bind (BOSH): Fix a missing stream:error in the returned
|
||||
remote-stream-error stanza
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
END
|
||||
@@ -1,281 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.0
|
||||
|
||||
ejabberd 2.1.0 is a major new version for ejabberd adding many
|
||||
new features, performance and scalability improvements.
|
||||
|
||||
ejabberd 2.1.0 includes many new features, improvements and bug fixes.
|
||||
A complete list of changes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.1.0
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
New features and improvements:
|
||||
|
||||
* Anti-abuse
|
||||
- Captcha support (XEP-0158). The example script uses ImageMagick.
|
||||
- New option: registration_timeout to limit registrations by time
|
||||
- Use send timeout to avoid locking on gen_tcp:send
|
||||
- mod_ip_blacklist: client blacklist support by IP
|
||||
|
||||
* API
|
||||
- ejabberd_http provides Host, Port, Headers and Protocol in HTTP requests
|
||||
- Export function to create MUC room
|
||||
- New events: s2s_send_packet and s2s_receive_packet
|
||||
- New event: webadmin_user_parse_query when POST in web admin user page
|
||||
- Support distributed hooks over the cluster
|
||||
|
||||
* Authentification
|
||||
- Extauth responses: log strange responses and add timeout
|
||||
|
||||
* Binary Installer
|
||||
- Includes exmpp library to support import/export XML files
|
||||
|
||||
* Caps
|
||||
- Remove useless caps tables entries
|
||||
- mod_caps must handle correctly external contacts with several resources
|
||||
- Complain if mod_caps disabled and mod_pubsub has PEP plugin enabled
|
||||
|
||||
* Clustering and Architecture
|
||||
|
||||
* Configuration
|
||||
- Added option access_max_user_messages for mod_offline
|
||||
- Added option backlog for ejabberd_listener to increase TCP backlog
|
||||
- Added option define_macro and use_macro
|
||||
- Added option include_config_file to include additional configuration files
|
||||
- Added option max_fsm_queue
|
||||
- Added option outgoing_s2s_options to define IP address families and timeout
|
||||
- Added option registration_timeout to ejabberd.cfg.example
|
||||
- Added option s2s_dns_options to define DNS timeout and retries
|
||||
- Added option ERL_OPTIONS to ejabberdctl.cfg
|
||||
- Added option FIREWALL_WINDOW to ejabberdctl.cfg
|
||||
- Added option EJABBERD_PID_PATH to ejabberdctl.cfg
|
||||
- Deleted option user_max_messages of mod_offline
|
||||
- Check certfiles are readable on server start and listener start
|
||||
- Config file management mix file reading and sanity check
|
||||
- Include example PAM configuration file: ejabberd.pam
|
||||
- New ejabberd listener: ejabberd_stun
|
||||
- Support to bind the same port to multiple interfaces
|
||||
- New syntax to specify the IP address and IPv6 in listeners
|
||||
configuration. The old options {ip,{1,2,3,4}} and inet6 are
|
||||
supported even if they aren't documented.
|
||||
- New syntax to specify the network protocol: tcp or udp
|
||||
- Report error at startup if a listener module isn't available
|
||||
- Only listen in a port when actually ready to serve requests
|
||||
- In default config, only local accounts can create rooms and PubSub nodes
|
||||
|
||||
* Core architecture
|
||||
- More verbose error reporting for xml:element_to_string
|
||||
- Deliver messages when first presence is Invisible
|
||||
- Better log message when config file is not found
|
||||
- Include original timestamp on delayed presences
|
||||
|
||||
* Crypto
|
||||
- Do not ask certificate for client (c2s)
|
||||
- SSL code remove from ejabberd in favor of TLS
|
||||
- Support Zlib compression after STARTTLS encryption
|
||||
- tls v1 client hello
|
||||
|
||||
* Documentation
|
||||
- Document possible default MUC room options
|
||||
- Document service_check_from in the Guide
|
||||
- Document s2s_default_policy and s2s_host in the Guide
|
||||
- new command and guide instructions to change node name in a Mnesia database
|
||||
|
||||
* ejabberd commands
|
||||
- ejabberd commands: separate command definition and calling interface
|
||||
- access_commands restricts who can execute what commands and arguments
|
||||
- ejabberdctl script now displays help and categorization of commands
|
||||
|
||||
* HTTP Binding and HTTP Polling
|
||||
- HTTP-Bind: module optimization and clean-up
|
||||
- HTTP-Bind: allow configuration of max_inactivity timeout
|
||||
- HTTP-Poll: turn session timeout into a config file parameter
|
||||
|
||||
* Jingle
|
||||
- STUN server that facilitates the client-to-client negotiation process
|
||||
|
||||
* LDAP
|
||||
- Faster reconnection to LDAP servers
|
||||
- LDAP filter optimisation: Add ability to filter user in ejabberd and not LDAP
|
||||
- LDAP differentiates failed auth and unavailable auth service
|
||||
- Improve LDAP logging
|
||||
- LDAPS support using TLS.
|
||||
|
||||
* Localization
|
||||
- Use Gettext PO for translators, export to ejabberd MSG
|
||||
- Support translation files for additional projects
|
||||
- Most translations are updated to latest code
|
||||
- New translation to Greek language
|
||||
|
||||
* Multi-User Chat (MUC)
|
||||
- Allow admins to send messages to rooms
|
||||
- Allow to store room description
|
||||
- Captcha support in MUC: the admin of a room can configure it to
|
||||
require participants to fill a captcha to join the room.
|
||||
- Limit number of characters in Room ID, Name and Description
|
||||
- Prevent unvoiced occupants from changing nick
|
||||
- Support Result Set Management (XEP-0059) for listing rooms
|
||||
- Support for decline of invitation to MUC room
|
||||
- mod_muc_log options: plaintext format; filename with only room name
|
||||
|
||||
* Performance
|
||||
- Run roster_get_jid_info only if privacy list has subscription or group item
|
||||
- Significant PubSub performance improvements
|
||||
|
||||
* Publish-Subscribe
|
||||
- Add nodetree filtering/authorization
|
||||
- Add subscription option support for collection nodes
|
||||
- Allow Multiple Subscriptions
|
||||
- Check option of the nodetree instead of checking configuration
|
||||
- Implement whitelist authorize and roster access model
|
||||
- Implicit item deletion is not notified when deleting node
|
||||
- Make PubSub x-data configuration form handles list value
|
||||
- Make default node name convention XEP-compatible, document usage of hierarchy
|
||||
- Node names are used verbatim, without separating by slash, unless a
|
||||
node plugin uses its own separator
|
||||
- Send authorization update event (XEP-0060, 8.6)
|
||||
- Support of collection node subscription options
|
||||
- Support ODBC storage. Experimental, needs more testing.
|
||||
|
||||
* Relational databases:
|
||||
- Added MSSQL 2000 and 2005
|
||||
- Privacy rules storage in MySQL
|
||||
- Implement reliable ODBC transaction nesting
|
||||
|
||||
* Source Package
|
||||
- Default installation directories changed. Please see the upgrade notes below.
|
||||
- Allow more environment variable overrides in ejabberdctl
|
||||
- ChangeLog is not edited manually anymore; it's generated automatically.
|
||||
- Install the ejabberd Guide
|
||||
- Install the ejabberd include files
|
||||
- New option for the 'configure' script: --enable-user which installs
|
||||
ejabberd granting permission to manage it to a regular system user;
|
||||
no need to use root account to.
|
||||
- Only try to install epam if pam was enabled in configure script
|
||||
- Spool, config and log dirs: owner writes, group reads, others do nothing.
|
||||
- Provides an example ejabberd.init file
|
||||
|
||||
* S2S
|
||||
- Option to define s2s outgoing behaviour: IPv4, IPv6 and timeout
|
||||
- DNS timeout and retries, configurable with s2s_dns_options.
|
||||
|
||||
* Shared rosters
|
||||
- When a member is added/removed to group, send roster upgrade to group members
|
||||
|
||||
* Users management
|
||||
- When account is deleted, cancel presence subscription for all roster items
|
||||
|
||||
* XEP Support
|
||||
- Added XEP-0059 Result Set Management (for listing rooms)
|
||||
- Added XEP-0082 Date Time
|
||||
- Added XEP-0085 Chat State Notifications
|
||||
- Added XEP-0157 Contact Addresses for XMPP Services
|
||||
- Added XEP-0158 CAPTCHA Forms (in MUC rooms)
|
||||
- Added STUN server, for XEP-0176: Jingle ICE-UDP Transport Method
|
||||
- Added XEP-0199 XMPP Ping
|
||||
- Added XEP-0202 Entity Time
|
||||
- Added XEP-0203 Delayed Delivery
|
||||
- Added XEP-0227 Portable Import/Export Format for XMPP-IM Servers
|
||||
- Added XEP-0237 Roster Versioning
|
||||
|
||||
* Web Admin
|
||||
- Display the connection method of user sessions
|
||||
- Cross link of ejabberd users in the list of users and rosters
|
||||
- Improved the browsing menu: don't disappear when browsing a host or node
|
||||
- Include Last-Modified HTTP header in responses to allow caching
|
||||
- Make some Input areas multiline: options of listening ports and modules
|
||||
- Support PUT and DELETE methods in ejabberd_http
|
||||
- WebAdmin serves Guide and links to related sections
|
||||
|
||||
* Web plugins
|
||||
- mod_http_fileserver: new option directory_indices, and improve logging
|
||||
|
||||
|
||||
Important Notes:
|
||||
|
||||
- ejabberd 2.1.0 requires Erlang R10B-9 or higher.
|
||||
R12B-5 is the recommended version. Support for R13B is experimental.
|
||||
|
||||
|
||||
Upgrading From ejabberd 1.x.x:
|
||||
|
||||
- Check the Release Notes of the intermediate versions for additional
|
||||
information about database or configuration changes.
|
||||
|
||||
|
||||
Upgrading From ejabberd 2.0.x:
|
||||
|
||||
- The database schemas have three changes since ejabberd 2.0.x.
|
||||
Check the database creation SQL files and update your database.
|
||||
1) New table roster_version to support roster versioning.
|
||||
2) Six new tables for optional pubsub ODBC storage.
|
||||
3) Some tables in the MySQL database have a new created_at column.
|
||||
|
||||
- As usual, it is recommended to backup the Mnesia spool directory and
|
||||
your SQL database (if used) before upgrading ejabberd.
|
||||
|
||||
- Between ejabberd 2.0.0 and 2.0.5, mod_pubsub used "default" as the
|
||||
default node plugin. But in 2.1.0 this is renamed to "hometree".
|
||||
You have to edit your ejabberd config file and replace those names.
|
||||
If you used ejabberd 2.0.5 or older, the database will be updated
|
||||
automatically. But if you were using ejabberd from SVN, you must
|
||||
manually run ejabberdctl with the command: rename_default_nodeplugin.
|
||||
Running this command on already updated database does nothing.
|
||||
|
||||
- The listener options 'ip' and 'inet6' are not documented anymore
|
||||
but they are supported and you can continue using them.
|
||||
There is a new syntax to define IP address and IP version.
|
||||
As usual, check the ejabberd Guide for more information.
|
||||
|
||||
- The log file sasl.log is now called erlang.log
|
||||
|
||||
- ejabberdctl commands now have _ characters instead of -.
|
||||
For backwards compatibility, it is still supported -.
|
||||
|
||||
- mod_offline has a new option: access_max_user_messages.
|
||||
The old option user_max_messages is no longer supported.
|
||||
|
||||
- If you upgrade from ejabberd trunk SVN, you must execute this:
|
||||
$ ejabberdctl rename_default_nodeplugin
|
||||
|
||||
- Default installation directories changed a bit:
|
||||
* The Mnesia spool files that were previously stored in
|
||||
/var/lib/ejabberd/db/NODENAME/*
|
||||
are now stored in
|
||||
/var/lib/ejabberd/*
|
||||
* The directories
|
||||
/var/lib/ejabberd/ebin
|
||||
/var/lib/ejabberd/priv
|
||||
and their content is now installed as
|
||||
/lib/ejabberd/ebin
|
||||
/lib/ejabberd/priv
|
||||
* There is a new directory with Erlang header files:
|
||||
/lib/ejabberd/include
|
||||
* There is a new directory for ejabberd documentation,
|
||||
which includes the Admin Guide and the release notes::
|
||||
/share/doc/ejabberd
|
||||
|
||||
- How to upgrade from previous version to ejabberd 2.1.0:
|
||||
1. Stop the old instance of ejabberd.
|
||||
2. Run 'make install' of new ejabberd 2.1.0 to create the new directories.
|
||||
3. Copy the content of your old directory:
|
||||
/var/lib/ejabberd/db/NODENAME/
|
||||
to the new location:
|
||||
/var/lib/ejabberd/
|
||||
so you will have the files like this:
|
||||
/var/lib/ejabberd/acl.DCD ...
|
||||
4. You can backup the content of those directories and delete them:
|
||||
/var/lib/ejabberd/ebin
|
||||
/var/lib/ejabberd/priv
|
||||
/var/lib/ejabberd/db
|
||||
5. Now try to start your new ejabberd 2.1.0.
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.1
|
||||
|
||||
ejabberd 2.1.1 is the first bugfix release in ejabberd 2.1.x branch.
|
||||
|
||||
ejabberd 2.1.1 includes several important bugfixes.
|
||||
More details of those fixes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.1.1
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
* Core
|
||||
- Call ejabberd_router:route/3 instead of sending a message
|
||||
- Can't connect if starttls_required and zlib are set
|
||||
- Routes vCard request to the occupant full JID, but should to bare JID
|
||||
- S2S: fix allow_host/2 on subdomains. added hook s2s_allow_host
|
||||
|
||||
* MUC
|
||||
- Support converting one-to-one chat to MUC
|
||||
- Add support for serving a Unique Room Name
|
||||
|
||||
* Publish Subscribe
|
||||
- Receive same last published PEP items at reconnect if several resources online
|
||||
- Typo in mod_pubsub_odbc breaks Service Discovery and more
|
||||
|
||||
* Web
|
||||
- Fix memory and port leak when TLS is enabled in HTTP
|
||||
- WebAdmin doesn't report correct last activity with postgresql backend
|
||||
- Option to define custom HTTP headers in mod_http_fileserver
|
||||
- Show informative webpage when browsing the HTTP-Poll page
|
||||
|
||||
* Other
|
||||
- Change captcha.sh to not depend on bash
|
||||
- Generate main XML file also when exporting only a vhost
|
||||
- Fix last newline in ejabberdctl result
|
||||
- Guide: fix -setcookie, mod_pubsub_odbc host, content_types
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.10
|
||||
|
||||
ejabberd 2.1.10 includes a few bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.10
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The major changes are:
|
||||
|
||||
* Erlang/OTP compatibility
|
||||
- Support Erlang/OTP R15B regexp and drivers (EJAB-1521)
|
||||
- Fix modules update in R14B04 and higher
|
||||
- Fix modules update of stripped beams (EJAB-1520)
|
||||
|
||||
* XMPP Core
|
||||
- Fix presence problem in C2S after first unavailable (EJAB-1466)
|
||||
- Fix bug on S2S shaper when TLS is used
|
||||
- Prevent overload of incoming S2S connections
|
||||
|
||||
* XEPs
|
||||
- BOSH: Get rid of useless mnesia transaction (EJAB-1502)
|
||||
- MUC: Don't reveal invitee resource when room informs invitor
|
||||
- Privacy: Activate "Blocked Contacts" to current c2s connection (EJAB-1519)
|
||||
- Privacy: Always allow packets from user's server and bare jid (EJAB-1441)
|
||||
- Pubsub: Add hooks for node creation/deletion (EJAB-1470)
|
||||
- Shared Rosters: support groupname@vhost in Displayed Groups (EJAB-506)
|
||||
- Vcard: Fix error when lowercasing some search results (EJAB-1490)
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.11
|
||||
|
||||
ejabberd 2.1.11 includes a few bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.11
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The major changes are:
|
||||
|
||||
* HTTP service
|
||||
- Fix ejabberd_http:get_line
|
||||
- Don't use binary:match to extract lines from binaries
|
||||
- Parse and encode https header names like native http parser does
|
||||
- Parse correctly https request split into multiple packets
|
||||
- Properly handle HEAD request in mod_http_bind (EJAB-1538)
|
||||
- New option default_host for handling requests with ambiguous Host (EJAB-1261)
|
||||
|
||||
* ODBC
|
||||
- New ODBC support for mod_announce
|
||||
- New ODBC support for mod_blocking
|
||||
- New ODBC support for mod_irc
|
||||
- New ODBC support for mod_muc
|
||||
- New ODBC support for mod_shared_roster
|
||||
- New ODBC support for mod_vcard_xupdate
|
||||
- Add ODBC exporting function for privacy table
|
||||
- Work also with some unicode strings in PgSQL (EJAB-1490)
|
||||
- Replace a single quote with double quotes in an ODBC escape
|
||||
|
||||
* SSL
|
||||
- Make sure that res is initialized in all cases
|
||||
- Parse correctly https request split into multiple packets (EJAB-1537)
|
||||
- Added missed tls:recv_data/2
|
||||
- Don't ignore Length parameter in tls:recv
|
||||
- Avoid quadratic behavior in reading SSL data
|
||||
- Dix http_bind webserver TLS fail on Chrome (EJAB-1530)
|
||||
|
||||
* Miscelanea
|
||||
- Assume we have only one CPU when an auto-detection fails (EJAB-1516)
|
||||
- Auth: Relax digest-uri handling (EJAB-1529)
|
||||
- Caps: Cache caps timestamp before the IQ-request is done
|
||||
- IRC: Use of MUC password
|
||||
- Private: misc errors cases fixes
|
||||
- Pubsub: return user affiliation for a specified node (EJAB-1294)
|
||||
- Shared Roster: Foreign items were not pushed (EJAB-1509)
|
||||
- Shared Roster LDAP: user substitution in ldap_rfilter (EJAB-1555)
|
||||
- Windows: Fix makefile rules for building DLLs
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,67 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.12
|
||||
|
||||
ejabberd 2.1.12 includes a many bugfixes and a few improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.12
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
* Core ejabberd
|
||||
- Make terms serialization faster
|
||||
- Reduce size of XML stream state
|
||||
|
||||
* Administration
|
||||
- Add SCRAM and remove MD5 support to ejabberd commands auth verification
|
||||
- Added command to list all the vhosts registered in an ejabberd node
|
||||
- Added export2odbc command, copied from mod_admin_extra.erl
|
||||
- Fix ejabberdctl number of arguments error report with R15
|
||||
- Check node name is available before starting ejabberd (EJAB-1572)
|
||||
- Fix ejabberd_xmlrpc commands authentication with SCRAM
|
||||
- Fix mod_offline:store_offline_msg argument (EJAB-1581)
|
||||
- Log IP address when auth attempt fails
|
||||
- Make sure update_info returns atoms only (EJAB-1595)
|
||||
- On shutdown, first stop listeners, then modules
|
||||
|
||||
* Encryption
|
||||
- Detect OpenSSL version at runtime, not at compile time
|
||||
- Fixed signedness issue in tls_drv GET_DESCRYPTED_INPUT (EJAB-1591)
|
||||
- Enable DHE key exchange in TLS driver
|
||||
- Enable ECDHE key exchange in TSL driver
|
||||
- Disable old and unsecure ciphers in TLS driver
|
||||
- Disable SSL 2.0 in TLS driver
|
||||
|
||||
* HTTP-Bind
|
||||
- Do not trigger item-not-found errors in mod_http_bind
|
||||
- Repeated http-bind request should abort only requests with same rid
|
||||
- Receiving missing request shouldn't close waiting out-ouf-order request
|
||||
|
||||
* XMPP
|
||||
- Allow multiple fqdn values in configuration (EJAB-1578)
|
||||
- Fix get_subscription_lists/4
|
||||
- Fix account registration
|
||||
- Send announce Message stanzas as Headline type instead of Normal
|
||||
|
||||
* Other
|
||||
- Guide: Fix file name of Name Service Switch
|
||||
- Guide: Document the db_type modules option (EJAB-1560)
|
||||
- LDAP: Fix broken JPEG photo (EJAB-1526)
|
||||
- LDAP: Fix compatibility with Erlang R16A (EJAB-1612)
|
||||
- MUC: Fix angle brackets handle in plaintext log (EJAB-1610)
|
||||
- MUC: Fix MUC start when Mnesia tables don't exist yet
|
||||
- MUC: New mod_muc_log option file_permissions (EJAB-1588)
|
||||
- ODBC: Merge SQL and Mnesia code into one module (EJAB-1560)
|
||||
- Translation: New Hebrew
|
||||
- Translation: Update Slovak
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.2
|
||||
|
||||
ejabberd 2.1.2 is the second bugfix release in ejabberd 2.1.x branch.
|
||||
|
||||
ejabberd 2.1.2 includes several bugfixes.
|
||||
More details of those fixes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.1.2
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The major changes are:
|
||||
|
||||
* Core
|
||||
- Close sessions that were half connected
|
||||
- Fix SASL PLAIN authentication message for RFC4616 compliance
|
||||
- Fix support for old Erlang/OTP R10 and R11
|
||||
- Return proper error (not 'conflict') when register is forbidden by ACL
|
||||
- When ejabberd stops, send stream close to clients
|
||||
|
||||
* ejabberdctl
|
||||
- Check for EGID in ejabberdctl command
|
||||
- Command to stop ejabberd informing users, with grace period
|
||||
- If there's a problem in config file, display config lines and stop node
|
||||
|
||||
* MUC
|
||||
- Kick occupants with reason when room is stopped due to MUC shutdown
|
||||
- Write in room log when a room is created, destroyed, started, stopped
|
||||
|
||||
* PubSub and PEP
|
||||
- Don't call gen_server on internal event (improves performance and scalability)
|
||||
- Fix duplicate SHIM header in Pubsub message
|
||||
- Notification messages of Pubsub node config change contained a SHIM header
|
||||
- SubID SHIM header missing in Pubsub message with multiple
|
||||
subscriptions on the same node
|
||||
- PEP: last published item not sent from unavailable users when the
|
||||
subscription is implicit (XEP-0115)
|
||||
- pep_mapping not working due to Node type mismatch
|
||||
|
||||
* WebAdmin
|
||||
- If big offline message queue, show only subset on WebAdmin
|
||||
- Support in user list page of WebAdmin when mod_offline is disabled
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,91 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.3
|
||||
|
||||
ejabberd 2.1.3 is the third release in ejabberd 2.1.x branch.
|
||||
|
||||
ejabberd 2.1.3 includes many bugfixes, and some improvements.
|
||||
More details of those fixes can be retrieved from:
|
||||
http://redir.process-one.net/ejabberd-2.1.3
|
||||
|
||||
The new code can be downloaded from ejabberd download page:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
This is the full list of changes:
|
||||
|
||||
* Client connections
|
||||
- Avoid 'invalid' value in iq record
|
||||
- Avoid resending stream:error stanzas on terminate (EJAB-1180)
|
||||
- Close also legacy sessions that were half connected (EJAB-1165)
|
||||
- iq_query_info/1 now returns 'invalid' if XMLNS is invalid
|
||||
- New ejabberd_c2s option support: max_fsm_queue
|
||||
- Rewrite mnesia counter functions to use dirty_update_counter (EJAB-1177)
|
||||
- Run user_receive_packet also when sending offline messages (EJAB-1193)
|
||||
- Use p1_fsm behaviour in c2s FSM (EJAB-1173)
|
||||
|
||||
* Clustering
|
||||
- Fix cluster race condition in route read
|
||||
- New command to set master Mnesia node
|
||||
- Use mnesia:async_dirty when cleaning table from failed node
|
||||
|
||||
* Documentation
|
||||
- Add quotes in documentation of some erl arguments (EJAB-1191)
|
||||
- Add option access_from (EJAB-1187)
|
||||
- Add option max_fsm_queue (EJAB-1185)
|
||||
- Fix documentation installation, no need for executable permission (EJAB-1170)
|
||||
- Fix typo in EJABBERD_BIN_PATH (EJAB-891)
|
||||
- Fix typos in example config comments (EJAB-1192)
|
||||
|
||||
* ejabberdctl
|
||||
- Support concurrent connections with bound connection names
|
||||
- Add support for Jot in ctl and TTY in debug
|
||||
- Support help command names with old - characters
|
||||
- Fix to really use the variable ERL_PROCESSES
|
||||
|
||||
* Erlang compatibility
|
||||
- Don't call queue:filter/2 to keep compatibility with older Erlang versions
|
||||
- Use alternative of file:read_line/1 to not require R13B02
|
||||
|
||||
* HTTP
|
||||
- Add new debugging hook to the http receiving process
|
||||
- Allow a request_handler to serve a file in root of HTTP
|
||||
|
||||
* HTTP-Bind (BOSH)
|
||||
- Cross-domain HTTP-Bind support (EJAB-1168)
|
||||
- Hibernate http-bind process after handling a request
|
||||
- Reduce verbosity of HTTP Binding log messages
|
||||
|
||||
* LDAP
|
||||
- Document ldap_dn_filter, fetch only needed attributes in search (EJAB-1204)
|
||||
- Use "%u" pattern as default for ldap_uids (EJAB-1203)
|
||||
|
||||
* Localization
|
||||
- Fix German translation (EJAB-1195)
|
||||
- Fix Russian translation
|
||||
|
||||
* ODBC
|
||||
- Fix MSSQL support, which was broken (EJAB-1201)
|
||||
- Improved SQL reconnect behaviour
|
||||
|
||||
* Pubsub, PEP and Caps
|
||||
- Add extended stanza addressing 'replyto' on PEP (EJAB-1198)
|
||||
- Add pubsub#purge_offline (EJAB-1186)
|
||||
- Fix pubsub#title option (EJAB-1190)
|
||||
- Fix remove_user for node subscriptions (EJAB-1172)
|
||||
- Optimizations in mod_caps
|
||||
|
||||
* Other
|
||||
- mod_register: Add new acl access_from, default is to deny
|
||||
- mod_sic: new module for the experimental XEP-0279 Server IP Check (EJAB-1205)
|
||||
- PIEFXIS: Catch errors when exporting to PIEFXIS file (EJAB-1178)
|
||||
- Proxy65: new option "hostname" (EJAB-838)
|
||||
- Roster: Fix resending authorization problem
|
||||
- Shared Roster Groups: get contacts nickname from vcard (EJAB-114)
|
||||
- S2S: Improved s2s connections clean up (EJAB-1202)
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.4
|
||||
|
||||
ejabberd 2.1.4 is the fourth release in ejabberd 2.1.x branch,
|
||||
and includes many small bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.4
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
This is the full list of changes:
|
||||
|
||||
* Authentication
|
||||
- Extauth: Optionally cache extauth users in mnesia (EJAB-641)
|
||||
- LDAP: Allow inband password change (EJAB-199)
|
||||
- LDAP: Extensible match support (EJAB-722)
|
||||
- LDAP: New option ldap_tls_verify is added (EJAB-1229)
|
||||
- PAM: New option pam_userinfotype to provide username or JID (EJAB-652)
|
||||
|
||||
* HTTP
|
||||
- Add xml default content type
|
||||
- Don't show HTTP request in logs, because reveals password (EJAB-1231)
|
||||
- Move HTTP session timeout log from warning level to info
|
||||
- New Access rule webadmin_view for read-only
|
||||
|
||||
* HTTP-Bind (BOSH)
|
||||
- Change max inactivity from 30 to 120 seconds
|
||||
- Export functions to facilitate prebinding methods
|
||||
- Use dirty_delete when removing the session
|
||||
- Remove an unneeded delay of 100 milliseconds
|
||||
|
||||
* Pubsub, PEP and Caps
|
||||
- Enforce pubsub#presence_based_delivery (EJAB-1221)
|
||||
- Enforce pubsub#show_values subscription option (EJAB-1096)
|
||||
- Fix error code when unsubscribing from a non-existent node
|
||||
- Fix to send node notifications (EJAB-1225)
|
||||
- Full support for XEP-0115 v1.5 (EJAB-1223)(EJAB-1189)
|
||||
- Make last_item_cache feature to be cluster aware
|
||||
- Prevent orphaned pubsub node (EJAB-1233)
|
||||
- Send created node notifications
|
||||
|
||||
* Other
|
||||
- Bounce messages when closing c2s session
|
||||
- Bugfixes when handling Service Discovery to contacts (EJAB-1207)
|
||||
- Compilation of ejabberd_debug.erl is now optional
|
||||
- Don't send error stanza as reply to error stanza (EJAB-930)
|
||||
- Don't store blocked messages in offline queue
|
||||
- Reduce verbosity of log when captcha_cmd is checked but not configured
|
||||
- Use a standard method to get a random seed (EJAB-1229)
|
||||
- Commands: new update_list and update to update modified modules (EJAB-1237)
|
||||
- Localization: Updated most translations
|
||||
- MUC: Refactor code to reduce calls to get_affiliation and get_role
|
||||
- ODBC: Add created_at column also to PostgreSQL schema
|
||||
- Vcard: Automatic vcard avatar addition in presence
|
||||
|
||||
|
||||
Upgrading From previous ejabberd releases:
|
||||
|
||||
- If you use PostgreSQL, maybe you want to add the column created_at
|
||||
to several tables. This is only a suggestion; ejabberd doesn't use
|
||||
that column. Add it to your existing database executing those SQL
|
||||
statements:
|
||||
|
||||
ALTER TABLE users ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
ALTER TABLE rosterusers ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
ALTER TABLE spool ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
ALTER TABLE vcard ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
ALTER TABLE privacy_list ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
ALTER TABLE privacy_storage ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.5
|
||||
|
||||
ejabberd 2.1.5 is the fifth release in ejabberd 2.1.x branch,
|
||||
and includes several minor bugfixes and a few improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.4
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
This is the full list of changes:
|
||||
|
||||
* Authentication
|
||||
- Extauth: Support parallel script running (EJAB-1280)
|
||||
- mod_register: Return Registered element when account exists
|
||||
|
||||
* ejabberdctl
|
||||
- Fix print of command result that contains ~
|
||||
- Fix problem when FIREWALL_WINDOW options for erl kernel were used
|
||||
- Fix typo in update_list command (EJAB-1237)
|
||||
- Some systems delete the lock dir; in such case don't use flock at all
|
||||
- The command Update now returns meaningful message and exit-status (EJAB-1237)
|
||||
|
||||
* HTTP-Bind (BOSH)
|
||||
- Don't say v1.2 in the Bind HTTP page
|
||||
- New optional BOSH connection attribute process-delay (EJAB-1257)
|
||||
|
||||
* MUC
|
||||
- Document the mod_muc option captcha_protected
|
||||
- Now admins are able to see private rooms in disco (EJAB-1269)
|
||||
- Show some more room options in the log file
|
||||
|
||||
* ODBC
|
||||
- Correct handling of SQL boolean types (EJAB-1275)
|
||||
- Discard too old queued requests (the caller has already got a timeout)
|
||||
- Fixes wrong SQL escaping when --enable-full-xml is set
|
||||
- Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1
|
||||
|
||||
* Pubsub, PEP and Caps
|
||||
- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238)
|
||||
- Support all the hash functions required by Caps XEP-0115
|
||||
|
||||
* Requirements
|
||||
- Fixed support for Erlang R12; which doesn't support: true andalso ok
|
||||
- Support OTP R14A by using public_key library instead of old ssl (EJAB-953)
|
||||
- Requirement of OpenSSL increased from 0.9.6 to 0.9.8
|
||||
- OpenSSL is now required, not optional
|
||||
|
||||
* Other
|
||||
- Don't ask for client certificate when using tls (EJAB-1267)
|
||||
- Fix typo in --enable-transient_supervisors
|
||||
- Fix privacy check when serving local Last (EJAB-1271)
|
||||
- Inform client that SSL session caching is disabled
|
||||
- New configure option: --enable-nif
|
||||
- Use driver allocator in C files for reflecting memory in erlang:memory(system)
|
||||
- Debug: New p1_prof compiled with: make debugtools=true
|
||||
- Debug: Added functions to collect stats about queues, memory, reductions etc
|
||||
- HTTP: Log error if request has ambiguous Host header (EJAB-1261)
|
||||
- Logs: When logging s2s out connection attempt or success, log if TLS is used
|
||||
- Shared Rosters: When account is deleted, delete also member of stored rosters
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,67 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.6
|
||||
|
||||
ejabberd 2.1.6 is the sixth release in ejabberd 2.1.x branch,
|
||||
and includes a lot of bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.6
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
Some of the changes are:
|
||||
|
||||
* Account register
|
||||
- mod_register: New ip_access option restricts which IPs can register (EJAB-915)
|
||||
- mod_register: Default configuration allows registrations only from localhost
|
||||
- mod_register: New password_strength for entropy check (EJAB-1326)
|
||||
- mod_register: New captcha_protected option to require CAPTCHA (EJAB-1262)
|
||||
- mod_register_web: New module, with CAPTCHA support (EJAB-471)
|
||||
|
||||
* BOSH
|
||||
- Don't loop when there is nothing after a stream start (EJAB-1358)
|
||||
- Fix http-bind supervisor to support multiple vhosts (EJAB-1321)
|
||||
- Support to restart http-bind (EJAB-1318)
|
||||
- Support for X-Forwarded-For HTTP header (EJAB-1356)
|
||||
|
||||
* Erlang/OTP compatibility
|
||||
- R11: Fix detection of Erlang R11 and older (EJAB-1287)
|
||||
- R12B5: Fix compatibility in ejabberd_http_bind.erl (EJAB-1343)
|
||||
- R14A: Make xml.c correctly compile (EJAB-1288)
|
||||
- R14A, R14B: Disapprove the use of R14A and R14B due to the rwlock bug
|
||||
- R14B: Use pg2 from this version in systems with older ones (EJAB-1349)
|
||||
|
||||
* Listeners
|
||||
- Bind listener ports early and start accepting connections later
|
||||
- Fix a leak of ejabberd_receiver processes
|
||||
- Speed up ejabberd_s2s:is_service/2, allow_host/2 (EJAB-1319)
|
||||
- S2S: New option to require encryption (EJAB-495)
|
||||
- S2S: New option to reject connection if untrusted certificate (EJAB-464)
|
||||
- S2S: Include From attribute in the stream header of outgoing S2S connections
|
||||
- S2S: Fix domain_certfile tlsopts modifications for S2S connections (EJAB-1086)
|
||||
|
||||
* Pubsub/PEP/Caps
|
||||
- Fix pubsub cross domain eventing (EJAB-1340)
|
||||
- Use one_queue IQ discipline by default
|
||||
- Implement lifetime for broken hashes
|
||||
- New CAPS processing
|
||||
|
||||
* ODBC
|
||||
- Increase maximum restart strategy to handle some SQL timeouts
|
||||
- Support PostgreSQL 9.0 (EJAB-1359)
|
||||
- Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252)
|
||||
|
||||
* Miscellanea:
|
||||
- mod_shared_roster_ldap: New Shared Roster Groups using LDAP information
|
||||
- mod_privacy: Fix to allow block by group and subscription again
|
||||
- Support timezone West of UTC (EJAB-1301)
|
||||
- Support to change loglevel per module at runtime (EJAB-225)
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.7
|
||||
|
||||
ejabberd 2.1.7 is the eighth release in ejabberd 2.1.x branch,
|
||||
and includes a lot of bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.7
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
* BOSH and Web
|
||||
- Clarify error message when BOSH query is sent to non-running module
|
||||
- Keep the order of stanzas when BOSH sends several (EJAB-1374)
|
||||
- Show configuration for HTTPS http_bind
|
||||
- Support as read-only HTTP method not only GET, also HEAD
|
||||
- The responses to HEAD must have empty Body
|
||||
|
||||
* CAPTCHA
|
||||
- If the port number isn't listener, then specify the protocol (EJAB-1418)
|
||||
- New CAPTCHA limit
|
||||
- New CAPTCHA whitelist support
|
||||
- Only check system at startup if option is enabled
|
||||
- Provide HTTPS URL in CAPTCHA form when listener has 'tls' option (EJAB-1406)
|
||||
- Show captcha_limit option in the example config
|
||||
- Support more captcha_host value formats (EJAB-1418)
|
||||
- Throw error when captcha fails at server start, not later at runtime
|
||||
- captcha_host must have the port number to get protocol (EJAB-1418)
|
||||
|
||||
* Core ejabberd
|
||||
- Disable all entity expansions (EJAB-1451)
|
||||
- Do not accept XML with undefined prefixes (EJAB-680)
|
||||
- Make jlib:ip_to_list safe to use
|
||||
- Make sure 'closed' event is correctly processed on every state
|
||||
- New route_iq/5 accepting Timeout (EJAB-1398)
|
||||
- Take into consideration internal queue length when sorting processes queues
|
||||
- Use route instead of send_element to go through standard workflow
|
||||
|
||||
* Erlang/OTP compatibility
|
||||
- Remove Type and Spec, backport list comprehensions, so R12B-5 can compile
|
||||
- Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349)
|
||||
|
||||
* ODBC
|
||||
- Don't let presence-in privacy rule block a presence subscription (EJAB-255)
|
||||
- Escape user input in mod_privacy_odbc (EJAB-1442)
|
||||
- Try to improve support for roster_version in MSSQL (EJAB-1437)
|
||||
|
||||
* Pubsub/PEP/Caps
|
||||
- Apply filtered notification to PEP last items (EJAB-1456)
|
||||
- Fix empty pubsub payload check
|
||||
- Owner can delete any items from its own node (EJAB-1445)
|
||||
- Pubsub node maxitem forced to 0 if non persistent node (EJAB-1434)
|
||||
- Reorganize the push_item function, and handle version not_found (EJAB-1420)
|
||||
|
||||
* Scripts
|
||||
- ejabberd.init: Several fixes and improvements
|
||||
- ejabberdctl: Escape output from ctlexec() to erl script (EJAB-1399)
|
||||
- ejabberdctl: Fix bashism and mimic master branch (EJAB-1404)
|
||||
- ejabberdctl: Fix space between INET_DIST_INTERFACE (EJAB-1416)
|
||||
- ejabberdctl: New DIST_USE_INTERFACE restricts IP of erlang listen (EJAB-1404)
|
||||
- ejabberdctl: New ERL_EPMD_ADDRESS that works since Erlang/OTP R14B03
|
||||
- extauth: Fix delayed response of timeout was reused for next login (EJAB-1385)
|
||||
- extauth: Forward old messages to newly spawned extauth process (EJAB-1385)
|
||||
- extauth: If script crashes, ejabberd should restart it (EJAB-1428)
|
||||
|
||||
* XEP support
|
||||
- mod_blocking: New XEP-0191 Simple Communications Blocking (EJAB-695)
|
||||
- No need to inform that XEP-0237 is optional; clarified in XEP version 1.2
|
||||
|
||||
* Miscellanea:
|
||||
- If a module start fails during server start, stop erlang (EJAB-1446)
|
||||
- New Indonesian translation (EJAB-1407)
|
||||
- LDAP: Note that ejabberd works with CGP LDAP server
|
||||
- S2S: Handle Tigase's unexpected version=1.0 (EJAB-1379)
|
||||
- mod_irc: Send presence unavailable to the departing occupant (EJAB-1417)
|
||||
- mod_last: Allow user to query his own Last activity
|
||||
- mod_muc: Do not decrease MUC admin's role/affiliation
|
||||
- mod_muc: Send jid attribute when occupant is banned (EJAB-1432)
|
||||
- mod_offline: Change c2s state before offline messages resending
|
||||
- mod_ping: Use iqdisc no_queue by default (EJAB-1435)
|
||||
- mod_pres_counter: Prevent subscription flood (EJAB-1388)
|
||||
- mod_register Access now also controls account unregistrations
|
||||
- mod_register: Clarify more the expected content of welcome_message option
|
||||
- mod_shared_roster: Fix support for anonymous accounts in @all@ (EJAB-1264)
|
||||
- mod_shared_roster: New @online@ directive (EJAB-1391)
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.8
|
||||
|
||||
ejabberd 2.1.8 is the ninth release in ejabberd 2.1.x branch,
|
||||
and includes a PubSub regression bugfix.
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The change is:
|
||||
|
||||
- Fix issue on PubSub preventing publication of items (EJAB-1457)
|
||||
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
@@ -1,56 +0,0 @@
|
||||
|
||||
Release Notes
|
||||
ejabberd 2.1.9
|
||||
|
||||
ejabberd 2.1.9 is the eighth release in ejabberd 2.1.x branch,
|
||||
and includes a lot of bugfixes and improvements.
|
||||
|
||||
Read more details about the changes in:
|
||||
http://redir.process-one.net/ejabberd-2.1.9
|
||||
|
||||
Download the source code and installers from:
|
||||
http://www.process-one.net/en/ejabberd/
|
||||
|
||||
|
||||
The changes are:
|
||||
|
||||
* Core ejabberd
|
||||
- Decrease CPU usage caused by tls:send with large data
|
||||
- Escape iolist correctly when NIFs are disabled (EJAB-1462)
|
||||
- Fix code to satisfy Dialyzer warnings
|
||||
- Fix compilation in Windows
|
||||
- Replace calls of OTP's Binary, since they would require R14
|
||||
|
||||
* LDAP
|
||||
- Document ldap_tls_cacertfile and ldap_tls_depth options (EJAB-1299)
|
||||
- Log an error when an LDAP filter is incorrect (EJAB-1395)
|
||||
- New options: ldap_tls_cacertfile and ldap_tls_depth (EJAB-1299)
|
||||
- New option: ldap_deref_aliases (EJAB-639)
|
||||
- Match ldap_uidattr_format case-insensitively (EJAB-1449)
|
||||
|
||||
* MUC
|
||||
- Support for multiple entry with same nick to MUC rooms (EJAB-305)
|
||||
- Support voice request and approvement
|
||||
- New room option: allow_private_messages_from_visitors
|
||||
- New room options: allow_voice_requests and voice_request_min_interval
|
||||
- Include status 110 in presence to new occupant (EJAB-740)
|
||||
- Fix mod_muc_log crash when first log entry is room destroy (EJAB-1499)
|
||||
- Many fixes and improvements in mod_muc
|
||||
|
||||
* Pubsub
|
||||
- Enable pubsub#deliver_notification checking (EJAB-1453)
|
||||
- Fix Denial of Service when user sends malformed publish stanza (EJAB-1498)
|
||||
|
||||
* ODBC
|
||||
- Fix ODBC account counting (EJAB-1491)
|
||||
- Optimized mod_roster_odbc:get_roster
|
||||
|
||||
* Miscellanea:
|
||||
- New SASL SCRAM-SHA-1 authentication mechanism (EJAB-1196)
|
||||
- New option: resource_conflict (EJAB-650)
|
||||
|
||||
|
||||
Bug reports
|
||||
|
||||
You can officially report bugs on ProcessOne support site:
|
||||
http://support.process-one.net/
|
||||
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 157 KiB |
@@ -1,5 +1,5 @@
|
||||
###
|
||||
### ejabberd configuration file
|
||||
###' ejabberd configuration file
|
||||
###
|
||||
###
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
### > Art thou not Romeo,
|
||||
### and a Montague?
|
||||
|
||||
### =======
|
||||
### LOGGING
|
||||
###. =======
|
||||
###' LOGGING
|
||||
|
||||
##
|
||||
## loglevel: Verbosity of log files generated by ejabberd.
|
||||
@@ -72,9 +72,18 @@ log_rate_limit: 100
|
||||
## watchdog_admins:
|
||||
## - "bob@example.com"
|
||||
|
||||
###. ===============
|
||||
###' NODE PARAMETERS
|
||||
|
||||
### ================
|
||||
### SERVED HOSTNAMES
|
||||
##
|
||||
## net_ticktime: Specifies net_kernel tick time in seconds. This options must have
|
||||
## identical value on all nodes, and in most cases shouldn't be changed at all from
|
||||
## default value.
|
||||
##
|
||||
## net_ticktime: 60
|
||||
|
||||
###. ================
|
||||
###' SERVED HOSTNAMES
|
||||
|
||||
##
|
||||
## hosts: Domains served by ejabberd.
|
||||
@@ -94,8 +103,8 @@ hosts:
|
||||
##
|
||||
## route_subdomains: s2s
|
||||
|
||||
### ===============
|
||||
### LISTENING PORTS
|
||||
###. ===============
|
||||
###' LISTENING PORTS
|
||||
|
||||
##
|
||||
## listen: The ports ejabberd will listen on, which service each is handled
|
||||
@@ -161,14 +170,17 @@ listen:
|
||||
-
|
||||
port: 5280
|
||||
module: ejabberd_http
|
||||
## request_handlers:
|
||||
## "/pub/archive": mod_http_fileserver
|
||||
request_handlers:
|
||||
"/websocket": ejabberd_http_ws
|
||||
## "/pub/archive": mod_http_fileserver
|
||||
web_admin: true
|
||||
http_poll: true
|
||||
http_bind: true
|
||||
## register: true
|
||||
captcha: true
|
||||
|
||||
###. ==================
|
||||
###' S2S GLOBAL OPTIONS
|
||||
|
||||
##
|
||||
## s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections.
|
||||
## Allowed values are: false optional required required_trusted
|
||||
@@ -214,8 +226,8 @@ listen:
|
||||
## - ipv6
|
||||
## outgoing_s2s_timeout: 10000
|
||||
|
||||
### ==============
|
||||
### AUTHENTICATION
|
||||
###. ==============
|
||||
###' AUTHENTICATION
|
||||
|
||||
##
|
||||
## auth_method: Method used to authenticate the users.
|
||||
@@ -305,8 +317,8 @@ auth_method: internal
|
||||
## - internal
|
||||
## - anonymous
|
||||
|
||||
### ==============
|
||||
### DATABASE SETUP
|
||||
###. ==============
|
||||
###' DATABASE SETUP
|
||||
|
||||
## ejabberd by default uses the internal Mnesia database,
|
||||
## so you do not necessarily need this section.
|
||||
@@ -343,6 +355,12 @@ auth_method: internal
|
||||
##
|
||||
## pgsql_users_number_estimate: true
|
||||
|
||||
##
|
||||
## SQLite:
|
||||
##
|
||||
## odbc_type: sqlite
|
||||
## odbc_database: "/path/to/database.db"
|
||||
|
||||
##
|
||||
## ODBC compatible or MSSQL server:
|
||||
##
|
||||
@@ -360,8 +378,8 @@ auth_method: internal
|
||||
##
|
||||
## odbc_keepalive_interval: undefined
|
||||
|
||||
### ===============
|
||||
### TRAFFIC SHAPERS
|
||||
###. ===============
|
||||
###' TRAFFIC SHAPERS
|
||||
|
||||
shaper:
|
||||
##
|
||||
@@ -442,8 +460,8 @@ acl:
|
||||
## user:
|
||||
## - "bob-local": "localhost"
|
||||
|
||||
### ============
|
||||
### ACCESS RULES
|
||||
###. ============
|
||||
###' ACCESS RULES
|
||||
access:
|
||||
## Maximum number of simultaneous sessions allowed for a single user:
|
||||
max_user_sessions:
|
||||
@@ -512,8 +530,8 @@ access:
|
||||
## register:
|
||||
## all: deny
|
||||
|
||||
### ================
|
||||
### DEFAULT LANGUAGE
|
||||
###. ================
|
||||
###' DEFAULT LANGUAGE
|
||||
|
||||
##
|
||||
## language: Default language used for server messages.
|
||||
@@ -527,8 +545,8 @@ language: "en"
|
||||
## "localhost":
|
||||
## language: "ru"
|
||||
|
||||
### =======
|
||||
### CAPTCHA
|
||||
###. =======
|
||||
###' CAPTCHA
|
||||
|
||||
##
|
||||
## Full path to a script that generates the image.
|
||||
@@ -545,14 +563,15 @@ language: "en"
|
||||
##
|
||||
## captcha_limit: 5
|
||||
|
||||
### =======
|
||||
### MODULES
|
||||
###. =======
|
||||
###' MODULES
|
||||
|
||||
##
|
||||
## Modules enabled in all ejabberd virtual hosts.
|
||||
##
|
||||
modules:
|
||||
mod_adhoc: {}
|
||||
## mod_admin_extra: {}
|
||||
mod_announce: # recommends mod_adhoc
|
||||
access: announce
|
||||
mod_blocking: {} # requires mod_privacy
|
||||
@@ -577,6 +596,7 @@ modules:
|
||||
access_persistent: muc_create
|
||||
access_admin: muc_admin
|
||||
## mod_muc_log: {}
|
||||
## mod_multicast: {}
|
||||
mod_offline:
|
||||
access_max_user_messages: max_user_offline_messages
|
||||
mod_ping: {}
|
||||
@@ -660,7 +680,9 @@ modules:
|
||||
|
||||
allow_contrib_modules: true
|
||||
|
||||
###.
|
||||
###'
|
||||
### Local Variables:
|
||||
### mode: yaml
|
||||
### End:
|
||||
### vim: set filetype=yaml tabstop=8
|
||||
### vim: set filetype=yaml tabstop=8 foldmarker=###',###. foldmethod=marker:
|
||||
|
||||
@@ -16,9 +16,6 @@ IEX={{bindir}}/iex
|
||||
EPMD={{bindir}}/epmd
|
||||
INSTALLUSER={{installuser}}
|
||||
|
||||
# Compatibility in ZSH
|
||||
#setopt shwordsplit 2>/dev/null
|
||||
|
||||
# check the proper system user is used if defined
|
||||
if [ "$INSTALLUSER" != "" ] ; then
|
||||
EXEC_CMD="false"
|
||||
@@ -112,6 +109,8 @@ DATETIME=`date "+%Y%m%d-%H%M%S"`
|
||||
ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump
|
||||
ERL_INETRC=$ETC_DIR/inetrc
|
||||
|
||||
# define mnesia options
|
||||
MNESIA_OPTS="-mnesia dir \"\\\"$SPOOL_DIR\\\"\" $MNESIA_OPTIONS"
|
||||
# define erl parameters
|
||||
ERL_OPTIONS=$(echo $ERL_OPTIONS | sed 's/ /\\ /g')
|
||||
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
|
||||
@@ -167,6 +166,7 @@ export ERL_EPMD_ADDRESS
|
||||
export ERL_INETRC
|
||||
export ERL_MAX_PORTS
|
||||
export ERL_MAX_ETS_TABLES
|
||||
export CONTRIB_MODULES_PATH
|
||||
|
||||
# start server
|
||||
start()
|
||||
@@ -176,7 +176,7 @@ start()
|
||||
$NAME $ERLANG_NODE \
|
||||
-noinput -detached \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
|
||||
$MNESIA_OPTS \
|
||||
$KERNEL_OPTS \
|
||||
$EJABBERD_OPTS \
|
||||
-s ejabberd \
|
||||
@@ -217,7 +217,7 @@ live()
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME $ERLANG_NODE \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
|
||||
$MNESIA_OPTS \
|
||||
$KERNEL_OPTS \
|
||||
$EJABBERD_OPTS \
|
||||
-s ejabberd \
|
||||
@@ -238,14 +238,6 @@ iexlive()
|
||||
--erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\""
|
||||
}
|
||||
|
||||
etop()
|
||||
{
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME debug-${TTY}-${ERLANG_NODE} \
|
||||
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
|
||||
}
|
||||
|
||||
# TODO: refactor debug warning and livewarning
|
||||
debugwarning()
|
||||
{
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
@@ -267,7 +259,7 @@ debugwarning()
|
||||
echo "Press return to continue"
|
||||
read foo
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
livewarning()
|
||||
@@ -294,7 +286,26 @@ livewarning()
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO: Make iex command display only if ejabberd Elixir support has been enabled
|
||||
etop()
|
||||
{
|
||||
TTY=`tty | sed -e 's/.*\///g'`
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME debug-${TTY}-${ERLANG_NODE} \
|
||||
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
|
||||
}
|
||||
|
||||
ping()
|
||||
{
|
||||
TTY=`tty | sed -e 's/.*\///g'`
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME ping-${TTY}-${ERLANG_NODE} \
|
||||
-hidden \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
$KERNEL_OPTS $ERLANG_OPTS \
|
||||
-eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \
|
||||
-s erlang halt -output text -noinput"
|
||||
}
|
||||
|
||||
help()
|
||||
{
|
||||
echo ""
|
||||
@@ -325,9 +336,9 @@ ctl()
|
||||
# flock that can lock a file descriptor.
|
||||
MAXCONNID=100
|
||||
CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl
|
||||
FLOCK='/usr/bin/flock'
|
||||
FLOCK=/usr/bin/flock
|
||||
if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then
|
||||
JOT='/usr/bin/jot'
|
||||
JOT=/usr/bin/jot
|
||||
if [ ! -x "$JOT" ] ; then
|
||||
# no flock or jot, simply invoke ctlexec()
|
||||
CTL_CONN="ctl-${ERLANG_NODE}"
|
||||
@@ -394,7 +405,7 @@ ctl()
|
||||
ctlexec()
|
||||
{
|
||||
CONN_NAME=$1; shift
|
||||
COMMAND=$@
|
||||
COMMAND=$(echo $@ | sed 's/;/\\;/g')
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME ${CONN_NAME} \
|
||||
-noinput \
|
||||
@@ -407,7 +418,7 @@ ctlexec()
|
||||
# stop epmd if there is no other running node
|
||||
stop_epmd()
|
||||
{
|
||||
$EPMD -names 2>/dev/null | grep -q name || epmd -kill >/dev/null
|
||||
$EPMD -names 2>/dev/null | grep -q name || $EPMD -kill >/dev/null
|
||||
}
|
||||
|
||||
# make sure node not already running and node name unregistered
|
||||
@@ -467,6 +478,7 @@ case $ARGS in
|
||||
' iexdebug') iexdebug;;
|
||||
' live') live;;
|
||||
' iexlive') iexlive;;
|
||||
' ping'*) ping ${ARGS# ping};;
|
||||
' etop') etop;;
|
||||
' started') wait_for_status 0 30 2;; # wait 30x2s before timeout
|
||||
' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
-define(MSGS_DIR, filename:join(["priv", "msgs"])).
|
||||
|
||||
-define(SQL_DIR, filename:join(["priv", "sql"])).
|
||||
|
||||
-define(CONFIG_PATH, <<"ejabberd.cfg">>).
|
||||
|
||||
-define(LOG_PATH, <<"ejabberd.log">>).
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
-ifndef(EJABBERD_SM_HRL).
|
||||
-define(EJABBERD_SM_HRL, true).
|
||||
|
||||
-record(session, {sid, usr, us, priority, info}).
|
||||
-record(session_counter, {vhost, count}).
|
||||
-type sid() :: {erlang:timestamp(), pid()}.
|
||||
@@ -5,3 +8,5 @@
|
||||
-type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()}
|
||||
| {oor, boolean()} | {auth_module, atom()}].
|
||||
-type prio() :: undefined | integer().
|
||||
|
||||
-endif.
|
||||
|
||||
@@ -110,8 +110,8 @@
|
||||
|
||||
-record(muc_online_users, {us = {<<>>, <<>>} :: {binary(), binary()},
|
||||
resource = <<>> :: binary() | '_',
|
||||
room = <<>> :: binary() | '_',
|
||||
host = <<>> :: binary() | '_'}).
|
||||
room = <<>> :: binary() | '_' | '$1',
|
||||
host = <<>> :: binary() | '_' | '$2'}).
|
||||
|
||||
-type muc_online_users() :: #muc_online_users{}.
|
||||
|
||||
|
||||
@@ -35,12 +35,10 @@
|
||||
-define(NS_BLOCKING, <<"urn:xmpp:blocking">>).
|
||||
-define(NS_PRIVATE, <<"jabber:iq:private">>).
|
||||
-define(NS_VERSION, <<"jabber:iq:version">>).
|
||||
-define(NS_TIME90, <<"jabber:iq:time">>).
|
||||
-define(NS_TIME, <<"urn:xmpp:time">>).
|
||||
-define(NS_LAST, <<"jabber:iq:last">>).
|
||||
-define(NS_XDATA, <<"jabber:x:data">>).
|
||||
-define(NS_IQDATA, <<"jabber:iq:data">>).
|
||||
-define(NS_DELAY91, <<"jabber:x:delay">>).
|
||||
-define(NS_DELAY, <<"urn:xmpp:delay">>).
|
||||
-define(NS_HINTS, <<"urn:xmpp:hints">>).
|
||||
-define(NS_EXPIRE, <<"jabber:x:expire">>).
|
||||
@@ -143,6 +141,8 @@
|
||||
-define(NS_CAPTCHA, <<"urn:xmpp:captcha">>).
|
||||
-define(NS_MEDIA, <<"urn:xmpp:media-element">>).
|
||||
-define(NS_BOB, <<"urn:xmpp:bob">>).
|
||||
-define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>).
|
||||
-define(NS_MAM_0, <<"urn:xmpp:mam:0">>).
|
||||
-define(NS_PING, <<"urn:xmpp:ping">>).
|
||||
-define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>).
|
||||
-define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>).
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
|
||||
%% -------------------------------
|
||||
%% Pubsub constants
|
||||
-define(ERR_EXTENDED(E, C),
|
||||
mod_pubsub:extended_error(E, C)).
|
||||
-define(ERR_EXTENDED(E, C), mod_pubsub:extended_error(E, C)).
|
||||
|
||||
%% The actual limit can be configured with mod_pubsub's option max_items_node
|
||||
-define(MAXITEMS, 10).
|
||||
@@ -40,7 +39,6 @@
|
||||
%% -------------------------------
|
||||
%% Pubsub types
|
||||
|
||||
%% @type hostPubsub() = string().
|
||||
-type(hostPubsub() :: binary()).
|
||||
%% <p><tt>hostPubsub</tt> is the name of the PubSub service. For example, it can be
|
||||
%% <tt>"pubsub.localhost"</tt>.</p>
|
||||
@@ -59,12 +57,15 @@
|
||||
-type(nodeId() :: binary()).
|
||||
%% @type nodeId() = binary().
|
||||
%% <p>A node is defined by a list of its ancestors. The last element is the name
|
||||
%% of the current node. For example:
|
||||
%% of the current node. For example:
|
||||
%% ```<<"/home/localhost/user">>'''</p>
|
||||
|
||||
-type(nodeIdx() :: pos_integer()).
|
||||
%% @type nodeIdx() = integer().
|
||||
-type(nodeIdx() :: pos_integer() | binary()).
|
||||
%% @type nodeIdx() = integer() | binary().
|
||||
%% note: pos_integer() should always be used, but we allow anything else coded
|
||||
%% as binary, so one can have a custom implementation of nodetree with custom
|
||||
%% indexing (see nodetree_virtual). this also allows to use any kind of key for
|
||||
%% indexing nodes, as this can be usefull with external backends such as odbc.
|
||||
|
||||
-type(itemId() :: binary()).
|
||||
%% @type itemId() = string().
|
||||
@@ -72,28 +73,12 @@
|
||||
-type(subId() :: binary()).
|
||||
%% @type subId() = string().
|
||||
|
||||
|
||||
%% @type payload() = [#xmlelement{} | #xmlcdata{}].
|
||||
|
||||
%% @type stanzaError() = #xmlelement{}.
|
||||
%% Example:
|
||||
%% Example:
|
||||
%% ```{xmlelement, "error",
|
||||
%% [{"code", Code}, {"type", Type}],
|
||||
%% [{xmlelement, Condition, [{"xmlns", ?NS_STANZAS}], []}]}'''
|
||||
%% @type pubsubIQResponse() = #xmlelement{}.
|
||||
%% Example:
|
||||
%% ```{xmlelement, "pubsub",
|
||||
%% [{"xmlns", ?NS_PUBSUB_EVENT}],
|
||||
%% [{xmlelement, "affiliations", [],
|
||||
%% []}]}'''
|
||||
|
||||
-type(nodeOption() ::
|
||||
{Option::atom(),
|
||||
Value::binary() | [binary()] | boolean() | non_neg_integer()
|
||||
Value::atom() | [binary()] | boolean() | non_neg_integer()
|
||||
}).
|
||||
|
||||
-type(nodeOptions() :: [NodeOption::mod_pubsub:nodeOption(),...]).
|
||||
-type(nodeOptions() :: [mod_pubsub:nodeOption(),...]).
|
||||
|
||||
%% @type nodeOption() = {Option, Value}
|
||||
%% Option = atom()
|
||||
@@ -106,31 +91,14 @@
|
||||
Value::binary() | [binary()] | boolean()
|
||||
}).
|
||||
|
||||
-type(subOptions() :: [SubOption::mod_pubsub:subOption(),...]).
|
||||
-type(subOptions() :: [mod_pubsub:subOption(),...]).
|
||||
|
||||
%% @type nodeType() = string().
|
||||
%% <p>The <tt>nodeType</tt> is a string containing the name of the PubSub
|
||||
%% plugin to use to manage a given node. For example, it can be
|
||||
%% <tt>"flat"</tt>, <tt>"hometree"</tt> or <tt>"blog"</tt>.</p>
|
||||
|
||||
%% @type jid() = {jid, User, Server, Resource, LUser, LServer, LResource}
|
||||
%% User = string()
|
||||
%% Server = string()
|
||||
%% Resource = string()
|
||||
%% LUser = string()
|
||||
%% LServer = string()
|
||||
%% LResource = string().
|
||||
|
||||
%-type(ljid() :: {binary(), binary(), binary()}).
|
||||
%% @type ljid() = {User, Server, Resource}
|
||||
%% User = string()
|
||||
%% Server = string()
|
||||
%% Resource = string().
|
||||
|
||||
-type(affiliation() :: 'none'
|
||||
| 'owner'
|
||||
| 'publisher'
|
||||
%| 'publish-only'
|
||||
| 'publish_only'
|
||||
| 'member'
|
||||
| 'outcast'
|
||||
).
|
||||
@@ -151,16 +119,11 @@
|
||||
).
|
||||
%% @type accessModel() = 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'.
|
||||
|
||||
%% @type pubsubIndex() = {pubsub_index, Index, Last, Free}
|
||||
%% Index = atom()
|
||||
%% Last = integer()
|
||||
%% Free = [integer()].
|
||||
%% internal pubsub index table
|
||||
-type(publishModel() :: 'publishers'
|
||||
| 'subscribers'
|
||||
| 'open'
|
||||
).
|
||||
|
||||
%% @type publishModel() = 'publishers' | 'subscribers' | 'open'
|
||||
|
||||
-record(pubsub_index,
|
||||
{
|
||||
@@ -169,91 +132,42 @@
|
||||
free :: [mod_pubsub:nodeIdx()]
|
||||
}).
|
||||
|
||||
%% @type pubsubNode() = {pubsub_node, NodeId, Id, Parents, Type, Owners, Options}
|
||||
%% NodeId = {host() | ljid(), nodeId()}
|
||||
%% Id = nodeIdx()
|
||||
%% Parents = [nodeId()]
|
||||
%% Type = nodeType()
|
||||
%% Owners = [ljid()]
|
||||
%% Options = [nodeOption()].
|
||||
%% <p>This is the format of the <tt>nodes</tt> table. The type of the table
|
||||
%% is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
|
||||
%% <p>The <tt>Parents</tt> and <tt>type</tt> fields are indexed.</p>
|
||||
%% <tt>id</tt> can be anything you want.
|
||||
-record(pubsub_node,
|
||||
{
|
||||
nodeid ,%:: {Host::mod_pubsub:host(), NodeId::mod_pubsub:nodeId()},
|
||||
id ,%:: mod_pubsub:nodeIdx(),
|
||||
parents = [] ,%:: [Parent_NodeId::mod_pubsub:nodeId()],
|
||||
type = <<"flat">> ,%:: binary(),
|
||||
owners = [] ,%:: [Owner::ljid(),...],
|
||||
options = [] %:: mod_pubsub:nodeOptions()
|
||||
nodeid ,% :: {mod_pubsub:host(), mod_pubsub:nodeId()},
|
||||
id ,% :: mod_pubsub:nodeIdx(),
|
||||
parents = [] ,% :: [mod_pubsub:nodeId(),...],
|
||||
type = <<"flat">>,% :: binary(),
|
||||
owners = [] ,% :: [jlib:ljid(),...],
|
||||
options = [] % :: mod_pubsub:nodeOptions()
|
||||
}).
|
||||
|
||||
%% @type pubsubState() = {pubsub_state, StateId, Items, Affiliation, Subscriptions}
|
||||
%% StateId = {ljid(), nodeIdx()}
|
||||
%% Items = [itemId()]
|
||||
%% Affiliation = affiliation()
|
||||
%% Subscriptions = [{subscription(), subId()}].
|
||||
%% <p>This is the format of the <tt>affiliations</tt> table. The type of the
|
||||
%% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
|
||||
|
||||
%-record(pubsub_state,
|
||||
% {stateid, items = [], affiliation = none,
|
||||
% subscriptions = []}).
|
||||
-record(pubsub_state,
|
||||
{
|
||||
stateid ,%:: {Entity::ljid(), NodeIdx::mod_pubsub:nodeIdx()},
|
||||
items = [] ,%:: [ItemId::mod_pubsub:itemId()],
|
||||
affiliation = 'none' ,%:: mod_pubsub:affiliation(),
|
||||
subscriptions = [] %:: [{mod_pubsub:subscription(), mod_pubsub:subId()}]
|
||||
stateid ,% :: {jlib:ljid(), mod_pubsub:nodeIdx()},
|
||||
items = [] ,% :: [mod_pubsub:itemId(),...],
|
||||
affiliation = 'none',% :: mod_pubsub:affiliation(),
|
||||
subscriptions = [] % :: [{mod_pubsub:subscription(), mod_pubsub:subId()}]
|
||||
}).
|
||||
|
||||
%% @type pubsubItem() = {pubsub_item, ItemId, Creation, Modification, Payload}
|
||||
%% ItemId = {itemId(), nodeIdx()}
|
||||
%% Creation = {now(), ljid()}
|
||||
%% Modification = {now(), ljid()}
|
||||
%% Payload = payload().
|
||||
%% <p>This is the format of the <tt>published items</tt> table. The type of the
|
||||
%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p>
|
||||
%-record(pubsub_item,
|
||||
% {itemid, creation = {unknown, unknown},
|
||||
% modification = {unknown, unknown}, payload = []}).
|
||||
|
||||
-record(pubsub_item,
|
||||
{
|
||||
itemid ,%:: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()},
|
||||
creation = {unknown, unknown} ,%:: {erlang:timestamp(), ljid()},
|
||||
modification = {unknown, unknown} ,%:: {erlang:timestamp(), ljid()},
|
||||
payload = [] %:: mod_pubsub:payload()
|
||||
itemid ,% :: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()},
|
||||
creation = {unknown, unknown},% :: {erlang:timestamp(), jlib:ljid()},
|
||||
modification = {unknown, unknown},% :: {erlang:timestamp(), jlib:ljid()},
|
||||
payload = [] % :: mod_pubsub:payload()
|
||||
}).
|
||||
|
||||
%% @type pubsubSubscription() = {pubsub_subscription, SubId, Options}
|
||||
%% SubId = subId()
|
||||
%% Options = [nodeOption()].
|
||||
%% <p>This is the format of the <tt>subscriptions</tt> table. The type of the
|
||||
%% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
|
||||
%-record(pubsub_subscription, {subid, options}).
|
||||
-record(pubsub_subscription,
|
||||
{
|
||||
subid ,%:: mod_pubsub:subId(),
|
||||
options %:: [] | mod_pubsub:subOptions()
|
||||
subid ,% :: mod_pubsub:subId(),
|
||||
options = [] % :: mod_pubsub:subOptions()
|
||||
}).
|
||||
|
||||
%% @type pubsubLastItem() = {pubsub_last_item, NodeId, ItemId, Creation, Payload}
|
||||
%% NodeId = nodeIdx()
|
||||
%% ItemId = itemId()
|
||||
%% Creation = {now(),ljid()}
|
||||
%% Payload = payload().
|
||||
%% <p>This is the format of the <tt>last items</tt> table. it stores last item payload
|
||||
%% for every node</p>
|
||||
%-record(pubsub_last_item,
|
||||
% {nodeid, itemid, creation, payload}).
|
||||
|
||||
-record(pubsub_last_item,
|
||||
{
|
||||
nodeid ,%:: mod_pubsub:nodeIdx(),
|
||||
itemid ,%:: mod_pubsub:itemId(),
|
||||
creation ,%:: {erlang:timestamp(), ljid()},
|
||||
payload %:: mod_pubsub:payload()
|
||||
nodeid ,% :: mod_pubsub:nodeIdx(),
|
||||
itemid ,% :: mod_pubsub:itemId(),
|
||||
creation ,% :: {erlang:timestamp(), jlib:ljid()},
|
||||
payload % :: mod_pubsub:payload()
|
||||
}).
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_lib_sqlite3.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_LIB_SQLITE3([MINIMUM-VERSION])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Test for the SQLite 3 library of a particular version (or newer)
|
||||
#
|
||||
# This macro takes only one optional argument, required version of SQLite
|
||||
# 3 library. If required version is not passed, 3.0.0 is used in the test
|
||||
# of existance of SQLite 3.
|
||||
#
|
||||
# If no intallation prefix to the installed SQLite library is given the
|
||||
# macro searches under /usr, /usr/local, and /opt.
|
||||
#
|
||||
# This macro calls:
|
||||
#
|
||||
# AC_SUBST(SQLITE3_CFLAGS)
|
||||
# AC_SUBST(SQLITE3_LDFLAGS)
|
||||
# AC_SUBST(SQLITE3_VERSION)
|
||||
#
|
||||
# And sets:
|
||||
#
|
||||
# HAVE_SQLITE3
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 14
|
||||
|
||||
AC_DEFUN([AX_LIB_SQLITE3],
|
||||
[
|
||||
AC_ARG_WITH([sqlite3],
|
||||
AS_HELP_STRING(
|
||||
[--with-sqlite3=@<:@ARG@:>@],
|
||||
[use SQLite 3 library @<:@default=yes@:>@, optionally specify the prefix for sqlite3 library]
|
||||
),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
WANT_SQLITE3="no"
|
||||
elif test "$withval" = "yes"; then
|
||||
WANT_SQLITE3="yes"
|
||||
ac_sqlite3_path=""
|
||||
else
|
||||
WANT_SQLITE3="yes"
|
||||
ac_sqlite3_path="$withval"
|
||||
fi
|
||||
],
|
||||
[WANT_SQLITE3="yes"]
|
||||
)
|
||||
|
||||
SQLITE3_CFLAGS=""
|
||||
SQLITE3_LDFLAGS=""
|
||||
SQLITE3_VERSION=""
|
||||
|
||||
if test "x$WANT_SQLITE3" = "xyes"; then
|
||||
|
||||
ac_sqlite3_header="sqlite3.h"
|
||||
|
||||
sqlite3_version_req=ifelse([$1], [], [3.0.0], [$1])
|
||||
sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
|
||||
sqlite3_version_req_major=`expr $sqlite3_version_req : '\([[0-9]]*\)'`
|
||||
sqlite3_version_req_minor=`expr $sqlite3_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
||||
sqlite3_version_req_micro=`expr $sqlite3_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
||||
if test "x$sqlite3_version_req_micro" = "x" ; then
|
||||
sqlite3_version_req_micro="0"
|
||||
fi
|
||||
|
||||
sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \
|
||||
\+ $sqlite3_version_req_minor \* 1000 \
|
||||
\+ $sqlite3_version_req_micro`
|
||||
|
||||
AC_MSG_CHECKING([for SQLite3 library >= $sqlite3_version_req])
|
||||
|
||||
if test "$ac_sqlite3_path" != ""; then
|
||||
ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib"
|
||||
ac_sqlite3_cppflags="-I$ac_sqlite3_path/include"
|
||||
else
|
||||
for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do
|
||||
if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \
|
||||
&& test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then
|
||||
ac_sqlite3_path=$ac_sqlite3_path_tmp
|
||||
ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include"
|
||||
ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
ac_sqlite3_ldflags="$ac_sqlite3_ldflags -lsqlite3"
|
||||
|
||||
saved_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags"
|
||||
|
||||
AC_LANG_PUSH(C)
|
||||
AC_COMPILE_IFELSE(
|
||||
[
|
||||
AC_LANG_PROGRAM([[@%:@include <sqlite3.h>]],
|
||||
[[
|
||||
#if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number)
|
||||
/* Everything is okay */
|
||||
#else
|
||||
# error SQLite version is too old
|
||||
#endif
|
||||
]]
|
||||
)
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
success="yes"
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([not found])
|
||||
success="no"
|
||||
]
|
||||
)
|
||||
AC_LANG_POP(C)
|
||||
|
||||
CPPFLAGS="$saved_CPPFLAGS"
|
||||
|
||||
if test "$success" = "yes"; then
|
||||
|
||||
SQLITE3_CFLAGS="$ac_sqlite3_cppflags"
|
||||
SQLITE3_LDFLAGS="$ac_sqlite3_ldflags"
|
||||
|
||||
ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header"
|
||||
|
||||
dnl Retrieve SQLite release version
|
||||
if test "x$ac_sqlite3_header_path" != "x"; then
|
||||
ac_sqlite3_version=`cat $ac_sqlite3_header_path \
|
||||
| grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \
|
||||
| sed -e 's/"//'`
|
||||
if test $ac_sqlite3_version != ""; then
|
||||
SQLITE3_VERSION=$ac_sqlite3_version
|
||||
else
|
||||
AC_MSG_WARN([Cannot find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(SQLITE3_CFLAGS)
|
||||
AC_SUBST(SQLITE3_LDFLAGS)
|
||||
AC_SUBST(SQLITE3_VERSION)
|
||||
AC_DEFINE([HAVE_SQLITE3], [], [Have the SQLITE3 library])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
@@ -0,0 +1,77 @@
|
||||
defmodule Ejabberd.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[app: :ejabberd,
|
||||
version: "@PACKAGE_VERSION@",
|
||||
elixir: "~> 1.0",
|
||||
elixirc_paths: ["lib"],
|
||||
compile_path: ".",
|
||||
compilers: [:asn1] ++ Mix.compilers,
|
||||
erlc_options: erlc_options,
|
||||
erlc_paths: ["asn1", "src"],
|
||||
deps: deps]
|
||||
end
|
||||
|
||||
def application do
|
||||
[mod: {:ejabberd_app, []},
|
||||
applications: [:kernel, :stdlib]]
|
||||
end
|
||||
|
||||
defp erlc_options do
|
||||
includes = Path.wildcard(Path.join("..", "/*/include"))
|
||||
[:debug_info, {:d, :NO_EXT_LIB}] ++ Enum.map(includes, fn(path) -> {:i, path} end)
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[
|
||||
{:p1_xml, github: "processone/xml"},
|
||||
{:p1_logger, github: "processone/p1_logger"},
|
||||
{:p1_yaml, github: "processone/p1_yaml"},
|
||||
{:p1_tls, github: "processone/tls"},
|
||||
{:p1_stringprep, github: "processone/stringprep"},
|
||||
{:p1_zlib, github: "processone/zlib"},
|
||||
{:p1_cache_tab, github: "processone/cache_tab"},
|
||||
{:p1_utils, github: "processone/p1_utils"},
|
||||
{:p1_iconv, github: "processone/eiconv"},
|
||||
{:esip, github: "processone/p1_sip"},
|
||||
{:p1_stun, github: "processone/stun"},
|
||||
{:ehyperloglog, github: "vaxelfel/eHyperLogLog"},
|
||||
{:p1_mysql, github: "processone/mysql"},
|
||||
{:p1_pgsql, github: "processone/pgsql"},
|
||||
{:eredis, github: "wooga/eredis"}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Mix.Tasks.Compile.Asn1 do
|
||||
use Mix.Task
|
||||
alias Mix.Compilers.Erlang
|
||||
|
||||
@recursive true
|
||||
@manifest ".compile.asn1"
|
||||
|
||||
def run(args) do
|
||||
{opts, _, _} = OptionParser.parse(args, switches: [force: :boolean])
|
||||
|
||||
project = Mix.Project.config
|
||||
source_paths = project[:asn1_paths] || ["asn1"]
|
||||
dest_paths = project[:asn1_target] || ["src"]
|
||||
mappings = Enum.zip(source_paths, dest_paths)
|
||||
options = project[:asn1_options] || []
|
||||
|
||||
Erlang.compile(manifest(), mappings, :asn1, :erl, opts[:force], fn
|
||||
input, output ->
|
||||
options = options ++ [:noobj, outdir: Erlang.to_erl_file(Path.dirname(output))]
|
||||
case :asn1ct.compile(Erlang.to_erl_file(input), options) do
|
||||
:ok -> {:ok, :done}
|
||||
error -> error
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def manifests, do: [manifest]
|
||||
defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest)
|
||||
|
||||
def clean, do: Erlang.clean(manifest())
|
||||
end
|
||||
@@ -6,6 +6,9 @@
|
||||
%%% @end
|
||||
%%% Created : 1 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
{require_min_otp_vsn, "16"}.
|
||||
|
||||
Cfg = case file:consult("vars.config") of
|
||||
{ok, Terms} ->
|
||||
Terms;
|
||||
@@ -51,15 +54,15 @@ SrcDirs = lists:foldl(
|
||||
Acc
|
||||
end, [], Cfg),
|
||||
|
||||
Deps = [{p1_cache_tab, ".*", {git, "git://github.com/processone/cache_tab"}},
|
||||
{p1_tls, ".*", {git, "git://github.com/processone/tls"}},
|
||||
{p1_stringprep, ".*", {git, "git://github.com/processone/stringprep"}},
|
||||
{p1_xml, ".*", {git, "git://github.com/processone/xml"}},
|
||||
{esip, ".*", {git, "git://github.com/processone/p1_sip"}},
|
||||
{p1_stun, ".*", {git, "git://github.com/processone/stun"}},
|
||||
{p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}},
|
||||
Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}},
|
||||
{p1_tls, ".*", {git, "https://github.com/processone/tls"}},
|
||||
{p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}},
|
||||
{p1_xml, ".*", {git, "https://github.com/processone/xml"}},
|
||||
{esip, ".*", {git, "https://github.com/processone/p1_sip"}},
|
||||
{p1_stun, ".*", {git, "https://github.com/processone/stun"}},
|
||||
{p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}},
|
||||
{ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}},
|
||||
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
|
||||
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}],
|
||||
|
||||
ConfigureCmd = fun(Pkg, Flags) ->
|
||||
{'get-deps',
|
||||
@@ -84,30 +87,32 @@ PostHooks = [ConfigureCmd("p1_tls", ""),
|
||||
|
||||
CfgDeps = lists:flatmap(
|
||||
fun({mysql, true}) ->
|
||||
[{p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}];
|
||||
[{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}];
|
||||
({pgsql, true}) ->
|
||||
[{p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}];
|
||||
[{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}];
|
||||
({sqlite, true}) ->
|
||||
[{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}];
|
||||
({pam, true}) ->
|
||||
[{p1_pam, ".*", {git, "git://github.com/processone/epam"}}];
|
||||
[{p1_pam, ".*", {git, "https://github.com/processone/epam"}}];
|
||||
({zlib, true}) ->
|
||||
[{p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}];
|
||||
[{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}];
|
||||
({riak, true}) ->
|
||||
[{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}];
|
||||
[{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}];
|
||||
({json, true}) ->
|
||||
[{jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}];
|
||||
[{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}];
|
||||
({elixir, true}) ->
|
||||
[{rebar_elixir_plugin, ".*", {git, "git://github.com/yrashk/rebar_elixir_plugin"}},
|
||||
{elixir, ".*", {git, "git://github.com/elixir-lang/elixir", {branch, "v1.0"}}}];
|
||||
[{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}},
|
||||
{elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}];
|
||||
({iconv, true}) ->
|
||||
[{p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}];
|
||||
[{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}];
|
||||
({lager, true}) ->
|
||||
[{lager, ".*", {git, "git://github.com/basho/lager"}}];
|
||||
[{lager, ".*", {git, "https://github.com/basho/lager"}}];
|
||||
({lager, false}) ->
|
||||
[{p1_logger, ".*", {git, "git://github.com/processone/p1_logger"}}];
|
||||
[{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}];
|
||||
({tools, true}) ->
|
||||
[{meck, "0.*", {git, "https://github.com/eproxus/meck"}}];
|
||||
({redis, true}) ->
|
||||
[{eredis, ".*", {git, "git://github.com/wooga/eredis"}}];
|
||||
({redis, true}) ->
|
||||
[{eredis, ".*", {git, "https://github.com/wooga/eredis"}}];
|
||||
(_) ->
|
||||
[]
|
||||
end, Cfg),
|
||||
@@ -159,12 +164,21 @@ ElixirConfig = case lists:keysearch(elixir, 1, Cfg) of
|
||||
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
|
||||
TestConfigFile = filename:join([Cwd, "test", "config.ctc"]),
|
||||
TestConfig = case file:read_file_info(TestConfigFile) of
|
||||
{ok, _} ->
|
||||
"-userconfig ct_config_plain " ++ TestConfigFile ++ " ";
|
||||
_ ->
|
||||
""
|
||||
end,
|
||||
|
||||
Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++
|
||||
[{src_dirs, [asn1, src | SrcDirs]}]},
|
||||
{sub_dirs, ["rel"]},
|
||||
{keep_build_info, true},
|
||||
{ct_extra_params, "-include "
|
||||
++ filename:join([Cwd, "tools"])},
|
||||
{ct_extra_params, "-ct_hooks cth_surefire "
|
||||
++ TestConfig
|
||||
++ "-include " ++ filename:join([Cwd, "tools"])},
|
||||
{xref_warnings, false},
|
||||
{xref_checks, []},
|
||||
{xref_queries,
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2015 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
-- published by the Free Software Foundation; either version 2 of the
|
||||
-- License, or (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License along
|
||||
-- with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
username text PRIMARY KEY,
|
||||
password text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE last (
|
||||
username text PRIMARY KEY,
|
||||
seconds text NOT NULL,
|
||||
state text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE rosterusers (
|
||||
username text NOT NULL,
|
||||
jid text NOT NULL,
|
||||
nick text NOT NULL,
|
||||
subscription character(1) NOT NULL,
|
||||
ask character(1) NOT NULL,
|
||||
askmessage text NOT NULL,
|
||||
server character(1) NOT NULL,
|
||||
subscribe text,
|
||||
type text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers (username, jid);
|
||||
CREATE INDEX i_rosteru_username ON rosterusers (username);
|
||||
CREATE INDEX i_rosteru_jid ON rosterusers (jid);
|
||||
|
||||
|
||||
CREATE TABLE rostergroups (
|
||||
username text NOT NULL,
|
||||
jid text NOT NULL,
|
||||
grp text NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups (username, jid);
|
||||
|
||||
CREATE TABLE sr_group (
|
||||
name text NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE sr_user (
|
||||
jid text NOT NULL,
|
||||
grp text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_sr_user_jid_grp ON sr_user (jid, grp);
|
||||
CREATE INDEX i_sr_user_jid ON sr_user (jid);
|
||||
CREATE INDEX i_sr_user_grp ON sr_user (grp);
|
||||
|
||||
CREATE TABLE spool (
|
||||
username text NOT NULL,
|
||||
xml text NOT NULL,
|
||||
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_despool ON spool (username);
|
||||
|
||||
|
||||
CREATE TABLE vcard (
|
||||
username text PRIMARY KEY,
|
||||
vcard text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE vcard_xupdate (
|
||||
username text PRIMARY KEY,
|
||||
hash text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE vcard_search (
|
||||
username text NOT NULL,
|
||||
lusername text PRIMARY KEY,
|
||||
fn text NOT NULL,
|
||||
lfn text NOT NULL,
|
||||
family text NOT NULL,
|
||||
lfamily text NOT NULL,
|
||||
given text NOT NULL,
|
||||
lgiven text NOT NULL,
|
||||
middle text NOT NULL,
|
||||
lmiddle text NOT NULL,
|
||||
nickname text NOT NULL,
|
||||
lnickname text NOT NULL,
|
||||
bday text NOT NULL,
|
||||
lbday text NOT NULL,
|
||||
ctry text NOT NULL,
|
||||
lctry text NOT NULL,
|
||||
locality text NOT NULL,
|
||||
llocality text NOT NULL,
|
||||
email text NOT NULL,
|
||||
lemail text NOT NULL,
|
||||
orgname text NOT NULL,
|
||||
lorgname text NOT NULL,
|
||||
orgunit text NOT NULL,
|
||||
lorgunit text NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
||||
CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
|
||||
CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
|
||||
CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle);
|
||||
CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname);
|
||||
CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday);
|
||||
CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry);
|
||||
CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
|
||||
CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
|
||||
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
|
||||
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
||||
|
||||
CREATE TABLE privacy_default_list (
|
||||
username text PRIMARY KEY,
|
||||
name text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE privacy_list (
|
||||
username text NOT NULL,
|
||||
name text NOT NULL,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_privacy_list_username ON privacy_list (username);
|
||||
CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list (username, name);
|
||||
|
||||
CREATE TABLE privacy_list_data (
|
||||
id bigint REFERENCES privacy_list(id) ON DELETE CASCADE,
|
||||
t character(1) NOT NULL,
|
||||
value text NOT NULL,
|
||||
action character(1) NOT NULL,
|
||||
ord NUMERIC NOT NULL,
|
||||
match_all boolean NOT NULL,
|
||||
match_iq boolean NOT NULL,
|
||||
match_message boolean NOT NULL,
|
||||
match_presence_in boolean NOT NULL,
|
||||
match_presence_out boolean NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE private_storage (
|
||||
username text NOT NULL,
|
||||
namespace text NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_private_storage_username ON private_storage (username);
|
||||
CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage (username, namespace);
|
||||
|
||||
|
||||
CREATE TABLE roster_version (
|
||||
username text PRIMARY KEY,
|
||||
version text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pubsub_node (
|
||||
host text,
|
||||
node text,
|
||||
parent text,
|
||||
type text,
|
||||
nodeid INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node (parent);
|
||||
CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node (host, node);
|
||||
|
||||
CREATE TABLE pubsub_node_option (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
name text,
|
||||
val text
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option (nodeid);
|
||||
|
||||
CREATE TABLE pubsub_node_owner (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
owner text
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner (nodeid);
|
||||
|
||||
CREATE TABLE pubsub_state (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
jid text,
|
||||
affiliation character(1),
|
||||
subscriptions text,
|
||||
stateid INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
);
|
||||
CREATE INDEX i_pubsub_state_jid ON pubsub_state (jid);
|
||||
CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state (nodeid, jid);
|
||||
|
||||
CREATE TABLE pubsub_item (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
itemid text,
|
||||
publisher text,
|
||||
creation text,
|
||||
modification text,
|
||||
payload text
|
||||
);
|
||||
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);
|
||||
CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item (nodeid, itemid);
|
||||
|
||||
CREATE TABLE pubsub_subscription_opt (
|
||||
subid text,
|
||||
opt_name varchar(32),
|
||||
opt_value text
|
||||
);
|
||||
CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt (subid, opt_name);
|
||||
|
||||
CREATE TABLE muc_room (
|
||||
name text NOT NULL,
|
||||
host text NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host);
|
||||
|
||||
CREATE TABLE muc_registered (
|
||||
jid text NOT NULL,
|
||||
host text NOT NULL,
|
||||
nick text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_muc_registered_nick ON muc_registered (nick);
|
||||
CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered (jid, host);
|
||||
|
||||
CREATE TABLE irc_custom (
|
||||
jid text NOT NULL,
|
||||
host text NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom (jid, host);
|
||||
|
||||
CREATE TABLE motd (
|
||||
username text PRIMARY KEY,
|
||||
xml text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE caps_features (
|
||||
node text NOT NULL,
|
||||
subnode text NOT NULL,
|
||||
feature text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_caps_features_node_subnode ON caps_features (node, subnode);
|
||||
|
||||
CREATE TABLE archive (
|
||||
username text NOT NULL,
|
||||
timestamp BIGINT UNSIGNED NOT NULL,
|
||||
peer text NOT NULL,
|
||||
bare_peer text NOT NULL,
|
||||
xml text NOT NULL,
|
||||
txt text,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_username ON archive(username);
|
||||
CREATE INDEX i_timestamp ON archive(timestamp);
|
||||
CREATE INDEX i_peer ON archive(peer);
|
||||
CREATE INDEX i_bare_peer ON archive(bare_peer);
|
||||
|
||||
CREATE TABLE archive_prefs (
|
||||
username text NOT NULL PRIMARY KEY,
|
||||
def text NOT NULL,
|
||||
always text NOT NULL,
|
||||
never text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
@@ -85,6 +85,31 @@ CREATE TABLE spool (
|
||||
CREATE INDEX i_despool USING BTREE ON spool(username);
|
||||
CREATE INDEX i_spool_created_at USING BTREE ON spool(created_at);
|
||||
|
||||
CREATE TABLE archive (
|
||||
username varchar(250) NOT NULL,
|
||||
timestamp BIGINT UNSIGNED NOT NULL,
|
||||
peer varchar(250) NOT NULL,
|
||||
bare_peer varchar(250) NOT NULL,
|
||||
xml text NOT NULL,
|
||||
txt text,
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE FULLTEXT INDEX i_text ON archive(txt);
|
||||
CREATE INDEX i_username USING BTREE ON archive(username);
|
||||
CREATE INDEX i_timestamp USING BTREE ON archive(timestamp);
|
||||
CREATE INDEX i_peer USING BTREE ON archive(peer);
|
||||
CREATE INDEX i_bare_peer USING BTREE ON archive(bare_peer);
|
||||
|
||||
CREATE TABLE archive_prefs (
|
||||
username varchar(250) NOT NULL PRIMARY KEY,
|
||||
def text NOT NULL,
|
||||
always text NOT NULL,
|
||||
never text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE vcard (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
vcard mediumtext NOT NULL,
|
||||
@@ -163,9 +188,8 @@ CREATE TABLE privacy_list_data (
|
||||
match_presence_in boolean NOT NULL,
|
||||
match_presence_out boolean NOT NULL
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_privacy_list_data_id ON privacy_list_data(id);
|
||||
|
||||
CREATE INDEX i_privacy_list_data_id USING BTREE ON privacy_list_data(id);
|
||||
CREATE INDEX i_privacy_list_data_id ON privacy_list_data(id);
|
||||
|
||||
CREATE TABLE private_storage (
|
||||
username varchar(250) NOT NULL,
|
||||
|
||||
@@ -85,6 +85,29 @@ CREATE TABLE spool (
|
||||
|
||||
CREATE INDEX i_despool ON spool USING btree (username);
|
||||
|
||||
CREATE TABLE archive (
|
||||
username text NOT NULL,
|
||||
timestamp BIGINT NOT NULL,
|
||||
peer text NOT NULL,
|
||||
bare_peer text NOT NULL,
|
||||
xml text NOT NULL,
|
||||
txt text,
|
||||
id SERIAL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX i_username ON archive USING btree (username);
|
||||
CREATE INDEX i_timestamp ON archive USING btree (timestamp);
|
||||
CREATE INDEX i_peer ON archive USING btree (peer);
|
||||
CREATE INDEX i_bare_peer ON archive USING btree (bare_peer);
|
||||
|
||||
CREATE TABLE archive_prefs (
|
||||
username text NOT NULL PRIMARY KEY,
|
||||
def text NOT NULL,
|
||||
always text NOT NULL,
|
||||
never text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE vcard (
|
||||
username text PRIMARY KEY,
|
||||
@@ -288,3 +311,17 @@ CREATE TABLE caps_features (
|
||||
);
|
||||
|
||||
CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode);
|
||||
|
||||
CREATE TABLE sm (
|
||||
usec bigint NOT NULL,
|
||||
pid text NOT NULL,
|
||||
node text NOT NULL,
|
||||
username text NOT NULL,
|
||||
resource text NOT NULL,
|
||||
priority text NOT NULL,
|
||||
info text NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_sm_sid ON sm USING btree (usec, pid);
|
||||
CREATE INDEX i_sm_node ON sm USING btree (node);
|
||||
CREATE INDEX i_sm_username ON sm USING btree (username);
|
||||
|
||||
@@ -25,11 +25,14 @@
|
||||
|
||||
-module(acl).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0, to_record/3, add/3, add_list/3,
|
||||
add_local/3, add_list_local/3, load_from_config/0,
|
||||
match_rule/3, match_acl/3, transform_options/1]).
|
||||
add_local/3, add_list_local/3, load_from_config/0,
|
||||
match_rule/3, match_acl/3, transform_options/1,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -476,3 +479,7 @@ transform_options({access, Name, Rules}, Opts) ->
|
||||
[{access, [{Name, NewRules}]}|Opts];
|
||||
transform_options(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
|
||||
opt_type(access) -> fun (V) -> V end;
|
||||
opt_type(acl) -> fun (V) -> V end;
|
||||
opt_type(_) -> [access, acl].
|
||||
|
||||
@@ -25,10 +25,13 @@
|
||||
|
||||
-module(cyrsasl).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0, register_mechanism/3, listmech/1,
|
||||
server_new/7, server_start/3, server_step/2]).
|
||||
server_new/7, server_start/3, server_step/2,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -237,3 +240,10 @@ is_disabled(Mechanism) ->
|
||||
[str:to_upper(V)]
|
||||
end, []),
|
||||
lists:member(Mechanism, Disabled).
|
||||
|
||||
opt_type(disable_sasl_mechanisms) ->
|
||||
fun (V) when is_list(V) ->
|
||||
lists:map(fun (M) -> str:to_upper(M) end, V);
|
||||
(V) -> [str:to_upper(V)]
|
||||
end;
|
||||
opt_type(_) -> [disable_sasl_mechanisms].
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
-module(cyrsasl_anonymous).
|
||||
|
||||
-protocol({xep, 175, '1.2'}).
|
||||
|
||||
-export([start/1, stop/0, mech_new/4, mech_step/2]).
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
@@ -25,9 +25,12 @@
|
||||
|
||||
-module(cyrsasl_digest).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@sevcom.net').
|
||||
|
||||
-export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]).
|
||||
-export([start/1, stop/0, mech_new/4, mech_step/2,
|
||||
parse/1, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -256,3 +259,6 @@ response(KeyVals, User, Passwd, Nonce, AuthzId,
|
||||
":", NC/binary, ":", CNonce/binary, ":", QOP/binary,
|
||||
":", (hex((erlang:md5(A2))))/binary>>,
|
||||
hex((erlang:md5(T))).
|
||||
|
||||
opt_type(fqdn) -> fun iolist_to_binary/1;
|
||||
opt_type(_) -> [fqdn].
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
-author('stephen.roettger@googlemail.com').
|
||||
|
||||
-protocol({rfc, 5802}).
|
||||
|
||||
-export([start/1, stop/0, mech_new/4, mech_step/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
@@ -160,7 +162,7 @@ mech_step(#state{step = 4} = State, ClientIn) ->
|
||||
{ok, [{username, State#state.username}],
|
||||
<<"v=",
|
||||
(jlib:encode_base64(ServerSignature))/binary>>};
|
||||
true -> {error, <<"bad-auth">>}
|
||||
true -> {error, <<"bad-auth">>, State#state.username}
|
||||
end;
|
||||
_Else -> {error, <<"bad-protocol">>}
|
||||
end;
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
-module(ejabberd).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-protocol({xep, 4, '2.9'}).
|
||||
-protocol({xep, 86, '1.0'}).
|
||||
-protocol({xep, 106, '1.1'}).
|
||||
-protocol({xep, 170, '1.0'}).
|
||||
-protocol({xep, 205, '1.0'}).
|
||||
-protocol({xep, 212, '1.0'}).
|
||||
-protocol({xep, 216, '1.0'}).
|
||||
-protocol({xep, 243, '1.0'}).
|
||||
-protocol({xep, 270, '1.0'}).
|
||||
|
||||
-export([start/0, stop/0, start_app/1, start_app/2,
|
||||
get_pid_file/0, check_app/1]).
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
%% Purge DB
|
||||
delete_expired_messages/0, delete_old_messages/1,
|
||||
%% Mnesia
|
||||
export2odbc/2,
|
||||
set_master/1,
|
||||
backup_mnesia/1, restore_mnesia/1,
|
||||
dump_mnesia/1, dump_table/2, load_mnesia/1,
|
||||
@@ -191,7 +190,7 @@ commands() ->
|
||||
|
||||
#ejabberd_commands{name = export2odbc, tags = [mnesia],
|
||||
desc = "Export virtual host information from Mnesia tables to SQL files",
|
||||
module = ?MODULE, function = export2odbc,
|
||||
module = ejd2odbc, function = export,
|
||||
args = [{host, string}, {directory, string}],
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = set_master, tags = [mnesia],
|
||||
@@ -408,23 +407,6 @@ delete_old_messages(Days) ->
|
||||
%%% Mnesia management
|
||||
%%%
|
||||
|
||||
export2odbc(Host, Directory) ->
|
||||
Tables = [{export_last, last},
|
||||
{export_offline, offline},
|
||||
{export_private_storage, private_storage},
|
||||
{export_roster, roster},
|
||||
{export_vcard, vcard},
|
||||
{export_vcard_search, vcard_search},
|
||||
{export_passwd, passwd}],
|
||||
Export = fun({TableFun, Table}) ->
|
||||
Filename = filename:join([Directory, atom_to_list(Table)++".txt"]),
|
||||
io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]),
|
||||
Res = (catch ejd2odbc:TableFun(Host, Filename)),
|
||||
io:format(" Result: ~p~n", [Res])
|
||||
end,
|
||||
lists:foreach(Export, Tables),
|
||||
ok.
|
||||
|
||||
set_master("self") ->
|
||||
set_master(node());
|
||||
set_master(NodeString) when is_list(NodeString) ->
|
||||
|
||||
@@ -24,11 +24,14 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_app).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
-export([start_modules/0,start/2, prep_stop/1, stop/1, init/0]).
|
||||
-export([start_modules/0, start/2, prep_stop/1, stop/1,
|
||||
init/0, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -51,7 +54,7 @@ start(normal, _Args) ->
|
||||
ejabberd_admin:start(),
|
||||
gen_mod:start(),
|
||||
ejabberd_config:start(),
|
||||
set_loglevel_from_config(),
|
||||
set_settings_from_config(),
|
||||
acl:start(),
|
||||
shaper:start(),
|
||||
connect_nodes(),
|
||||
@@ -59,14 +62,14 @@ start(normal, _Args) ->
|
||||
ejabberd_rdbms:start(),
|
||||
ejabberd_riak_sup:start(),
|
||||
ejabberd_sm:start(),
|
||||
ejabberd_auth:start(),
|
||||
cyrsasl:start(),
|
||||
% Profiling
|
||||
%ejabberd_debug:eprof_start(),
|
||||
%ejabberd_debug:fprof_start(),
|
||||
maybe_add_nameservers(),
|
||||
start_modules(),
|
||||
ext_mod:start(),
|
||||
ejabberd_auth:start(),
|
||||
start_modules(),
|
||||
ejabberd_listener:start_listeners(),
|
||||
?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
|
||||
Sup;
|
||||
@@ -110,6 +113,7 @@ loop() ->
|
||||
end.
|
||||
|
||||
db_init() ->
|
||||
ejabberd_config:env_binary_to_list(mnesia, dir),
|
||||
MyNode = node(),
|
||||
DbNodes = mnesia:system_info(db_nodes),
|
||||
case lists:member(MyNode, DbNodes) of
|
||||
@@ -230,14 +234,20 @@ delete_pid_file() ->
|
||||
file:delete(PidFilename)
|
||||
end.
|
||||
|
||||
set_loglevel_from_config() ->
|
||||
set_settings_from_config() ->
|
||||
Level = ejabberd_config:get_option(
|
||||
loglevel,
|
||||
fun(P) when P>=0, P=<5 -> P end,
|
||||
4),
|
||||
ejabberd_logger:set(Level).
|
||||
ejabberd_logger:set(Level),
|
||||
Ticktime = ejabberd_config:get_option(
|
||||
net_ticktime,
|
||||
opt_type(net_ticktime),
|
||||
60),
|
||||
net_kernel:set_net_ticktime(Ticktime).
|
||||
|
||||
start_apps() ->
|
||||
crypto:start(),
|
||||
ejabberd:start_app(sasl),
|
||||
ejabberd:start_app(ssl),
|
||||
ejabberd:start_app(p1_yaml),
|
||||
@@ -246,3 +256,18 @@ start_apps() ->
|
||||
ejabberd:start_app(p1_stringprep),
|
||||
ejabberd:start_app(p1_zlib),
|
||||
ejabberd:start_app(p1_cache_tab).
|
||||
|
||||
opt_type(net_ticktime) ->
|
||||
fun (P) when is_integer(P), P > 0 -> P end;
|
||||
opt_type(cluster_nodes) ->
|
||||
fun (Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end;
|
||||
opt_type(loglevel) ->
|
||||
fun (P) when P >= 0, P =< 5 -> P end;
|
||||
opt_type(modules) ->
|
||||
fun (Mods) ->
|
||||
lists:map(fun ({M, A}) when is_atom(M), is_list(A) ->
|
||||
{M, A}
|
||||
end,
|
||||
Mods)
|
||||
end;
|
||||
opt_type(_) -> [cluster_nodes, loglevel, modules, net_ticktime].
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
-module(ejabberd_auth).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
%% External exports
|
||||
@@ -42,7 +44,7 @@
|
||||
remove_user/2, remove_user/3, plain_password_required/1,
|
||||
store_type/1, entropy/1]).
|
||||
|
||||
-export([auth_modules/1]).
|
||||
-export([auth_modules/1, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -71,8 +73,8 @@
|
||||
-callback get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}].
|
||||
-callback get_vh_registered_users_number(binary()) -> number().
|
||||
-callback get_vh_registered_users_number(binary(), opts()) -> number().
|
||||
-callback get_password(binary(), binary()) -> false | binary().
|
||||
-callback get_password_s(binary(), binary()) -> binary().
|
||||
-callback get_password(binary(), binary()) -> false | binary() | {binary(), binary(), binary(), integer()}.
|
||||
-callback get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}.
|
||||
|
||||
start() ->
|
||||
%% This is only executed by ejabberd_c2s for non-SASL auth client
|
||||
@@ -267,7 +269,7 @@ get_vh_registered_users_number(Server, Opts) ->
|
||||
end,
|
||||
auth_modules(Server))).
|
||||
|
||||
-spec get_password(binary(), binary()) -> false | binary().
|
||||
-spec get_password(binary(), binary()) -> false | binary() | {binary(), binary(), binary(), integer()}.
|
||||
|
||||
get_password(User, Server) ->
|
||||
lists:foldl(fun (M, false) ->
|
||||
@@ -276,7 +278,7 @@ get_password(User, Server) ->
|
||||
end,
|
||||
false, auth_modules(Server)).
|
||||
|
||||
-spec get_password_s(binary(), binary()) -> binary().
|
||||
-spec get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}.
|
||||
|
||||
get_password_s(User, Server) ->
|
||||
case get_password(User, Server) of
|
||||
@@ -425,6 +427,10 @@ auth_modules() ->
|
||||
%% Return the list of authenticated modules for a given host
|
||||
auth_modules(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
Default = case gen_mod:default_db(LServer) of
|
||||
mnesia -> internal;
|
||||
DBType -> DBType
|
||||
end,
|
||||
Methods = ejabberd_config:get_option(
|
||||
{auth_method, LServer},
|
||||
fun(V) when is_list(V) ->
|
||||
@@ -432,7 +438,7 @@ auth_modules(Server) ->
|
||||
V;
|
||||
(V) when is_atom(V) ->
|
||||
[V]
|
||||
end, []),
|
||||
end, [Default]),
|
||||
[jlib:binary_to_atom(<<"ejabberd_auth_",
|
||||
(jlib:atom_to_binary(M))/binary>>)
|
||||
|| M <- Methods].
|
||||
@@ -449,3 +455,10 @@ import(Server, riak, Passwd) ->
|
||||
ejabberd_auth_riak:import(Server, riak, Passwd);
|
||||
import(_, _, _) ->
|
||||
pass.
|
||||
|
||||
opt_type(auth_method) ->
|
||||
fun (V) when is_list(V) ->
|
||||
true = lists:all(fun is_atom/1, V), V;
|
||||
(V) when is_atom(V) -> [V]
|
||||
end;
|
||||
opt_type(_) -> [auth_method].
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_auth_anonymous).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
-author('mickael.remond@process-one.net').
|
||||
|
||||
-export([start/1,
|
||||
@@ -36,16 +38,15 @@
|
||||
unregister_connection/3
|
||||
]).
|
||||
|
||||
|
||||
%% Function used by ejabberd_auth:
|
||||
-export([login/2, set_password/3, check_password/3,
|
||||
check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
get_vh_registered_users/2, get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password_s/2,
|
||||
get_vh_registered_users/2,
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password_s/2,
|
||||
get_password/2, get_password/3, is_user_exists/2,
|
||||
remove_user/2, remove_user/3, store_type/0,
|
||||
plain_password_required/0]).
|
||||
plain_password_required/0, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -141,7 +142,7 @@ remove_connection(SID, LUser, LServer) ->
|
||||
%% Register connection
|
||||
register_connection(SID,
|
||||
#jid{luser = LUser, lserver = LServer}, Info) ->
|
||||
AuthModule = list_to_atom(binary_to_list(xml:get_attr_s(<<"auth_module">>, Info))),
|
||||
AuthModule = proplists:get_value(auth_module, Info, undefined),
|
||||
case AuthModule == (?MODULE) of
|
||||
true ->
|
||||
ejabberd_hooks:run(register_user, LServer,
|
||||
@@ -269,3 +270,13 @@ plain_password_required() -> false.
|
||||
|
||||
store_type() ->
|
||||
plain.
|
||||
|
||||
opt_type(allow_multiple_connections) ->
|
||||
fun (V) when is_boolean(V) -> V end;
|
||||
opt_type(anonymous_protocol) ->
|
||||
fun (sasl_anon) -> sasl_anon;
|
||||
(login_anon) -> login_anon;
|
||||
(both) -> both
|
||||
end;
|
||||
opt_type(_) ->
|
||||
[allow_multiple_connections, anonymous_protocol].
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
|
||||
-module(ejabberd_auth_external).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
%% External exports
|
||||
-export([start/1, set_password/3, check_password/3,
|
||||
check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
@@ -37,8 +38,8 @@
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password/2,
|
||||
get_password_s/2, is_user_exists/2, remove_user/2,
|
||||
remove_user/3, store_type/0,
|
||||
plain_password_required/0]).
|
||||
remove_user/3, store_type/0, plain_password_required/0,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -311,3 +312,11 @@ get_mod_last_configured(Server) ->
|
||||
|
||||
is_configured(Host, Module) ->
|
||||
gen_mod:is_loaded(Host, Module).
|
||||
|
||||
opt_type(extauth_cache) ->
|
||||
fun (false) -> undefined;
|
||||
(I) when is_integer(I), I >= 0 -> I
|
||||
end;
|
||||
opt_type(extauth_program) ->
|
||||
fun (V) -> binary_to_list(iolist_to_binary(V)) end;
|
||||
opt_type(_) -> [extauth_cache, extauth_program].
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
|
||||
-module(ejabberd_auth_internal).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
%% External exports
|
||||
-export([start/1, set_password/3, check_password/3,
|
||||
check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
@@ -38,7 +39,7 @@
|
||||
get_vh_registered_users_number/2, get_password/2,
|
||||
get_password_s/2, is_user_exists/2, remove_user/2,
|
||||
remove_user/3, store_type/0, export/1, import/1,
|
||||
import/3, plain_password_required/0]).
|
||||
import/3, plain_password_required/0, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -151,7 +152,10 @@ set_password(User, Server, Password) ->
|
||||
try_register(User, Server, PasswordList) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
Password = iolist_to_binary(PasswordList),
|
||||
Password = if is_list(PasswordList); is_binary(PasswordList) ->
|
||||
iolist_to_binary(PasswordList);
|
||||
true -> PasswordList
|
||||
end,
|
||||
US = {LUser, LServer},
|
||||
if (LUser == error) or (LServer == error) ->
|
||||
{error, invalid_jid};
|
||||
@@ -481,3 +485,6 @@ import(_LServer, mnesia, #passwd{} = P) ->
|
||||
mnesia:dirty_write(P);
|
||||
import(_, _, _) ->
|
||||
pass.
|
||||
|
||||
opt_type(auth_password_format) -> fun (V) -> V end;
|
||||
opt_type(_) -> [auth_password_format].
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
-module(ejabberd_auth_ldap).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(gen_server).
|
||||
@@ -34,16 +36,15 @@
|
||||
-export([init/1, handle_info/2, handle_call/3,
|
||||
handle_cast/2, terminate/2, code_change/3]).
|
||||
|
||||
%% External exports
|
||||
-export([start/1, stop/1, start_link/1, set_password/3,
|
||||
check_password/3, check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
get_vh_registered_users/2,
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users/2,
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password/2,
|
||||
get_password_s/2, is_user_exists/2, remove_user/2,
|
||||
remove_user/3, store_type/0,
|
||||
plain_password_required/0]).
|
||||
remove_user/3, store_type/0, plain_password_required/0,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -360,7 +361,7 @@ parse_options(Host) ->
|
||||
Eldap_ID = jlib:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)),
|
||||
Bind_Eldap_ID = jlib:atom_to_binary(
|
||||
gen_mod:get_module_proc(Host, bind_ejabberd_auth_ldap)),
|
||||
UIDsTemp = eldap_utils:get_opt(
|
||||
UIDsTemp = gen_mod:get_opt(
|
||||
{ldap_uids, Host}, [],
|
||||
fun(Us) ->
|
||||
lists:map(
|
||||
@@ -375,7 +376,7 @@ parse_options(Host) ->
|
||||
end, [{<<"uid">>, <<"%u">>}]),
|
||||
UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp),
|
||||
SubFilter = eldap_utils:generate_subfilter(UIDs),
|
||||
UserFilter = case eldap_utils:get_opt(
|
||||
UserFilter = case gen_mod:get_opt(
|
||||
{ldap_filter, Host}, [],
|
||||
fun check_filter/1, <<"">>) of
|
||||
<<"">> ->
|
||||
@@ -386,7 +387,7 @@ parse_options(Host) ->
|
||||
SearchFilter = eldap_filter:do_sub(UserFilter,
|
||||
[{<<"%u">>, <<"*">>}]),
|
||||
{DNFilter, DNFilterAttrs} =
|
||||
eldap_utils:get_opt({ldap_dn_filter, Host}, [],
|
||||
gen_mod:get_opt({ldap_dn_filter, Host}, [],
|
||||
fun([{DNF, DNFA}]) ->
|
||||
NewDNFA = case DNFA of
|
||||
undefined ->
|
||||
@@ -398,7 +399,7 @@ parse_options(Host) ->
|
||||
NewDNF = check_filter(DNF),
|
||||
{NewDNF, NewDNFA}
|
||||
end, {undefined, []}),
|
||||
LocalFilter = eldap_utils:get_opt(
|
||||
LocalFilter = gen_mod:get_opt(
|
||||
{ldap_local_filter, Host}, [], fun(V) -> V end),
|
||||
#state{host = Host, eldap_id = Eldap_ID,
|
||||
bind_eldap_id = Bind_Eldap_ID,
|
||||
@@ -418,3 +419,27 @@ check_filter(F) ->
|
||||
NewF = iolist_to_binary(F),
|
||||
{ok, _} = eldap_filter:parse(NewF),
|
||||
NewF.
|
||||
|
||||
opt_type(ldap_dn_filter) ->
|
||||
fun ([{DNF, DNFA}]) ->
|
||||
NewDNFA = case DNFA of
|
||||
undefined -> [];
|
||||
_ -> [iolist_to_binary(A) || A <- DNFA]
|
||||
end,
|
||||
NewDNF = check_filter(DNF),
|
||||
{NewDNF, NewDNFA}
|
||||
end;
|
||||
opt_type(ldap_filter) -> fun check_filter/1;
|
||||
opt_type(ldap_local_filter) -> fun (V) -> V end;
|
||||
opt_type(ldap_uids) ->
|
||||
fun (Us) ->
|
||||
lists:map(fun ({U, P}) ->
|
||||
{iolist_to_binary(U), iolist_to_binary(P)};
|
||||
({U}) -> {iolist_to_binary(U)};
|
||||
(U) -> {iolist_to_binary(U)}
|
||||
end,
|
||||
lists:flatten(Us))
|
||||
end;
|
||||
opt_type(_) ->
|
||||
[ldap_dn_filter, ldap_filter, ldap_local_filter,
|
||||
ldap_uids].
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
|
||||
-module(ejabberd_auth_odbc).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
%% External exports
|
||||
-export([start/1, set_password/3, check_password/3,
|
||||
check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
@@ -37,9 +38,8 @@
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password/2,
|
||||
get_password_s/2, is_user_exists/2, remove_user/2,
|
||||
remove_user/3, store_type/0,
|
||||
plain_password_required/0,
|
||||
convert_to_scram/1]).
|
||||
remove_user/3, store_type/0, plain_password_required/0,
|
||||
convert_to_scram/1, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -83,7 +83,7 @@ check_password(User, Server, Password) ->
|
||||
#scram{storedkey = StoredKey,
|
||||
serverkey = ServerKey,
|
||||
salt = Salt,
|
||||
iterationcount = binary_to_integer(
|
||||
iterationcount = jlib:binary_to_integer(
|
||||
IterationCount)},
|
||||
is_password_scram_valid(Password, Scram);
|
||||
{selected, [<<"password">>, <<"serverkey">>,
|
||||
@@ -168,7 +168,7 @@ set_password(User, Server, Password) ->
|
||||
ejabberd_odbc:escape(Scram#scram.storedkey),
|
||||
ejabberd_odbc:escape(Scram#scram.serverkey),
|
||||
ejabberd_odbc:escape(Scram#scram.salt),
|
||||
integer_to_binary(Scram#scram.iterationcount)
|
||||
jlib:integer_to_binary(Scram#scram.iterationcount)
|
||||
)
|
||||
of
|
||||
{atomic, ok} -> ok;
|
||||
@@ -204,7 +204,7 @@ try_register(User, Server, Password) ->
|
||||
ejabberd_odbc:escape(Scram#scram.storedkey),
|
||||
ejabberd_odbc:escape(Scram#scram.serverkey),
|
||||
ejabberd_odbc:escape(Scram#scram.salt),
|
||||
integer_to_binary(Scram#scram.iterationcount)
|
||||
jlib:integer_to_binary(Scram#scram.iterationcount)
|
||||
) of
|
||||
{updated, 1} -> {atomic, ok};
|
||||
_ -> {atomic, exists}
|
||||
@@ -278,7 +278,7 @@ get_password(User, Server) ->
|
||||
{jlib:decode_base64(StoredKey),
|
||||
jlib:decode_base64(ServerKey),
|
||||
jlib:decode_base64(Salt),
|
||||
binary_to_integer(IterationCount)};
|
||||
jlib:binary_to_integer(IterationCount)};
|
||||
_ -> false
|
||||
end;
|
||||
false ->
|
||||
@@ -439,7 +439,7 @@ convert_to_scram(Server) ->
|
||||
case ejabberd_odbc:sql_query_t(
|
||||
[<<"select username, password from users where "
|
||||
"iterationcount=0 limit ">>,
|
||||
integer_to_binary(?BATCH_SIZE),
|
||||
jlib:integer_to_binary(?BATCH_SIZE),
|
||||
<<";">>]) of
|
||||
{selected, [<<"username">>, <<"password">>], []} ->
|
||||
ok;
|
||||
@@ -453,7 +453,7 @@ convert_to_scram(Server) ->
|
||||
ejabberd_odbc:escape(Scram#scram.storedkey),
|
||||
ejabberd_odbc:escape(Scram#scram.serverkey),
|
||||
ejabberd_odbc:escape(Scram#scram.salt),
|
||||
integer_to_binary(Scram#scram.iterationcount)
|
||||
jlib:integer_to_binary(Scram#scram.iterationcount)
|
||||
)
|
||||
end, Rs),
|
||||
continue;
|
||||
@@ -467,3 +467,6 @@ convert_to_scram(Server) ->
|
||||
Error -> Error
|
||||
end
|
||||
end.
|
||||
|
||||
opt_type(auth_password_format) -> fun (V) -> V end;
|
||||
opt_type(_) -> [auth_password_format].
|
||||
|
||||
@@ -24,22 +24,21 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_auth_pam).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('xram@jabber.ru').
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
%% External exports
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
-export([start/1, set_password/3, check_password/3,
|
||||
check_password/5, try_register/3,
|
||||
dirty_get_registered_users/0, get_vh_registered_users/1,
|
||||
get_vh_registered_users/2, get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2,
|
||||
get_password/2, get_password_s/2, is_user_exists/2,
|
||||
remove_user/2, remove_user/3, store_type/0,
|
||||
plain_password_required/0]).
|
||||
get_vh_registered_users/2,
|
||||
get_vh_registered_users_number/1,
|
||||
get_vh_registered_users_number/2, get_password/2,
|
||||
get_password_s/2, is_user_exists/2, remove_user/2,
|
||||
remove_user/3, store_type/0, plain_password_required/0,
|
||||
opt_type/1]).
|
||||
|
||||
start(_Host) ->
|
||||
ejabberd:start_app(p1_pam).
|
||||
@@ -118,3 +117,10 @@ get_pam_userinfotype(Host) ->
|
||||
(jid) -> jid
|
||||
end,
|
||||
username).
|
||||
|
||||
opt_type(pam_service) -> fun iolist_to_binary/1;
|
||||
opt_type(pam_userinfotype) ->
|
||||
fun (username) -> username;
|
||||
(jid) -> jid
|
||||
end;
|
||||
opt_type(_) -> [pam_service, pam_userinfotype].
|
||||
|
||||
@@ -124,7 +124,10 @@ set_password(User, Server, Password) ->
|
||||
try_register(User, Server, PasswordList) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
Password = iolist_to_binary(PasswordList),
|
||||
Password = if is_list(PasswordList); is_binary(PasswordList) ->
|
||||
iolist_to_binary(PasswordList);
|
||||
true -> PasswordList
|
||||
end,
|
||||
US = {LUser, LServer},
|
||||
if (LUser == error) or (LServer == error) ->
|
||||
{error, invalid_jid};
|
||||
|
||||
@@ -25,8 +25,14 @@
|
||||
|
||||
-module(ejabberd_c2s).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-protocol({xep, 78, '2.5'}).
|
||||
-protocol({xep, 138, '2.0'}).
|
||||
-protocol({xep, 198, '1.3'}).
|
||||
|
||||
-update_info({update, 0}).
|
||||
|
||||
-define(GEN_FSM, p1_fsm).
|
||||
@@ -50,23 +56,12 @@
|
||||
get_subscribed/1,
|
||||
transform_listen_option/2]).
|
||||
|
||||
%% gen_fsm callbacks
|
||||
-export([init/1,
|
||||
wait_for_stream/2,
|
||||
wait_for_auth/2,
|
||||
wait_for_feature_request/2,
|
||||
wait_for_bind/2,
|
||||
wait_for_session/2,
|
||||
wait_for_sasl_response/2,
|
||||
wait_for_resume/2,
|
||||
session_established/2,
|
||||
handle_event/3,
|
||||
handle_sync_event/4,
|
||||
code_change/4,
|
||||
handle_info/3,
|
||||
terminate/3,
|
||||
print_state/1
|
||||
]).
|
||||
-export([init/1, wait_for_stream/2, wait_for_auth/2,
|
||||
wait_for_feature_request/2, wait_for_bind/2,
|
||||
wait_for_session/2, wait_for_sasl_response/2,
|
||||
wait_for_resume/2, session_established/2,
|
||||
handle_event/3, handle_sync_event/4, code_change/4,
|
||||
handle_info/3, terminate/3, print_state/1, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -169,14 +164,14 @@
|
||||
%% XEP-0198:
|
||||
|
||||
-define(IS_STREAM_MGMT_TAG(Name),
|
||||
Name == <<"enable">>;
|
||||
Name == <<"resume">>;
|
||||
Name == <<"a">>;
|
||||
Name == <<"r">>).
|
||||
(Name == <<"enable">>) or
|
||||
(Name == <<"resume">>) or
|
||||
(Name == <<"a">>) or
|
||||
(Name == <<"r">>)).
|
||||
|
||||
-define(IS_SUPPORTED_MGMT_XMLNS(Xmlns),
|
||||
Xmlns == ?NS_STREAM_MGMT_2;
|
||||
Xmlns == ?NS_STREAM_MGMT_3).
|
||||
(Xmlns == ?NS_STREAM_MGMT_2) or
|
||||
(Xmlns == ?NS_STREAM_MGMT_3)).
|
||||
|
||||
-define(MGMT_FAILED(Condition, Xmlns),
|
||||
#xmlel{name = <<"failed">>,
|
||||
@@ -288,6 +283,7 @@ init([{SockMod, Socket}, Opts]) ->
|
||||
StartTLSRequired orelse TLSEnabled,
|
||||
TLSOpts1 = lists:filter(fun ({certfile, _}) -> true;
|
||||
({ciphers, _}) -> true;
|
||||
({dhfile, _}) -> true;
|
||||
(_) -> false
|
||||
end,
|
||||
Opts),
|
||||
@@ -457,14 +453,14 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
false ->
|
||||
[]
|
||||
end,
|
||||
StreamFeatures1 = TLSFeature ++ CompressFeature ++ Mechs,
|
||||
StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
|
||||
Server, StreamFeatures1, [Server]),
|
||||
send_element(StateData,
|
||||
#xmlel{name = <<"stream:features">>,
|
||||
attrs = [],
|
||||
children =
|
||||
TLSFeature ++ CompressFeature ++ Mechs
|
||||
++
|
||||
ejabberd_hooks:run_fold(c2s_stream_features,
|
||||
Server, [], [Server])}),
|
||||
StreamFeatures}),
|
||||
fsm_next_state(wait_for_feature_request,
|
||||
StateData#state{
|
||||
server = Server,
|
||||
@@ -489,7 +485,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
false ->
|
||||
[]
|
||||
end,
|
||||
StreamFeatures = [#xmlel{name = <<"bind">>,
|
||||
StreamFeatures1 = [#xmlel{name = <<"bind">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_BIND}],
|
||||
children = []},
|
||||
#xmlel{name = <<"session">>,
|
||||
@@ -499,9 +495,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
RosterVersioningFeature ++
|
||||
StreamManagementFeature ++
|
||||
ejabberd_hooks:run_fold(c2s_post_auth_features,
|
||||
Server, [], [Server]) ++
|
||||
ejabberd_hooks:run_fold(c2s_stream_features,
|
||||
Server, [], [Server]),
|
||||
StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
|
||||
Server, StreamFeatures1, [Server]),
|
||||
send_element(StateData,
|
||||
#xmlel{name = <<"stream:features">>,
|
||||
attrs = [],
|
||||
@@ -643,7 +639,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s",
|
||||
[StateData#state.socket,
|
||||
jlib:jid_to_string(JID), AuthModule,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[true, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -684,7 +680,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s",
|
||||
[StateData#state.socket,
|
||||
jlib:jid_to_string(JID),
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[false, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -705,7 +701,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
"for ~s from ~s",
|
||||
[StateData#state.socket,
|
||||
jlib:jid_to_string(JID),
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[false, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -760,7 +756,7 @@ wait_for_feature_request({xmlstreamelement, El},
|
||||
?INFO_MSG("(~w) Accepted authentication for ~s "
|
||||
"by ~p from ~s",
|
||||
[StateData#state.socket, U, AuthModule,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[true, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -787,7 +783,7 @@ wait_for_feature_request({xmlstreamelement, El},
|
||||
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
|
||||
[StateData#state.socket,
|
||||
Username, StateData#state.server,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[false, Username, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -913,7 +909,7 @@ wait_for_sasl_response({xmlstreamelement, El},
|
||||
?INFO_MSG("(~w) Accepted authentication for ~s "
|
||||
"by ~p from ~s",
|
||||
[StateData#state.socket, U, AuthModule,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[true, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -936,7 +932,7 @@ wait_for_sasl_response({xmlstreamelement, El},
|
||||
?INFO_MSG("(~w) Accepted authentication for ~s "
|
||||
"by ~p from ~s",
|
||||
[StateData#state.socket, U, AuthModule,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[true, U, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -965,7 +961,7 @@ wait_for_sasl_response({xmlstreamelement, El},
|
||||
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
|
||||
[StateData#state.socket,
|
||||
Username, StateData#state.server,
|
||||
jlib:ip_to_list(StateData#state.ip)]),
|
||||
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
|
||||
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
|
||||
[false, Username, StateData#state.server,
|
||||
StateData#state.ip]),
|
||||
@@ -1264,12 +1260,14 @@ session_established2(El, StateData) ->
|
||||
_ ->
|
||||
case Name of
|
||||
<<"presence">> ->
|
||||
PresenceEl =
|
||||
PresenceEl0 =
|
||||
ejabberd_hooks:run_fold(c2s_update_presence,
|
||||
Server, NewEl,
|
||||
[User, Server]),
|
||||
ejabberd_hooks:run(user_send_packet, Server,
|
||||
[FromJID, ToJID, PresenceEl]),
|
||||
PresenceEl =
|
||||
ejabberd_hooks:run_fold(
|
||||
user_send_packet, Server, PresenceEl0,
|
||||
[NewStateData, FromJID, ToJID]),
|
||||
case ToJID of
|
||||
#jid{user = User, server = Server,
|
||||
resource = <<"">>} ->
|
||||
@@ -1289,18 +1287,18 @@ session_established2(El, StateData) ->
|
||||
process_privacy_iq(FromJID, ToJID, IQ,
|
||||
NewStateData);
|
||||
_ ->
|
||||
ejabberd_hooks:run(user_send_packet, Server,
|
||||
[FromJID, ToJID, NewEl]),
|
||||
NewEl0 = ejabberd_hooks:run_fold(
|
||||
user_send_packet, Server, NewEl,
|
||||
[NewStateData, FromJID, ToJID]),
|
||||
check_privacy_route(FromJID, NewStateData,
|
||||
FromJID, ToJID, NewEl),
|
||||
NewStateData
|
||||
FromJID, ToJID, NewEl0)
|
||||
end;
|
||||
<<"message">> ->
|
||||
ejabberd_hooks:run(user_send_packet, Server,
|
||||
[FromJID, ToJID, NewEl]),
|
||||
NewEl0 = ejabberd_hooks:run_fold(
|
||||
user_send_packet, Server, NewEl,
|
||||
[NewStateData, FromJID, ToJID]),
|
||||
check_privacy_route(FromJID, NewStateData, FromJID,
|
||||
ToJID, NewEl),
|
||||
NewStateData;
|
||||
ToJID, NewEl0);
|
||||
_ -> NewStateData
|
||||
end
|
||||
end,
|
||||
@@ -1679,38 +1677,34 @@ handle_info({route, From, To,
|
||||
Packet, in)
|
||||
of
|
||||
allow -> {true, Attrs, StateData};
|
||||
deny -> {false, Attrs, StateData}
|
||||
deny ->
|
||||
case xml:get_attr_s(<<"type">>, Attrs) of
|
||||
<<"error">> -> ok;
|
||||
<<"result">> -> ok;
|
||||
_ ->
|
||||
Err =
|
||||
jlib:make_error_reply(Packet,
|
||||
?ERR_SERVICE_UNAVAILABLE),
|
||||
ejabberd_router:route(To, From,
|
||||
Err)
|
||||
end,
|
||||
{false, Attrs, StateData}
|
||||
end;
|
||||
_ -> {true, Attrs, StateData}
|
||||
end,
|
||||
if Pass == exit ->
|
||||
%% When Pass==exit, NewState contains a string instead of a #state{}
|
||||
Lang = StateData#state.lang,
|
||||
send_element(StateData, ?SERRT_CONFLICT(Lang, NewState)),
|
||||
send_trailer(StateData),
|
||||
{stop, normal, StateData};
|
||||
Pass ->
|
||||
if Pass ->
|
||||
Attrs2 =
|
||||
jlib:replace_from_to_attrs(jlib:jid_to_string(From),
|
||||
jlib:jid_to_string(To), NewAttrs),
|
||||
FixedPacket = #xmlel{name = Name, attrs = Attrs2, children = Els},
|
||||
FinalState =
|
||||
case ejabberd_hooks:run_fold(c2s_filter_packet_in,
|
||||
NewState#state.server, FixedPacket,
|
||||
[NewState#state.jid, From, To])
|
||||
of
|
||||
drop ->
|
||||
NewState;
|
||||
FinalPacket = #xmlel{} ->
|
||||
SentState = send_packet(NewState, FinalPacket),
|
||||
ejabberd_hooks:run(user_receive_packet,
|
||||
SentState#state.server,
|
||||
[SentState#state.jid, From, To,
|
||||
FinalPacket]),
|
||||
SentState
|
||||
end,
|
||||
FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els},
|
||||
FixedPacket = ejabberd_hooks:run_fold(
|
||||
user_receive_packet,
|
||||
NewState#state.server,
|
||||
FixedPacket0,
|
||||
[NewState, NewState#state.jid, From, To]),
|
||||
SentStateData = send_packet(NewState, FixedPacket),
|
||||
ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]),
|
||||
fsm_next_state(StateName, FinalState);
|
||||
fsm_next_state(StateName, SentStateData);
|
||||
true ->
|
||||
ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]),
|
||||
fsm_next_state(StateName, NewState)
|
||||
@@ -1737,6 +1731,10 @@ handle_info(system_shutdown, StateName, StateData) ->
|
||||
ok
|
||||
end,
|
||||
{stop, normal, StateData};
|
||||
handle_info({route_xmlstreamelement, El}, _StateName, StateData) ->
|
||||
{next_state, NStateName, NStateData, _Timeout} =
|
||||
session_established({xmlstreamelement, El}, StateData),
|
||||
fsm_next_state(NStateName, NStateData);
|
||||
handle_info({force_update_presence, LUser}, StateName,
|
||||
#state{user = LUser, server = LServer} = StateData) ->
|
||||
NewStateData = case StateData#state.pres_last of
|
||||
@@ -1805,7 +1803,7 @@ print_state(State = #state{pres_t = T, pres_f = F, pres_a = A}) ->
|
||||
pres_f = {pres_f, ?SETS:size(F)},
|
||||
pres_a = {pres_a, ?SETS:size(A)}
|
||||
}.
|
||||
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: terminate/3
|
||||
%% Purpose: Shutdown the fsm
|
||||
@@ -1888,14 +1886,14 @@ send_text(StateData, Text) when StateData#state.mgmt_state == pending ->
|
||||
?DEBUG("Cannot send text while waiting for resumption: ~p", [Text]);
|
||||
send_text(StateData, Text) when StateData#state.xml_socket ->
|
||||
?DEBUG("Send Text on stream = ~p", [Text]),
|
||||
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
||||
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
||||
{xmlstreamraw, Text});
|
||||
send_text(StateData, Text) when StateData#state.mgmt_state == active ->
|
||||
?DEBUG("Send XML on stream = ~p", [Text]),
|
||||
case catch (StateData#state.sockmod):send(StateData#state.socket, Text) of
|
||||
{'EXIT', _} ->
|
||||
(StateData#state.sockmod):close(StateData#state.socket),
|
||||
error;
|
||||
{error, closed};
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
@@ -1916,12 +1914,7 @@ send_stanza(StateData, Stanza) when StateData#state.csi_state == inactive ->
|
||||
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == pending ->
|
||||
mgmt_queue_add(StateData, Stanza);
|
||||
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == active ->
|
||||
NewStateData = case send_stanza_and_ack_req(StateData, Stanza) of
|
||||
ok ->
|
||||
StateData;
|
||||
error ->
|
||||
StateData#state{mgmt_state = pending}
|
||||
end,
|
||||
NewStateData = send_stanza_and_ack_req(StateData, Stanza),
|
||||
mgmt_queue_add(NewStateData, Stanza);
|
||||
send_stanza(StateData, Stanza) ->
|
||||
send_element(StateData, Stanza),
|
||||
@@ -2031,7 +2024,6 @@ get_conn_type(StateData) ->
|
||||
gen_tcp -> c2s_compressed;
|
||||
p1_tls -> c2s_compressed_tls
|
||||
end;
|
||||
ejabberd_http_poll -> http_poll;
|
||||
ejabberd_http_bind -> http_bind;
|
||||
_ -> unknown
|
||||
end.
|
||||
@@ -2141,37 +2133,29 @@ presence_track(From, To, Packet, StateData) ->
|
||||
Server = StateData#state.server,
|
||||
case xml:get_attr_s(<<"type">>, Attrs) of
|
||||
<<"unavailable">> ->
|
||||
check_privacy_route(From, StateData, From, To, Packet),
|
||||
A = remove_element(LTo, StateData#state.pres_a),
|
||||
StateData#state{pres_a = A};
|
||||
check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet);
|
||||
<<"subscribe">> ->
|
||||
try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData),
|
||||
StateData;
|
||||
try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData);
|
||||
<<"subscribed">> ->
|
||||
ejabberd_hooks:run(roster_out_subscription, Server,
|
||||
[User, Server, To, subscribed]),
|
||||
check_privacy_route(From, StateData,
|
||||
jlib:jid_remove_resource(From), To, Packet),
|
||||
StateData;
|
||||
jlib:jid_remove_resource(From), To, Packet);
|
||||
<<"unsubscribe">> ->
|
||||
try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData),
|
||||
StateData;
|
||||
try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData);
|
||||
<<"unsubscribed">> ->
|
||||
ejabberd_hooks:run(roster_out_subscription, Server,
|
||||
[User, Server, To, unsubscribed]),
|
||||
check_privacy_route(From, StateData,
|
||||
jlib:jid_remove_resource(From), To, Packet),
|
||||
StateData;
|
||||
jlib:jid_remove_resource(From), To, Packet);
|
||||
<<"error">> ->
|
||||
check_privacy_route(From, StateData, From, To, Packet),
|
||||
StateData;
|
||||
check_privacy_route(From, StateData, From, To, Packet);
|
||||
<<"probe">> ->
|
||||
check_privacy_route(From, StateData, From, To, Packet),
|
||||
StateData;
|
||||
check_privacy_route(From, StateData, From, To, Packet);
|
||||
_ ->
|
||||
check_privacy_route(From, StateData, From, To, Packet),
|
||||
A = (?SETS):add_element(LTo, StateData#state.pres_a),
|
||||
StateData#state{pres_a = A}
|
||||
check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet)
|
||||
end.
|
||||
|
||||
check_privacy_route(From, StateData, FromRoute, To,
|
||||
@@ -2179,15 +2163,17 @@ check_privacy_route(From, StateData, FromRoute, To,
|
||||
case privacy_check_packet(StateData, From, To, Packet,
|
||||
out)
|
||||
of
|
||||
deny ->
|
||||
Lang = StateData#state.lang,
|
||||
ErrText = <<"Your active privacy list has denied "
|
||||
"the routing of this stanza.">>,
|
||||
Err = jlib:make_error_reply(Packet,
|
||||
?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||
ejabberd_router:route(To, From, Err),
|
||||
ok;
|
||||
allow -> ejabberd_router:route(FromRoute, To, Packet)
|
||||
deny ->
|
||||
Lang = StateData#state.lang,
|
||||
ErrText = <<"Your active privacy list has denied "
|
||||
"the routing of this stanza.">>,
|
||||
Err = jlib:make_error_reply(Packet,
|
||||
?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||
Err2 = jlib:replace_from_to(To, From, Err),
|
||||
send_stanza(StateData, Err2);
|
||||
allow ->
|
||||
ejabberd_router:route(FromRoute, To, Packet),
|
||||
StateData
|
||||
end.
|
||||
|
||||
%% Check if privacy rules allow this delivery
|
||||
@@ -2210,7 +2196,7 @@ try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) ->
|
||||
case acl:match_rule(Server, Access, JID1) of
|
||||
deny ->
|
||||
%% Silently drop this (un)subscription request
|
||||
ok;
|
||||
StateData;
|
||||
allow ->
|
||||
ejabberd_hooks:run(roster_out_subscription,
|
||||
Server,
|
||||
@@ -2223,14 +2209,16 @@ try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) ->
|
||||
presence_broadcast(StateData, From, JIDSet, Packet) ->
|
||||
JIDs = ?SETS:to_list(JIDSet),
|
||||
JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs, out),
|
||||
send_multiple(StateData, From, JIDs2, Packet).
|
||||
Server = StateData#state.server,
|
||||
send_multiple(From, Server, JIDs2, Packet).
|
||||
|
||||
%% Send presence when updating presence
|
||||
presence_broadcast_to_trusted(StateData, From, Trusted, JIDSet, Packet) ->
|
||||
JIDs = ?SETS:to_list(JIDSet),
|
||||
JIDs_trusted = [JID || JID <- JIDs, ?SETS:is_element(JID, Trusted)],
|
||||
JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs_trusted, out),
|
||||
send_multiple(StateData, From, JIDs2, Packet).
|
||||
Server = StateData#state.server,
|
||||
send_multiple(From, Server, JIDs2, Packet).
|
||||
|
||||
%% Send presence when connecting
|
||||
presence_broadcast_first(From, StateData, Packet) ->
|
||||
@@ -2242,7 +2230,7 @@ presence_broadcast_first(From, StateData, Packet) ->
|
||||
PacketProbe = #xmlel{name = <<"presence">>, attrs = [{<<"type">>,<<"probe">>}], children = []},
|
||||
JIDs2Probe = format_and_check_privacy(From, StateData, PacketProbe, JIDsProbe, out),
|
||||
Server = StateData#state.server,
|
||||
send_multiple(StateData, From, JIDs2Probe, PacketProbe),
|
||||
send_multiple(From, Server, JIDs2Probe, PacketProbe),
|
||||
{As, JIDs} =
|
||||
?SETS:fold(
|
||||
fun(JID, {A, JID_list}) ->
|
||||
@@ -2251,8 +2239,7 @@ presence_broadcast_first(From, StateData, Packet) ->
|
||||
{StateData#state.pres_a, []},
|
||||
StateData#state.pres_f),
|
||||
JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs, out),
|
||||
Server = StateData#state.server,
|
||||
send_multiple(StateData, From, JIDs2, Packet),
|
||||
send_multiple(From, Server, JIDs2, Packet),
|
||||
StateData#state{pres_a = As}.
|
||||
|
||||
format_and_check_privacy(From, StateData, Packet, JIDs, Dir) ->
|
||||
@@ -2273,16 +2260,8 @@ format_and_check_privacy(From, StateData, Packet, JIDs, Dir) ->
|
||||
end,
|
||||
FJIDs).
|
||||
|
||||
send_multiple(StateData, From, JIDs, Packet) ->
|
||||
lists:foreach(
|
||||
fun(JID) ->
|
||||
case privacy_check_packet(StateData, From, JID, Packet, out) of
|
||||
deny ->
|
||||
ok;
|
||||
allow ->
|
||||
ejabberd_router:route(From, JID, Packet)
|
||||
end
|
||||
end, JIDs).
|
||||
send_multiple(From, Server, JIDs, Packet) ->
|
||||
ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet).
|
||||
|
||||
remove_element(E, Set) ->
|
||||
case (?SETS):is_element(E, Set) of
|
||||
@@ -2848,8 +2827,13 @@ send_stanza_and_ack_req(StateData, Stanza) ->
|
||||
AckReq = #xmlel{name = <<"r">>,
|
||||
attrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}],
|
||||
children = []},
|
||||
send_element(StateData, Stanza),
|
||||
send_element(StateData, AckReq).
|
||||
case send_element(StateData, Stanza) == ok andalso
|
||||
send_element(StateData, AckReq) == ok of
|
||||
true ->
|
||||
StateData;
|
||||
false ->
|
||||
StateData#state{mgmt_state = pending}
|
||||
end.
|
||||
|
||||
mgmt_queue_add(StateData, El) ->
|
||||
NewNum = case StateData#state.mgmt_stanzas_out of
|
||||
@@ -3140,3 +3124,15 @@ pack_string(String, Pack) ->
|
||||
|
||||
transform_listen_option(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
|
||||
opt_type(domain_certfile) -> fun iolist_to_binary/1;
|
||||
opt_type(max_fsm_queue) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(resource_conflict) ->
|
||||
fun (setresource) -> setresource;
|
||||
(closeold) -> closeold;
|
||||
(closenew) -> closenew;
|
||||
(acceptnew) -> acceptnew
|
||||
end;
|
||||
opt_type(_) ->
|
||||
[domain_certfile, max_fsm_queue, resource_conflict].
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
-module(ejabberd_c2s_config).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('mremond@process-one.net').
|
||||
|
||||
-export([get_c2s_limits/0]).
|
||||
-export([get_c2s_limits/0, opt_type/1]).
|
||||
|
||||
%% Get first c2s configuration limitations to apply it to other c2s
|
||||
%% connectors.
|
||||
@@ -63,3 +65,6 @@ select_opts_values([{max_stanza_size, Value} | Opts],
|
||||
[{max_stanza_size, Value} | SelectedValues]);
|
||||
select_opts_values([_Opt | Opts], SelectedValues) ->
|
||||
select_opts_values(Opts, SelectedValues).
|
||||
|
||||
opt_type(listen) -> fun (V) -> V end;
|
||||
opt_type(_) -> [listen].
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
|
||||
-module(ejabberd_captcha).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-protocol({xep, 158, '1.0'}).
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
@@ -37,7 +41,7 @@
|
||||
-export([create_captcha/6, build_captcha_html/2,
|
||||
check_captcha/2, process_reply/1, process/2,
|
||||
is_feature_available/0, create_captcha_x/5,
|
||||
create_captcha_x/6]).
|
||||
create_captcha_x/6, opt_type/1]).
|
||||
|
||||
-include("jlib.hrl").
|
||||
|
||||
@@ -693,3 +697,14 @@ clean_treap(Treap, CleanPriority) ->
|
||||
now_priority() ->
|
||||
{MSec, Sec, USec} = now(),
|
||||
-((MSec * 1000000 + Sec) * 1000000 + USec).
|
||||
|
||||
opt_type(captcha_cmd) ->
|
||||
fun (FileName) ->
|
||||
F = iolist_to_binary(FileName), if F /= <<"">> -> F end
|
||||
end;
|
||||
opt_type(captcha_host) -> fun iolist_to_binary/1;
|
||||
opt_type(captcha_limit) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(listen) -> fun (V) -> V end;
|
||||
opt_type(_) ->
|
||||
[captcha_cmd, captcha_host, captcha_limit, listen].
|
||||
|
||||
@@ -317,7 +317,13 @@ execute_command2(Command, Arguments) ->
|
||||
Module = Command#ejabberd_commands.module,
|
||||
Function = Command#ejabberd_commands.function,
|
||||
?DEBUG("Executing command ~p:~p with Args=~p", [Module, Function, Arguments]),
|
||||
apply(Module, Function, Arguments).
|
||||
try apply(Module, Function, Arguments) of
|
||||
Response ->
|
||||
Response
|
||||
catch
|
||||
Problem ->
|
||||
{error, Problem}
|
||||
end.
|
||||
|
||||
-spec get_tags_commands() -> [{string(), [string()]}].
|
||||
|
||||
@@ -370,6 +376,15 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) ->
|
||||
AccessCommandsAllowed =
|
||||
lists:filter(
|
||||
fun({Access, Commands, ArgumentRestrictions}) ->
|
||||
case check_access(Access, Auth) of
|
||||
true ->
|
||||
check_access_command(Commands, Command, ArgumentRestrictions,
|
||||
Method, Arguments);
|
||||
false ->
|
||||
false
|
||||
end;
|
||||
({Access, Commands}) ->
|
||||
ArgumentRestrictions = [],
|
||||
case check_access(Access, Auth) of
|
||||
true ->
|
||||
check_access_command(Commands, Command, ArgumentRestrictions,
|
||||
|
||||
@@ -35,13 +35,15 @@
|
||||
get_version/0, get_myhosts/0, get_mylang/0,
|
||||
prepare_opt_val/4, convert_table_to_binary/5,
|
||||
transform_options/1, collect_options/1,
|
||||
convert_to_yaml/1, convert_to_yaml/2]).
|
||||
convert_to_yaml/1, convert_to_yaml/2,
|
||||
env_binary_to_list/2, opt_type/1, may_hide_data/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
-include("ejabberd_config.hrl").
|
||||
-include_lib("kernel/include/file.hrl").
|
||||
|
||||
-callback opt_type(atom()) -> function() | [atom()].
|
||||
|
||||
%% @type macro() = {macro_key(), macro_value()}
|
||||
|
||||
@@ -64,7 +66,8 @@ start() ->
|
||||
{attributes, record_info(fields, local_config)}]),
|
||||
mnesia:add_table_copy(local_config, node(), ram_copies),
|
||||
Config = get_ejabberd_config_path(),
|
||||
State = read_file(Config),
|
||||
State0 = read_file(Config),
|
||||
State = validate_opts(State0),
|
||||
%% This start time is used by mod_last:
|
||||
{MegaSecs, Secs, _} = now(),
|
||||
UnixTime = MegaSecs*1000000 + Secs,
|
||||
@@ -84,7 +87,7 @@ start() ->
|
||||
%% If not specified, the default value 'ejabberd.yml' is assumed.
|
||||
%% @spec () -> string()
|
||||
get_ejabberd_config_path() ->
|
||||
case application:get_env(config) of
|
||||
case get_env_config() of
|
||||
{ok, Path} -> Path;
|
||||
undefined ->
|
||||
case os:getenv("EJABBERD_CONFIG_PATH") of
|
||||
@@ -95,13 +98,26 @@ get_ejabberd_config_path() ->
|
||||
end
|
||||
end.
|
||||
|
||||
-spec get_env_config() -> {ok, string()} | undefined.
|
||||
get_env_config() ->
|
||||
%% First case: the filename can be specified with: erl -config "/path/to/ejabberd.yml".
|
||||
case application:get_env(config) of
|
||||
R = {ok, _Path} -> R;
|
||||
undefined ->
|
||||
%% Second case for embbeding ejabberd in another app, for example for Elixir:
|
||||
%% config :ejabberd,
|
||||
%% file: "config/ejabberd.yml"
|
||||
application:get_env(ejabberd, file)
|
||||
end.
|
||||
|
||||
%% @doc Read the ejabberd configuration file.
|
||||
%% It also includes additional configuration files and replaces macros.
|
||||
%% This function will crash if finds some error in the configuration file.
|
||||
%% @spec (File::string()) -> #state{}.
|
||||
read_file(File) ->
|
||||
read_file(File, [{replace_macros, true},
|
||||
{include_files, true}]).
|
||||
{include_files, true},
|
||||
{include_modules_configs, true}]).
|
||||
|
||||
read_file(File, Opts) ->
|
||||
Terms1 = get_plain_terms_file(File, Opts),
|
||||
@@ -155,6 +171,22 @@ convert_to_yaml(File, Output) ->
|
||||
file:write_file(FileName, Data)
|
||||
end.
|
||||
|
||||
%% Some Erlang apps expects env parameters to be list and not binary.
|
||||
%% For example, Mnesia is not able to start if mnesia dir is passed as a binary.
|
||||
%% However, binary is most common on Elixir, so it is easy to make a setup mistake.
|
||||
-spec env_binary_to_list(atom(), atom()) -> {ok, any()}|undefined.
|
||||
env_binary_to_list(Application, Parameter) ->
|
||||
%% Application need to be loaded to allow setting parameters
|
||||
application:load(Application),
|
||||
case application:get_env(Application, Parameter) of
|
||||
{ok, Val} when is_binary(Val) ->
|
||||
BVal = binary_to_list(Val),
|
||||
application:set_env(Application, Parameter, BVal),
|
||||
{ok, BVal};
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
%% @doc Read an ejabberd configuration file and return the terms.
|
||||
%% Input is an absolute or relative path to an ejabberd config file.
|
||||
%% Returns a list of plain terms,
|
||||
@@ -171,7 +203,14 @@ get_plain_terms_file(File1, Opts) ->
|
||||
File = get_absolute_path(File1),
|
||||
case consult(File) of
|
||||
{ok, Terms} ->
|
||||
BinTerms = strings_to_binary(Terms),
|
||||
BinTerms1 = strings_to_binary(Terms),
|
||||
ModInc = case proplists:get_bool(include_modules_configs, Opts) of
|
||||
true ->
|
||||
filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.yaml");
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc],
|
||||
case proplists:get_bool(include_files, Opts) of
|
||||
true ->
|
||||
include_config_files(BinTerms);
|
||||
@@ -345,7 +384,25 @@ include_config_files(Terms) ->
|
||||
fun({File, Opts}) ->
|
||||
include_config_file(File, Opts)
|
||||
end, lists:flatten(FileOpts)),
|
||||
Terms1 ++ Terms2.
|
||||
|
||||
SpecialTerms = dict:from_list([{hosts, none}, {listen, none}, {modules, none}]),
|
||||
Partition = fun(L) ->
|
||||
lists:foldr(fun({Name, Val} = Pair, Dict) ->
|
||||
case dict:find(Name, SpecialTerms) of
|
||||
{ok, _} ->
|
||||
dict:store(Name, Val, Dict);
|
||||
_ ->
|
||||
dict:update(rest, fun(L1) -> [Pair|L1] end, Dict)
|
||||
end;
|
||||
(Tuple, Dict2) ->
|
||||
dict:update(rest, fun(L2) -> [Tuple|L2] end, Dict2)
|
||||
end, dict:from_list([{rest, []}]), L)
|
||||
end,
|
||||
|
||||
Merged = dict:merge(fun(_Name, V1, V2) -> V1 ++ V2 end,
|
||||
Partition(Terms1), Partition(Terms2)),
|
||||
Rest = dict:fetch(rest, Merged),
|
||||
dict:to_list(dict:erase(rest, Merged)) ++ Rest.
|
||||
|
||||
transform_include_option({include_config_file, File}) when is_list(File) ->
|
||||
case is_string(File) of
|
||||
@@ -423,11 +480,11 @@ split_terms_macros(Terms) ->
|
||||
lists:foldl(
|
||||
fun(Term, {TOs, Ms}) ->
|
||||
case Term of
|
||||
{define_macro, Key, Value} ->
|
||||
{define_macro, Key, Value} ->
|
||||
case is_correct_macro({Key, Value}) of
|
||||
true ->
|
||||
true ->
|
||||
{TOs, Ms++[{Key, Value}]};
|
||||
false ->
|
||||
false ->
|
||||
exit({macro_not_properly_defined, Term})
|
||||
end;
|
||||
{define_macro, KeyVals} ->
|
||||
@@ -657,6 +714,48 @@ get_option(Opt, F, Default) ->
|
||||
end
|
||||
end.
|
||||
|
||||
get_modules_with_options() ->
|
||||
{ok, Mods} = application:get_key(ejabberd, modules),
|
||||
lists:foldl(
|
||||
fun(Mod, D) ->
|
||||
Attrs = Mod:module_info(attributes),
|
||||
Behavs = proplists:get_value(behaviour, Attrs, []),
|
||||
case lists:member(ejabberd_config, Behavs) or (Mod == ?MODULE) of
|
||||
true ->
|
||||
Opts = Mod:opt_type(''),
|
||||
lists:foldl(
|
||||
fun(Opt, Acc) ->
|
||||
dict:append(Opt, Mod, Acc)
|
||||
end, D, Opts);
|
||||
false ->
|
||||
D
|
||||
end
|
||||
end, dict:new(), [?MODULE|Mods]).
|
||||
|
||||
validate_opts(#state{opts = Opts} = State) ->
|
||||
ModOpts = get_modules_with_options(),
|
||||
NewOpts = lists:filter(
|
||||
fun(#local_config{key = {Opt, _Host}, value = Val}) ->
|
||||
case dict:find(Opt, ModOpts) of
|
||||
{ok, [Mod|_]} ->
|
||||
VFun = Mod:opt_type(Opt),
|
||||
case catch VFun(Val) of
|
||||
{'EXIT', _} ->
|
||||
?ERROR_MSG("ignoring option '~s' with "
|
||||
"invalid value: ~p",
|
||||
[Opt, Val]),
|
||||
false;
|
||||
_ ->
|
||||
true
|
||||
end;
|
||||
_ ->
|
||||
?ERROR_MSG("unknown option '~s' will be likely"
|
||||
" ignored", [Opt]),
|
||||
true
|
||||
end
|
||||
end, Opts),
|
||||
State#state{opts = NewOpts}.
|
||||
|
||||
-spec get_vh_by_auth_method(atom()) -> [binary()].
|
||||
|
||||
%% Return the list of hosts handled by a given module
|
||||
@@ -679,7 +778,10 @@ is_file_readable(Path) ->
|
||||
end.
|
||||
|
||||
get_version() ->
|
||||
list_to_binary(element(2, application:get_key(ejabberd, vsn))).
|
||||
case application:get_key(ejabberd, vsn) of
|
||||
undefined -> "";
|
||||
{ok, Vsn} -> list_to_binary(Vsn)
|
||||
end.
|
||||
|
||||
-spec get_myhosts() -> [binary()].
|
||||
|
||||
@@ -713,14 +815,24 @@ replace_module(Module) ->
|
||||
false -> Module
|
||||
end.
|
||||
|
||||
replace_modules(Modules) -> lists:map( fun({Module, Opts}) -> case
|
||||
replace_module(Module) of {NewModule, DBType} ->
|
||||
emit_deprecation_warning(Module, NewModule, DBType), NewOpts =
|
||||
[{db_type, DBType} | lists:keydelete(db_type, 1, Opts)],
|
||||
{NewModule, transform_module_options(Module, NewOpts)}; NewModule
|
||||
-> if Module /= NewModule -> emit_deprecation_warning(Module,
|
||||
NewModule); true -> ok end, {NewModule,
|
||||
transform_module_options(Module, Opts)} end end, Modules).
|
||||
replace_modules(Modules) ->
|
||||
lists:map(
|
||||
fun({Module, Opts}) ->
|
||||
case replace_module(Module) of
|
||||
{NewModule, DBType} ->
|
||||
emit_deprecation_warning(Module, NewModule, DBType),
|
||||
NewOpts = [{db_type, DBType} |
|
||||
lists:keydelete(db_type, 1, Opts)],
|
||||
{NewModule, transform_module_options(Module, NewOpts)};
|
||||
NewModule ->
|
||||
if Module /= NewModule ->
|
||||
emit_deprecation_warning(Module, NewModule);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
{NewModule, transform_module_options(Module, Opts)}
|
||||
end
|
||||
end, Modules).
|
||||
|
||||
%% Elixir module naming
|
||||
%% ====================
|
||||
@@ -1030,3 +1142,30 @@ emit_deprecation_warning(Module, NewModule) ->
|
||||
?WARNING_MSG("Module ~s is deprecated, use ~s instead",
|
||||
[Module, NewModule])
|
||||
end.
|
||||
|
||||
opt_type(hosts) ->
|
||||
fun(L) when is_list(L) ->
|
||||
lists:map(
|
||||
fun(H) ->
|
||||
iolist_to_binary(H)
|
||||
end, L)
|
||||
end;
|
||||
opt_type(language) ->
|
||||
fun iolist_to_binary/1;
|
||||
opt_type(_) ->
|
||||
[hosts, language].
|
||||
|
||||
-spec may_hide_data(string()) -> string().
|
||||
|
||||
may_hide_data(Data) ->
|
||||
case ejabberd_config:get_option(
|
||||
hide_sensitive_log_data,
|
||||
fun(false) -> false;
|
||||
(true) -> true
|
||||
end,
|
||||
false) of
|
||||
false ->
|
||||
Data;
|
||||
true ->
|
||||
"hidden_by_ejabberd"
|
||||
end.
|
||||
|
||||
@@ -44,14 +44,13 @@
|
||||
|
||||
|
||||
-module(ejabberd_ctl).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0,
|
||||
init/0,
|
||||
process/1,
|
||||
process2/2,
|
||||
register_commands/3,
|
||||
unregister_commands/3]).
|
||||
-export([start/0, init/0, process/1, process2/2,
|
||||
register_commands/3, unregister_commands/3,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd_ctl.hrl").
|
||||
-include("ejabberd_commands.hrl").
|
||||
@@ -353,6 +352,15 @@ format_result(String, {_Name, string}) when is_list(String) ->
|
||||
format_result(Binary, {_Name, string}) when is_binary(Binary) ->
|
||||
io_lib:format("~s", [binary_to_list(Binary)]);
|
||||
|
||||
format_result(Atom, {_Name, string}) when is_atom(Atom) ->
|
||||
io_lib:format("~s", [atom_to_list(Atom)]);
|
||||
|
||||
format_result(Integer, {_Name, string}) when is_integer(Integer) ->
|
||||
io_lib:format("~s", [integer_to_list(Integer)]);
|
||||
|
||||
format_result(Other, {_Name, string}) ->
|
||||
io_lib:format("~p", [Other]);
|
||||
|
||||
format_result(Code, {_Name, rescode}) ->
|
||||
make_status(Code);
|
||||
|
||||
@@ -792,3 +800,7 @@ print(Format, Args) ->
|
||||
%%format_usage_xmlrpc(ArgsDef, ResultDef) ->
|
||||
%% ["aaaa bbb ccc"].
|
||||
|
||||
|
||||
opt_type(ejabberdctl_access_commands) ->
|
||||
fun (V) when is_list(V) -> V end;
|
||||
opt_type(_) -> [ejabberdctl_access_commands].
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
-module(ejabberd_http).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
%% External exports
|
||||
@@ -32,8 +34,7 @@
|
||||
socket_type/0, receive_headers/1, url_encode/1,
|
||||
transform_listen_option/2]).
|
||||
|
||||
%% Callbacks
|
||||
-export([init/2]).
|
||||
-export([init/2, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -56,7 +57,7 @@
|
||||
%% to have the module test_web handle requests with
|
||||
%% paths starting with "/test/module":
|
||||
%%
|
||||
%% {5280, ejabberd_http, [http_poll, web_admin,
|
||||
%% {5280, ejabberd_http, [http_bind, web_admin,
|
||||
%% {request_handlers, [{["test", "module"], mod_test_web}]}]}
|
||||
%%
|
||||
request_handlers = [],
|
||||
@@ -94,14 +95,25 @@ start_link(SockData, Opts) ->
|
||||
init({SockMod, Socket}, Opts) ->
|
||||
TLSEnabled = proplists:get_bool(tls, Opts),
|
||||
TLSOpts1 = lists:filter(fun ({certfile, _}) -> true;
|
||||
({ciphers, _}) -> true;
|
||||
({dhfile, _}) -> true;
|
||||
(_) -> false
|
||||
end,
|
||||
Opts),
|
||||
TLSOpts2 = case proplists:get_bool(tls_compression, Opts) of
|
||||
false -> [compression_none | TLSOpts1];
|
||||
true -> TLSOpts1
|
||||
TLSOpts2 = case lists:keysearch(protocol_options, 1, Opts) of
|
||||
{value, {_, O}} ->
|
||||
[_|ProtocolOptions] = lists:foldl(
|
||||
fun(X, Acc) -> X ++ Acc end, [],
|
||||
[["|" | binary_to_list(Opt)] || Opt <- O, is_binary(Opt)]
|
||||
),
|
||||
[{protocol_options, iolist_to_binary(ProtocolOptions)} | TLSOpts1];
|
||||
_ -> TLSOpts1
|
||||
end,
|
||||
TLSOpts = [verify_none | TLSOpts2],
|
||||
TLSOpts3 = case proplists:get_bool(tls_compression, Opts) of
|
||||
false -> [compression_none | TLSOpts2];
|
||||
true -> TLSOpts2
|
||||
end,
|
||||
TLSOpts = [verify_none | TLSOpts3],
|
||||
{SockMod1, Socket1} = if TLSEnabled ->
|
||||
inet:setopts(Socket, [{recbuf, 8192}]),
|
||||
{ok, TLSSocket} = p1_tls:tcp_to_tls(Socket,
|
||||
@@ -125,10 +137,6 @@ init({SockMod, Socket}, Opts) ->
|
||||
true -> [{[<<"http-bind">>], mod_http_bind}];
|
||||
false -> []
|
||||
end,
|
||||
Poll = case proplists:get_bool(http_poll, Opts) of
|
||||
true -> [{[<<"http-poll">>], ejabberd_http_poll}];
|
||||
false -> []
|
||||
end,
|
||||
XMLRPC = case proplists:get_bool(xmlrpc, Opts) of
|
||||
true -> [{[], ejabberd_xmlrpc}];
|
||||
false -> []
|
||||
@@ -141,7 +149,7 @@ init({SockMod, Socket}, Opts) ->
|
||||
Mod} || {Path, Mod} <- Hs]
|
||||
end, []),
|
||||
RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++
|
||||
Admin ++ Bind ++ Poll ++ XMLRPC,
|
||||
Admin ++ Bind ++ XMLRPC,
|
||||
?DEBUG("S: ~p~n", [RequestHandlers]),
|
||||
|
||||
DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined),
|
||||
@@ -852,7 +860,7 @@ transform_listen_option(web_admin, Opts) ->
|
||||
transform_listen_option(http_bind, Opts) ->
|
||||
[{http_bind, true}|Opts];
|
||||
transform_listen_option(http_poll, Opts) ->
|
||||
[{http_poll, true}|Opts];
|
||||
Opts;
|
||||
transform_listen_option({request_handlers, Hs}, Opts) ->
|
||||
Hs1 = lists:map(
|
||||
fun({PList, Mod}) when is_list(PList) ->
|
||||
@@ -864,3 +872,7 @@ transform_listen_option({request_handlers, Hs}, Opts) ->
|
||||
[{request_handlers, Hs1} | Opts];
|
||||
transform_listen_option(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
|
||||
opt_type(trusted_proxies) ->
|
||||
fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end;
|
||||
opt_type(_) -> [trusted_proxies].
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
-module(ejabberd_http_bind).
|
||||
|
||||
-protocol({xep, 124, '1.11'}).
|
||||
-protocol({xep, 206, '1.4'}).
|
||||
|
||||
-behaviour(gen_fsm).
|
||||
|
||||
%% External exports
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_http_poll.erl
|
||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||
%%% Purpose : HTTP Polling support (XEP-0025)
|
||||
%%% Created : 4 Mar 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2015 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License along
|
||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_http_poll).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(gen_fsm).
|
||||
|
||||
%% External exports
|
||||
-export([start_link/3, init/1, handle_event/3,
|
||||
handle_sync_event/4, code_change/4, handle_info/3,
|
||||
terminate/3, send/2, setopts/2, sockname/1, peername/1,
|
||||
controlling_process/2, close/1, process/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-include("jlib.hrl").
|
||||
|
||||
-include("ejabberd_http.hrl").
|
||||
|
||||
-record(http_poll, {id :: pid() | binary(), pid :: pid()}).
|
||||
|
||||
-type poll_socket() :: #http_poll{}.
|
||||
-export_type([poll_socket/0]).
|
||||
|
||||
-record(state,
|
||||
{id, key, socket, output = [], input = <<"">>,
|
||||
waiting_input = false, last_receiver, http_poll_timeout,
|
||||
timer}).
|
||||
|
||||
%-define(DBGFSM, true).
|
||||
|
||||
-ifdef(DBGFSM).
|
||||
|
||||
-define(FSMOPTS, [{debug, [trace]}]).
|
||||
|
||||
-else.
|
||||
|
||||
-define(FSMOPTS, []).
|
||||
|
||||
-endif.
|
||||
|
||||
-define(HTTP_POLL_TIMEOUT, 300).
|
||||
|
||||
-define(CT,
|
||||
{<<"Content-Type">>, <<"text/xml; charset=utf-8">>}).
|
||||
|
||||
-define(BAD_REQUEST,
|
||||
[?CT, {<<"Set-Cookie">>, <<"ID=-3:0; expires=-1">>}]).
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% API
|
||||
%%%----------------------------------------------------------------------
|
||||
start(ID, Key, IP) ->
|
||||
mnesia:create_table(http_poll,
|
||||
[{ram_copies, [node()]},
|
||||
{attributes, record_info(fields, http_poll)}]),
|
||||
supervisor:start_child(ejabberd_http_poll_sup, [ID, Key, IP]).
|
||||
|
||||
start_link(ID, Key, IP) ->
|
||||
gen_fsm:start_link(?MODULE, [ID, Key, IP], ?FSMOPTS).
|
||||
|
||||
send({http_poll, FsmRef, _IP}, Packet) ->
|
||||
gen_fsm:sync_send_all_state_event(FsmRef,
|
||||
{send, Packet}).
|
||||
|
||||
setopts({http_poll, FsmRef, _IP}, Opts) ->
|
||||
case lists:member({active, once}, Opts) of
|
||||
true ->
|
||||
gen_fsm:send_all_state_event(FsmRef,
|
||||
{activate, self()});
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
sockname(_Socket) -> {ok, {{0, 0, 0, 0}, 0}}.
|
||||
|
||||
peername({http_poll, _FsmRef, IP}) -> {ok, IP}.
|
||||
|
||||
controlling_process(_Socket, _Pid) -> ok.
|
||||
|
||||
close({http_poll, FsmRef, _IP}) ->
|
||||
catch gen_fsm:sync_send_all_state_event(FsmRef, close).
|
||||
|
||||
process([],
|
||||
#request{data = Data, ip = IP} = _Request) ->
|
||||
case catch parse_request(Data) of
|
||||
{ok, ID1, Key, NewKey, Packet} ->
|
||||
ID = if
|
||||
(ID1 == <<"0">>) or (ID1 == <<"mobile">>) ->
|
||||
NewID = p1_sha:sha(term_to_binary({now(), make_ref()})),
|
||||
{ok, Pid} = start(NewID, <<"">>, IP),
|
||||
mnesia:transaction(
|
||||
fun() ->
|
||||
mnesia:write(#http_poll{id = NewID, pid = Pid})
|
||||
end),
|
||||
NewID;
|
||||
true ->
|
||||
ID1
|
||||
end,
|
||||
case http_put(ID, Key, NewKey, Packet) of
|
||||
{error, not_exists} ->
|
||||
{200, ?BAD_REQUEST, <<"">>};
|
||||
{error, bad_key} ->
|
||||
{200, ?BAD_REQUEST, <<"">>};
|
||||
ok ->
|
||||
receive
|
||||
after 100 -> ok
|
||||
end,
|
||||
case http_get(ID) of
|
||||
{error, not_exists} ->
|
||||
{200, ?BAD_REQUEST, <<"">>};
|
||||
{ok, OutPacket} ->
|
||||
if
|
||||
ID == ID1 ->
|
||||
Cookie = <<"ID=", ID/binary, "; expires=-1">>,
|
||||
{200, [?CT, {<<"Set-Cookie">>, Cookie}],
|
||||
OutPacket};
|
||||
ID1 == <<"mobile">> ->
|
||||
{200, [?CT], [ID, $\n, OutPacket]};
|
||||
true ->
|
||||
Cookie = <<"ID=", ID/binary, "; expires=-1">>,
|
||||
{200, [?CT, {<<"Set-Cookie">>, Cookie}],
|
||||
OutPacket}
|
||||
end
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
HumanHTMLxmlel = get_human_html_xmlel(),
|
||||
{200, [?CT, {<<"Set-Cookie">>, <<"ID=-2:0; expires=-1">>}], HumanHTMLxmlel}
|
||||
end;
|
||||
process(_, _Request) ->
|
||||
{400, [],
|
||||
#xmlel{name = <<"h1">>, attrs = [],
|
||||
children = [{xmlcdata, <<"400 Bad Request">>}]}}.
|
||||
|
||||
%% Code copied from mod_http_bind.erl and customized
|
||||
get_human_html_xmlel() ->
|
||||
Heading = <<"ejabberd ",
|
||||
(iolist_to_binary(atom_to_list(?MODULE)))/binary>>,
|
||||
#xmlel{name = <<"html">>,
|
||||
attrs =
|
||||
[{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}],
|
||||
children =
|
||||
[#xmlel{name = <<"head">>, attrs = [],
|
||||
children =
|
||||
[#xmlel{name = <<"title">>, attrs = [],
|
||||
children = [{xmlcdata, Heading}]}]},
|
||||
#xmlel{name = <<"body">>, attrs = [],
|
||||
children =
|
||||
[#xmlel{name = <<"h1">>, attrs = [],
|
||||
children = [{xmlcdata, Heading}]},
|
||||
#xmlel{name = <<"p">>, attrs = [],
|
||||
children =
|
||||
[{xmlcdata, <<"An implementation of ">>},
|
||||
#xmlel{name = <<"a">>,
|
||||
attrs =
|
||||
[{<<"href">>,
|
||||
<<"http://xmpp.org/extensions/xep-0025.html">>}],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
<<"Jabber HTTP Polling (XEP-0025)">>}]}]},
|
||||
#xmlel{name = <<"p">>, attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
<<"This web page is only informative. To "
|
||||
"use HTTP-Poll you need a Jabber/XMPP "
|
||||
"client that supports it.">>}]}]}]}.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Callback functions from gen_fsm
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: init/1
|
||||
%% Returns: {ok, StateName, StateData} |
|
||||
%% {ok, StateName, StateData, Timeout} |
|
||||
%% ignore |
|
||||
%% {stop, StopReason}
|
||||
%%----------------------------------------------------------------------
|
||||
init([ID, Key, IP]) ->
|
||||
?INFO_MSG("started: ~p", [{ID, Key, IP}]),
|
||||
Opts = ejabberd_c2s_config:get_c2s_limits(),
|
||||
HTTPPollTimeout = ejabberd_config:get_option(
|
||||
{http_poll_timeout, ?MYNAME},
|
||||
fun(I) when is_integer(I), I>0 -> I end,
|
||||
?HTTP_POLL_TIMEOUT) * 1000,
|
||||
Socket = {http_poll, self(), IP},
|
||||
ejabberd_socket:start(ejabberd_c2s, ?MODULE, Socket,
|
||||
Opts),
|
||||
Timer = erlang:start_timer(HTTPPollTimeout, self(), []),
|
||||
{ok, loop,
|
||||
#state{id = ID, key = Key, socket = Socket,
|
||||
http_poll_timeout = HTTPPollTimeout, timer = Timer}}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: StateName/2
|
||||
%% Returns: {next_state, NextStateName, NextStateData} |
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData}
|
||||
%% {stop, Reason, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: StateName/3
|
||||
%% Returns: {next_state, NextStateName, NextStateData} |
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {reply, Reply, NextStateName, NextStateData} |
|
||||
%% {reply, Reply, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData} |
|
||||
%% {stop, Reason, Reply, NewStateData}
|
||||
%% {stop, Reason, Reply, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
%state_name(Event, From, StateData) ->
|
||||
% Reply = ok,
|
||||
% {reply, Reply, state_name, StateData}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: handle_event/3
|
||||
%% Returns: {next_state, NextStateName, NextStateData} |
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_event({activate, From}, StateName, StateData) ->
|
||||
case StateData#state.input of
|
||||
<<"">> ->
|
||||
{next_state, StateName,
|
||||
StateData#state{waiting_input = {From, ok}}};
|
||||
Input ->
|
||||
Receiver = From,
|
||||
Receiver !
|
||||
{tcp, StateData#state.socket, Input},
|
||||
{next_state, StateName,
|
||||
StateData#state{input = <<"">>, waiting_input = false,
|
||||
last_receiver = Receiver}}
|
||||
end;
|
||||
handle_event(_Event, StateName, StateData) ->
|
||||
{next_state, StateName, StateData}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: handle_sync_event/4
|
||||
%% Returns: {next_state, NextStateName, NextStateData} |
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {reply, Reply, NextStateName, NextStateData} |
|
||||
%% {reply, Reply, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData} |
|
||||
%% {stop, Reason, Reply, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_sync_event({send, Packet}, _From, StateName,
|
||||
StateData) ->
|
||||
Packet2 = iolist_to_binary(Packet),
|
||||
Output = StateData#state.output ++ [Packet2],
|
||||
Reply = ok,
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{output = Output}};
|
||||
handle_sync_event(stop, _From, _StateName, StateData) ->
|
||||
Reply = ok, {stop, normal, Reply, StateData};
|
||||
handle_sync_event({http_put, Key, NewKey, Packet},
|
||||
_From, StateName, StateData) ->
|
||||
Allow = case StateData#state.key of
|
||||
<<"">> -> true;
|
||||
OldKey ->
|
||||
NextKey = jlib:encode_base64((p1_sha:sha1(Key))),
|
||||
if OldKey == NextKey -> true;
|
||||
true -> false
|
||||
end
|
||||
end,
|
||||
if Allow ->
|
||||
case StateData#state.waiting_input of
|
||||
false ->
|
||||
Input = <<(StateData#state.input)/binary, Packet/binary>>,
|
||||
Reply = ok,
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{input = Input, key = NewKey}};
|
||||
{Receiver, _Tag} ->
|
||||
Receiver !
|
||||
{tcp, StateData#state.socket, iolist_to_binary(Packet)},
|
||||
cancel_timer(StateData#state.timer),
|
||||
Timer =
|
||||
erlang:start_timer(StateData#state.http_poll_timeout,
|
||||
self(), []),
|
||||
Reply = ok,
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{waiting_input = false,
|
||||
last_receiver = Receiver, key = NewKey,
|
||||
timer = Timer}}
|
||||
end;
|
||||
true ->
|
||||
Reply = {error, bad_key},
|
||||
{reply, Reply, StateName, StateData}
|
||||
end;
|
||||
handle_sync_event(http_get, _From, StateName,
|
||||
StateData) ->
|
||||
Reply = {ok, StateData#state.output},
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{output = []}};
|
||||
handle_sync_event(_Event, _From, StateName,
|
||||
StateData) ->
|
||||
Reply = ok, {reply, Reply, StateName, StateData}.
|
||||
|
||||
code_change(_OldVsn, StateName, StateData, _Extra) ->
|
||||
{ok, StateName, StateData}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: handle_info/3
|
||||
%% Returns: {next_state, NextStateName, NextStateData} |
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_info({timeout, Timer, _}, _StateName,
|
||||
#state{timer = Timer} = StateData) ->
|
||||
{stop, normal, StateData};
|
||||
handle_info(_, StateName, StateData) ->
|
||||
{next_state, StateName, StateData}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: terminate/3
|
||||
%% Purpose: Shutdown the fsm
|
||||
%% Returns: any
|
||||
%%----------------------------------------------------------------------
|
||||
terminate(_Reason, _StateName, StateData) ->
|
||||
mnesia:transaction(
|
||||
fun() ->
|
||||
mnesia:delete({http_poll, StateData#state.id})
|
||||
end),
|
||||
case StateData#state.waiting_input of
|
||||
false ->
|
||||
case StateData#state.last_receiver of
|
||||
undefined -> ok;
|
||||
Receiver ->
|
||||
Receiver ! {tcp_closed, StateData#state.socket}
|
||||
end;
|
||||
{Receiver, _Tag} ->
|
||||
Receiver ! {tcp_closed, StateData#state.socket}
|
||||
end,
|
||||
catch resend_messages(StateData#state.output),
|
||||
ok.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
http_put(ID, Key, NewKey, Packet) ->
|
||||
case mnesia:dirty_read({http_poll, ID}) of
|
||||
[] ->
|
||||
{error, not_exists};
|
||||
[#http_poll{pid = FsmRef}] ->
|
||||
gen_fsm:sync_send_all_state_event(
|
||||
FsmRef, {http_put, Key, NewKey, Packet})
|
||||
end.
|
||||
|
||||
http_get(ID) ->
|
||||
case mnesia:dirty_read({http_poll, ID}) of
|
||||
[] ->
|
||||
{error, not_exists};
|
||||
[#http_poll{pid = FsmRef}] ->
|
||||
gen_fsm:sync_send_all_state_event(FsmRef, http_get)
|
||||
end.
|
||||
|
||||
parse_request(Data) ->
|
||||
Comma = str:chr(Data, $,),
|
||||
Header = str:substr(Data, 1, Comma - 1),
|
||||
Packet = str:substr(Data, Comma + 1, byte_size(Data)),
|
||||
{ID, Key, NewKey} = case str:tokens(Header, <<";">>) of
|
||||
[ID1] -> {ID1, <<"">>, <<"">>};
|
||||
[ID1, Key1] -> {ID1, Key1, Key1};
|
||||
[ID1, Key1, NewKey1] -> {ID1, Key1, NewKey1}
|
||||
end,
|
||||
{ok, ID, Key, NewKey, Packet}.
|
||||
|
||||
cancel_timer(Timer) ->
|
||||
erlang:cancel_timer(Timer),
|
||||
receive {timeout, Timer, _} -> ok after 0 -> ok end.
|
||||
|
||||
%% Resend the polled messages
|
||||
resend_messages(Messages) ->
|
||||
%% This function is used to resend messages that have been polled but not
|
||||
%% delivered.
|
||||
lists:foreach(fun (Packet) -> resend_message(Packet)
|
||||
end,
|
||||
Messages).
|
||||
|
||||
resend_message(Packet) ->
|
||||
#xmlel{name = Name} = ParsedPacket =
|
||||
xml_stream:parse_element(Packet),
|
||||
if Name == <<"iq">>;
|
||||
Name == <<"message">>;
|
||||
Name == <<"presence">> ->
|
||||
From = get_jid(<<"from">>, ParsedPacket),
|
||||
To = get_jid(<<"to">>, ParsedPacket),
|
||||
?DEBUG("Resend ~p ~p ~p~n", [From, To, ParsedPacket]),
|
||||
ejabberd_router:route(From, To, ParsedPacket);
|
||||
true -> ok
|
||||
end.
|
||||
|
||||
%% Type can be "from" or "to"
|
||||
%% Parsed packet is a parsed Jabber packet.
|
||||
get_jid(Type, ParsedPacket) ->
|
||||
case xml:get_tag_attr(Type, ParsedPacket) of
|
||||
{value, StringJid} -> jlib:string_to_jid(StringJid);
|
||||
false -> jlib:make_jid(<<"">>, <<"">>, <<"">>)
|
||||
end.
|
||||
@@ -24,16 +24,17 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
-module(ejabberd_http_ws).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('ecestari@process-one.net').
|
||||
|
||||
-behaviour(gen_fsm).
|
||||
|
||||
% External exports
|
||||
-export([start/1, start_link/1, init/1, handle_event/3,
|
||||
handle_sync_event/4, code_change/4, handle_info/3,
|
||||
terminate/3, send_xml/2, setopts/2, sockname/1, peername/1,
|
||||
controlling_process/2, become_controller/2, close/1,
|
||||
socket_handoff/6]).
|
||||
terminate/3, send_xml/2, setopts/2, sockname/1,
|
||||
peername/1, controlling_process/2, become_controller/2,
|
||||
close/1, socket_handoff/6, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -138,7 +139,11 @@ handle_event({activate, From}, StateName, StateData) ->
|
||||
StateData#state{waiting_input = From}};
|
||||
Input ->
|
||||
Receiver = From,
|
||||
Receiver ! {tcp, StateData#state.socket, Input},
|
||||
lists:foreach(fun(I) when is_binary(I)->
|
||||
Receiver ! {tcp, StateData#state.socket, I};
|
||||
(I2) ->
|
||||
Receiver ! {tcp, StateData#state.socket, [I2]}
|
||||
end, Input),
|
||||
{next_state, StateName,
|
||||
StateData#state{input = [], waiting_input = false,
|
||||
last_receiver = Receiver}}
|
||||
@@ -187,7 +192,19 @@ handle_sync_event({send_xml, Packet}, _From, StateName,
|
||||
skip ->
|
||||
ok
|
||||
end,
|
||||
{reply, ok, StateName, StateData};
|
||||
SN2 = case Packet2 of
|
||||
{xmlstreamelement, #xmlel{name = <<"close">>}} ->
|
||||
stream_end_sent;
|
||||
_ ->
|
||||
StateName
|
||||
end,
|
||||
{reply, ok, SN2, StateData};
|
||||
handle_sync_event(close, _From, StateName, #state{ws = {_, WsPid}, rfc_compilant = true} = StateData)
|
||||
when StateName /= stream_end_sent ->
|
||||
Close = #xmlel{name = <<"close">>,
|
||||
attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}]},
|
||||
WsPid ! {send, xml:element_to_binary(Close)},
|
||||
{stop, normal, StateData};
|
||||
handle_sync_event(close, _From, _StateName, StateData) ->
|
||||
{stop, normal, StateData}.
|
||||
|
||||
@@ -197,7 +214,7 @@ handle_info({received, Packet}, StateName, StateDataI) ->
|
||||
{StateData, Parsed} = parse(StateDataI, Packet),
|
||||
SD = case StateData#state.waiting_input of
|
||||
false ->
|
||||
Input = StateData#state.input ++ Parsed,
|
||||
Input = StateData#state.input ++ if is_binary(Parsed) -> [Parsed]; true -> Parsed end,
|
||||
StateData#state{input = Input};
|
||||
Receiver ->
|
||||
Receiver ! {tcp, StateData#state.socket, Parsed},
|
||||
@@ -337,3 +354,10 @@ parsed_items(List) ->
|
||||
after 0 ->
|
||||
lists:reverse(List)
|
||||
end.
|
||||
|
||||
opt_type(websocket_ping_interval) ->
|
||||
fun (I) when is_integer(I), I >= 0 -> I end;
|
||||
opt_type(websocket_timeout) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(_) ->
|
||||
[websocket_ping_interval, websocket_timeout].
|
||||
|
||||
@@ -24,20 +24,15 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_listener).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start_link/0, init/1, start/3,
|
||||
init/3,
|
||||
start_listeners/0,
|
||||
start_listener/3,
|
||||
stop_listeners/0,
|
||||
stop_listener/2,
|
||||
parse_listener_portip/2,
|
||||
add_listener/3,
|
||||
delete_listener/2,
|
||||
transform_options/1,
|
||||
validate_cfg/1
|
||||
]).
|
||||
-export([start_link/0, init/1, start/3, init/3,
|
||||
start_listeners/0, start_listener/3, stop_listeners/0,
|
||||
stop_listener/2, parse_listener_portip/2,
|
||||
add_listener/3, delete_listener/2, transform_options/1,
|
||||
validate_cfg/1, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -195,20 +190,15 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
|
||||
ets:delete(listen_sockets, Port),
|
||||
ListenSocket;
|
||||
_ ->
|
||||
SockOpts2 = try erlang:system_info(otp_release) >= "R13B" of
|
||||
true -> [{send_timeout_close, true} | SockOpts];
|
||||
false -> SockOpts
|
||||
catch
|
||||
_:_ -> []
|
||||
end,
|
||||
Res = gen_tcp:listen(Port, [binary,
|
||||
{packet, 0},
|
||||
{active, false},
|
||||
{reuseaddr, true},
|
||||
{nodelay, true},
|
||||
{send_timeout, ?TCP_SEND_TIMEOUT},
|
||||
{send_timeout_close, true},
|
||||
{keepalive, true} |
|
||||
SockOpts2]),
|
||||
SockOpts]),
|
||||
case Res of
|
||||
{ok, ListenSocket} ->
|
||||
ListenSocket;
|
||||
@@ -307,7 +297,7 @@ accept(ListenSocket, Module, Opts) ->
|
||||
case {inet:sockname(Socket), inet:peername(Socket)} of
|
||||
{{ok, {Addr, Port}}, {ok, {PAddr, PPort}}} ->
|
||||
?INFO_MSG("(~w) Accepted connection ~s:~p -> ~s:~p",
|
||||
[Socket, inet_parse:ntoa(PAddr), PPort,
|
||||
[Socket, ejabberd_config:may_hide_data(inet_parse:ntoa(PAddr)), PPort,
|
||||
inet_parse:ntoa(Addr), Port]);
|
||||
_ ->
|
||||
ok
|
||||
@@ -546,7 +536,7 @@ normalize_proto(UnknownProto) ->
|
||||
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) ->
|
||||
ReasonT = case Reason of
|
||||
eaddrnotavail ->
|
||||
"IP address not available: " ++ IPS;
|
||||
"IP address not available: " ++ binary_to_list(IPS);
|
||||
eaddrinuse ->
|
||||
"IP address and port number already used: "
|
||||
++binary_to_list(IPS)++" "++integer_to_list(Port);
|
||||
@@ -665,3 +655,6 @@ prepare_mod(sip) ->
|
||||
esip_socket;
|
||||
prepare_mod(Mod) when is_atom(Mod) ->
|
||||
Mod.
|
||||
|
||||
opt_type(listen) -> fun validate_cfg/1;
|
||||
opt_type(_) -> [listen].
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_logger).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
%% API
|
||||
-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0]).
|
||||
-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
@@ -46,8 +48,10 @@
|
||||
%% If not defined it checks the environment variable EJABBERD_LOG_PATH.
|
||||
%% And if that one is neither defined, returns the default value:
|
||||
%% "ejabberd.log" in current directory.
|
||||
%% Note: If the directory where to place the ejabberd log file to not exist,
|
||||
%% it is not created and no log file will be generated.
|
||||
get_log_path() ->
|
||||
case application:get_env(ejabberd, log_path) of
|
||||
case ejabberd_config:env_binary_to_list(ejabberd, log_path) of
|
||||
{ok, Path} ->
|
||||
Path;
|
||||
undefined ->
|
||||
@@ -59,6 +63,17 @@ get_log_path() ->
|
||||
end
|
||||
end.
|
||||
|
||||
opt_type(log_rotate_date) ->
|
||||
fun(S) -> binary_to_list(iolist_to_binary(S)) end;
|
||||
opt_type(log_rotate_size) ->
|
||||
fun(I) when is_integer(I), I >= 0 -> I end;
|
||||
opt_type(log_rotate_count) ->
|
||||
fun(I) when is_integer(I), I >= 0 -> I end;
|
||||
opt_type(log_rate_limit) ->
|
||||
fun(I) when is_integer(I), I >= 0 -> I end;
|
||||
opt_type(_) ->
|
||||
[log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit].
|
||||
|
||||
-ifdef(LAGER).
|
||||
|
||||
get_integer_env(Name, Default) ->
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_node_groups).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(gen_server).
|
||||
@@ -35,9 +37,8 @@
|
||||
get_members/1,
|
||||
get_closest_node/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
handle_info/2, terminate/2, code_change/3, opt_type/1]).
|
||||
|
||||
-define(PG2, pg2).
|
||||
|
||||
@@ -163,3 +164,10 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%%--------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
opt_type(node_type) ->
|
||||
fun (frontend) -> frontend;
|
||||
(backend) -> backend;
|
||||
(generic) -> generic
|
||||
end;
|
||||
opt_type(_) -> [node_type].
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
-module(ejabberd_odbc).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-define(GEN_FSM, p1_fsm).
|
||||
@@ -40,6 +42,8 @@
|
||||
escape/1,
|
||||
escape_like/1,
|
||||
to_bool/1,
|
||||
sqlite_db/1,
|
||||
sqlite_file/1,
|
||||
encode_term/1,
|
||||
decode_term/1,
|
||||
keep_alive/1]).
|
||||
@@ -49,16 +53,16 @@
|
||||
handle_info/3, terminate/3, print_state/1,
|
||||
code_change/4]).
|
||||
|
||||
%% gen_fsm states
|
||||
-export([connecting/2, connecting/3,
|
||||
session_established/2, session_established/3]).
|
||||
session_established/2, session_established/3,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-record(state,
|
||||
{db_ref = self() :: pid(),
|
||||
db_type = odbc :: pgsql | mysql | odbc,
|
||||
db_type = odbc :: pgsql | mysql | sqlite | odbc,
|
||||
start_interval = 0 :: non_neg_integer(),
|
||||
host = <<"">> :: binary(),
|
||||
max_pending_requests_len :: non_neg_integer(),
|
||||
@@ -191,7 +195,8 @@ to_bool(_) -> false.
|
||||
|
||||
encode_term(Term) ->
|
||||
escape(list_to_binary(
|
||||
erl_prettypr:format(erl_syntax:abstract(Term)))).
|
||||
erl_prettypr:format(erl_syntax:abstract(Term),
|
||||
[{paper, 65535}, {ribbon, 65535}]))).
|
||||
|
||||
decode_term(Bin) ->
|
||||
Str = binary_to_list(<<Bin/binary, ".">>),
|
||||
@@ -199,6 +204,22 @@ decode_term(Bin) ->
|
||||
{ok, Term} = erl_parse:parse_term(Tokens),
|
||||
Term.
|
||||
|
||||
-spec sqlite_db(binary()) -> atom().
|
||||
sqlite_db(Host) ->
|
||||
list_to_atom("ejabberd_sqlite_" ++ binary_to_list(Host)).
|
||||
|
||||
-spec sqlite_file(binary()) -> string().
|
||||
sqlite_file(Host) ->
|
||||
case ejabberd_config:get_option({odbc_database, Host},
|
||||
fun iolist_to_binary/1) of
|
||||
undefined ->
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
filename:join([Cwd, "sqlite", atom_to_list(node()),
|
||||
binary_to_list(Host), "ejabberd.db"]);
|
||||
File ->
|
||||
binary_to_list(File)
|
||||
end.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Callback functions from gen_fsm
|
||||
%%%----------------------------------------------------------------------
|
||||
@@ -224,7 +245,8 @@ init([Host, StartInterval]) ->
|
||||
connecting(connect, #state{host = Host} = State) ->
|
||||
ConnectRes = case db_opts(Host) of
|
||||
[mysql | Args] -> apply(fun mysql_connect/5, Args);
|
||||
[pgsql | Args] -> apply(fun pgsql_connect/5, Args);
|
||||
[pgsql | Args] -> apply(fun pgsql_connect/5, Args);
|
||||
[sqlite | Args] -> apply(fun sqlite_connect/1, Args);
|
||||
[odbc | Args] -> apply(fun odbc_connect/1, Args)
|
||||
end,
|
||||
{_, PendingRequests} = State#state.pending_requests,
|
||||
@@ -327,8 +349,9 @@ handle_info(Info, StateName, State) ->
|
||||
terminate(_Reason, _StateName, State) ->
|
||||
ejabberd_odbc_sup:remove_pid(State#state.host, self()),
|
||||
case State#state.db_type of
|
||||
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
|
||||
_ -> ok
|
||||
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
|
||||
sqlite -> catch sqlite3:close(sqlite_db(State#state.host));
|
||||
_ -> ok
|
||||
end,
|
||||
ok.
|
||||
|
||||
@@ -456,7 +479,10 @@ sql_query_internal(Query) ->
|
||||
[{timeout, (?TRANSACTION_TIMEOUT) - 1000},
|
||||
{result_type, binary}])),
|
||||
%% ?INFO_MSG("MySQL, Received result~n~p~n", [R]),
|
||||
R
|
||||
R;
|
||||
sqlite ->
|
||||
Host = State#state.host,
|
||||
sqlite_to_odbc(Host, sqlite3:sql_exec(sqlite_db(Host), Query))
|
||||
end,
|
||||
case Res of
|
||||
{error, <<"No SQL-driver information available.">>} ->
|
||||
@@ -486,7 +512,49 @@ abort_on_driver_error(Reply, From) ->
|
||||
%% Open an ODBC database connection
|
||||
odbc_connect(SQLServer) ->
|
||||
ejabberd:start_app(odbc),
|
||||
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}]).
|
||||
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off},
|
||||
{binary_strings, on}]).
|
||||
|
||||
%% == Native SQLite code
|
||||
|
||||
%% part of init/1
|
||||
%% Open a database connection to SQLite
|
||||
|
||||
sqlite_connect(Host) ->
|
||||
File = sqlite_file(Host),
|
||||
case filelib:ensure_dir(File) of
|
||||
ok ->
|
||||
case sqlite3:open(sqlite_db(Host), [{file, File}]) of
|
||||
{ok, Ref} ->
|
||||
sqlite3:sql_exec(
|
||||
sqlite_db(Host), "pragma foreign_keys = on"),
|
||||
{ok, Ref};
|
||||
{error, {already_started, Ref}} ->
|
||||
{ok, Ref};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
Err ->
|
||||
Err
|
||||
end.
|
||||
|
||||
%% Convert SQLite query result to Erlang ODBC result formalism
|
||||
sqlite_to_odbc(Host, ok) ->
|
||||
{updated, sqlite3:changes(sqlite_db(Host))};
|
||||
sqlite_to_odbc(Host, {rowid, _}) ->
|
||||
{updated, sqlite3:changes(sqlite_db(Host))};
|
||||
sqlite_to_odbc(_Host, [{columns, Columns}, {rows, TRows}]) ->
|
||||
Rows = [lists:map(
|
||||
fun(I) when is_integer(I) ->
|
||||
jlib:integer_to_binary(I);
|
||||
(B) ->
|
||||
B
|
||||
end, tuple_to_list(Row)) || Row <- TRows],
|
||||
{selected, [list_to_binary(C) || C <- Columns], Rows};
|
||||
sqlite_to_odbc(_Host, {error, _Code, Reason}) ->
|
||||
{error, Reason};
|
||||
sqlite_to_odbc(_Host, _) ->
|
||||
{updated, undefined}.
|
||||
|
||||
%% == Native PostgreSQL code
|
||||
|
||||
@@ -570,7 +638,7 @@ mysql_item_to_odbc(Columns, Recs) ->
|
||||
{selected, [element(2, Column) || Column <- Columns], Recs}.
|
||||
|
||||
to_odbc({selected, Columns, Recs}) ->
|
||||
{selected, Columns, [tuple_to_list(Rec) || Rec <- Recs]};
|
||||
{selected, [list_to_binary(Column) || Column <- Columns], [tuple_to_list(Rec) || Rec <- Recs]};
|
||||
to_odbc(Res) ->
|
||||
Res.
|
||||
|
||||
@@ -585,6 +653,7 @@ db_opts(Host) ->
|
||||
Type = ejabberd_config:get_option({odbc_type, Host},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, odbc),
|
||||
Server = ejabberd_config:get_option({odbc_server, Host},
|
||||
@@ -593,6 +662,8 @@ db_opts(Host) ->
|
||||
case Type of
|
||||
odbc ->
|
||||
[odbc, Server];
|
||||
sqlite ->
|
||||
[sqlite, Host];
|
||||
_ ->
|
||||
Port = ejabberd_config:get_option(
|
||||
{odbc_port, Host},
|
||||
@@ -623,3 +694,24 @@ fsm_limit_opts() ->
|
||||
N when is_integer(N) -> [{max_queue, N}];
|
||||
_ -> []
|
||||
end.
|
||||
|
||||
opt_type(max_fsm_queue) ->
|
||||
fun (N) when is_integer(N), N > 0 -> N end;
|
||||
opt_type(odbc_database) -> fun iolist_to_binary/1;
|
||||
opt_type(odbc_keepalive_interval) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(odbc_password) -> fun iolist_to_binary/1;
|
||||
opt_type(odbc_port) ->
|
||||
fun (P) when is_integer(P), P > 0, P < 65536 -> P end;
|
||||
opt_type(odbc_server) -> fun iolist_to_binary/1;
|
||||
opt_type(odbc_type) ->
|
||||
fun (mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end;
|
||||
opt_type(odbc_username) -> fun iolist_to_binary/1;
|
||||
opt_type(_) ->
|
||||
[max_fsm_queue, odbc_database, odbc_keepalive_interval,
|
||||
odbc_password, odbc_port, odbc_server, odbc_type,
|
||||
odbc_username].
|
||||
|
||||
@@ -25,11 +25,13 @@
|
||||
|
||||
-module(ejabberd_odbc_sup).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
%% API
|
||||
-export([start_link/1, init/1, add_pid/2, remove_pid/2,
|
||||
get_pids/1, get_random_pid/1, transform_options/1]).
|
||||
get_pids/1, get_random_pid/1, transform_options/1,
|
||||
opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -67,6 +69,19 @@ init([Host]) ->
|
||||
{odbc_start_interval, Host},
|
||||
fun(I) when is_integer(I), I>0 -> I end,
|
||||
?DEFAULT_ODBC_START_INTERVAL),
|
||||
Type = ejabberd_config:get_option({odbc_type, Host},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, odbc),
|
||||
case Type of
|
||||
sqlite ->
|
||||
check_sqlite_db(Host);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
|
||||
{ok,
|
||||
{{one_for_one, PoolSize * 10, 1},
|
||||
lists:map(fun (I) ->
|
||||
@@ -113,5 +128,95 @@ transform_options({odbc_server, {mysql, Server, DB, User, Pass}}, Opts) ->
|
||||
transform_options({odbc_server, {mysql, Server, ?MYSQL_PORT, DB, User, Pass}}, Opts);
|
||||
transform_options({odbc_server, {pgsql, Server, DB, User, Pass}}, Opts) ->
|
||||
transform_options({odbc_server, {pgsql, Server, ?PGSQL_PORT, DB, User, Pass}}, Opts);
|
||||
transform_options({odbc_server, {sqlite, DB}}, Opts) ->
|
||||
transform_options({odbc_server, {sqlite, DB}}, Opts);
|
||||
transform_options(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
|
||||
check_sqlite_db(Host) ->
|
||||
DB = ejabberd_odbc:sqlite_db(Host),
|
||||
File = ejabberd_odbc:sqlite_file(Host),
|
||||
Ret = case filelib:ensure_dir(File) of
|
||||
ok ->
|
||||
case sqlite3:open(DB, [{file, File}]) of
|
||||
{ok, _Ref} -> ok;
|
||||
{error, {already_started, _Ref}} -> ok;
|
||||
{error, R} -> {error, R}
|
||||
end;
|
||||
Err ->
|
||||
Err
|
||||
end,
|
||||
case Ret of
|
||||
ok ->
|
||||
sqlite3:sql_exec(DB, "pragma foreign_keys = on"),
|
||||
case sqlite3:list_tables(DB) of
|
||||
[] ->
|
||||
create_sqlite_tables(DB),
|
||||
sqlite3:close(DB),
|
||||
ok;
|
||||
[_H | _] ->
|
||||
ok
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?INFO_MSG("Failed open sqlite database, reason ~p", [Reason])
|
||||
end.
|
||||
|
||||
create_sqlite_tables(DB) ->
|
||||
SqlDir = case code:priv_dir(ejabberd) of
|
||||
{error, _} ->
|
||||
?SQL_DIR;
|
||||
PrivDir ->
|
||||
filename:join(PrivDir, "sql")
|
||||
end,
|
||||
File = filename:join(SqlDir, "lite.sql"),
|
||||
case file:open(File, [read, binary]) of
|
||||
{ok, Fd} ->
|
||||
Qs = read_lines(Fd, File, []),
|
||||
ok = sqlite3:sql_exec(DB, "begin"),
|
||||
[ok = sqlite3:sql_exec(DB, Q) || Q <- Qs],
|
||||
ok = sqlite3:sql_exec(DB, "commit");
|
||||
{error, Reason} ->
|
||||
?INFO_MSG("Failed to read SQLite schema file: ~s",
|
||||
[file:format_error(Reason)])
|
||||
end.
|
||||
|
||||
read_lines(Fd, File, Acc) ->
|
||||
case file:read_line(Fd) of
|
||||
{ok, Line} ->
|
||||
NewAcc = case str:strip(str:strip(Line, both, $\r), both, $\n) of
|
||||
<<"--", _/binary>> ->
|
||||
Acc;
|
||||
<<>> ->
|
||||
Acc;
|
||||
_ ->
|
||||
[Line|Acc]
|
||||
end,
|
||||
read_lines(Fd, File, NewAcc);
|
||||
eof ->
|
||||
QueryList = str:tokens(list_to_binary(lists:reverse(Acc)), <<";">>),
|
||||
lists:flatmap(
|
||||
fun(Query) ->
|
||||
case str:strip(str:strip(Query, both, $\r), both, $\n) of
|
||||
<<>> ->
|
||||
[];
|
||||
Q ->
|
||||
[<<Q/binary, $;>>]
|
||||
end
|
||||
end, QueryList);
|
||||
{error, _} = Err ->
|
||||
?ERROR_MSG("Failed read from lite.sql, reason: ~p", [Err]),
|
||||
[]
|
||||
end.
|
||||
|
||||
opt_type(odbc_pool_size) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(odbc_start_interval) ->
|
||||
fun (I) when is_integer(I), I > 0 -> I end;
|
||||
opt_type(odbc_type) ->
|
||||
fun (mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end;
|
||||
opt_type(_) ->
|
||||
[odbc_pool_size, odbc_start_interval, odbc_type].
|
||||
|
||||
@@ -38,8 +38,12 @@
|
||||
|
||||
-module(ejabberd_piefxis).
|
||||
|
||||
%% API
|
||||
-export([import_file/1, export_server/1, export_host/2]).
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-protocol({xep, 227, '1.0'}).
|
||||
|
||||
-export([import_file/1, export_server/1, export_host/2,
|
||||
opt_type/1]).
|
||||
|
||||
-define(CHUNK_SIZE, 1024*20). %20k
|
||||
|
||||
@@ -238,7 +242,17 @@ export_users([], _Server, _Fd) ->
|
||||
%%%==================================
|
||||
%%%% Utilities
|
||||
export_user(User, Server, Fd) ->
|
||||
Pass = ejabberd_auth:get_password_s(User, Server),
|
||||
Password = ejabberd_auth:get_password_s(User, Server),
|
||||
LServer = jlib:nameprep(Server),
|
||||
PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain),
|
||||
Pass = case Password of
|
||||
{_,_,_,_} ->
|
||||
case PasswordFormat of
|
||||
scram -> format_scram_password(Password);
|
||||
_ -> <<"">>
|
||||
end;
|
||||
_ -> Password
|
||||
end,
|
||||
Els = get_offline(User, Server) ++
|
||||
get_vcard(User, Server) ++
|
||||
get_privacy(User, Server) ++
|
||||
@@ -250,6 +264,23 @@ export_user(User, Server, Fd) ->
|
||||
{<<"password">>, Pass}],
|
||||
children = Els})).
|
||||
|
||||
format_scram_password({StoredKey, ServerKey, Salt, IterationCount}) ->
|
||||
StoredKeyB64 = base64:encode(StoredKey),
|
||||
ServerKeyB64 = base64:encode(ServerKey),
|
||||
SaltB64 = base64:encode(Salt),
|
||||
IterationCountBin = list_to_binary(integer_to_list(IterationCount)),
|
||||
<<"scram:", StoredKeyB64/binary, ",", ServerKeyB64/binary, ",", SaltB64/binary, ",", IterationCountBin/binary>>.
|
||||
|
||||
parse_scram_password(PassData) ->
|
||||
Split = binary:split(PassData, <<",">>, [global]),
|
||||
[StoredKeyB64, ServerKeyB64, SaltB64, IterationCountBin] = Split,
|
||||
#scram{
|
||||
storedkey = StoredKeyB64,
|
||||
serverkey = ServerKeyB64,
|
||||
salt = SaltB64,
|
||||
iterationcount = list_to_integer(binary_to_list(IterationCountBin))
|
||||
}.
|
||||
|
||||
get_vcard(User, Server) ->
|
||||
JID = jlib:make_jid(User, Server, <<>>),
|
||||
case mod_vcard:process_sm_iq(JID, JID, #iq{type = get}) of
|
||||
@@ -457,7 +488,18 @@ process_users([], State) ->
|
||||
process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els},
|
||||
#state{server = LServer} = State) ->
|
||||
Name = xml:get_attr_s(<<"name">>, Attrs),
|
||||
Pass = xml:get_attr_s(<<"password">>, Attrs),
|
||||
Password = xml:get_attr_s(<<"password">>, Attrs),
|
||||
PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain),
|
||||
Pass = case PasswordFormat of
|
||||
scram ->
|
||||
case Password of
|
||||
<<"scram:", PassData/binary>> ->
|
||||
parse_scram_password(PassData);
|
||||
P -> P
|
||||
end;
|
||||
_ -> Password
|
||||
end,
|
||||
|
||||
case jlib:nodeprep(Name) of
|
||||
error ->
|
||||
stop("Invalid 'user': ~s", [Name]);
|
||||
@@ -541,8 +583,23 @@ process_privacy(El, State = #state{user = U, server = S}) ->
|
||||
JID = jlib:make_jid(U, S, <<"">>),
|
||||
case mod_privacy:process_iq_set(
|
||||
[], JID, JID, #iq{type = set, sub_el = El}) of
|
||||
{error, _} = Err ->
|
||||
stop("Failed to write privacy: ~p", [Err]);
|
||||
{error, Error} = Err ->
|
||||
#xmlel{children = Els} = El,
|
||||
Name = case xml:remove_cdata(Els) of
|
||||
[#xmlel{name = N}] -> N;
|
||||
_ -> undefined
|
||||
end,
|
||||
#xmlel{attrs = Attrs} = Error,
|
||||
ErrorCode = case lists:keysearch(<<"code">>, 1, Attrs) of
|
||||
{value, {_, V}} -> V;
|
||||
false -> undefined
|
||||
end,
|
||||
if
|
||||
ErrorCode == <<"404">>, Name == <<"default">> ->
|
||||
{ok, State};
|
||||
true ->
|
||||
stop("Failed to write privacy: ~p", [Err])
|
||||
end;
|
||||
_ ->
|
||||
{ok, State}
|
||||
end.
|
||||
@@ -682,3 +739,6 @@ print(Fd, String) ->
|
||||
%%%==================================
|
||||
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%%,%%%= foldmethod=marker:
|
||||
file:write(Fd, String).
|
||||
|
||||
opt_type(auth_password_format) -> fun (X) -> X end;
|
||||
opt_type(_) -> [auth_password_format].
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
|
||||
-module(ejabberd_rdbms).
|
||||
|
||||
-behaviour(ejabberd_config).
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0]).
|
||||
-export([start/0, opt_type/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -74,10 +76,20 @@ needs_odbc(Host) ->
|
||||
case ejabberd_config:get_option({odbc_type, LHost},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, undefined) of
|
||||
mysql -> {true, p1_mysql};
|
||||
pgsql -> {true, p1_pgsql};
|
||||
sqlite -> {true, sqlite3};
|
||||
odbc -> {true, odbc};
|
||||
undefined -> false
|
||||
end.
|
||||
|
||||
opt_type(odbc_type) ->
|
||||
fun (mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end;
|
||||
opt_type(_) -> [odbc_type].
|
||||
|
||||