Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1035e2064d | |||
| 1f91eb0b11 | |||
| 2db19b901a |
@@ -9,7 +9,9 @@ To compile ejabberd you need:
|
||||
- GNU Make
|
||||
- GCC
|
||||
- libexpat 1.95 or higher
|
||||
- Erlang/OTP R10B-9 or higher
|
||||
- Erlang/OTP R10B-9 up to R11B-5. Erlang R12 releases are not yet
|
||||
officially supported, and are not recommended for production
|
||||
servers
|
||||
- OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL
|
||||
encryption. Optional, highly recommended.
|
||||
- Zlib 1.2.3 or higher, for Stream Compression support
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
% List of ejabberd-modules to add for ejabberd packaging (source archive and installer)
|
||||
%
|
||||
% HTTP-binding:
|
||||
https://svn.process-one.net/ejabberd-modules/http_bind/tags/ejabberd-2.0.5
|
||||
https://svn.process-one.net/ejabberd-modules/mod_http_fileserver/tags/ejabberd-2.0.4
|
||||
https://svn.process-one.net/ejabberd-modules/http_bind/tags/ejabberd-2.0.0
|
||||
https://svn.process-one.net/ejabberd-modules/mod_http_fileserver/tags/ejabberd-2.0.0
|
||||
|
||||
+5
-8
@@ -21,7 +21,7 @@ release:
|
||||
@echo "Press any key to continue"
|
||||
@read foo
|
||||
@echo "% ejabberd version (automatically generated)." > version.tex
|
||||
@echo "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../src/ejabberd.app`"}" >> version.tex
|
||||
@echo "\newcommand{\version}{"`sed '/VERSION/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../src/ejabberd.hrl`"}" >> version.tex
|
||||
@echo -n "% Contributed modules (automatically generated)." > contributed_modules.tex
|
||||
@echo -e "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex
|
||||
|
||||
@@ -32,6 +32,7 @@ pdf: guide.pdf features.pdf
|
||||
clean:
|
||||
rm -f *.aux
|
||||
rm -f *.haux
|
||||
rm -f *.html
|
||||
rm -f *.htoc
|
||||
rm -f *.idx
|
||||
rm -f *.ilg
|
||||
@@ -40,19 +41,15 @@ clean:
|
||||
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
|
||||
hevea -fix -noiso -pedantic guide.tex
|
||||
|
||||
dev.html: dev.tex
|
||||
hevea -fix -pedantic dev.tex
|
||||
hevea -fix -noiso -pedantic dev.tex
|
||||
|
||||
features.html: features.tex
|
||||
hevea -fix -pedantic features.tex
|
||||
hevea -fix -noiso -pedantic features.tex
|
||||
|
||||
guide.pdf: guide.tex
|
||||
pdflatex guide.tex
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
APPNAME = ejabberd
|
||||
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../../src/ejabberd.app)
|
||||
VSN = SVN
|
||||
|
||||
DOCDIR=.
|
||||
SRCDIR=../../src
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@author Mickael Remond <mickael.remond@process-one.net>
|
||||
[http://www.process-one.net/]
|
||||
@copyright 2007 ProcessOne
|
||||
@copyright 2007 Process-one
|
||||
@version {@vsn}, {@date} {@time}
|
||||
@title ejabberd Development API Documentation
|
||||
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Ejabberd 2.0.5 Developers Guide
|
||||
<TITLE>Ejabberd 2.0.0 Developers Guide
|
||||
</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
@@ -46,10 +46,10 @@ TD P{margin:0px;}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<BODY >
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex -->
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -noiso -pedantic dev.tex -->
|
||||
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
|
||||
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.0.5 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.0.0 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
|
||||
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
|
||||
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD></TR>
|
||||
</TABLE><DIV CLASS="center">
|
||||
@@ -139,7 +139,7 @@ Support for virtual hosting.
|
||||
</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"><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-00163.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">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
+4
-4
@@ -2,7 +2,7 @@
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Ejabberd 2.0.5 Feature Sheet
|
||||
<TITLE>Ejabberd 2.0.0 Feature Sheet
|
||||
</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
@@ -47,10 +47,10 @@ SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<BODY >
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex -->
|
||||
<!--HEVEA command line is: /usr/bin/hevea -fix -noiso -pedantic features.tex -->
|
||||
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
|
||||
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.0.5 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.0.0 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
|
||||
<A HREF="mailto:s.devrieze@pandora.be"><TT>mailto:s.devrieze@pandora.be</TT></A><BR>
|
||||
<A HREF="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD></TR>
|
||||
</TABLE><DIV CLASS="center">
|
||||
@@ -118,7 +118,7 @@ Support for virtual hosting.
|
||||
</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"><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-00163.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">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
|
||||
+1457
-1486
File diff suppressed because it is too large
Load Diff
+1267
-1502
File diff suppressed because it is too large
Load Diff
@@ -125,7 +125,7 @@ Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features
|
||||
\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 \txepref{0060}{Publish-Subscribe} component with support for \txepref{00163}{Personal Eventing via Pubsub}.
|
||||
\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services.
|
||||
\item IRC transport.
|
||||
\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
|
||||
@@ -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
-1
@@ -1,2 +1,2 @@
|
||||
% ejabberd version (automatically generated).
|
||||
\newcommand{\version}{2.0.5}
|
||||
\newcommand{\version}{2.0.0}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
+10
-26
@@ -40,34 +40,24 @@ ifeq (@transient_supervisors@, false)
|
||||
ERLC_FLAGS+=-DNO_TRANSIENT_SUPERVISORS
|
||||
endif
|
||||
|
||||
INSTALL_EPAM=
|
||||
ifeq (@pam@, pam)
|
||||
INSTALL_EPAM=install -m 750 epam $(PBINDIR)
|
||||
endif
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ stringprep @tls@ @odbc@ @ejabberd_zlib@
|
||||
ERLSHLIBS = expat_erl.so
|
||||
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
|
||||
SOURCES_ALL = $(wildcard *.erl)
|
||||
SOURCES = $(filter-out $(ERLBEHAVS),$(SOURCES_ALL))
|
||||
ERLBEHAVBEAMS = $(ERLBEHAVS:.erl=.beam)
|
||||
SOURCES = $(ERLBEHAVS) $(wildcard *.erl)
|
||||
BEAMS = $(SOURCES:.erl=.beam)
|
||||
|
||||
DESTDIR =
|
||||
|
||||
EJABBERDDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
|
||||
EJABBERDDIR = $(DESTDIR)@prefix@/var/lib/ejabberd
|
||||
BEAMDIR = $(EJABBERDDIR)/ebin
|
||||
SPOOLDIR = $(EJABBERDDIR)/db
|
||||
PRIVDIR = $(EJABBERDDIR)/priv
|
||||
SODIR = $(PRIVDIR)/lib
|
||||
PBINDIR = $(PRIVDIR)/bin
|
||||
MSGSDIR = $(PRIVDIR)/msgs
|
||||
LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd
|
||||
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd
|
||||
SBINDIR = $(DESTDIR)@sbindir@
|
||||
LOGDIR = $(DESTDIR)@prefix@/var/log/ejabberd
|
||||
ETCDIR = $(DESTDIR)@prefix@/etc/ejabberd
|
||||
SBINDIR = $(DESTDIR)@prefix@/sbin
|
||||
|
||||
ifeq ($(shell uname),Darwin)
|
||||
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
|
||||
@@ -78,11 +68,7 @@ endif
|
||||
|
||||
all: $(ERLSHLIBS) compile-beam all-recursive
|
||||
|
||||
compile-beam: XmppAddr.hrl $(ERLBEHAVBEAMS) $(BEAMS)
|
||||
|
||||
$(BEAMS): $(ERLBEHAVBEAMS)
|
||||
|
||||
all-recursive: $(ERLBEHAVBEAMS)
|
||||
compile-beam: XmppAddr.hrl $(BEAMS)
|
||||
|
||||
%.beam: %.erl
|
||||
@ERLC@ -W $(ERLC_FLAGS) $<
|
||||
@@ -114,21 +100,19 @@ install: all
|
||||
install -m 644 *.beam $(BEAMDIR)
|
||||
rm -f $(BEAMDIR)/configure.beam
|
||||
install -m 644 *.app $(BEAMDIR)
|
||||
install -d -m 750 $(SPOOLDIR)
|
||||
install -d $(SODIR)
|
||||
install -d $(PBINDIR)
|
||||
install -m 644 *.so $(SODIR)
|
||||
$(INSTALL_EPAM)
|
||||
-install -m 750 epam $(SODIR)
|
||||
install -d $(MSGSDIR)
|
||||
install -m 644 msgs/*.msg $(MSGSDIR)
|
||||
install -d -m 750 $(ETCDIR)
|
||||
install -d $(ETCDIR)
|
||||
[ -f $(ETCDIR)/ejabberd.cfg ] && install -b -m 644 ejabberd.cfg.example $(ETCDIR)/ejabberd.cfg-new || install -b -m 644 ejabberd.cfg.example $(ETCDIR)/ejabberd.cfg
|
||||
sed -e "s*@rootdir@*@prefix@*" -e "s*@erl@*@ERL@*" ejabberdctl.template > ejabberdctl.example
|
||||
sed -e "s*@rootdir@*@prefix@*" ejabberdctl.template > ejabberdctl.example
|
||||
[ -f $(ETCDIR)/ejabberdctl.cfg ] && install -b -m 644 ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg-new || install -b -m 644 ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg
|
||||
install -b -m 644 inetrc $(ETCDIR)/inetrc
|
||||
install -d $(SBINDIR)
|
||||
install -m 755 ejabberdctl.example $(SBINDIR)/ejabberdctl
|
||||
install -d -m 750 $(LOGDIR)
|
||||
install -d $(LOGDIR)
|
||||
|
||||
uninstall: uninstall-binary
|
||||
|
||||
|
||||
+2
-6
@@ -5,7 +5,7 @@
|
||||
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -178,10 +178,6 @@ match_acl(ACL, JID, Host) ->
|
||||
((Host == global) andalso
|
||||
lists:member(Server, ?MYHOSTS)))
|
||||
andalso is_regexp_match(User, UR);
|
||||
{shared_group, G} ->
|
||||
mod_shared_roster:is_user_in_group({User, Server}, G, Host);
|
||||
{shared_group, G, H} ->
|
||||
mod_shared_roster:is_user_in_group({User, Server}, G, H);
|
||||
{user_regexp, UR, S} ->
|
||||
(S == Server) andalso
|
||||
is_regexp_match(User, UR);
|
||||
|
||||
Vendored
+15
-17
@@ -1,6 +1,6 @@
|
||||
AC_DEFUN(AM_WITH_EXPAT,
|
||||
[ AC_ARG_WITH(expat,
|
||||
[AC_HELP_STRING([--with-expat=PREFIX], [prefix where EXPAT is installed])])
|
||||
[ --with-expat=PREFIX prefix where EXPAT is installed])
|
||||
|
||||
EXPAT_CFLAGS=
|
||||
EXPAT_LIBS=
|
||||
@@ -15,7 +15,7 @@ AC_DEFUN(AM_WITH_EXPAT,
|
||||
[ expat_found=no ],
|
||||
"$EXPAT_LIBS")
|
||||
if test $expat_found = no; then
|
||||
AC_MSG_ERROR([Could not find development files of Expat library])
|
||||
AC_MSG_ERROR([Could not find the Expat library])
|
||||
fi
|
||||
expat_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $EXPAT_CFLAGS"
|
||||
@@ -34,9 +34,8 @@ AC_DEFUN(AM_WITH_EXPAT,
|
||||
|
||||
AC_DEFUN(AM_WITH_ZLIB,
|
||||
[ AC_ARG_WITH(zlib,
|
||||
[AC_HELP_STRING([--with-zlib=PREFIX], [prefix where zlib is installed])])
|
||||
[ --with-zlib=PREFIX prefix where zlib is installed])
|
||||
|
||||
if test x"$ejabberd_zlib" != x; then
|
||||
ZLIB_CFLAGS=
|
||||
ZLIB_LIBS=
|
||||
if test x"$with_zlib" != x; then
|
||||
@@ -50,7 +49,7 @@ if test x"$ejabberd_zlib" != x; then
|
||||
[ zlib_found=no ],
|
||||
"$ZLIB_LIBS")
|
||||
if test $zlib_found = no; then
|
||||
AC_MSG_ERROR([Could not find development files of zlib library. Install them or disable `ejabberd_zlib' with: --disable-ejabberd_zlib])
|
||||
AC_MSG_ERROR([Could not find the zlib library])
|
||||
fi
|
||||
zlib_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ZLIB_CFLAGS"
|
||||
@@ -58,20 +57,19 @@ if test x"$ejabberd_zlib" != x; then
|
||||
CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS"
|
||||
AC_CHECK_HEADERS(zlib.h, , zlib_found=no)
|
||||
if test $zlib_found = no; then
|
||||
AC_MSG_ERROR([Could not find zlib.h. Install it or disable `ejabberd_zlib' with: --disable-ejabberd_zlib])
|
||||
AC_MSG_ERROR([Could not find zlib.h])
|
||||
fi
|
||||
CFLAGS="$zlib_save_CFLAGS"
|
||||
CPPFLAGS="$zlib_save_CPPFLAGS"
|
||||
|
||||
AC_SUBST(ZLIB_CFLAGS)
|
||||
AC_SUBST(ZLIB_LIBS)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(AM_WITH_PAM,
|
||||
[ AC_ARG_WITH(pam,
|
||||
[AC_HELP_STRING([--with-pam=PREFIX], [prefix where PAM is installed])])
|
||||
if test x"$pam" != x; then
|
||||
[ --with-pam=PREFIX prefix where PAM is installed])
|
||||
|
||||
PAM_CFLAGS=
|
||||
PAM_LIBS=
|
||||
if test x"$with_pam" != x; then
|
||||
@@ -85,7 +83,7 @@ if test x"$pam" != x; then
|
||||
[ pam_found=no ],
|
||||
"$PAM_LIBS")
|
||||
if test $pam_found = no; then
|
||||
AC_MSG_ERROR([Could not find development files of PAM library. Install them or disable `pam' with: --disable-pam])
|
||||
AC_MSG_WARN([Could not find the PAM library])
|
||||
fi
|
||||
pam_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PAM_CFLAGS"
|
||||
@@ -93,19 +91,18 @@ if test x"$pam" != x; then
|
||||
CPPFLAGS="$CPPFLAGS $PAM_CFLAGS"
|
||||
AC_CHECK_HEADERS(security/pam_appl.h, , pam_found=no)
|
||||
if test $pam_found = no; then
|
||||
AC_MSG_ERROR([Could not find security/pam_appl.h. Install it or disable `pam' with: --disable-pam])
|
||||
AC_MSG_WARN([Could not find security/pam_appl.h])
|
||||
fi
|
||||
CFLAGS="$pam_save_CFLAGS"
|
||||
CPPFLAGS="$pam_save_CPPFLAGS"
|
||||
|
||||
AC_SUBST(PAM_CFLAGS)
|
||||
AC_SUBST(PAM_LIBS)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(AM_WITH_ERLANG,
|
||||
[ AC_ARG_WITH(erlang,
|
||||
[AC_HELP_STRING([--with-erlang=PREFIX], [path to erlc and erl])])
|
||||
[ --with-erlang=PREFIX path to erlc and erl ])
|
||||
|
||||
AC_PATH_TOOL(ERLC, erlc, , $with_erlang:$with_erlang/bin:$PATH)
|
||||
AC_PATH_TOOL(ERL, erl, , $with_erlang:$with_erlang/bin:$PATH)
|
||||
@@ -198,13 +195,14 @@ _EOF
|
||||
AC_SUBST(ERL)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(AC_MOD_ENABLE,
|
||||
[
|
||||
$1=
|
||||
make_$1=
|
||||
AC_MSG_CHECKING([whether build $1])
|
||||
AC_ARG_ENABLE($1,
|
||||
[AC_HELP_STRING([--enable-$1], [enable $1 (default: $2)])],
|
||||
[ --enable-$1 enable $1 (default: $2)],
|
||||
[mr_enable_$1="$enableval"],
|
||||
[mr_enable_$1=$2])
|
||||
if test "$mr_enable_$1" = "yes"; then
|
||||
@@ -225,7 +223,7 @@ AC_DEFUN([AM_ICONV],
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[AC_HELP_STRING([--with-libiconv-prefix=PREFIX], [prefix where libiconv is installed])], [
|
||||
[ --with-libiconv-prefix=PREFIX prefix where libiconv is installed], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/include; then CFLAGS="$CFLAGS -I$dir/include"; fi
|
||||
@@ -310,7 +308,7 @@ size_t iconv();
|
||||
dnl <openssl>
|
||||
AC_DEFUN(AM_WITH_OPENSSL,
|
||||
[ AC_ARG_WITH(openssl,
|
||||
[AC_HELP_STRING([--with-openssl=PREFIX], [prefix where OPENSSL is installed])])
|
||||
[ --with-openssl=PREFIX prefix where OPENSSL is installed ])
|
||||
unset SSL_LIBS;
|
||||
unset SSL_CFLAGS;
|
||||
have_openssl=no
|
||||
@@ -340,7 +338,7 @@ if test x"$tls" != x; then
|
||||
fi
|
||||
done
|
||||
if test x${have_openssl} != xyes; then
|
||||
AC_MSG_ERROR([Could not find development files of OpenSSL library. Install them or disable `tls' with: --disable-tls])
|
||||
AC_MSG_ERROR([openssl library cannot be found. Install openssl or disable `tls' module (--disable-tls).])
|
||||
fi
|
||||
AC_SUBST(SSL_LIBS)
|
||||
AC_SUBST(SSL_CFLAGS)
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
Vendored
+625
-634
File diff suppressed because it is too large
Load Diff
+23
-19
@@ -18,13 +18,14 @@ AM_WITH_ERLANG
|
||||
AM_ICONV
|
||||
#locating libexpat
|
||||
AM_WITH_EXPAT
|
||||
#locating zlib
|
||||
AM_WITH_ZLIB
|
||||
#locating PAM
|
||||
AM_WITH_PAM
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
|
||||
# Check Erlang headers are installed
|
||||
#AC_CHECK_HEADER(erl_driver.h,,[AC_MSG_ERROR([cannot find Erlang header files])])
|
||||
|
||||
# Change default prefix
|
||||
AC_PREFIX_DEFAULT(/)
|
||||
|
||||
@@ -32,25 +33,19 @@ AC_PREFIX_DEFAULT(/)
|
||||
AC_FUNC_MALLOC
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_MOD_ENABLE(mod_pubsub, yes)
|
||||
AC_MOD_ENABLE(mod_irc, yes)
|
||||
AC_MOD_ENABLE(mod_muc, yes)
|
||||
AC_MOD_ENABLE(mod_proxy65, yes)
|
||||
AC_MOD_ENABLE(mod_pubsub, yes)
|
||||
AC_MOD_ENABLE(eldap, yes)
|
||||
AC_MOD_ENABLE(odbc, no)
|
||||
AC_MOD_ENABLE(tls, yes)
|
||||
AC_MOD_ENABLE(web, yes)
|
||||
|
||||
AC_MOD_ENABLE(ejabberd_zlib, yes)
|
||||
#locating zlib
|
||||
AM_WITH_ZLIB
|
||||
|
||||
AC_MOD_ENABLE(pam, no)
|
||||
#locating PAM
|
||||
AM_WITH_PAM
|
||||
AC_MOD_ENABLE(web, yes)
|
||||
AC_MOD_ENABLE(tls, yes)
|
||||
AC_MOD_ENABLE(odbc, no)
|
||||
AC_MOD_ENABLE(ejabberd_zlib, yes)
|
||||
|
||||
AC_ARG_ENABLE(hipe,
|
||||
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
|
||||
[ --enable-hipe Compile natively with HiPE, not recommended (default: no)],
|
||||
[case "${enableval}" in
|
||||
yes) hipe=true ;;
|
||||
no) hipe=false ;;
|
||||
@@ -59,7 +54,7 @@ esac],[hipe=false])
|
||||
AC_SUBST(hipe)
|
||||
|
||||
AC_ARG_ENABLE(roster_gateway_workaround,
|
||||
[AC_HELP_STRING([--enable-roster-gateway-workaround], [turn on workaround for processing gateway subscriptions (default: no)])],
|
||||
[ --enable-roster-gateway-workaround Turn on workaround for processing gateway subscriptions (default: no)],
|
||||
[case "${enableval}" in
|
||||
yes) roster_gateway_workaround=true ;;
|
||||
no) roster_gateway_workaround=false ;;
|
||||
@@ -68,7 +63,7 @@ esac],[roster_gateway_workaround=false])
|
||||
AC_SUBST(roster_gateway_workaround)
|
||||
|
||||
AC_ARG_ENABLE(mssql,
|
||||
[AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])],
|
||||
[ --enable-mssql Use Microsoft SQL Server database (default: no, requires --enable-odbc)],
|
||||
[case "${enableval}" in
|
||||
yes) db_type=mssql ;;
|
||||
no) db_type=generic ;;
|
||||
@@ -77,7 +72,7 @@ esac],[db_type=generic])
|
||||
AC_SUBST(db_type)
|
||||
|
||||
AC_ARG_ENABLE(transient_supervisors,
|
||||
[AC_HELP_STRING([--enable-transient_supervisors], [use Erlang supervision for transient process (default: yes)])],
|
||||
[ --enable-transient_supervisors Use Erlang supervision for transient process (default: yes)],
|
||||
[case "${enableval}" in
|
||||
yes) transient_supervisors=true ;;
|
||||
no) transient_supervisors=false ;;
|
||||
@@ -86,7 +81,7 @@ esac],[transient_supervisors=true])
|
||||
AC_SUBST(transient_supervisors)
|
||||
|
||||
AC_ARG_ENABLE(full_xml,
|
||||
[AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
|
||||
[ --enable-full-xml Use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)],
|
||||
[case "${enableval}" in
|
||||
yes) full_xml=true ;;
|
||||
no) full_xml=false ;;
|
||||
@@ -125,3 +120,12 @@ fi
|
||||
AC_CHECK_HEADER(krb5.h,,)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
if test -n "$ERLANG_SSL39" ; then
|
||||
echo
|
||||
echo "**************** WARNING ! ********************"
|
||||
echo "ejabberd will be compiled with Erlang R12."
|
||||
echo "This version of Erlang is not supported"
|
||||
echo "and not recommended for production servers"
|
||||
echo "***********************************************"
|
||||
fi
|
||||
|
||||
+2
-4
@@ -5,7 +5,7 @@
|
||||
%%% Created : 27 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -60,8 +60,6 @@ start() ->
|
||||
EVersion = "ERLANG_VERSION = " ++ erlang:system_info(version) ++ "\n",
|
||||
EIDirS = "EI_DIR = " ++ code:lib_dir("erl_interface") ++ "\n",
|
||||
RootDirS = "ERLANG_DIR = " ++ code:root_dir() ++ "\n",
|
||||
%% Load the ejabberd application description so that ?VERSION can read the vsn key
|
||||
application:load(ejabberd),
|
||||
Version = "EJABBERD_VERSION = " ++ ?VERSION ++ "\n",
|
||||
ExpatDir = "EXPAT_DIR = c:\\sdk\\Expat-2.0.0\n",
|
||||
OpenSSLDir = "OPENSSL_DIR = c:\\sdk\\OpenSSL\n",
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%%% Created : 23 Aug 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -17,7 +17,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -51,6 +51,5 @@ mech_step(State, _ClientIn) ->
|
||||
%% Checks that the username is available
|
||||
case ejabberd_auth:is_user_exists(User, Server) of
|
||||
true -> {error, "not-authorized"};
|
||||
false -> {ok, [{username, User},
|
||||
{auth_module, ejabberd_auth_anonymous}]}
|
||||
false -> {ok, [{username, User}]}
|
||||
end.
|
||||
|
||||
+24
-57
@@ -14,12 +14,9 @@
|
||||
mech_new/3,
|
||||
mech_step/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
-record(state, {step, nonce, username, authzid, get_password, auth_module,
|
||||
host}).
|
||||
-record(state, {step, nonce, username, authzid, get_password}).
|
||||
|
||||
start(_Opts) ->
|
||||
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
|
||||
@@ -27,10 +24,9 @@ start(_Opts) ->
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
mech_new(Host, GetPassword, _CheckPassword) ->
|
||||
mech_new(_Host, GetPassword, _CheckPassword) ->
|
||||
{ok, #state{step = 1,
|
||||
nonce = randoms:get_string(),
|
||||
host = Host,
|
||||
get_password = GetPassword}}.
|
||||
|
||||
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
|
||||
@@ -43,48 +39,38 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
|
||||
bad ->
|
||||
{error, "bad-protocol"};
|
||||
KeyVals ->
|
||||
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
|
||||
UserName = xml:get_attr_s("username", KeyVals),
|
||||
case is_digesturi_valid(DigestURI, State#state.host) of
|
||||
AuthzId = xml:get_attr_s("authzid", KeyVals),
|
||||
case (State#state.get_password)(UserName) of
|
||||
false ->
|
||||
?DEBUG("User login not authorized because digest-uri "
|
||||
"seems invalid: ~p", [DigestURI]),
|
||||
{error, "not-authorized", UserName};
|
||||
true ->
|
||||
AuthzId = xml:get_attr_s("authzid", KeyVals),
|
||||
case (State#state.get_password)(UserName) of
|
||||
{false, _} ->
|
||||
{error, "not-authorized", UserName};
|
||||
{Passwd, AuthModule} ->
|
||||
Response = response(KeyVals, UserName, Passwd,
|
||||
Nonce, AuthzId, "AUTHENTICATE"),
|
||||
case xml:get_attr_s("response", KeyVals) of
|
||||
Response ->
|
||||
RspAuth = response(KeyVals,
|
||||
UserName, Passwd,
|
||||
Nonce, AuthzId, ""),
|
||||
{continue,
|
||||
"rspauth=" ++ RspAuth,
|
||||
State#state{step = 5,
|
||||
auth_module = AuthModule,
|
||||
username = UserName,
|
||||
authzid = AuthzId}};
|
||||
_ ->
|
||||
{error, "not-authorized", UserName}
|
||||
end
|
||||
Passwd ->
|
||||
Response = response(KeyVals, UserName, Passwd,
|
||||
Nonce, AuthzId, "AUTHENTICATE"),
|
||||
case xml:get_attr_s("response", KeyVals) of
|
||||
Response ->
|
||||
RspAuth = response(KeyVals,
|
||||
UserName, Passwd,
|
||||
Nonce, AuthzId, ""),
|
||||
{continue,
|
||||
"rspauth=" ++ RspAuth,
|
||||
State#state{step = 5,
|
||||
username = UserName,
|
||||
authzid = AuthzId}};
|
||||
_ ->
|
||||
{error, "not-authorized", UserName}
|
||||
end
|
||||
end
|
||||
end;
|
||||
mech_step(#state{step = 5,
|
||||
auth_module = AuthModule,
|
||||
username = UserName,
|
||||
authzid = AuthzId}, "") ->
|
||||
{ok, [{username, UserName}, {authzid, AuthzId},
|
||||
{auth_module, AuthModule}]};
|
||||
{ok, [{username, UserName}, {authzid, AuthzId}]};
|
||||
mech_step(A, B) ->
|
||||
?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]),
|
||||
io:format("SASL DIGEST: A ~p B ~p", [A,B]),
|
||||
{error, "bad-protocol"}.
|
||||
|
||||
|
||||
parse(S) ->
|
||||
parse1(S, "", []).
|
||||
|
||||
@@ -101,17 +87,15 @@ parse1([], [], T) ->
|
||||
parse1([], _S, _T) ->
|
||||
bad.
|
||||
|
||||
parse2([$\" | Cs], Key, Val, Ts) ->
|
||||
parse2([$" | Cs], Key, Val, Ts) ->
|
||||
parse3(Cs, Key, Val, Ts);
|
||||
parse2([C | Cs], Key, Val, Ts) ->
|
||||
parse4(Cs, Key, [C | Val], Ts);
|
||||
parse2([], _, _, _) ->
|
||||
bad.
|
||||
|
||||
parse3([$\" | Cs], Key, Val, Ts) ->
|
||||
parse3([$" | Cs], Key, Val, Ts) ->
|
||||
parse4(Cs, Key, Val, Ts);
|
||||
parse3([$\\, C | Cs], Key, Val, Ts) ->
|
||||
parse3(Cs, Key, [C | Val], Ts);
|
||||
parse3([C | Cs], Key, Val, Ts) ->
|
||||
parse3(Cs, Key, [C | Val], Ts);
|
||||
parse3([], _, _, _) ->
|
||||
@@ -127,23 +111,6 @@ parse4([], Key, Val, Ts) ->
|
||||
parse1([], "", [{Key, lists:reverse(Val)} | Ts]).
|
||||
|
||||
|
||||
%% @doc Check if the digest-uri is valid.
|
||||
%% RFC-2831 allows to provide the IP address in Host,
|
||||
%% however ejabberd doesn't allow that.
|
||||
%% If the service (for example jabber.example.org)
|
||||
%% is provided by several hosts (being one of them server3.example.org),
|
||||
%% then digest-uri can be like xmpp/server3.example.org/jabber.example.org
|
||||
%% In that case, ejabberd only checks the service name, not the host.
|
||||
is_digesturi_valid(DigestURICase, JabberHost) ->
|
||||
DigestURI = stringprep:tolower(DigestURICase),
|
||||
case catch string:tokens(DigestURI, "/") of
|
||||
["xmpp", Host] when Host == JabberHost ->
|
||||
true;
|
||||
["xmpp", _Host, ServName] when ServName == JabberHost ->
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -47,9 +47,8 @@ mech_step(State, ClientIn) ->
|
||||
case parse(ClientIn) of
|
||||
[AuthzId, User, Password] ->
|
||||
case (State#state.check_password)(User, Password) of
|
||||
{true, AuthModule} ->
|
||||
{ok, [{username, User}, {authzid, AuthzId},
|
||||
{auth_module, AuthModule}]};
|
||||
true ->
|
||||
{ok, [{username, User}, {authzid, AuthzId}]};
|
||||
_ ->
|
||||
{error, "not-authorized", User}
|
||||
end;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
{application, ejabberd,
|
||||
[{description, "ejabberd"},
|
||||
{vsn, "2.0.5"},
|
||||
{vsn, "2.0.0"},
|
||||
{modules, [acl,
|
||||
adhoc,
|
||||
configure,
|
||||
|
||||
+10
-52
@@ -72,9 +72,8 @@
|
||||
{loglevel, 4}.
|
||||
|
||||
%%
|
||||
%% watchdog_admins: Only useful for developers: if an ejabberd process
|
||||
%% consumes a lot of memory, send live notifications to these Jabber
|
||||
%% accounts.
|
||||
%% watchdog_admins: If an ejabberd process consumes too much memory,
|
||||
%% send live notifications to those Jabber accounts.
|
||||
%%
|
||||
%%{watchdog_admins, ["bob@example.com"]}.
|
||||
|
||||
@@ -342,20 +341,11 @@
|
||||
%%{acl, test, {user_regexp, "^test"}}.
|
||||
%%{acl, test, {user_glob, "test*"}}.
|
||||
|
||||
%%
|
||||
%% Define specific ACLs in a virtual host.
|
||||
%%
|
||||
%%{host_config, "localhost",
|
||||
%% [
|
||||
%% {acl, admin, {user, "bob-local", "localhost"}}
|
||||
%% ]
|
||||
%%}.
|
||||
|
||||
|
||||
%%% ============
|
||||
%%% ACCESS RULES
|
||||
|
||||
%% Maximum number of simultaneous sessions allowed for a single user:
|
||||
%% Define the maximum number of time a single user is allowed to connect:
|
||||
{access, max_user_sessions, [{10, all}]}.
|
||||
|
||||
%% This rule allows access only for local users:
|
||||
@@ -365,11 +355,11 @@
|
||||
{access, c2s, [{deny, blocked},
|
||||
{allow, all}]}.
|
||||
|
||||
%% For C2S connections, all users except admins use "normal" shaper
|
||||
%% For all users except admins used "normal" shaper
|
||||
{access, c2s_shaper, [{none, admin},
|
||||
{normal, all}]}.
|
||||
|
||||
%% All S2S connections use "fast" shaper
|
||||
%% For all S2S connections used "fast" shaper
|
||||
{access, s2s_shaper, [{fast, all}]}.
|
||||
|
||||
%% Only admins can send announcement messages:
|
||||
@@ -384,26 +374,12 @@
|
||||
%% All users are allowed to use MUC service:
|
||||
{access, muc, [{allow, all}]}.
|
||||
|
||||
%% Everybody can create pubsub nodes
|
||||
{access, pubsub_createnode, [{allow, all}]}.
|
||||
|
||||
%% In-band registration allows registration of any possible username.
|
||||
%% Every username can be registered via in-band registration:
|
||||
%% To disable in-band registration, replace 'allow' with 'deny'.
|
||||
{access, register, [{allow, all}]}.
|
||||
|
||||
%% By default frequency of account registrations from a the same IP
|
||||
%% is limited to 1 account every 10 minutes. To disable put: infinity
|
||||
%%{registration_timeout, 600}.
|
||||
|
||||
%%
|
||||
%% Define specific Access rules in a virtual host.
|
||||
%%
|
||||
%%{host_config, "localhost",
|
||||
%% [
|
||||
%% {access, c2s, [{allow, admin}, {deny, all}]},
|
||||
%% {access, register, [{deny, all}]}
|
||||
%% ]
|
||||
%%}.
|
||||
%% Everybody can create pubsub nodes
|
||||
{access, pubsub_createnode, [{allow, all}]}.
|
||||
|
||||
|
||||
%%% ================
|
||||
@@ -414,13 +390,6 @@
|
||||
%%
|
||||
{language, "en"}.
|
||||
|
||||
%%
|
||||
%% Set a different default language in a virtual host.
|
||||
%%
|
||||
%%{host_config, "localhost",
|
||||
%% [{language, "ru"}]
|
||||
%%}.
|
||||
|
||||
|
||||
%%% =======
|
||||
%%% MODULES
|
||||
@@ -431,7 +400,7 @@
|
||||
{modules,
|
||||
[
|
||||
{mod_adhoc, []},
|
||||
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
|
||||
{mod_announce, [{access, announce}]}, % requires mod_adhoc
|
||||
{mod_caps, []},
|
||||
{mod_configure,[]}, % requires mod_adhoc
|
||||
{mod_disco, []},
|
||||
@@ -460,7 +429,7 @@
|
||||
%% a message with this subject and body.
|
||||
%%
|
||||
{welcome_message, {"Welcome!",
|
||||
"Hi\nWelcome to this Jabber server."}},
|
||||
"Welcome to this Jabber server."}},
|
||||
|
||||
%%
|
||||
%% When a user registers, send a notification to
|
||||
@@ -479,17 +448,6 @@
|
||||
{mod_version, []}
|
||||
]}.
|
||||
|
||||
%%
|
||||
%% Enable modules with custom options in a specific virtual host
|
||||
%%
|
||||
%%{host_config, "localhost",
|
||||
%% [{{add, modules},
|
||||
%% [
|
||||
%% {mod_echo, [{host, "mirror.localhost"}]}
|
||||
%% ]
|
||||
%% }
|
||||
%% ]}.
|
||||
|
||||
|
||||
%%% $Id$
|
||||
|
||||
|
||||
+3
-16
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -28,7 +28,7 @@
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0, stop/0,
|
||||
get_so_path/0, get_bin_path/0]).
|
||||
get_so_path/0]).
|
||||
|
||||
start() ->
|
||||
application:start(ejabberd).
|
||||
@@ -49,16 +49,3 @@ get_so_path() ->
|
||||
Path ->
|
||||
Path
|
||||
end.
|
||||
|
||||
get_bin_path() ->
|
||||
case os:getenv("EJABBERD_BIN_PATH") of
|
||||
false ->
|
||||
case code:priv_dir(ejabberd) of
|
||||
{error, _} ->
|
||||
".";
|
||||
Path ->
|
||||
filename:join([Path, "bin"])
|
||||
end;
|
||||
Path ->
|
||||
Path
|
||||
end.
|
||||
|
||||
+17
-22
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -19,31 +19,14 @@
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
%% This macro returns a string of the ejabberd version running, e.g. "2.3.4"
|
||||
%% If the ejabberd application description isn't loaded, returns atom: undefined
|
||||
-define(VERSION, element(2, application:get_key(ejabberd,vsn))).
|
||||
%-define(ejabberd_debug, true).
|
||||
%-define(DBGFSM, true).
|
||||
|
||||
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)).
|
||||
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
|
||||
-define(MYLANG, ejabberd_config:get_global_option(language)).
|
||||
|
||||
-define(MSGS_DIR, "msgs").
|
||||
-define(CONFIG_PATH, "ejabberd.cfg").
|
||||
-define(LOG_PATH, "ejabberd.log").
|
||||
|
||||
-define(EJABBERD_URI, "http://www.process-one.net/en/ejabberd/").
|
||||
|
||||
-define(S2STIMEOUT, 600000).
|
||||
|
||||
%%-define(DBGFSM, true).
|
||||
-define(VERSION, "2.0.0").
|
||||
|
||||
%% ---------------------------------
|
||||
%% Logging mechanism
|
||||
|
||||
%% Print in standard output
|
||||
-define(PRINT(Format, Args),
|
||||
io:format(Format, Args)).
|
||||
|
||||
-define(DEBUG(Format, Args),
|
||||
ejabberd_logger:debug_msg(?MODULE,?LINE,Format, Args)).
|
||||
|
||||
@@ -59,3 +42,15 @@
|
||||
-define(CRITICAL_MSG(Format, Args),
|
||||
ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
|
||||
|
||||
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)).
|
||||
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
|
||||
-define(S2STIMEOUT, 600000).
|
||||
-define(MYLANG, ejabberd_config:get_global_option(language)).
|
||||
|
||||
-define(MSGS_DIR, "msgs").
|
||||
-define(CONFIG_PATH, "ejabberd.cfg").
|
||||
-define(LOG_PATH, "ejabberd.log").
|
||||
|
||||
-define(PRIVACY_SUPPORT, true).
|
||||
|
||||
-define(EJABBERD_URI, "http://www.process-one.net/en/ejabberd/").
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -20,7 +20,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+8
-54
@@ -1,11 +1,11 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_app.erl
|
||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||
%%% Purpose : ejabberd's application callback module
|
||||
%%% Purpose : ejabberd OTP application definition.
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -29,15 +29,10 @@
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
-export([start/2, prep_stop/1, stop/1, init/0]).
|
||||
-export([start/2, stop/1, init/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
|
||||
%%%
|
||||
%%% Application API
|
||||
%%%
|
||||
|
||||
start(normal, _Args) ->
|
||||
ejabberd_loglevel:set(4),
|
||||
application:start(sasl),
|
||||
@@ -46,13 +41,12 @@ start(normal, _Args) ->
|
||||
sha:start(),
|
||||
catch ssl:start(),
|
||||
stringprep_sup:start_link(),
|
||||
start(),
|
||||
translate:start(),
|
||||
acl:start(),
|
||||
ejabberd_ctl:init(),
|
||||
gen_mod:start(),
|
||||
ejabberd_config:start(),
|
||||
ejabberd_check:config(),
|
||||
start(),
|
||||
connect_nodes(),
|
||||
Sup = ejabberd_sup:start_link(),
|
||||
ejabberd_rdbms:start(),
|
||||
@@ -62,28 +56,14 @@ start(normal, _Args) ->
|
||||
%eprof:start(),
|
||||
%eprof:profile([self()]),
|
||||
%fprof:trace(start, "/tmp/fprof"),
|
||||
maybe_add_nameservers(),
|
||||
start_modules(),
|
||||
load_modules(),
|
||||
Sup;
|
||||
start(_, _) ->
|
||||
{error, badarg}.
|
||||
|
||||
%% Prepare the application for termination.
|
||||
%% This function is called when an application is about to be stopped,
|
||||
%% before shutting down the processes of the application.
|
||||
prep_stop(State) ->
|
||||
stop_modules(),
|
||||
State.
|
||||
|
||||
%% All the processes were killed when this function is called
|
||||
stop(_State) ->
|
||||
stop(_StartArgs) ->
|
||||
ok.
|
||||
|
||||
|
||||
%%%
|
||||
%%% Internal functions
|
||||
%%%
|
||||
|
||||
start() ->
|
||||
spawn_link(?MODULE, init, []).
|
||||
|
||||
@@ -129,8 +109,7 @@ db_init() ->
|
||||
mnesia:start(),
|
||||
mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
|
||||
|
||||
%% Start all the modules in all the hosts
|
||||
start_modules() ->
|
||||
load_modules() ->
|
||||
lists:foreach(
|
||||
fun(Host) ->
|
||||
case ejabberd_config:get_local_option({modules, Host}) of
|
||||
@@ -144,21 +123,6 @@ start_modules() ->
|
||||
end
|
||||
end, ?MYHOSTS).
|
||||
|
||||
%% Stop all the modules in all the hosts
|
||||
stop_modules() ->
|
||||
lists:foreach(
|
||||
fun(Host) ->
|
||||
case ejabberd_config:get_local_option({modules, Host}) of
|
||||
undefined ->
|
||||
ok;
|
||||
Modules ->
|
||||
lists:foreach(
|
||||
fun({Module, _Args}) ->
|
||||
gen_mod:stop_module_keep_config(Host, Module)
|
||||
end, Modules)
|
||||
end
|
||||
end, ?MYHOSTS).
|
||||
|
||||
connect_nodes() ->
|
||||
case ejabberd_config:get_local_option(cluster_nodes) of
|
||||
undefined ->
|
||||
@@ -170,14 +134,4 @@ connect_nodes() ->
|
||||
end.
|
||||
|
||||
|
||||
%% If ejabberd is running on some Windows machine, get nameservers and add to Erlang
|
||||
maybe_add_nameservers() ->
|
||||
case os:type() of
|
||||
{win32, _} -> add_windows_nameservers();
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
add_windows_nameservers() ->
|
||||
IPTs = win32_dns:get_nameservers(),
|
||||
?INFO_MSG("Adding machine's DNS IPs to Erlang system:~n~p", [IPTs]),
|
||||
lists:foreach(fun(IPT) -> inet_db:add_ns(IPT) end, IPTs).
|
||||
|
||||
+23
-133
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -34,8 +34,6 @@
|
||||
set_password/3,
|
||||
check_password/3,
|
||||
check_password/5,
|
||||
check_password_with_authmodule/3,
|
||||
check_password_with_authmodule/5,
|
||||
try_register/3,
|
||||
dirty_get_registered_users/0,
|
||||
get_vh_registered_users/1,
|
||||
@@ -44,7 +42,6 @@
|
||||
get_vh_registered_users_number/2,
|
||||
get_password/2,
|
||||
get_password_s/2,
|
||||
get_password_with_authmodule/2,
|
||||
is_user_exists/2,
|
||||
is_user_exists_in_other_modules/3,
|
||||
remove_user/2,
|
||||
@@ -76,60 +73,18 @@ plain_password_required(Server) ->
|
||||
M:plain_password_required()
|
||||
end, auth_modules(Server)).
|
||||
|
||||
%% @doc Check if the user and password can login in server.
|
||||
%% @spec (User::string(), Server::string(), Password::string()) ->
|
||||
%% true | false
|
||||
check_password(User, Server, Password) ->
|
||||
case check_password_with_authmodule(User, Server, Password) of
|
||||
{true, _AuthModule} -> true;
|
||||
false -> false
|
||||
end.
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:check_password(User, Server, Password)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
%% @doc Check if the user and password can login in server.
|
||||
%% @spec (User::string(), Server::string(), Password::string(),
|
||||
%% StreamID::string(), Digest::string()) ->
|
||||
%% true | false
|
||||
check_password(User, Server, Password, StreamID, Digest) ->
|
||||
case check_password_with_authmodule(User, Server, Password,
|
||||
StreamID, Digest) of
|
||||
{true, _AuthModule} -> true;
|
||||
false -> false
|
||||
end.
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:check_password(User, Server, Password, StreamID, Digest)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
%% @doc Check if the user and password can login in server.
|
||||
%% The user can login if at least an authentication method accepts the user
|
||||
%% and the password.
|
||||
%% The first authentication method that accepts the credentials is returned.
|
||||
%% @spec (User::string(), Server::string(), Password::string()) ->
|
||||
%% {true, AuthModule} | false
|
||||
%% where
|
||||
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
|
||||
%% | ejabberd_auth_internal | ejabberd_auth_ldap
|
||||
%% | ejabberd_auth_odbc | ejabberd_auth_pam
|
||||
check_password_with_authmodule(User, Server, Password) ->
|
||||
check_password_loop(auth_modules(Server), [User, Server, Password]).
|
||||
|
||||
check_password_with_authmodule(User, Server, Password, StreamID, Digest) ->
|
||||
check_password_loop(auth_modules(Server), [User, Server, Password,
|
||||
StreamID, Digest]).
|
||||
|
||||
check_password_loop([], _Args) ->
|
||||
false;
|
||||
check_password_loop([AuthModule | AuthModules], Args) ->
|
||||
case apply(AuthModule, check_password, Args) of
|
||||
true ->
|
||||
{true, AuthModule};
|
||||
false ->
|
||||
check_password_loop(AuthModules, Args)
|
||||
end.
|
||||
|
||||
|
||||
%% @spec (User::string(), Server::string(), Password::string()) ->
|
||||
%% ok | {error, ErrorType}
|
||||
%% where ErrorType = empty_password | not_allowed | invalid_jid
|
||||
set_password(_User, _Server, "") ->
|
||||
%% We do not allow empty password
|
||||
{error, empty_password};
|
||||
set_password(User, Server, Password) ->
|
||||
lists:foldl(
|
||||
fun(M, {error, _}) ->
|
||||
@@ -138,10 +93,6 @@ set_password(User, Server, Password) ->
|
||||
Res
|
||||
end, {error, not_allowed}, auth_modules(Server)).
|
||||
|
||||
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed}
|
||||
try_register(_User, _Server, "") ->
|
||||
%% We do not allow empty password
|
||||
{error, not_allowed};
|
||||
try_register(User, Server, Password) ->
|
||||
case is_user_exists(User,Server) of
|
||||
true ->
|
||||
@@ -149,19 +100,12 @@ try_register(User, Server, Password) ->
|
||||
false ->
|
||||
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
|
||||
true ->
|
||||
Res = lists:foldl(
|
||||
lists:foldl(
|
||||
fun(_M, {atomic, ok} = Res) ->
|
||||
Res;
|
||||
(M, _) ->
|
||||
M:try_register(User, Server, Password)
|
||||
end, {error, not_allowed}, auth_modules(Server)),
|
||||
case Res of
|
||||
{atomic, ok} ->
|
||||
ejabberd_hooks:run(register_user, Server,
|
||||
[User, Server]),
|
||||
{atomic, ok};
|
||||
_ -> Res
|
||||
end;
|
||||
end, {error, not_allowed}, auth_modules(Server));
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
end
|
||||
@@ -184,13 +128,7 @@ get_vh_registered_users(Server) ->
|
||||
get_vh_registered_users(Server, Opts) ->
|
||||
lists:flatmap(
|
||||
fun(M) ->
|
||||
case erlang:function_exported(
|
||||
M, get_vh_registered_users, 2) of
|
||||
true ->
|
||||
M:get_vh_registered_users(Server, Opts);
|
||||
false ->
|
||||
M:get_vh_registered_users(Server)
|
||||
end
|
||||
M:get_vh_registered_users(Server, Opts)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
get_vh_registered_users_number(Server) ->
|
||||
@@ -219,8 +157,6 @@ get_vh_registered_users_number(Server, Opts) ->
|
||||
end
|
||||
end, auth_modules(Server))).
|
||||
|
||||
%% @doc Get the password of the user.
|
||||
%% @spec (User::string(), Server::string()) -> Password::string()
|
||||
get_password(User, Server) ->
|
||||
lists:foldl(
|
||||
fun(M, false) ->
|
||||
@@ -237,17 +173,6 @@ get_password_s(User, Server) ->
|
||||
Password
|
||||
end.
|
||||
|
||||
%% @doc Get the password of the user and the auth module.
|
||||
%% @spec (User::string(), Server::string()) ->
|
||||
%% {Password::string(), AuthModule::atom()} | {false, none}
|
||||
get_password_with_authmodule(User, Server) ->
|
||||
lists:foldl(
|
||||
fun(M, {false, _}) ->
|
||||
{M:get_password(User, Server), M};
|
||||
(_M, {Password, AuthModule}) ->
|
||||
{Password, AuthModule}
|
||||
end, {false, none}, auth_modules(Server)).
|
||||
|
||||
%% Returns true if the user exists in the DB or if an anonymous user is logged
|
||||
%% under the given name
|
||||
is_user_exists(User, Server) ->
|
||||
@@ -258,65 +183,30 @@ is_user_exists(User, Server) ->
|
||||
|
||||
%% Check if the user exists in all authentications module except the module
|
||||
%% passed as parameter
|
||||
%% @spec (Module::atom(), User, Server) -> true | false | maybe
|
||||
is_user_exists_in_other_modules(Module, User, Server) ->
|
||||
is_user_exists_in_other_modules_loop(
|
||||
auth_modules(Server)--[Module],
|
||||
User, Server).
|
||||
is_user_exists_in_other_modules_loop([], _User, _Server) ->
|
||||
false;
|
||||
is_user_exists_in_other_modules_loop([AuthModule|AuthModules], User, Server) ->
|
||||
case AuthModule:is_user_exists(User, Server) of
|
||||
true ->
|
||||
true;
|
||||
false ->
|
||||
is_user_exists_in_other_modules_loop(AuthModules, User, Server);
|
||||
{error, Error} ->
|
||||
?DEBUG("The authentication module ~p returned an error~nwhen "
|
||||
"checking user ~p in server ~p~nError message: ~p",
|
||||
[AuthModule, User, Server, Error]),
|
||||
maybe
|
||||
end.
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:is_user_exists(User, Server)
|
||||
end, auth_modules(Server)--[Module]).
|
||||
|
||||
|
||||
%% @spec (User, Server) -> ok | error | {error, not_allowed}
|
||||
%% @doc Remove user.
|
||||
%% Note: it may return ok even if there was some problem removing the user.
|
||||
remove_user(User, Server) ->
|
||||
R = lists:foreach(
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
M:remove_user(User, Server)
|
||||
end, auth_modules(Server)),
|
||||
case R of
|
||||
ok -> ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]);
|
||||
_ -> none
|
||||
end,
|
||||
R.
|
||||
end, auth_modules(Server)).
|
||||
|
||||
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
|
||||
%% @doc Try to remove user if the provided password is correct.
|
||||
%% The removal is attempted in each auth method provided:
|
||||
%% when one returns 'ok' the loop stops;
|
||||
%% if no method returns 'ok' then it returns the error message indicated by the last method attempted.
|
||||
remove_user(User, Server, Password) ->
|
||||
R = lists:foldl(
|
||||
fun(_M, ok = Res) ->
|
||||
Res;
|
||||
(M, _) ->
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
M:remove_user(User, Server, Password)
|
||||
end, error, auth_modules(Server)),
|
||||
case R of
|
||||
ok -> ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]);
|
||||
_ -> none
|
||||
end,
|
||||
R.
|
||||
end, auth_modules(Server)).
|
||||
|
||||
ctl_process_get_registered(_Val, Host, ["registered-users"]) ->
|
||||
Users = ejabberd_auth:get_vh_registered_users(Host),
|
||||
NewLine = io_lib:format("~n", []),
|
||||
SUsers = lists:sort(Users),
|
||||
FUsers = lists:map(fun({U, _S}) -> [U, NewLine] end, SUsers),
|
||||
?PRINT("~s", [FUsers]),
|
||||
io:format("~s", [FUsers]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process_get_registered(Val, _Host, _Args) ->
|
||||
Val.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -141,17 +141,11 @@ remove_connection(SID, LUser, LServer) ->
|
||||
mnesia:transaction(F).
|
||||
|
||||
%% Register connection
|
||||
register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) ->
|
||||
AuthModule = xml:get_attr_s(auth_module, Info),
|
||||
case AuthModule == ?MODULE of
|
||||
true ->
|
||||
US = {LUser, LServer},
|
||||
mnesia:sync_dirty(
|
||||
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
|
||||
end);
|
||||
false ->
|
||||
ok
|
||||
end.
|
||||
register_connection(SID, #jid{luser = LUser, lserver = LServer}, _) ->
|
||||
US = {LUser, LServer},
|
||||
mnesia:sync_dirty(
|
||||
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
|
||||
end).
|
||||
|
||||
%% Remove an anonymous user from the anonymous users table
|
||||
unregister_connection(SID, #jid{luser = LUser, lserver = LServer}, _) ->
|
||||
@@ -178,10 +172,7 @@ check_password(User, Server, _Password, _StreamID, _Digest) ->
|
||||
%% they however are "reserved")
|
||||
case ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
|
||||
User, Server) of
|
||||
%% If user exists in other module, reject anonnymous authentication
|
||||
true -> false;
|
||||
%% If we are not sure whether the user exists in other module, reject anon auth
|
||||
maybe -> false;
|
||||
false -> login(User, Server)
|
||||
end.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -61,10 +61,7 @@ check_password(User, Server, Password, _StreamID, _Digest) ->
|
||||
check_password(User, Server, Password).
|
||||
|
||||
set_password(User, Server, Password) ->
|
||||
case extauth:set_password(User, Server, Password) of
|
||||
true -> ok;
|
||||
_ -> {error, unknown_problem}
|
||||
end.
|
||||
extauth:set_password(User, Server, Password).
|
||||
|
||||
try_register(_User, _Server, _Password) ->
|
||||
{error, not_allowed}.
|
||||
@@ -83,13 +80,8 @@ get_password(_User, _Server) ->
|
||||
get_password_s(_User, _Server) ->
|
||||
"".
|
||||
|
||||
%% @spec (User, Server) -> true | false | {error, Error}
|
||||
is_user_exists(User, Server) ->
|
||||
try extauth:is_user_exists(User, Server) of
|
||||
Res -> Res
|
||||
catch
|
||||
_:Error -> {error, Error}
|
||||
end.
|
||||
extauth:is_user_exists(User, Server).
|
||||
|
||||
remove_user(_User, _Server) ->
|
||||
{error, not_allowed}.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -98,8 +98,6 @@ check_password(User, Server, Password, StreamID, Digest) ->
|
||||
false
|
||||
end.
|
||||
|
||||
%% @spec (User::string(), Server::string(), Password::string()) ->
|
||||
%% ok | {error, invalid_jid}
|
||||
set_password(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -112,12 +110,10 @@ set_password(User, Server, Password) ->
|
||||
mnesia:write(#passwd{us = US,
|
||||
password = Password})
|
||||
end,
|
||||
{atomic, ok} = mnesia:transaction(F),
|
||||
ok
|
||||
mnesia:transaction(F)
|
||||
end.
|
||||
|
||||
|
||||
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {aborted, Reason}
|
||||
try_register(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -230,7 +226,6 @@ get_password_s(User, Server) ->
|
||||
[]
|
||||
end.
|
||||
|
||||
%% @spec (User, Server) -> true | false | {error, Error}
|
||||
is_user_exists(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -240,13 +235,10 @@ is_user_exists(User, Server) ->
|
||||
false;
|
||||
[_] ->
|
||||
true;
|
||||
Other ->
|
||||
{error, Other}
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
%% @spec (User, Server) -> ok
|
||||
%% @doc Remove user.
|
||||
%% Note: it returns ok even if there was some problem removing the user.
|
||||
remove_user(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -255,10 +247,8 @@ remove_user(User, Server) ->
|
||||
mnesia:delete({passwd, US})
|
||||
end,
|
||||
mnesia:transaction(F),
|
||||
ok.
|
||||
ejabberd_hooks:run(remove_user, LServer, [User, Server]).
|
||||
|
||||
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
|
||||
%% @doc Remove user if the provided password is correct.
|
||||
remove_user(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -276,6 +266,7 @@ remove_user(User, Server, Password) ->
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, ok} ->
|
||||
ejabberd_hooks:run(remove_user, LServer, [User, Server]),
|
||||
ok;
|
||||
{atomic, Res} ->
|
||||
Res;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -48,7 +48,6 @@
|
||||
try_register/3,
|
||||
dirty_get_registered_users/0,
|
||||
get_vh_registered_users/1,
|
||||
get_vh_registered_users_number/1,
|
||||
get_password/2,
|
||||
get_password_s/2,
|
||||
is_user_exists/2,
|
||||
@@ -86,10 +85,6 @@ handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
%% -----
|
||||
|
||||
|
||||
-define(LDAP_SEARCH_TIMEOUT, 5). % Timeout for LDAP search queries in seconds
|
||||
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% API
|
||||
%%%----------------------------------------------------------------------
|
||||
@@ -160,7 +155,6 @@ check_password(User, Server, Password, _StreamID, _Digest) ->
|
||||
set_password(_User, _Server, _Password) ->
|
||||
{error, not_allowed}.
|
||||
|
||||
%% @spec (User, Server, Password) -> {error, not_allowed}
|
||||
try_register(_User, _Server, _Password) ->
|
||||
{error, not_allowed}.
|
||||
|
||||
@@ -177,20 +171,16 @@ get_vh_registered_users(Server) ->
|
||||
Result -> Result
|
||||
end.
|
||||
|
||||
get_vh_registered_users_number(Server) ->
|
||||
length(get_vh_registered_users(Server)).
|
||||
|
||||
get_password(_User, _Server) ->
|
||||
false.
|
||||
|
||||
get_password_s(_User, _Server) ->
|
||||
"".
|
||||
|
||||
%% @spec (User, Server) -> true | false | {error, Error}
|
||||
is_user_exists(User, Server) ->
|
||||
case catch is_user_exists_ldap(User, Server) of
|
||||
{'EXIT', Error} ->
|
||||
{error, Error};
|
||||
{'EXIT', _} ->
|
||||
false;
|
||||
Result ->
|
||||
Result
|
||||
end.
|
||||
@@ -226,7 +216,6 @@ get_vh_registered_users_ldap(Server) ->
|
||||
{ok, EldapFilter} ->
|
||||
case eldap_pool:search(Eldap_ID, [{base, State#state.base},
|
||||
{filter, EldapFilter},
|
||||
{timeout, ?LDAP_SEARCH_TIMEOUT},
|
||||
{attributes, SortedDNAttrs}]) of
|
||||
#eldap_search_result{entries = Entries} ->
|
||||
lists:flatmap(
|
||||
|
||||
+18
-47
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -61,7 +61,6 @@ start(Host) ->
|
||||
plain_password_required() ->
|
||||
false.
|
||||
|
||||
%% @spec (User, Server, Password) -> true | false | {error, Error}
|
||||
check_password(User, Server, Password) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -69,22 +68,14 @@ check_password(User, Server, Password) ->
|
||||
LUser ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
LServer = jlib:nameprep(Server),
|
||||
try odbc_queries:get_password(LServer, Username) of
|
||||
case catch odbc_queries:get_password(LServer, Username) of
|
||||
{selected, ["password"], [{Password}]} ->
|
||||
true; %% Password is correct
|
||||
{selected, ["password"], [{_Password2}]} ->
|
||||
false; %% Password is not correct
|
||||
{selected, ["password"], []} ->
|
||||
false; %% Account does not exist
|
||||
{error, _Error} ->
|
||||
false %% Typical error is that table doesn't exist
|
||||
catch
|
||||
_:_ ->
|
||||
false %% Typical error is database not accessible
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end.
|
||||
|
||||
%% @spec (User, Server, Password, StreamID, Digest) -> true | false | {error, Error}
|
||||
check_password(User, Server, Password, StreamID, Digest) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -92,8 +83,7 @@ check_password(User, Server, Password, StreamID, Digest) ->
|
||||
LUser ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
LServer = jlib:nameprep(Server),
|
||||
try odbc_queries:get_password(LServer, Username) of
|
||||
%% Account exists, check if password is valid
|
||||
case catch odbc_queries:get_password(LServer, Username) of
|
||||
{selected, ["password"], [{Passwd}]} ->
|
||||
DigRes = if
|
||||
Digest /= "" ->
|
||||
@@ -106,18 +96,11 @@ check_password(User, Server, Password, StreamID, Digest) ->
|
||||
true ->
|
||||
(Passwd == Password) and (Password /= "")
|
||||
end;
|
||||
{selected, ["password"], []} ->
|
||||
false; %% Account does not exist
|
||||
{error, _Error} ->
|
||||
false %% Typical error is that table doesn't exist
|
||||
catch
|
||||
_:_ ->
|
||||
false %% Typical error is database not accessible
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end.
|
||||
|
||||
%% @spec (User::string(), Server::string(), Password::string()) ->
|
||||
%% ok | {error, invalid_jid}
|
||||
set_password(User, Server, Password) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -126,14 +109,10 @@ set_password(User, Server, Password) ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
Pass = ejabberd_odbc:escape(Password),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case catch odbc_queries:set_password_t(LServer, Username, Pass) of
|
||||
{atomic, ok} -> ok;
|
||||
Other -> {error, Other}
|
||||
end
|
||||
catch odbc_queries:set_password_t(LServer, Username, Pass)
|
||||
end.
|
||||
|
||||
|
||||
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid}
|
||||
try_register(User, Server, Password) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -223,7 +202,6 @@ get_password_s(User, Server) ->
|
||||
end
|
||||
end.
|
||||
|
||||
%% @spec (User, Server) -> true | false | {error, Error}
|
||||
is_user_exists(User, Server) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -231,22 +209,14 @@ is_user_exists(User, Server) ->
|
||||
LUser ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
LServer = jlib:nameprep(Server),
|
||||
try odbc_queries:get_password(LServer, Username) of
|
||||
case catch odbc_queries:get_password(LServer, Username) of
|
||||
{selected, ["password"], [{_Password}]} ->
|
||||
true; %% Account exists
|
||||
{selected, ["password"], []} ->
|
||||
false; %% Account does not exist
|
||||
{error, Error} ->
|
||||
{error, Error} %% Typical error is that table doesn't exist
|
||||
catch
|
||||
_:B ->
|
||||
{error, B} %% Typical error is database not accessible
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end.
|
||||
|
||||
%% @spec (User, Server) -> ok | error
|
||||
%% @doc Remove user.
|
||||
%% Note: it may return ok even if there was some problem removing the user.
|
||||
remove_user(User, Server) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -255,11 +225,10 @@ remove_user(User, Server) ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
LServer = jlib:nameprep(Server),
|
||||
catch odbc_queries:del_user(LServer, Username),
|
||||
ok
|
||||
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
|
||||
[User, Server])
|
||||
end.
|
||||
|
||||
%% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed
|
||||
%% @doc Remove user if the provided password is correct.
|
||||
remove_user(User, Server, Password) ->
|
||||
case jlib:nodeprep(User) of
|
||||
error ->
|
||||
@@ -273,6 +242,8 @@ remove_user(User, Server, Password) ->
|
||||
LServer, Username, Pass),
|
||||
case Result of
|
||||
{selected, ["password"], [{Password}]} ->
|
||||
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
|
||||
[User, Server]),
|
||||
ok;
|
||||
{selected, ["password"], []} ->
|
||||
not_exists;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -80,8 +80,6 @@ get_password(_User, _Server) ->
|
||||
get_password_s(_User, _Server) ->
|
||||
"".
|
||||
|
||||
%% @spec (User, Server) -> true | false | {error, Error}
|
||||
%% TODO: Improve this function to return an error instead of 'false' when connection to PAM failed
|
||||
is_user_exists(User, Host) ->
|
||||
Service = get_pam_service(Host),
|
||||
case catch epam:acct_mgmt(Service, User) of
|
||||
@@ -93,7 +91,7 @@ remove_user(_User, _Server) ->
|
||||
{error, not_allowed}.
|
||||
|
||||
remove_user(_User, _Server, _Password) ->
|
||||
not_allowed.
|
||||
{error, not_allowed}.
|
||||
|
||||
plain_password_required() ->
|
||||
true.
|
||||
|
||||
+124
-194
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -37,7 +37,7 @@
|
||||
send_element/2,
|
||||
socket_type/0,
|
||||
get_presence/1,
|
||||
get_subscribed/1]).
|
||||
get_subscribed_and_online/1]).
|
||||
|
||||
%% gen_fsm callbacks
|
||||
-export([init/1,
|
||||
@@ -56,13 +56,10 @@
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
|
||||
-define(SETS, gb_sets).
|
||||
-define(DICT, dict).
|
||||
|
||||
%% pres_a contains all the presence available send (either through roster mechanism or directed).
|
||||
%% Directed presence unavailable remove user from pres_a.
|
||||
-record(state, {socket,
|
||||
sockmod,
|
||||
socket_monitor,
|
||||
@@ -83,12 +80,12 @@
|
||||
pres_f = ?SETS:new(),
|
||||
pres_a = ?SETS:new(),
|
||||
pres_i = ?SETS:new(),
|
||||
pres_available = ?DICT:new(),
|
||||
pres_last, pres_pri,
|
||||
pres_timestamp,
|
||||
pres_invis = false,
|
||||
privacy_list = #userlist{},
|
||||
privacy_list = none,
|
||||
conn = unknown,
|
||||
auth_module = unknown,
|
||||
ip,
|
||||
lang}).
|
||||
|
||||
@@ -131,9 +128,6 @@
|
||||
xml:element_to_string(?SERR_HOST_UNKNOWN)).
|
||||
-define(POLICY_VIOLATION_ERR(Lang, Text),
|
||||
xml:element_to_string(?SERRT_POLICY_VIOLATION(Lang, Text))).
|
||||
-define(INVALID_FROM,
|
||||
xml:element_to_string(?SERR_INVALID_FROM)).
|
||||
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% API
|
||||
@@ -176,44 +170,37 @@ init([{SockMod, Socket}, Opts]) ->
|
||||
StartTLSRequired = lists:member(starttls_required, Opts),
|
||||
TLSEnabled = lists:member(tls, Opts),
|
||||
TLS = StartTLS orelse StartTLSRequired orelse TLSEnabled,
|
||||
TLSOpts1 =
|
||||
lists:filter(fun({certfile, _}) -> true;
|
||||
(_) -> false
|
||||
end, Opts),
|
||||
TLSOpts = [verify_none | TLSOpts1],
|
||||
TLSOpts = lists:filter(fun({certfile, _}) -> true;
|
||||
(_) -> false
|
||||
end, Opts),
|
||||
IP = peerip(SockMod, Socket),
|
||||
%% Check if IP is blacklisted:
|
||||
case is_ip_blacklisted(IP) of
|
||||
true ->
|
||||
?INFO_MSG("Connection attempt from blacklisted IP: ~s",
|
||||
[jlib:ip_to_list(IP)]),
|
||||
{stop, normal};
|
||||
false ->
|
||||
Socket1 =
|
||||
if
|
||||
TLSEnabled ->
|
||||
SockMod:starttls(Socket, TLSOpts);
|
||||
true ->
|
||||
Socket
|
||||
end,
|
||||
SocketMonitor = SockMod:monitor(Socket1),
|
||||
{ok, wait_for_stream, #state{socket = Socket1,
|
||||
sockmod = SockMod,
|
||||
socket_monitor = SocketMonitor,
|
||||
zlib = Zlib,
|
||||
tls = TLS,
|
||||
tls_required = StartTLSRequired,
|
||||
tls_enabled = TLSEnabled,
|
||||
tls_options = TLSOpts,
|
||||
streamid = new_id(),
|
||||
access = Access,
|
||||
shaper = Shaper,
|
||||
ip = IP}, ?C2S_OPEN_TIMEOUT}
|
||||
end.
|
||||
Socket1 =
|
||||
if
|
||||
TLSEnabled ->
|
||||
SockMod:starttls(Socket, TLSOpts);
|
||||
true ->
|
||||
Socket
|
||||
end,
|
||||
SocketMonitor = SockMod:monitor(Socket1),
|
||||
{ok, wait_for_stream, #state{socket = Socket1,
|
||||
sockmod = SockMod,
|
||||
socket_monitor = SocketMonitor,
|
||||
zlib = Zlib,
|
||||
tls = TLS,
|
||||
tls_required = StartTLSRequired,
|
||||
tls_enabled = TLSEnabled,
|
||||
tls_options = TLSOpts,
|
||||
streamid = new_id(),
|
||||
access = Access,
|
||||
shaper = Shaper,
|
||||
ip = IP}, ?C2S_OPEN_TIMEOUT}.
|
||||
|
||||
%% Return list of all available resources of contacts,
|
||||
get_subscribed(FsmRef) ->
|
||||
gen_fsm:sync_send_all_state_event(FsmRef, get_subscribed, 1000).
|
||||
%% in form [{JID, Caps}].
|
||||
get_subscribed_and_online(FsmRef) ->
|
||||
gen_fsm:sync_send_all_state_event(
|
||||
FsmRef, get_subscribed_and_online, 1000).
|
||||
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: StateName/2
|
||||
@@ -250,11 +237,11 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
cyrsasl:server_new(
|
||||
"jabber", Server, "", [],
|
||||
fun(U) ->
|
||||
ejabberd_auth:get_password_with_authmodule(
|
||||
ejabberd_auth:get_password(
|
||||
U, Server)
|
||||
end,
|
||||
fun(U, P) ->
|
||||
ejabberd_auth:check_password_with_authmodule(
|
||||
ejabberd_auth:check_password(
|
||||
U, Server, P)
|
||||
end),
|
||||
Mechs = lists:map(
|
||||
@@ -355,9 +342,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
true ->
|
||||
send_text(StateData, Header),
|
||||
fsm_next_state(wait_for_auth,
|
||||
StateData#state{
|
||||
server = Server,
|
||||
lang = Lang})
|
||||
StateData#state{
|
||||
server = Server,
|
||||
lang = Lang})
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
@@ -442,18 +429,17 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
(acl:match_rule(StateData#state.server,
|
||||
StateData#state.access, JID) == allow) of
|
||||
true ->
|
||||
case ejabberd_auth:check_password_with_authmodule(
|
||||
case ejabberd_auth:check_password(
|
||||
U, StateData#state.server, P,
|
||||
StateData#state.streamid, D) of
|
||||
{true, AuthModule} ->
|
||||
true ->
|
||||
?INFO_MSG(
|
||||
"(~w) Accepted legacy authentication for ~s",
|
||||
[StateData#state.socket,
|
||||
jlib:jid_to_string(JID)]),
|
||||
SID = {now(), self()},
|
||||
Conn = get_conn_type(StateData),
|
||||
Info = [{ip, StateData#state.ip}, {conn, Conn},
|
||||
{auth_module, AuthModule}],
|
||||
Info = [{ip, StateData#state.ip}, {conn, Conn}],
|
||||
ejabberd_sm:open_session(
|
||||
SID, U, StateData#state.server, R, Info),
|
||||
Res1 = jlib:make_result_iq_reply(El),
|
||||
@@ -472,7 +458,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
PrivList =
|
||||
ejabberd_hooks:run_fold(
|
||||
privacy_get_user_list, StateData#state.server,
|
||||
#userlist{},
|
||||
none,
|
||||
[U, StateData#state.server]),
|
||||
fsm_next_state(session_established,
|
||||
StateData#state{
|
||||
@@ -481,7 +467,6 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||
jid = JID,
|
||||
sid = SID,
|
||||
conn = Conn,
|
||||
auth_module = AuthModule,
|
||||
pres_f = ?SETS:from_list(Fs1),
|
||||
pres_t = ?SETS:from_list(Ts1),
|
||||
privacy_list = PrivList});
|
||||
@@ -688,14 +673,12 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
|
||||
{xmlelement, "success",
|
||||
[{"xmlns", ?NS_SASL}], []}),
|
||||
U = xml:get_attr_s(username, Props),
|
||||
AuthModule = xml:get_attr_s(auth_module, Props),
|
||||
?INFO_MSG("(~w) Accepted authentication for ~s",
|
||||
[StateData#state.socket, U]),
|
||||
fsm_next_state(wait_for_stream,
|
||||
StateData#state{
|
||||
streamid = new_id(),
|
||||
authenticated = true,
|
||||
auth_module = AuthModule,
|
||||
user = U});
|
||||
{continue, ServerOut, NewSASLState} ->
|
||||
send_element(StateData,
|
||||
@@ -806,8 +789,7 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
|
||||
jlib:jid_to_string(JID)]),
|
||||
SID = {now(), self()},
|
||||
Conn = get_conn_type(StateData),
|
||||
Info = [{ip, StateData#state.ip}, {conn, Conn},
|
||||
{auth_module, StateData#state.auth_module}],
|
||||
Info = [{ip, StateData#state.ip}, {conn, Conn}],
|
||||
ejabberd_sm:open_session(
|
||||
SID, U, StateData#state.server, R, Info),
|
||||
Res = jlib:make_result_iq_reply(El),
|
||||
@@ -824,7 +806,7 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
|
||||
PrivList =
|
||||
ejabberd_hooks:run_fold(
|
||||
privacy_get_user_list, StateData#state.server,
|
||||
#userlist{},
|
||||
none,
|
||||
[U, StateData#state.server]),
|
||||
fsm_next_state(session_established,
|
||||
StateData#state{
|
||||
@@ -860,41 +842,13 @@ wait_for_session(closed, StateData) ->
|
||||
{stop, normal, StateData}.
|
||||
|
||||
|
||||
|
||||
|
||||
session_established({xmlstreamelement, El}, StateData) ->
|
||||
FromJID = StateData#state.jid,
|
||||
% Check 'from' attribute in stanza RFC 3920 Section 9.1.2
|
||||
case check_from(El, FromJID) of
|
||||
'invalid-from' ->
|
||||
send_text(StateData, ?INVALID_FROM ++ ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
_NewEl ->
|
||||
session_established2(El, StateData)
|
||||
end;
|
||||
|
||||
%% We hibernate the process to reduce memory consumption after a
|
||||
%% configurable activity timeout
|
||||
session_established(timeout, StateData) ->
|
||||
%% TODO: Options must be stored in state:
|
||||
Options = [],
|
||||
proc_lib:hibernate(gen_fsm, enter_loop,
|
||||
[?MODULE, Options, session_established, StateData]),
|
||||
fsm_next_state(session_established, StateData);
|
||||
|
||||
session_established({xmlstreamend, _Name}, StateData) ->
|
||||
send_text(StateData, ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
|
||||
session_established({xmlstreamerror, _}, StateData) ->
|
||||
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
|
||||
session_established(closed, StateData) ->
|
||||
{stop, normal, StateData}.
|
||||
|
||||
session_established2(El, StateData) ->
|
||||
{xmlelement, Name, Attrs, _Els} = El,
|
||||
User = StateData#state.user,
|
||||
Server = StateData#state.server,
|
||||
% TODO: check 'from' attribute in stanza
|
||||
FromJID = StateData#state.jid,
|
||||
To = xml:get_attr_s("to", Attrs),
|
||||
ToJID = case To of
|
||||
@@ -946,18 +900,24 @@ session_established2(El, StateData) ->
|
||||
StateData)
|
||||
end;
|
||||
"iq" ->
|
||||
case jlib:iq_query_info(NewEl) of
|
||||
#iq{xmlns = ?NS_PRIVACY} = IQ ->
|
||||
process_privacy_iq(
|
||||
FromJID, ToJID, IQ, StateData);
|
||||
_ ->
|
||||
ejabberd_hooks:run(
|
||||
user_send_packet,
|
||||
Server,
|
||||
[FromJID, ToJID, NewEl]),
|
||||
ejabberd_router:route(
|
||||
FromJID, ToJID, NewEl),
|
||||
StateData
|
||||
case StateData#state.privacy_list of
|
||||
none ->
|
||||
ejabberd_router:route(FromJID, ToJID, NewEl),
|
||||
StateData;
|
||||
_PrivList ->
|
||||
case jlib:iq_query_info(NewEl) of
|
||||
#iq{xmlns = ?NS_PRIVACY} = IQ ->
|
||||
process_privacy_iq(
|
||||
FromJID, ToJID, IQ, StateData);
|
||||
_ ->
|
||||
ejabberd_hooks:run(
|
||||
user_send_packet,
|
||||
Server,
|
||||
[FromJID, ToJID, NewEl]),
|
||||
ejabberd_router:route(
|
||||
FromJID, ToJID, NewEl),
|
||||
StateData
|
||||
end
|
||||
end;
|
||||
"message" ->
|
||||
ejabberd_hooks:run(user_send_packet,
|
||||
@@ -970,7 +930,27 @@ session_established2(El, StateData) ->
|
||||
end
|
||||
end,
|
||||
ejabberd_hooks:run(c2s_loop_debug, [{xmlstreamelement, El}]),
|
||||
fsm_next_state(session_established, NewState).
|
||||
fsm_next_state(session_established, NewState);
|
||||
|
||||
%% We hibernate the process to reduce memory consumption after a
|
||||
%% configurable activity timeout
|
||||
session_established(timeout, StateData) ->
|
||||
%% TODO: Options must be stored in state:
|
||||
Options = [],
|
||||
proc_lib:hibernate(gen_fsm, enter_loop,
|
||||
[?MODULE, Options, session_established, StateData]),
|
||||
fsm_next_state(session_established, StateData);
|
||||
|
||||
session_established({xmlstreamend, _Name}, StateData) ->
|
||||
send_text(StateData, ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
|
||||
session_established({xmlstreamerror, _}, StateData) ->
|
||||
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
|
||||
session_established(closed, StateData) ->
|
||||
{stop, normal, StateData}.
|
||||
|
||||
|
||||
|
||||
@@ -1016,9 +996,16 @@ handle_sync_event({get_presence}, _From, StateName, StateData) ->
|
||||
Reply = {User, Resource, Show, Status},
|
||||
fsm_reply(Reply, StateName, StateData);
|
||||
|
||||
handle_sync_event(get_subscribed, _From, StateName, StateData) ->
|
||||
Subscribed = ?SETS:to_list(StateData#state.pres_f),
|
||||
{reply, Subscribed, StateName, StateData};
|
||||
handle_sync_event(get_subscribed_and_online, _From, StateName, StateData) ->
|
||||
Subscribed = StateData#state.pres_f,
|
||||
Online = StateData#state.pres_available,
|
||||
Pred = fun(User, _Caps) ->
|
||||
?SETS:is_element(jlib:jid_remove_resource(User),
|
||||
Subscribed) orelse
|
||||
?SETS:is_element(User, Subscribed)
|
||||
end,
|
||||
SubscribedAndOnline = ?DICT:filter(Pred, Online),
|
||||
{reply, ?DICT:to_list(SubscribedAndOnline), StateName, StateData};
|
||||
|
||||
handle_sync_event(_Event, _From, StateName, StateData) ->
|
||||
Reply = ok,
|
||||
@@ -1091,17 +1078,13 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
|
||||
Attrs1 = lists:keydelete("type", 1, Attrs),
|
||||
{true, [{"type", "unavailable"} | Attrs1], StateData};
|
||||
"subscribe" ->
|
||||
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
|
||||
{SRes, Attrs, StateData};
|
||||
{true, Attrs, StateData};
|
||||
"subscribed" ->
|
||||
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
|
||||
{SRes, Attrs, StateData};
|
||||
{true, Attrs, StateData};
|
||||
"unsubscribe" ->
|
||||
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
|
||||
{SRes, Attrs, StateData};
|
||||
{true, Attrs, StateData};
|
||||
"unsubscribed" ->
|
||||
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
|
||||
{SRes, Attrs, StateData};
|
||||
{true, Attrs, StateData};
|
||||
_ ->
|
||||
case ejabberd_hooks:run_fold(
|
||||
privacy_check_packet, StateData#state.server,
|
||||
@@ -1115,41 +1098,41 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
|
||||
LFrom = jlib:jid_tolower(From),
|
||||
LBFrom = jlib:jid_remove_resource(LFrom),
|
||||
%% Note contact availability
|
||||
case xml:get_attr_s("type", Attrs) of
|
||||
"unavailable" ->
|
||||
%mod_caps:clear_caps(From);
|
||||
% caps clear disabled cause it breaks things
|
||||
ok;
|
||||
_ ->
|
||||
Caps = mod_caps:read_caps(Els),
|
||||
mod_caps:note_caps(StateData#state.server, From, Caps)
|
||||
end,
|
||||
Caps = mod_caps:read_caps(Els),
|
||||
mod_caps:note_caps(StateData#state.server, From, Caps),
|
||||
NewAvailable = case xml:get_attr_s("type", Attrs) of
|
||||
"unavailable" ->
|
||||
?DICT:erase(LFrom, StateData#state.pres_available);
|
||||
_ ->
|
||||
?DICT:store(LFrom, Caps, StateData#state.pres_available)
|
||||
end,
|
||||
NewStateData = StateData#state{pres_available = NewAvailable},
|
||||
case ?SETS:is_element(
|
||||
LFrom, StateData#state.pres_a) orelse
|
||||
LFrom, NewStateData#state.pres_a) orelse
|
||||
?SETS:is_element(
|
||||
LBFrom, StateData#state.pres_a) of
|
||||
LBFrom, NewStateData#state.pres_a) of
|
||||
true ->
|
||||
{true, Attrs, StateData};
|
||||
{true, Attrs, NewStateData};
|
||||
false ->
|
||||
case ?SETS:is_element(
|
||||
LFrom, StateData#state.pres_f) of
|
||||
LFrom, NewStateData#state.pres_f) of
|
||||
true ->
|
||||
A = ?SETS:add_element(
|
||||
LFrom,
|
||||
StateData#state.pres_a),
|
||||
NewStateData#state.pres_a),
|
||||
{true, Attrs,
|
||||
StateData#state{pres_a = A}};
|
||||
NewStateData#state{pres_a = A}};
|
||||
false ->
|
||||
case ?SETS:is_element(
|
||||
LBFrom, StateData#state.pres_f) of
|
||||
LBFrom, NewStateData#state.pres_f) of
|
||||
true ->
|
||||
A = ?SETS:add_element(
|
||||
LBFrom,
|
||||
StateData#state.pres_a),
|
||||
NewStateData#state.pres_a),
|
||||
{true, Attrs,
|
||||
StateData#state{pres_a = A}};
|
||||
NewStateData#state{pres_a = A}};
|
||||
false ->
|
||||
{true, Attrs, StateData}
|
||||
{true, Attrs, NewStateData}
|
||||
end
|
||||
end
|
||||
end;
|
||||
@@ -1177,7 +1160,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
|
||||
NewPL ->
|
||||
PrivPushIQ =
|
||||
#iq{type = set, xmlns = ?NS_PRIVACY,
|
||||
id = "push" ++ randoms:get_string(),
|
||||
id = "push",
|
||||
sub_el = [{xmlelement, "query",
|
||||
[{"xmlns", ?NS_PRIVACY}],
|
||||
[{xmlelement, "list",
|
||||
@@ -1436,13 +1419,7 @@ process_presence_probe(From, To, StateData) ->
|
||||
allow ->
|
||||
Pid=element(2, StateData#state.sid),
|
||||
ejabberd_hooks:run(presence_probe_hook, StateData#state.server, [From, To, Pid]),
|
||||
%% Don't route a presence probe to oneself
|
||||
case From == To of
|
||||
false ->
|
||||
ejabberd_router:route(To, From, Packet);
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
ejabberd_router:route(To, From, Packet)
|
||||
end;
|
||||
Cond2 ->
|
||||
ejabberd_router:route(To, From,
|
||||
@@ -1464,8 +1441,7 @@ presence_update(From, Packet, StateData) ->
|
||||
StatusTag ->
|
||||
xml:get_tag_cdata(StatusTag)
|
||||
end,
|
||||
Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn},
|
||||
{auth_module, StateData#state.auth_module}],
|
||||
Info = [{ip, StateData#state.ip},{conn, StateData#state.conn}],
|
||||
ejabberd_sm:unset_presence(StateData#state.sid,
|
||||
StateData#state.user,
|
||||
StateData#state.server,
|
||||
@@ -1623,19 +1599,6 @@ presence_track(From, To, Packet, StateData) ->
|
||||
pres_a = A}
|
||||
end.
|
||||
|
||||
%% Check if privacy rules allow this delivery
|
||||
is_privacy_allow(From, To, Packet, PrivacyList) ->
|
||||
User = To#jid.user,
|
||||
Server = To#jid.server,
|
||||
allow == ejabberd_hooks:run_fold(
|
||||
privacy_check_packet, Server,
|
||||
allow,
|
||||
[User,
|
||||
Server,
|
||||
PrivacyList,
|
||||
{From, To, Packet},
|
||||
in]).
|
||||
|
||||
presence_broadcast(StateData, From, JIDSet, Packet) ->
|
||||
lists:foreach(fun(JID) ->
|
||||
FJID = jlib:make_jid(JID),
|
||||
@@ -1810,8 +1773,7 @@ roster_change(IJID, ISubscription, StateData) ->
|
||||
|
||||
|
||||
update_priority(Priority, Packet, StateData) ->
|
||||
Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn},
|
||||
{auth_module, StateData#state.auth_module}],
|
||||
Info = [{ip, StateData#state.ip},{conn, StateData#state.conn}],
|
||||
ejabberd_sm:set_presence(StateData#state.sid,
|
||||
StateData#state.user,
|
||||
StateData#state.server,
|
||||
@@ -1939,8 +1901,7 @@ process_unauthenticated_stanza(StateData, El) ->
|
||||
Res = ejabberd_hooks:run_fold(c2s_unauthenticated_iq,
|
||||
StateData#state.server,
|
||||
empty,
|
||||
[StateData#state.server, IQ,
|
||||
StateData#state.ip]),
|
||||
[StateData#state.server, IQ]),
|
||||
case Res of
|
||||
empty ->
|
||||
% The only reasonable IQ's here are auth and register IQ's
|
||||
@@ -1983,34 +1944,3 @@ fsm_reply(Reply, session_established, StateData) ->
|
||||
{reply, Reply, session_established, StateData, ?C2S_HIBERNATE_TIMEOUT};
|
||||
fsm_reply(Reply, StateName, StateData) ->
|
||||
{reply, Reply, StateName, StateData, ?C2S_OPEN_TIMEOUT}.
|
||||
|
||||
%% Used by c2s blacklist plugins
|
||||
is_ip_blacklisted({IP,_Port}) ->
|
||||
ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]).
|
||||
|
||||
%% Check from attributes
|
||||
%% returns invalid-from|NewElement
|
||||
check_from(El, FromJID) ->
|
||||
case xml:get_tag_attr("from", El) of
|
||||
false ->
|
||||
El;
|
||||
{value, SJID} ->
|
||||
JID = jlib:string_to_jid(SJID),
|
||||
case JID of
|
||||
error ->
|
||||
'invalid-from';
|
||||
#jid{} ->
|
||||
if
|
||||
(JID#jid.luser == FromJID#jid.luser) and
|
||||
(JID#jid.lserver == FromJID#jid.lserver) and
|
||||
(JID#jid.lresource == FromJID#jid.lresource) ->
|
||||
El;
|
||||
(JID#jid.luser == FromJID#jid.luser) and
|
||||
(JID#jid.lserver == FromJID#jid.lserver) and
|
||||
(JID#jid.lresource == "") ->
|
||||
El;
|
||||
true ->
|
||||
'invalid-from'
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -17,7 +17,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_check.erl
|
||||
%%% Author : Mickael Remond <mremond@process-one.net>
|
||||
%%% Purpose : Check ejabberd configuration and
|
||||
%%% Created : 27 Feb 2008 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
%%% 02111-1307 USA
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_check).
|
||||
|
||||
-export([libs/0, config/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("ejabberd_config.hrl").
|
||||
|
||||
-compile([export_all]).
|
||||
|
||||
%% TODO:
|
||||
%% We want to implement library checking at launch time to issue
|
||||
%% human readable user messages.
|
||||
libs() ->
|
||||
ok.
|
||||
|
||||
%% @doc Consistency check on ejabberd configuration
|
||||
config() ->
|
||||
check_database_modules().
|
||||
|
||||
check_database_modules() ->
|
||||
[check_database_module(M)||M<-get_db_used()].
|
||||
|
||||
check_database_module(odbc) ->
|
||||
check_modules(odbc, [odbc, odbc_app, odbc_sup, ejabberd_odbc, ejabberd_odbc_sup, odbc_queries]);
|
||||
check_database_module(mysql) ->
|
||||
check_modules(mysql, [mysql, mysql_auth, mysql_conn, mysql_recv]);
|
||||
check_database_module(pgsql) ->
|
||||
check_modules(pgsql, [pgsql, pgsql_proto, pgsql_tcp, pgsql_util]).
|
||||
|
||||
%% @doc Issue a critical error and throw an exit if needing module is
|
||||
%% missing.
|
||||
check_modules(DB, Modules) ->
|
||||
case get_missing_modules(Modules) of
|
||||
[] ->
|
||||
ok;
|
||||
MissingModules when is_list(MissingModules) ->
|
||||
?CRITICAL_MSG("ejabberd is configured to use '~p', but the following Erlang modules are not installed: '~p'", [DB, MissingModules]),
|
||||
exit(database_module_missing)
|
||||
end.
|
||||
|
||||
|
||||
%% @doc Return the list of undefined modules
|
||||
get_missing_modules(Modules) ->
|
||||
lists:filter(fun(Module) ->
|
||||
case catch Module:module_info() of
|
||||
{'EXIT', {undef, _}} ->
|
||||
true;
|
||||
_ -> false
|
||||
end
|
||||
end, Modules).
|
||||
|
||||
%% @doc Return the list of databases used
|
||||
get_db_used() ->
|
||||
%% Retrieve domains with a database configured:
|
||||
Domains =
|
||||
ets:match(local_config, #local_config{key={odbc_server, '$1'},
|
||||
value='$2'}),
|
||||
%% Check that odbc is the auth method used for those domains:
|
||||
%% and return the database name
|
||||
DBs = lists:foldr(
|
||||
fun([Domain, DB], Acc) ->
|
||||
case check_odbc_option(
|
||||
ejabberd_config:get_local_option(
|
||||
{auth_method, Domain})) of
|
||||
true -> [get_db_type(DB)|Acc];
|
||||
_ -> Acc
|
||||
end
|
||||
end,
|
||||
[], Domains),
|
||||
lists:usort(DBs).
|
||||
|
||||
%% @doc Depending in the DB definition, return which type of DB this is
|
||||
%% Note that MSSQL is detected as ODBC.
|
||||
%% @spec (DB) -> mysql | pgsql | odbc
|
||||
get_db_type(DB) when is_tuple(DB) ->
|
||||
element(1, DB);
|
||||
get_db_type(DB) when is_list(DB) ->
|
||||
odbc.
|
||||
|
||||
%% @doc Return true if odbc option is used
|
||||
check_odbc_option(odbc) ->
|
||||
true;
|
||||
check_odbc_option(AuthMethods) when is_list(AuthMethods) ->
|
||||
lists:member(odbc, AuthMethods);
|
||||
check_odbc_option(_) ->
|
||||
false.
|
||||
+37
-19
@@ -5,7 +5,7 @@
|
||||
%%% Created : 14 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -64,15 +64,9 @@ load_file(File) ->
|
||||
State = lists:foldl(fun search_hosts/2, #state{}, Terms),
|
||||
Res = lists:foldl(fun process_term/2, State, Terms),
|
||||
set_opts(Res);
|
||||
{error, {_LineNumber, erl_parse, _ParseMessage} = Reason} ->
|
||||
ExitText = lists:flatten(File ++ " approximately in the line "
|
||||
++ file:format_error(Reason)),
|
||||
?ERROR_MSG("Problem loading ejabberd config file ~n~s", [ExitText]),
|
||||
exit(ExitText);
|
||||
{error, Reason} ->
|
||||
ExitText = lists:flatten(File ++ ": " ++ file:format_error(Reason)),
|
||||
?ERROR_MSG("Problem loading ejabberd config file ~n~s", [ExitText]),
|
||||
exit(ExitText)
|
||||
?ERROR_MSG("Can't load config file ~p: ~p", [File, Reason]),
|
||||
exit(File ++ ": " ++ file:format_error(Reason))
|
||||
end.
|
||||
|
||||
search_hosts(Term, State) ->
|
||||
@@ -162,8 +156,6 @@ process_term(Term, State) ->
|
||||
add_option({domain_balancing_component_number, Domain}, N, State);
|
||||
{watchdog_admins, Admins} ->
|
||||
add_option(watchdog_admins, Admins, State);
|
||||
{registration_timeout, Timeout} ->
|
||||
add_option(registration_timeout, Timeout, State);
|
||||
{loglevel, Loglevel} ->
|
||||
ejabberd_loglevel:set(Loglevel),
|
||||
State;
|
||||
@@ -190,6 +182,7 @@ process_host_term(Term, Host, State) ->
|
||||
{hosts, _Hosts} ->
|
||||
State;
|
||||
{odbc_server, ODBC_server} ->
|
||||
odbc_modules_found = check_odbc_modules(ODBC_server),
|
||||
add_option({odbc_server, Host}, ODBC_server, State);
|
||||
{Opt, Val} ->
|
||||
add_option({Opt, Host}, Val, State)
|
||||
@@ -219,16 +212,11 @@ add_option(Opt, Val, State) ->
|
||||
end
|
||||
end.
|
||||
|
||||
compact({OptName, Host} = Opt, Val, [], Os) ->
|
||||
?WARNING_MSG("The option '~p' is defined for the host ~p using host_config "
|
||||
"before the global '~p' option. This host_config option may get overwritten.", [OptName, Host, OptName]),
|
||||
compact(Opt, Val, [], Os) ->
|
||||
[#local_config{key = Opt, value = Val}] ++ Os;
|
||||
%% Traverse the list of the options already parsed
|
||||
compact(Opt, Val, [O | Os1], Os2) ->
|
||||
case catch O#local_config.key of
|
||||
%% If the key of a local_config matches the Opt that wants to be added
|
||||
case O#local_config.key of
|
||||
Opt ->
|
||||
%% Then prepend the new value to the list of old values
|
||||
Os2 ++ [#local_config{key = Opt,
|
||||
value = Val++O#local_config.value}
|
||||
] ++ Os1;
|
||||
@@ -321,3 +309,33 @@ get_vh_by_auth_method(AuthMethod) ->
|
||||
mnesia:dirty_select(local_config,
|
||||
[{#local_config{key = {auth_method, '$1'},
|
||||
value=AuthMethod},[],['$1']}]).
|
||||
|
||||
check_odbc_modules(ODBC_server) ->
|
||||
case catch check_odbc_modules2(ODBC_server) of
|
||||
{'EXIT', {undef, [{Module, module_info, []} | _]}} ->
|
||||
?CRITICAL_MSG("ejabberd is configured to use ODBC, but the Erlang module '~p' is not installed.", [Module]),
|
||||
odbc_module_not_found;
|
||||
_ -> odbc_modules_found
|
||||
end.
|
||||
|
||||
check_odbc_modules2(ODBC_server) ->
|
||||
check_modules_exists([ejabberd_odbc, ejabberd_odbc_sup, odbc_queries]),
|
||||
case ODBC_server of
|
||||
{mysql, _Server, _DB, _Username, _Password} ->
|
||||
check_modules_exists([mysql, mysql_auth, mysql_conn, mysql_recv]);
|
||||
|
||||
{mysql, _Server, _Port, _DB, _Username, _Password} ->
|
||||
check_modules_exists([mysql, mysql_auth, mysql_conn, mysql_recv]);
|
||||
|
||||
{pgsql, _Server, _DB, _Username, _Password} ->
|
||||
check_modules_exists([pgsql, pgsql_proto, pgsql_tcp, pgsql_util]);
|
||||
|
||||
{pgsql, _Server, _Port, _DB, _Username, _Password} ->
|
||||
check_modules_exists([pgsql, pgsql_proto, pgsql_tcp, pgsql_util]);
|
||||
|
||||
Server when is_list(Server) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
check_modules_exists(Modules) ->
|
||||
[true = is_list(Module:module_info()) || Module <- Modules].
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+31
-50
@@ -5,7 +5,7 @@
|
||||
%%% Created : 11 Jan 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -30,7 +30,6 @@
|
||||
-export([start/0,
|
||||
init/0,
|
||||
process/1,
|
||||
dump_to_textfile/1,
|
||||
register_commands/3,
|
||||
register_commands/4,
|
||||
unregister_commands/3,
|
||||
@@ -59,7 +58,7 @@ start() ->
|
||||
Node = list_to_atom(SNode1),
|
||||
Status = case rpc:call(Node, ?MODULE, process, [Args]) of
|
||||
{badrpc, Reason} ->
|
||||
?PRINT("RPC failed on the node ~p: ~p~n",
|
||||
io:format("RPC failed on the node ~p: ~p~n",
|
||||
[Node, Reason]),
|
||||
?STATUS_BADRPC;
|
||||
S ->
|
||||
@@ -78,14 +77,14 @@ init() ->
|
||||
|
||||
process(["status"]) ->
|
||||
{InternalStatus, ProvidedStatus} = init:get_status(),
|
||||
?PRINT("Node ~p is ~p. Status: ~p~n",
|
||||
io:format("Node ~p is ~p. Status: ~p~n",
|
||||
[node(), InternalStatus, ProvidedStatus]),
|
||||
case lists:keysearch(ejabberd, 1, application:which_applications()) of
|
||||
false ->
|
||||
?PRINT("ejabberd is not running~n", []),
|
||||
io:format("ejabberd is not running~n", []),
|
||||
?STATUS_ERROR;
|
||||
{value,_Version} ->
|
||||
?PRINT("ejabberd is running~n", []),
|
||||
io:format("ejabberd is running~n", []),
|
||||
?STATUS_SUCCESS
|
||||
end;
|
||||
|
||||
@@ -99,14 +98,6 @@ process(["restart"]) ->
|
||||
|
||||
process(["reopen-log"]) ->
|
||||
ejabberd_logger_h:reopen_log(),
|
||||
case application:get_env(sasl,sasl_error_logger) of
|
||||
{ok, {file, SASLfile}} ->
|
||||
error_logger:delete_report_handler(sasl_report_file_h),
|
||||
ejabberd_logger_h:rotate_log(SASLfile),
|
||||
error_logger:add_report_handler(sasl_report_file_h,
|
||||
{SASLfile, get_sasl_error_logger_type()});
|
||||
_ -> false
|
||||
end,
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["register", User, Server, Password]) ->
|
||||
@@ -114,11 +105,11 @@ process(["register", User, Server, Password]) ->
|
||||
{atomic, ok} ->
|
||||
?STATUS_SUCCESS;
|
||||
{atomic, exists} ->
|
||||
?PRINT("User ~p already registered at node ~p~n",
|
||||
io:format("User ~p already registered at node ~p~n",
|
||||
[User ++ "@" ++ Server, node()]),
|
||||
?STATUS_ERROR;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't register user ~p at node ~p: ~p~n",
|
||||
io:format("Can't register user ~p at node ~p: ~p~n",
|
||||
[User ++ "@" ++ Server, node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -126,7 +117,7 @@ process(["register", User, Server, Password]) ->
|
||||
process(["unregister", User, Server]) ->
|
||||
case ejabberd_auth:remove_user(User, Server) of
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't unregister user ~p at node ~p: ~p~n",
|
||||
io:format("Can't unregister user ~p at node ~p: ~p~n",
|
||||
[User ++ "@" ++ Server, node(), Reason]),
|
||||
?STATUS_ERROR;
|
||||
_ ->
|
||||
@@ -138,7 +129,7 @@ process(["backup", Path]) ->
|
||||
ok ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't store backup in ~p at node ~p: ~p~n",
|
||||
io:format("Can't store backup in ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -148,7 +139,7 @@ process(["dump", Path]) ->
|
||||
ok ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't store dump in ~p at node ~p: ~p~n",
|
||||
io:format("Can't store dump in ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -158,7 +149,7 @@ process(["load", Path]) ->
|
||||
{atomic, ok} ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't load dump in ~p at node ~p: ~p~n",
|
||||
io:format("Can't load dump in ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -168,15 +159,15 @@ process(["restore", Path]) ->
|
||||
{atomic, _} ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't restore backup from ~p at node ~p: ~p~n",
|
||||
io:format("Can't restore backup from ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR;
|
||||
{aborted,{no_exists,Table}} ->
|
||||
?PRINT("Can't restore backup from ~p at node ~p: Table ~p does not exist.~n",
|
||||
io:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.~n",
|
||||
[filename:absname(Path), node(), Table]),
|
||||
?STATUS_ERROR;
|
||||
{aborted,enoent} ->
|
||||
?PRINT("Can't restore backup from ~p at node ~p: File not found.~n",
|
||||
io:format("Can't restore backup from ~p at node ~p: File not found.~n",
|
||||
[filename:absname(Path), node()]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -186,7 +177,7 @@ process(["install-fallback", Path]) ->
|
||||
ok ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't install fallback from ~p at node ~p: ~p~n",
|
||||
io:format("Can't install fallback from ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -196,7 +187,7 @@ process(["import-file", Path]) ->
|
||||
ok ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't import jabberd 1.4 spool file ~p at node ~p: ~p~n",
|
||||
io:format("Can't import jabberd 1.4 spool file ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -206,7 +197,7 @@ process(["import-dir", Path]) ->
|
||||
ok ->
|
||||
?STATUS_SUCCESS;
|
||||
{error, Reason} ->
|
||||
?PRINT("Can't import jabberd 1.4 spool dir ~p at node ~p: ~p~n",
|
||||
io:format("Can't import jabberd 1.4 spool dir ~p at node ~p: ~p~n",
|
||||
[filename:absname(Path), node(), Reason]),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
@@ -216,7 +207,7 @@ process(["delete-expired-messages"]) ->
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["mnesia"]) ->
|
||||
?PRINT("~p~n", [mnesia:system_info(all)]),
|
||||
io:format("~p~n", [mnesia:system_info(all)]),
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["mnesia", "info"]) ->
|
||||
@@ -225,30 +216,30 @@ process(["mnesia", "info"]) ->
|
||||
|
||||
process(["mnesia", Arg]) when is_list(Arg) ->
|
||||
case catch mnesia:system_info(list_to_atom(Arg)) of
|
||||
{'EXIT', Error} -> ?PRINT("Error: ~p~n", [Error]);
|
||||
Return -> ?PRINT("~p~n", [Return])
|
||||
{'EXIT', Error} -> io:format("Error: ~p~n", [Error]);
|
||||
Return -> io:format("~p~n", [Return])
|
||||
end,
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["delete-old-messages", Days]) ->
|
||||
case catch list_to_integer(Days) of
|
||||
{'EXIT',{Reason, _Stack}} ->
|
||||
?PRINT("Can't delete old messages (~p). Please pass an integer as parameter.~n",
|
||||
io:format("Can't delete old messages (~p). Please pass an integer as parameter.~n",
|
||||
[Reason]),
|
||||
?STATUS_ERROR;
|
||||
Integer when Integer >= 0 ->
|
||||
{atomic, _} = mod_offline:remove_old_messages(Integer),
|
||||
?PRINT("Removed messages older than ~s days~n", [Days]),
|
||||
io:format("Removed messages older than ~s days~n", [Days]),
|
||||
?STATUS_SUCCESS;
|
||||
_Integer ->
|
||||
?PRINT("Can't delete old messages. Please pass a positive integer as parameter.~n", []),
|
||||
io:format("Can't delete old messages. Please pass a positive integer as parameter.~n", []),
|
||||
?STATUS_ERROR
|
||||
end;
|
||||
|
||||
process(["vhost", H | Args]) ->
|
||||
case jlib:nameprep(H) of
|
||||
false ->
|
||||
?PRINT("Bad hostname: ~p~n", [H]),
|
||||
io:format("Bad hostname: ~p~n", [H]),
|
||||
?STATUS_ERROR;
|
||||
Host ->
|
||||
case ejabberd_hooks:run_fold(
|
||||
@@ -303,7 +294,7 @@ print_usage() ->
|
||||
[" ", Cmd, string:chars($\s, MaxCmdLen - length(Cmd) + 2),
|
||||
Desc, NewLine]
|
||||
end, CmdDescs),
|
||||
?PRINT(
|
||||
io:format(
|
||||
"Usage: ejabberdctl [--node nodename] command [options]~n"
|
||||
"~n"
|
||||
"Available commands in this ejabberd node:~n"
|
||||
@@ -312,8 +303,8 @@ print_usage() ->
|
||||
"Examples:~n"
|
||||
" ejabberdctl restart~n"
|
||||
" ejabberdctl --node ejabberd@host restart~n"
|
||||
" ejabberdctl vhost jabber.example.org ...~n",
|
||||
[]).
|
||||
" ejabberdctl vhost jabber.example.org ...~n"
|
||||
).
|
||||
|
||||
print_vhost_usage(Host) ->
|
||||
CmdDescs =
|
||||
@@ -336,15 +327,15 @@ print_vhost_usage(Host) ->
|
||||
[" ", Cmd, string:chars($\s, MaxCmdLen - length(Cmd) + 2),
|
||||
Desc, NewLine]
|
||||
end, CmdDescs),
|
||||
?PRINT(
|
||||
io:format(
|
||||
"Usage: ejabberdctl [--node nodename] vhost hostname command [options]~n"
|
||||
"~n"
|
||||
"Available commands in this ejabberd node and this vhost:~n"
|
||||
++ FmtCmdDescs ++
|
||||
"~n"
|
||||
"Examples:~n"
|
||||
" ejabberdctl vhost "++Host++" registered-users~n",
|
||||
[]).
|
||||
" ejabberdctl vhost "++Host++" registered-users~n"
|
||||
).
|
||||
|
||||
register_commands(CmdDescs, Module, Function) ->
|
||||
ets:insert(ejabberd_ctl_cmds, CmdDescs),
|
||||
@@ -409,13 +400,3 @@ dump_tab(F, T) ->
|
||||
fun() -> mnesia:match_object(T, W, read) end),
|
||||
lists:foreach(
|
||||
fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All).
|
||||
|
||||
%% Function copied from Erlang/OTP lib/sasl/src/sasl.erl which doesn't export it
|
||||
get_sasl_error_logger_type () ->
|
||||
case application:get_env (sasl, errlog_type) of
|
||||
{ok, error} -> error;
|
||||
{ok, progress} -> progress;
|
||||
{ok, all} -> all;
|
||||
{ok, Bad} -> exit ({bad_config, {sasl, {errlog_type, Bad}}});
|
||||
_ -> all
|
||||
end.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -53,8 +53,6 @@
|
||||
|
||||
-record(state, {sockmod, socket, receiver}).
|
||||
|
||||
-define(HIBERNATE_TIMEOUT, 90000).
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
@@ -175,8 +173,7 @@ handle_call({starttls, TLSOpts}, _From, State) ->
|
||||
{ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts),
|
||||
ejabberd_receiver:starttls(State#state.receiver, TLSSocket),
|
||||
Reply = ok,
|
||||
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls},
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls}};
|
||||
|
||||
handle_call({starttls, TLSOpts, Data}, _From, State) ->
|
||||
{ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts),
|
||||
@@ -184,8 +181,7 @@ handle_call({starttls, TLSOpts, Data}, _From, State) ->
|
||||
catch (State#state.sockmod):send(
|
||||
State#state.socket, Data),
|
||||
Reply = ok,
|
||||
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls},
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls}};
|
||||
|
||||
handle_call(compress, _From, State) ->
|
||||
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
|
||||
@@ -193,8 +189,7 @@ handle_call(compress, _From, State) ->
|
||||
State#state.socket),
|
||||
ejabberd_receiver:compress(State#state.receiver, ZlibSocket),
|
||||
Reply = ok,
|
||||
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib},
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib}};
|
||||
|
||||
handle_call({compress, Data}, _From, State) ->
|
||||
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
|
||||
@@ -204,36 +199,35 @@ handle_call({compress, Data}, _From, State) ->
|
||||
catch (State#state.sockmod):send(
|
||||
State#state.socket, Data),
|
||||
Reply = ok,
|
||||
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib},
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib}};
|
||||
|
||||
handle_call(reset_stream, _From, State) ->
|
||||
ejabberd_receiver:reset_stream(State#state.receiver),
|
||||
Reply = ok,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call({send, Data}, _From, State) ->
|
||||
catch (State#state.sockmod):send(
|
||||
State#state.socket, Data),
|
||||
Reply = ok,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call({change_shaper, Shaper}, _From, State) ->
|
||||
ejabberd_receiver:change_shaper(State#state.receiver, Shaper),
|
||||
Reply = ok,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(get_sockmod, _From, State) ->
|
||||
Reply = State#state.sockmod,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(get_peer_certificate, _From, State) ->
|
||||
Reply = tls:get_peer_certificate(State#state.socket),
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(get_verify_result, _From, State) ->
|
||||
Reply = tls:get_verify_result(State#state.socket),
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(close, _From, State) ->
|
||||
ejabberd_receiver:close(State#state.receiver),
|
||||
@@ -249,7 +243,7 @@ handle_call(sockname, _From, State) ->
|
||||
_ ->
|
||||
SockMod:sockname(Socket)
|
||||
end,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(peername, _From, State) ->
|
||||
#state{sockmod = SockMod, socket = Socket} = State,
|
||||
@@ -260,11 +254,11 @@ handle_call(peername, _From, State) ->
|
||||
_ ->
|
||||
SockMod:peername(Socket)
|
||||
end,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State};
|
||||
|
||||
handle_call(_Request, _From, State) ->
|
||||
Reply = ok,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{reply, Reply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: handle_cast(Msg, State) -> {noreply, State} |
|
||||
@@ -273,7 +267,7 @@ handle_call(_Request, _From, State) ->
|
||||
%% Description: Handling cast messages
|
||||
%%--------------------------------------------------------------------
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{noreply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: handle_info(Info, State) -> {noreply, State} |
|
||||
@@ -281,11 +275,8 @@ handle_cast(_Msg, State) ->
|
||||
%% {stop, Reason, State}
|
||||
%% Description: Handling all non call/cast messages
|
||||
%%--------------------------------------------------------------------
|
||||
handle_info(timeout, State) ->
|
||||
proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]),
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT};
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{noreply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: terminate(Reason, State) -> void()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -38,9 +38,6 @@
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
%% We do not block on send anymore.
|
||||
-define(TCP_SEND_TIMEOUT, 15000).
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []).
|
||||
|
||||
@@ -92,11 +89,10 @@ init(Port, Module, Opts) ->
|
||||
end, Opts),
|
||||
|
||||
Res = gen_tcp:listen(Port, [binary,
|
||||
{packet, 0},
|
||||
{packet, 0},
|
||||
{active, false},
|
||||
{reuseaddr, true},
|
||||
{nodelay, true},
|
||||
{send_timeout, ?TCP_SEND_TIMEOUT},
|
||||
{keepalive, true} |
|
||||
SockOpts]),
|
||||
case Res of
|
||||
|
||||
+2
-10
@@ -5,7 +5,7 @@
|
||||
%%% Created : 30 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -37,7 +37,6 @@
|
||||
register_iq_handler/5,
|
||||
register_iq_response_handler/4,
|
||||
unregister_iq_handler/2,
|
||||
unregister_iq_response_handler/2,
|
||||
refresh_iq_handlers/0,
|
||||
bounce_resource_packet/3
|
||||
]).
|
||||
@@ -139,9 +138,6 @@ register_iq_handler(Host, XMLNS, Module, Fun) ->
|
||||
register_iq_handler(Host, XMLNS, Module, Fun, Opts) ->
|
||||
ejabberd_local ! {register_iq_handler, Host, XMLNS, Module, Fun, Opts}.
|
||||
|
||||
unregister_iq_response_handler(Host, ID) ->
|
||||
ejabberd_local ! {unregister_iq_response_handler, Host, ID}.
|
||||
|
||||
unregister_iq_handler(Host, XMLNS) ->
|
||||
ejabberd_local ! {unregister_iq_handler, Host, XMLNS}.
|
||||
|
||||
@@ -175,7 +171,6 @@ init([]) ->
|
||||
mnesia:create_table(iq_response,
|
||||
[{ram_copies, [node()]},
|
||||
{attributes, record_info(fields, iq_response)}]),
|
||||
mnesia:add_table_copy(iq_response, node(), ram_copies),
|
||||
{ok, #state{}}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
@@ -218,9 +213,6 @@ handle_info({route, From, To, Packet}, State) ->
|
||||
handle_info({register_iq_response_handler, _Host, ID, Module, Function}, State) ->
|
||||
mnesia:dirty_write(#iq_response{id = ID, module = Module, function = Function}),
|
||||
{noreply, State};
|
||||
handle_info({unregister_iq_response_handler, _Host, ID}, State) ->
|
||||
mnesia:dirty_delete({iq_response, ID}),
|
||||
{noreply, State};
|
||||
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
||||
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
|
||||
catch mod_disco:register_feature(Host, XMLNS),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Oct 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
%% gen_event callbacks
|
||||
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2,
|
||||
code_change/3, reopen_log/0, rotate_log/1]).
|
||||
code_change/3, reopen_log/0]).
|
||||
|
||||
-record(state, {fd, file}).
|
||||
|
||||
@@ -206,11 +206,10 @@ write_time({{Y,Mo,D},{H,Mi,S}}, Type) ->
|
||||
io_lib:format("~n=~s==== ~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w ===~n",
|
||||
[Type, Y, Mo, D, H, Mi, S]).
|
||||
|
||||
%% @doc Rename the log file if exists, to "*-old.log".
|
||||
%% Rename the log file if it the filename exists
|
||||
%% This is needed in systems when the file must be closed before rotation (Windows).
|
||||
%% On most Unix-like system, the file can be renamed from the command line and
|
||||
%% the log can directly be reopened.
|
||||
%% @spec (Filename::string()) -> ok
|
||||
%%the log can directly be reopened.
|
||||
rotate_log(Filename) ->
|
||||
case file:read_file_info(Filename) of
|
||||
{ok, _FileInfo} ->
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
%%% Created : 29 Nov 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -20,7 +20,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
-export([set/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
-define(LOGMODULE, "error_logger").
|
||||
|
||||
%% Error levels:
|
||||
@@ -82,7 +80,7 @@ load_logger(Forms, Mod, Loglevel) ->
|
||||
{ok, M, Bin} ->
|
||||
code:load_binary(M, Fname, Bin);
|
||||
Error ->
|
||||
?CRITICAL_MSG("Error ~p~n", [Error])
|
||||
io:format("Error ~p~n", [Error])
|
||||
end.
|
||||
|
||||
%% --------------------------------------------------------------
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 1 Nov 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+5
-12
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -52,21 +52,14 @@ start_hosts() ->
|
||||
|
||||
%% Start the ODBC module on the given host
|
||||
start_odbc(Host) ->
|
||||
Supervisor_name = gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
||||
ChildSpec =
|
||||
{Supervisor_name,
|
||||
{gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
||||
{ejabberd_odbc_sup, start_link, [Host]},
|
||||
transient,
|
||||
temporary,
|
||||
infinity,
|
||||
supervisor,
|
||||
[ejabberd_odbc_sup]},
|
||||
case supervisor:start_child(ejabberd_sup, ChildSpec) of
|
||||
{ok, _PID} ->
|
||||
ok;
|
||||
_Error ->
|
||||
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", [Supervisor_name, _Error]),
|
||||
start_odbc(Host)
|
||||
end.
|
||||
supervisor:start_child(ejabberd_sup, ChildSpec).
|
||||
|
||||
%% Returns true if we have configured odbc_server for the given host
|
||||
needs_odbc(Host) ->
|
||||
|
||||
+16
-27
@@ -5,7 +5,7 @@
|
||||
%%% Created : 10 Nov 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -54,8 +54,6 @@
|
||||
xml_stream_state,
|
||||
timeout}).
|
||||
|
||||
-define(HIBERNATE_TIMEOUT, 90000).
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
@@ -148,7 +146,7 @@ handle_call({starttls, TLSSocket}, _From,
|
||||
xml_stream_state = NewXMLStreamState},
|
||||
case tls:recv_data(TLSSocket, "") of
|
||||
{ok, TLSData} ->
|
||||
{reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT};
|
||||
{reply, ok, process_data(TLSData, NewState)};
|
||||
{error, _Reason} ->
|
||||
{stop, normal, ok, NewState}
|
||||
end;
|
||||
@@ -163,7 +161,7 @@ handle_call({compress, ZlibSocket}, _From,
|
||||
xml_stream_state = NewXMLStreamState},
|
||||
case ejabberd_zlib:recv_data(ZlibSocket, "") of
|
||||
{ok, ZlibData} ->
|
||||
{reply, ok, process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT};
|
||||
{reply, ok, process_data(ZlibData, NewState)};
|
||||
{error, _Reason} ->
|
||||
{stop, normal, ok, NewState}
|
||||
end;
|
||||
@@ -174,18 +172,17 @@ handle_call(reset_stream, _From,
|
||||
xml_stream:close(XMLStreamState),
|
||||
NewXMLStreamState = xml_stream:new(C2SPid, MaxStanzaSize),
|
||||
Reply = ok,
|
||||
{reply, Reply, State#state{xml_stream_state = NewXMLStreamState},
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, State#state{xml_stream_state = NewXMLStreamState}};
|
||||
handle_call({become_controller, C2SPid}, _From, State) ->
|
||||
XMLStreamState = xml_stream:new(C2SPid, State#state.max_stanza_size),
|
||||
NewState = State#state{c2s_pid = C2SPid,
|
||||
xml_stream_state = XMLStreamState},
|
||||
activate_socket(NewState),
|
||||
Reply = ok,
|
||||
{reply, Reply, NewState, ?HIBERNATE_TIMEOUT};
|
||||
{reply, Reply, NewState};
|
||||
handle_call(_Request, _From, State) ->
|
||||
Reply = ok,
|
||||
{reply, Reply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{reply, Reply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: handle_cast(Msg, State) -> {noreply, State} |
|
||||
@@ -195,11 +192,11 @@ handle_call(_Request, _From, State) ->
|
||||
%%--------------------------------------------------------------------
|
||||
handle_cast({change_shaper, Shaper}, State) ->
|
||||
NewShaperState = shaper:new(Shaper),
|
||||
{noreply, State#state{shaper_state = NewShaperState}, ?HIBERNATE_TIMEOUT};
|
||||
{noreply, State#state{shaper_state = NewShaperState}};
|
||||
handle_cast(close, State) ->
|
||||
{stop, normal, State};
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{noreply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: handle_info(Info, State) -> {noreply, State} |
|
||||
@@ -215,21 +212,19 @@ handle_info({Tag, _TCPSocket, Data},
|
||||
tls ->
|
||||
case tls:recv_data(Socket, Data) of
|
||||
{ok, TLSData} ->
|
||||
{noreply, process_data(TLSData, State),
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{noreply, process_data(TLSData, State)};
|
||||
{error, _Reason} ->
|
||||
{stop, normal, State}
|
||||
end;
|
||||
ejabberd_zlib ->
|
||||
case ejabberd_zlib:recv_data(Socket, Data) of
|
||||
{ok, ZlibData} ->
|
||||
{noreply, process_data(ZlibData, State),
|
||||
?HIBERNATE_TIMEOUT};
|
||||
{noreply, process_data(ZlibData, State)};
|
||||
{error, _Reason} ->
|
||||
{stop, normal, State}
|
||||
end;
|
||||
_ ->
|
||||
{noreply, process_data(Data, State), ?HIBERNATE_TIMEOUT}
|
||||
{noreply, process_data(Data, State)}
|
||||
end;
|
||||
handle_info({Tag, _TCPSocket}, State)
|
||||
when (Tag == tcp_closed) or (Tag == ssl_closed) ->
|
||||
@@ -238,18 +233,15 @@ handle_info({Tag, _TCPSocket, Reason}, State)
|
||||
when (Tag == tcp_error) or (Tag == ssl_error) ->
|
||||
case Reason of
|
||||
timeout ->
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT};
|
||||
{noreply, State};
|
||||
_ ->
|
||||
{stop, normal, State}
|
||||
end;
|
||||
handle_info({timeout, _Ref, activate}, State) ->
|
||||
activate_socket(State),
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT};
|
||||
handle_info(timeout, State) ->
|
||||
proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]),
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT};
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State, ?HIBERNATE_TIMEOUT}.
|
||||
{noreply, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: terminate(Reason, State) -> void()
|
||||
@@ -301,14 +293,11 @@ activate_socket(#state{socket = Socket,
|
||||
|
||||
process_data(Data,
|
||||
#state{xml_stream_state = XMLStreamState,
|
||||
shaper_state = ShaperState,
|
||||
c2s_pid = C2SPid} = State) ->
|
||||
shaper_state = ShaperState} = State) ->
|
||||
?DEBUG("Received XML on stream = ~p", [binary_to_list(Data)]),
|
||||
XMLStreamState1 = xml_stream:parse(XMLStreamState, Data),
|
||||
{NewShaperState, Pause} = shaper:update(ShaperState, size(Data)),
|
||||
if
|
||||
C2SPid == undefined ->
|
||||
ok;
|
||||
Pause > 0 ->
|
||||
erlang:start_timer(Pause, self(), activate);
|
||||
true ->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 27 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -150,9 +150,9 @@ unregister_route(Domain) ->
|
||||
mnesia:transaction(F);
|
||||
_ ->
|
||||
F = fun() ->
|
||||
case mnesia:match_object(#route{domain=LDomain,
|
||||
pid = Pid,
|
||||
_ = '_'}) of
|
||||
case mnesia:match(#route{domain = LDomain,
|
||||
pid = Pid,
|
||||
_ = '_'}) of
|
||||
[R] ->
|
||||
I = R#route.local_hint,
|
||||
mnesia:write(
|
||||
|
||||
+4
-13
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -34,7 +34,6 @@
|
||||
route/3,
|
||||
have_connection/1,
|
||||
has_key/2,
|
||||
get_connections_pids/1,
|
||||
try_register/1,
|
||||
remove_connection/3,
|
||||
dirty_get_connections/0,
|
||||
@@ -109,14 +108,6 @@ has_key(FromTo, Key) ->
|
||||
true
|
||||
end.
|
||||
|
||||
get_connections_pids(FromTo) ->
|
||||
case catch mnesia:dirty_read(s2s, FromTo) of
|
||||
L when is_list(L) ->
|
||||
[Connection#s2s.pid || Connection <- L];
|
||||
_ ->
|
||||
[]
|
||||
end.
|
||||
|
||||
try_register(FromTo) ->
|
||||
Key = randoms:get_string(),
|
||||
MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo),
|
||||
@@ -424,11 +415,11 @@ send_element(Pid, El) ->
|
||||
|
||||
ctl_process(_Val, ["incoming-s2s-number"]) ->
|
||||
N = length(supervisor:which_children(ejabberd_s2s_in_sup)),
|
||||
?PRINT("~p~n", [N]),
|
||||
io:format("~p~n", [N]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process(_Val, ["outgoing-s2s-number"]) ->
|
||||
N = length(supervisor:which_children(ejabberd_s2s_out_sup)),
|
||||
?PRINT("~p~n", [N]),
|
||||
io:format("~p~n", [N]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process(Val, _Args) ->
|
||||
Val.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -50,13 +50,9 @@
|
||||
-include("jlib.hrl").
|
||||
-ifdef(SSL39).
|
||||
-include_lib("ssl/include/ssl_pkix.hrl").
|
||||
-define(PKIXEXPLICIT, 'OTP-PKIX').
|
||||
-define(PKIXIMPLICIT, 'OTP-PKIX').
|
||||
-else.
|
||||
-include_lib("ssl/include/PKIX1Explicit88.hrl").
|
||||
-include_lib("ssl/include/PKIX1Implicit88.hrl").
|
||||
-define(PKIXEXPLICIT, 'PKIX1Explicit88').
|
||||
-define(PKIXIMPLICIT, 'PKIX1Implicit88').
|
||||
-endif.
|
||||
-include("XmppAddr.hrl").
|
||||
|
||||
@@ -352,7 +348,6 @@ stream_established({xmlstreamelement, El}, StateData) ->
|
||||
case {ejabberd_s2s:allow_host(To, From),
|
||||
lists:member(LTo, ejabberd_router:dirty_get_all_domains())} of
|
||||
{true, true} ->
|
||||
ejabberd_s2s_out:terminate_if_waiting_delay(To, From),
|
||||
ejabberd_s2s_out:start(To, From,
|
||||
{verify, self(),
|
||||
Key, StateData#state.streamid}),
|
||||
@@ -608,7 +603,7 @@ get_cert_domains(Cert) ->
|
||||
lists:flatmap(
|
||||
fun(#'AttributeTypeAndValue'{type = ?'id-at-commonName',
|
||||
value = Val}) ->
|
||||
case ?PKIXEXPLICIT:decode('X520CommonName', Val) of
|
||||
case 'PKIX1Explicit88':decode('X520CommonName', Val) of
|
||||
{ok, {_, D1}} ->
|
||||
D = if
|
||||
is_list(D1) -> D1;
|
||||
@@ -642,7 +637,7 @@ get_cert_domains(Cert) ->
|
||||
is_binary(Val) -> Val;
|
||||
true -> Val
|
||||
end,
|
||||
case ?PKIXIMPLICIT:decode('SubjectAltName', BVal) of
|
||||
case 'PKIX1Implicit88':decode('SubjectAltName', BVal) of
|
||||
{ok, SANs} ->
|
||||
lists:flatmap(
|
||||
fun({otherName,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -33,7 +33,6 @@
|
||||
-export([start/3,
|
||||
start_link/3,
|
||||
start_connection/1,
|
||||
terminate_if_waiting_delay/2,
|
||||
stop_connection/1]).
|
||||
|
||||
%% p1_fsm callbacks (same as gen_fsm)
|
||||
@@ -52,8 +51,7 @@
|
||||
handle_info/3,
|
||||
terminate/3,
|
||||
code_change/4,
|
||||
test_get_addr_port/1,
|
||||
get_addr_port/1]).
|
||||
test_get_addr_port/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
@@ -69,7 +67,6 @@
|
||||
db_enabled = true,
|
||||
try_auth = true,
|
||||
myname, server, queue,
|
||||
delay_to_retry = undefined_delay,
|
||||
new = false, verify = false,
|
||||
timer}).
|
||||
|
||||
@@ -93,14 +90,7 @@
|
||||
%% Only change this value if you now what your are doing:
|
||||
-define(FSMLIMITS,[]).
|
||||
%% -define(FSMLIMITS, [{max_queue, 2000}]).
|
||||
-define(FSMTIMEOUT, 30000).
|
||||
|
||||
%% We do not block on send anymore.
|
||||
-define(TCP_SEND_TIMEOUT, 15000).
|
||||
|
||||
%% Maximum delay to wait before retrying to connect after a failed attempt.
|
||||
%% Specified in miliseconds. Default value is 5 minutes.
|
||||
-define(MAX_RETRY_DELAY, 300000).
|
||||
-define(FSMTIMEOUT, 5000).
|
||||
|
||||
-define(STREAM_HEADER,
|
||||
"<?xml version='1.0'?>"
|
||||
@@ -227,7 +217,7 @@ open_socket(init, StateData) ->
|
||||
{error, _Reason} ->
|
||||
?INFO_MSG("s2s connection: ~s -> ~s (remote server not found)",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
wait_before_reconnect(StateData)
|
||||
wait_before_reconnect(StateData, 300000)
|
||||
%%{stop, normal, StateData}
|
||||
end;
|
||||
open_socket(stop, StateData) ->
|
||||
@@ -254,7 +244,6 @@ open_socket1(Addr, Port) ->
|
||||
catch ejabberd_socket:connect(
|
||||
Addr, Port,
|
||||
[binary, {packet, 0},
|
||||
{send_timeout, ?TCP_SEND_TIMEOUT},
|
||||
{active, false}, inet6]);
|
||||
{'EXIT', Reason1} ->
|
||||
?DEBUG("s2s_out: connect crashed ~p~n", [Reason1]),
|
||||
@@ -323,9 +312,6 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
|
||||
send_queue(StateData, StateData#state.queue),
|
||||
?INFO_MSG("Connection established: ~s -> ~s",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
ejabberd_hooks:run(s2s_connect_hook,
|
||||
[StateData#state.myname,
|
||||
StateData#state.server]),
|
||||
{next_state, stream_established,
|
||||
StateData#state{queue = queue:new()}};
|
||||
_ ->
|
||||
@@ -380,14 +366,6 @@ wait_for_validation({xmlstreamerror, _}, StateData) ->
|
||||
?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||
{stop, normal, StateData};
|
||||
|
||||
wait_for_validation(timeout, #state{verify = {VPid, VKey, SID}} = StateData)
|
||||
when is_pid(VPid) and is_list(VKey) and is_list(SID) ->
|
||||
%% This is an auxiliary s2s connection for dialback.
|
||||
%% This timeout is normal and doesn't represent a problem.
|
||||
?DEBUG("wait_for_validation: ~s -> ~s (timeout in verify connection)",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
{stop, normal, StateData};
|
||||
|
||||
wait_for_validation(timeout, StateData) ->
|
||||
?INFO_MSG("wait_for_validation: ~s -> ~s (connect timeout)",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
@@ -442,9 +420,6 @@ wait_for_features({xmlstreamelement, El}, StateData) ->
|
||||
send_queue(StateData, StateData#state.queue),
|
||||
?INFO_MSG("Connection established: ~s -> ~s",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
ejabberd_hooks:run(s2s_connect_hook,
|
||||
[StateData#state.myname,
|
||||
StateData#state.server]),
|
||||
{next_state, stream_established,
|
||||
StateData#state{queue = queue:new()}};
|
||||
SASLEXT and StateData#state.try_auth and
|
||||
@@ -787,12 +762,6 @@ handle_info({timeout, Timer, _}, _StateName,
|
||||
?INFO_MSG("Closing connection with ~s: timeout", [StateData#state.server]),
|
||||
{stop, normal, StateData};
|
||||
|
||||
handle_info(terminate_if_waiting_before_retry, wait_before_retry, StateData) ->
|
||||
{stop, normal, StateData};
|
||||
|
||||
handle_info(terminate_if_waiting_before_retry, StateName, StateData) ->
|
||||
{next_state, StateName, StateData, get_timeout_interval(StateName)};
|
||||
|
||||
handle_info(_, StateName, StateData) ->
|
||||
{next_state, StateName, StateData, get_timeout_interval(StateName)}.
|
||||
|
||||
@@ -1014,7 +983,7 @@ log_s2s_out(false, _, _) -> ok;
|
||||
log_s2s_out(_, Myname, Server) ->
|
||||
?INFO_MSG("Trying to open s2s connection: ~s -> ~s",[Myname, Server]).
|
||||
|
||||
%% Calculate timeout depending on which state we are in:
|
||||
%% Calcultate timeout depending on which state we are in:
|
||||
%% Can return integer > 0 | infinity
|
||||
get_timeout_interval(StateName) ->
|
||||
case StateName of
|
||||
@@ -1030,45 +999,11 @@ get_timeout_interval(StateName) ->
|
||||
|
||||
%% This function is intended to be called at the end of a state
|
||||
%% function that want to wait for a reconnect delay before stopping.
|
||||
wait_before_reconnect(StateData) ->
|
||||
wait_before_reconnect(StateData, Delay) ->
|
||||
%% bounce queue manage by process and Erlang message queue
|
||||
bounce_queue(StateData#state.queue, ?ERR_REMOTE_SERVER_NOT_FOUND),
|
||||
bounce_messages(?ERR_REMOTE_SERVER_NOT_FOUND),
|
||||
cancel_timer(StateData#state.timer),
|
||||
Delay = case StateData#state.delay_to_retry of
|
||||
undefined_delay ->
|
||||
%% The initial delay is random between 1 and 15 seconds
|
||||
%% Return a random integer between 1000 and 15000
|
||||
{_, _, MicroSecs} = now(),
|
||||
(MicroSecs rem 14000) + 1000;
|
||||
D1 ->
|
||||
%% Duplicate the delay with each successive failed
|
||||
%% reconnection attempt, but don't exceed the max
|
||||
lists:min([D1 * 2, get_max_retry_delay()])
|
||||
end,
|
||||
Timer = erlang:start_timer(Delay, self(), []),
|
||||
{next_state, wait_before_retry, StateData#state{timer=Timer,
|
||||
delay_to_retry = Delay,
|
||||
queue = queue:new()}}.
|
||||
|
||||
%% @doc Get the maximum allowed delay for retry to reconnect (in miliseconds).
|
||||
%% The default value is 5 minutes.
|
||||
%% The option {s2s_max_retry_delay, Seconds} can be used (in seconds).
|
||||
%% @spec () -> integer()
|
||||
get_max_retry_delay() ->
|
||||
case ejabberd_config:get_local_option(s2s_max_retry_delay) of
|
||||
Seconds when is_integer(Seconds) ->
|
||||
Seconds*1000;
|
||||
_ ->
|
||||
?MAX_RETRY_DELAY
|
||||
end.
|
||||
|
||||
%% Terminate s2s_out connections that are in state wait_before_retry
|
||||
terminate_if_waiting_delay(From, To) ->
|
||||
FromTo = {From, To},
|
||||
Pids = ejabberd_s2s:get_connections_pids(FromTo),
|
||||
lists:foreach(
|
||||
fun(Pid) ->
|
||||
Pid ! terminate_if_waiting_before_retry
|
||||
end,
|
||||
Pids).
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_service.erl
|
||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||
%%% Purpose : External component management (XEP-0114)
|
||||
%%% Purpose : External component management
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -73,8 +73,7 @@
|
||||
-define(STREAM_TRAILER, "</stream:stream>").
|
||||
|
||||
-define(INVALID_HEADER_ERR,
|
||||
"<stream:stream "
|
||||
"xmlns:stream='http://etherx.jabber.org/streams'>"
|
||||
"<stream:stream>"
|
||||
"<stream:error>Invalid Stream Header</stream:error>"
|
||||
"</stream:stream>"
|
||||
).
|
||||
@@ -169,15 +168,11 @@ init([{SockMod, Socket}, Opts]) ->
|
||||
%%----------------------------------------------------------------------
|
||||
|
||||
wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
||||
% TODO
|
||||
case xml:get_attr_s("xmlns", Attrs) of
|
||||
"jabber:component:accept" ->
|
||||
%% Note: XEP-0114 requires to check that destination is a Jabber
|
||||
%% component served by this Jabber server.
|
||||
%% However several transports don't respect that,
|
||||
%% so ejabberd doesn't check 'to' attribute (EJAB-717)
|
||||
To = xml:get_attr_s("to", Attrs),
|
||||
Header = io_lib:format(?STREAM_HEADER,
|
||||
[StateData#state.streamid, xml:crypt(To)]),
|
||||
[StateData#state.streamid, ?MYNAME]),
|
||||
send_text(StateData, Header),
|
||||
{next_state, wait_for_handshake, StateData};
|
||||
_ ->
|
||||
|
||||
+9
-39
@@ -5,7 +5,7 @@
|
||||
%%% Created : 24 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -59,7 +59,6 @@
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
-include("ejabberd_ctl.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
|
||||
-record(session, {sid, usr, us, priority, info}).
|
||||
-record(state, {}).
|
||||
@@ -385,32 +384,28 @@ do_route(From, To, Packet) ->
|
||||
Reason = xml:get_path_s(
|
||||
Packet,
|
||||
[{elem, "status"}, cdata]),
|
||||
{is_privacy_allow(From, To, Packet) andalso
|
||||
ejabberd_hooks:run_fold(
|
||||
{ejabberd_hooks:run_fold(
|
||||
roster_in_subscription,
|
||||
LServer,
|
||||
false,
|
||||
[User, Server, From, subscribe, Reason]),
|
||||
true};
|
||||
"subscribed" ->
|
||||
{is_privacy_allow(From, To, Packet) andalso
|
||||
ejabberd_hooks:run_fold(
|
||||
{ejabberd_hooks:run_fold(
|
||||
roster_in_subscription,
|
||||
LServer,
|
||||
false,
|
||||
[User, Server, From, subscribed, ""]),
|
||||
true};
|
||||
"unsubscribe" ->
|
||||
{is_privacy_allow(From, To, Packet) andalso
|
||||
ejabberd_hooks:run_fold(
|
||||
{ejabberd_hooks:run_fold(
|
||||
roster_in_subscription,
|
||||
LServer,
|
||||
false,
|
||||
[User, Server, From, unsubscribe, ""]),
|
||||
true};
|
||||
"unsubscribed" ->
|
||||
{is_privacy_allow(From, To, Packet) andalso
|
||||
ejabberd_hooks:run_fold(
|
||||
{ejabberd_hooks:run_fold(
|
||||
roster_in_subscription,
|
||||
LServer,
|
||||
false,
|
||||
@@ -474,31 +469,6 @@ do_route(From, To, Packet) ->
|
||||
end
|
||||
end.
|
||||
|
||||
%% The default list applies to the user as a whole,
|
||||
%% and is processed if there is no active list set
|
||||
%% for the target session/resource to which a stanza is addressed,
|
||||
%% or if there are no current sessions for the user.
|
||||
is_privacy_allow(From, To, Packet) ->
|
||||
User = To#jid.user,
|
||||
Server = To#jid.server,
|
||||
PrivacyList = ejabberd_hooks:run_fold(privacy_get_user_list, Server,
|
||||
#userlist{}, [User, Server]),
|
||||
is_privacy_allow(From, To, Packet, PrivacyList).
|
||||
|
||||
%% Check if privacy rules allow this delivery
|
||||
%% Function copied from ejabberd_c2s.erl
|
||||
is_privacy_allow(From, To, Packet, PrivacyList) ->
|
||||
User = To#jid.user,
|
||||
Server = To#jid.server,
|
||||
allow == ejabberd_hooks:run_fold(
|
||||
privacy_check_packet, Server,
|
||||
allow,
|
||||
[User,
|
||||
Server,
|
||||
PrivacyList,
|
||||
{From, To, Packet},
|
||||
in]).
|
||||
|
||||
route_message(From, To, Packet) ->
|
||||
LUser = To#jid.luser,
|
||||
LServer = To#jid.lserver,
|
||||
@@ -682,18 +652,18 @@ ctl_process(_Val, ["connected-users"]) ->
|
||||
NewLine = io_lib:format("~n", []),
|
||||
SUSRs = lists:sort(USRs),
|
||||
FUSRs = lists:map(fun({U, S, R}) -> [U, $@, S, $/, R, NewLine] end, SUSRs),
|
||||
?PRINT("~s", [FUSRs]),
|
||||
io:format("~s", [FUSRs]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process(_Val, ["connected-users-number"]) ->
|
||||
N = length(dirty_get_sessions_list()),
|
||||
?PRINT("~p~n", [N]),
|
||||
io:format("~p~n", [N]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process(_Val, ["user-resources", User, Server]) ->
|
||||
Resources = get_user_resources(User, Server),
|
||||
NewLine = io_lib:format("~n", []),
|
||||
SResources = lists:sort(Resources),
|
||||
FResources = lists:map(fun(R) -> [R, NewLine] end, SResources),
|
||||
?PRINT("~s", [FResources]),
|
||||
io:format("~s", [FResources]),
|
||||
{stop, ?STATUS_SUCCESS};
|
||||
ctl_process(Val, _Args) ->
|
||||
Val.
|
||||
|
||||
+12
-20
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -65,27 +65,19 @@ start(Module, SockMod, Socket, Opts) ->
|
||||
SocketData = #socket_state{sockmod = SockMod,
|
||||
socket = Socket,
|
||||
receiver = Receiver},
|
||||
case Module:start({?MODULE, SocketData}, Opts) of
|
||||
{ok, Pid} ->
|
||||
case SockMod:controlling_process(Socket, Receiver) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _Reason} ->
|
||||
SockMod:close(Socket)
|
||||
end,
|
||||
ejabberd_receiver:become_controller(Receiver, Pid);
|
||||
{ok, Pid} = Module:start({?MODULE, SocketData}, Opts),
|
||||
case SockMod:controlling_process(Socket, Receiver) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _Reason} ->
|
||||
SockMod:close(Socket)
|
||||
end;
|
||||
end,
|
||||
ejabberd_receiver:become_controller(Receiver, Pid);
|
||||
raw ->
|
||||
case Module:start({SockMod, Socket}, Opts) of
|
||||
{ok, Pid} ->
|
||||
case SockMod:controlling_process(Socket, Pid) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _Reason} ->
|
||||
SockMod:close(Socket)
|
||||
end;
|
||||
{ok, Pid} = Module:start({SockMod, Socket}, Opts),
|
||||
case SockMod:controlling_process(Socket, Pid) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _Reason} ->
|
||||
SockMod:close(Socket)
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 21 Mar 2007 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 18 Jul 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+9
-11
@@ -5,7 +5,7 @@
|
||||
%%% Created : 27 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -30,8 +30,6 @@
|
||||
%% API
|
||||
-export([update/0, update_info/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
@@ -42,7 +40,7 @@ update() ->
|
||||
release_handler_1:eval_script(
|
||||
LowLevelScript, [],
|
||||
[{ejabberd, "", filename:join(Dir, "..")}]),
|
||||
?INFO_MSG("eval: ~p~n", [Eval]),
|
||||
io:format("eval: ~p~n", [Eval]),
|
||||
Eval;
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
@@ -57,28 +55,28 @@ update_info() ->
|
||||
UpdatedBeams =
|
||||
lists:filter(
|
||||
fun(Module) ->
|
||||
{ok, {Module, NewVsn}} =
|
||||
{ok, {Module, [NewVsn]}} =
|
||||
beam_lib:version(code:which(Module)),
|
||||
case code:is_loaded(Module) of
|
||||
{file, _} ->
|
||||
Attrs = Module:module_info(attributes),
|
||||
{value, {vsn, CurVsn}} =
|
||||
{value, {vsn, [CurVsn]}} =
|
||||
lists:keysearch(vsn, 1, Attrs),
|
||||
NewVsn /= CurVsn;
|
||||
false ->
|
||||
false
|
||||
end
|
||||
end, Beams),
|
||||
?INFO_MSG("beam files: ~p~n", [UpdatedBeams]),
|
||||
io:format("beam files: ~p~n", [UpdatedBeams]),
|
||||
Script = make_script(UpdatedBeams),
|
||||
?INFO_MSG("script: ~p~n", [Script]),
|
||||
io:format("script: ~p~n", [Script]),
|
||||
LowLevelScript = make_low_level_script(UpdatedBeams, Script),
|
||||
?INFO_MSG("low level script: ~p~n", [LowLevelScript]),
|
||||
io:format("low level script: ~p~n", [LowLevelScript]),
|
||||
Check =
|
||||
release_handler_1:check_script(
|
||||
LowLevelScript,
|
||||
[{ejabberd, "", filename:join(Dir, "..")}]),
|
||||
?INFO_MSG("check: ~p~n", [Check]),
|
||||
io:format("check: ~p~n", [Check]),
|
||||
{ok, Dir, UpdatedBeams, Script, LowLevelScript, Check};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
|
||||
@@ -4,7 +4,8 @@ include ..\Makefile.inc
|
||||
EFLAGS = -I .. -pz ..
|
||||
|
||||
OUTDIR = ..
|
||||
BEAMS = ..\ejabberd_zlib.beam
|
||||
SOURCES = $(wildcard *.erl)
|
||||
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
|
||||
|
||||
SOURCE = ejabberd_zlib_drv.c
|
||||
OBJECT = ejabberd_zlib_drv.o
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 19 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
* ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -107,14 +107,14 @@ static int ejabberd_zlib_drv_control(ErlDrvData handle,
|
||||
b = driver_alloc_binary(size);
|
||||
b->orig_bytes[0] = 0;
|
||||
|
||||
d->d_stream->next_in = (unsigned char *)buf;
|
||||
d->d_stream->next_in = buf;
|
||||
d->d_stream->avail_in = len;
|
||||
d->d_stream->avail_out = 0;
|
||||
err = Z_OK;
|
||||
|
||||
while (err == Z_OK && d->d_stream->avail_out == 0)
|
||||
{
|
||||
d->d_stream->next_out = (unsigned char *)b->orig_bytes + rlen;
|
||||
d->d_stream->next_out = b->orig_bytes + rlen;
|
||||
d->d_stream->avail_out = BUF_SIZE;
|
||||
|
||||
err = deflate(d->d_stream, Z_SYNC_FLUSH);
|
||||
@@ -135,14 +135,14 @@ static int ejabberd_zlib_drv_control(ErlDrvData handle,
|
||||
b->orig_bytes[0] = 0;
|
||||
|
||||
if (len > 0) {
|
||||
d->i_stream->next_in = (unsigned char *)buf;
|
||||
d->i_stream->next_in = buf;
|
||||
d->i_stream->avail_in = len;
|
||||
d->i_stream->avail_out = 0;
|
||||
err = Z_OK;
|
||||
|
||||
while (err == Z_OK && d->i_stream->avail_out == 0)
|
||||
{
|
||||
d->i_stream->next_out = (unsigned char *)b->orig_bytes + rlen;
|
||||
d->i_stream->next_out = b->orig_bytes + rlen;
|
||||
d->i_stream->avail_out = BUF_SIZE;
|
||||
|
||||
err = inflate(d->i_stream, Z_SYNC_FLUSH);
|
||||
|
||||
@@ -11,7 +11,6 @@ ERL_MAX_ETS_TABLES=1400
|
||||
NODE=ejabberd
|
||||
HOST=localhost
|
||||
ERLANG_NODE=$NODE@$HOST
|
||||
ERL=@erl@
|
||||
ROOTDIR=@rootdir@
|
||||
EJABBERD_CONFIG_PATH=$ROOTDIR/etc/ejabberd/ejabberd.cfg
|
||||
LOGS_DIR=$ROOTDIR/var/log/ejabberd/
|
||||
@@ -46,7 +45,6 @@ ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES"
|
||||
EJABBERD_EBIN=$ROOTDIR/var/lib/ejabberd/ebin
|
||||
EJABBERD_MSGS_PATH=$ROOTDIR/var/lib/ejabberd/priv/msgs
|
||||
EJABBERD_SO_PATH=$ROOTDIR/var/lib/ejabberd/priv/lib
|
||||
EJABBERD_BIN_PATH=$ROOTDIR/var/lib/ejabberd/priv/bin
|
||||
EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log
|
||||
SASL_LOG_PATH=$LOGS_DIR/sasl.log
|
||||
DATETIME=`date "+%Y%m%d-%H%M%S"`
|
||||
@@ -59,7 +57,6 @@ export EJABBERD_CONFIG_PATH
|
||||
export EJABBERD_MSGS_PATH
|
||||
export EJABBERD_LOG_PATH
|
||||
export EJABBERD_SO_PATH
|
||||
export EJABBERD_BIN_PATH
|
||||
export ERL_CRASH_DUMP
|
||||
export ERL_INETRC
|
||||
export ERL_MAX_PORTS
|
||||
@@ -75,7 +72,7 @@ export HOME
|
||||
# start server
|
||||
start ()
|
||||
{
|
||||
$ERL \
|
||||
erl \
|
||||
$NAME $ERLANG_NODE \
|
||||
-noinput -detached \
|
||||
-pa $EJABBERD_EBIN \
|
||||
@@ -104,7 +101,7 @@ debug ()
|
||||
echo "Press any key to continue"
|
||||
read foo
|
||||
echo ""
|
||||
$ERL \
|
||||
erl \
|
||||
$NAME ${NODE}debug \
|
||||
-remsh $ERLANG_NODE \
|
||||
$ERLANG_OPTS $ARGS "$@"
|
||||
@@ -128,8 +125,9 @@ live ()
|
||||
echo "Press any key to continue"
|
||||
read foo
|
||||
echo ""
|
||||
$ERL \
|
||||
erl \
|
||||
$NAME $ERLANG_NODE \
|
||||
$ERLANG_OPTS \
|
||||
-pa $EJABBERD_EBIN \
|
||||
-mnesia dir "\"$EJABBERD_DB\"" \
|
||||
-s ejabberd \
|
||||
@@ -139,7 +137,7 @@ live ()
|
||||
# common control function
|
||||
ctl ()
|
||||
{
|
||||
$ERL \
|
||||
erl \
|
||||
$NAME ejabberdctl \
|
||||
-noinput \
|
||||
-pa $EJABBERD_EBIN \
|
||||
@@ -159,7 +157,6 @@ ctl ()
|
||||
echo " --ctl-config file Config file of ejabberdctl: $CONFIG"
|
||||
echo " --logs dir Directory for logs: $LOGS_DIR"
|
||||
echo " --spool dir Database spool dir: $EJABBERD_DB"
|
||||
echo " --node nodename ejabberd node name: $ERLANG_NODE"
|
||||
echo "";;
|
||||
esac
|
||||
return $result
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 22 Aug 2005 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -6,8 +6,6 @@ CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
|
||||
ASN_FLAGS = -bber_bin +optimize +driver
|
||||
|
||||
ERLANG_CFLAGS = @ERLANG_CFLAGS@
|
||||
ERLANG_LIBS = @ERLANG_LIBS@
|
||||
|
||||
@@ -18,16 +16,14 @@ ifdef debug
|
||||
endif
|
||||
|
||||
OUTDIR = ..
|
||||
SOURCES = $(wildcard *.erl) ELDAPv3.erl
|
||||
SOURCES = $(wildcard *.erl)
|
||||
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
|
||||
|
||||
|
||||
all: $(BEAMS) ELDAPv3.beam
|
||||
|
||||
ELDAPv3.beam: ELDAPv3.erl
|
||||
all: $(BEAMS)
|
||||
|
||||
ELDAPv3.erl: ELDAPv3.asn
|
||||
@ERLC@ $(ASN_FLAGS) -W $(EFLAGS) $<
|
||||
@ERLC@ -bber_bin -W $(EFLAGS) $<
|
||||
|
||||
$(OUTDIR)/%.beam: %.erl ELDAPv3.erl
|
||||
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
|
||||
|
||||
@@ -4,9 +4,8 @@ include ..\Makefile.inc
|
||||
EFLAGS = -I .. -pz ..
|
||||
|
||||
OUTDIR = ..
|
||||
BEAMS = ..\eldap.beam ..\eldap_filter.beam ..\eldap_pool.beam ..\eldap_utils.beam
|
||||
|
||||
ASN_FLAGS = -bber_bin +optimize +driver
|
||||
SOURCES = $(wildcard *.erl)
|
||||
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
|
||||
|
||||
ALL : $(BEAMS)
|
||||
|
||||
@@ -18,7 +17,7 @@ Clean :
|
||||
-@erase $(BEAMS)
|
||||
|
||||
ELDAPv3.erl : ELDAPv3.asn
|
||||
erlc $(ASN_FLAGS) -W $(EFLAGS) ELDAPv3.asn
|
||||
erlc -bber_bin -W $(EFLAGS) ELDAPv3.asn
|
||||
|
||||
$(OUTDIR)\eldap.beam : eldap.erl ELDAPv3.erl
|
||||
erlc -W $(EFLAGS) -o $(OUTDIR) eldap.erl
|
||||
|
||||
+174
-164
@@ -35,14 +35,6 @@
|
||||
|
||||
%%% Modified by Evgeniy Khramtsov <xram@jabber.ru>
|
||||
%%% Implemented queue for bind() requests to prevent pending binds.
|
||||
|
||||
%%% Modified by Christophe Romain <christophe.romain@process-one.net>
|
||||
%%% Improve error case handling
|
||||
|
||||
%%% Modified by Mickael Remond <mremond@process-one.net>
|
||||
%%% Now use ejabberd log mechanism
|
||||
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
-vc('$Id$ ').
|
||||
|
||||
@@ -56,19 +48,20 @@
|
||||
%%% active_bind - sent bind() request and waiting for response
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
%%-compile(export_all).
|
||||
%%-export([Function/Arity, ...]).
|
||||
|
||||
-behaviour(gen_fsm).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
%% External exports
|
||||
-export([start_link/1, start_link/5]).
|
||||
-export([start_link/1, start_link/5, start_link/6]).
|
||||
|
||||
-export([baseObject/0,singleLevel/0,wholeSubtree/0,close/1,
|
||||
equalityMatch/2,greaterOrEqual/2,lessOrEqual/2,
|
||||
approxMatch/2,search/2,substrings/2,present/1,
|
||||
'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2,
|
||||
mod_replace/2, add/3, delete/2, modify_dn/5, bind/3]).
|
||||
-export([get_status/1]).
|
||||
-export([debug_level/2, get_status/1]).
|
||||
|
||||
%% gen_fsm callbacks
|
||||
-export([init/1, connecting/2,
|
||||
@@ -82,28 +75,26 @@
|
||||
-include("eldap.hrl").
|
||||
|
||||
-define(LDAP_VERSION, 3).
|
||||
-define(RETRY_TIMEOUT, 500).
|
||||
-define(RETRY_TIMEOUT, 5000).
|
||||
-define(BIND_TIMEOUT, 10000).
|
||||
-define(CMD_TIMEOUT, 100000).
|
||||
%% Used in gen_fsm sync calls.
|
||||
-define(CALL_TIMEOUT, ?CMD_TIMEOUT + ?BIND_TIMEOUT + ?RETRY_TIMEOUT).
|
||||
%% Used as a timeout for gen_tcp:send/2
|
||||
-define(SEND_TIMEOUT, 30000).
|
||||
-define(MAX_TRANSACTION_ID, 65535).
|
||||
-define(MIN_TRANSACTION_ID, 0).
|
||||
|
||||
-record(eldap, {version = ?LDAP_VERSION,
|
||||
hosts, % Possible hosts running LDAP servers
|
||||
hosts, % Possible hosts running LDAP servers
|
||||
host = null, % Connected Host LDAP server
|
||||
port = 389, % The LDAP server port
|
||||
port = 389 , % The LDAP server port
|
||||
fd = null, % Socket filedescriptor.
|
||||
rootdn = "", % Name of the entry to bind as
|
||||
passwd, % Password for (above) entry
|
||||
id = 0, % LDAP Request ID
|
||||
log, % User provided log function
|
||||
bind_timer, % Ref to bind timeout
|
||||
dict, % dict holding operation params and results
|
||||
req_q % Queue for requests
|
||||
}).
|
||||
bind_q, % Queue for bind() requests
|
||||
debug_level % Integer debug/logging level
|
||||
}).
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% API
|
||||
@@ -113,8 +104,20 @@ start_link(Name) ->
|
||||
gen_fsm:start_link({local, Reg_name}, ?MODULE, [], []).
|
||||
|
||||
start_link(Name, Hosts, Port, Rootdn, Passwd) ->
|
||||
Log = fun(_N, Fmt, Args) -> io:format("---- " ++ Fmt, [Args]) end,
|
||||
Reg_name = list_to_atom("eldap_" ++ Name),
|
||||
gen_fsm:start_link({local, Reg_name}, ?MODULE, {Hosts, Port, Rootdn, Passwd}, []).
|
||||
gen_fsm:start_link({local, Reg_name}, ?MODULE, {Hosts, Port, Rootdn, Passwd, Log}, []).
|
||||
|
||||
start_link(Name, Hosts, Port, Rootdn, Passwd, Log) ->
|
||||
Reg_name = list_to_atom("eldap_" ++ Name),
|
||||
gen_fsm:start_link({local, Reg_name}, ?MODULE, {Hosts, Port, Rootdn, Passwd, Log}, []).
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
%%% Set Debug Level. 0 - none, 1 - errors, 2 - ldap events
|
||||
%%% --------------------------------------------------------------------
|
||||
debug_level(Handle, N) when integer(N) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_all_state_event(Handle1, {debug_level,N}).
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
%%% Get status of connection.
|
||||
@@ -145,8 +148,7 @@ close(Handle) ->
|
||||
%%% --------------------------------------------------------------------
|
||||
add(Handle, Entry, Attributes) when list(Entry),list(Attributes) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(Handle1, {add, Entry, add_attrs(Attributes)},
|
||||
?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {add, Entry, add_attrs(Attributes)}).
|
||||
|
||||
%%% Do sanity check !
|
||||
add_attrs(Attrs) ->
|
||||
@@ -171,7 +173,7 @@ add_attrs(Attrs) ->
|
||||
%%% --------------------------------------------------------------------
|
||||
delete(Handle, Entry) when list(Entry) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(Handle1, {delete, Entry}, ?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {delete, Entry}).
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
%%% Modify an entry. Given an entry a number of modification
|
||||
@@ -186,7 +188,7 @@ delete(Handle, Entry) when list(Entry) ->
|
||||
%%% --------------------------------------------------------------------
|
||||
modify(Handle, Object, Mods) when list(Object), list(Mods) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(Handle1, {modify, Object, Mods}, ?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {modify, Object, Mods}).
|
||||
|
||||
%%%
|
||||
%%% Modification operations.
|
||||
@@ -219,10 +221,7 @@ m(Operation, Type, Values) ->
|
||||
modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup)
|
||||
when list(Entry),list(NewRDN),atom(DelOldRDN),list(NewSup) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(
|
||||
Handle1,
|
||||
{modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)},
|
||||
?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)}).
|
||||
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
@@ -236,7 +235,7 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup)
|
||||
bind(Handle, RootDN, Passwd)
|
||||
when list(RootDN),list(Passwd) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(Handle1, {bind, RootDN, Passwd}, ?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {bind, RootDN, Passwd}, infinity).
|
||||
|
||||
%%% Sanity checks !
|
||||
|
||||
@@ -281,7 +280,7 @@ search(Handle, L) when list(L) ->
|
||||
|
||||
call_search(Handle, A) ->
|
||||
Handle1 = get_handle(Handle),
|
||||
gen_fsm:sync_send_event(Handle1, {search, A}, ?CALL_TIMEOUT).
|
||||
gen_fsm:sync_send_event(Handle1, {search, A}, infinity).
|
||||
|
||||
parse_search_args(Args) ->
|
||||
parse_search_args(Args, #eldap_search{scope = wholeSubtree}).
|
||||
@@ -378,19 +377,21 @@ get_handle(Name) when list(Name) -> list_to_atom("eldap_" ++ Name).
|
||||
%%----------------------------------------------------------------------
|
||||
init([]) ->
|
||||
case get_config() of
|
||||
{ok, Hosts, Rootdn, Passwd} ->
|
||||
init({Hosts, Rootdn, Passwd});
|
||||
{ok, Hosts, Rootdn, Passwd, Log} ->
|
||||
init({Hosts, Rootdn, Passwd, Log});
|
||||
{error, Reason} ->
|
||||
{stop, Reason}
|
||||
end;
|
||||
init({Hosts, Port, Rootdn, Passwd}) ->
|
||||
init({Hosts, Port, Rootdn, Passwd, Log}) ->
|
||||
{ok, connecting, #eldap{hosts = Hosts,
|
||||
port = Port,
|
||||
rootdn = Rootdn,
|
||||
passwd = Passwd,
|
||||
id = 0,
|
||||
log = Log,
|
||||
dict = dict:new(),
|
||||
req_q = queue:new()}, 0}.
|
||||
bind_q = queue:new(),
|
||||
debug_level = 0}, 0}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: StateName/2
|
||||
@@ -413,20 +414,38 @@ connecting(timeout, S) ->
|
||||
%% {stop, Reason, NewStateData} |
|
||||
%% {stop, Reason, Reply, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
connecting(Event, From, S) ->
|
||||
Q = queue:in({Event, From}, S#eldap.req_q),
|
||||
{next_state, connecting, S#eldap{req_q=Q}}.
|
||||
connecting(_Event, _From, S) ->
|
||||
Reply = {error, connecting},
|
||||
{reply, Reply, connecting, S}.
|
||||
|
||||
wait_bind_response(Event, From, S) ->
|
||||
Q = queue:in({Event, From}, S#eldap.req_q),
|
||||
{next_state, wait_bind_response, S#eldap{req_q=Q}}.
|
||||
|
||||
active_bind(Event, From, S) ->
|
||||
Q = queue:in({Event, From}, S#eldap.req_q),
|
||||
{next_state, active_bind, S#eldap{req_q=Q}}.
|
||||
wait_bind_response(_Event, _From, S) ->
|
||||
Reply = {error, wait_bind_response},
|
||||
{reply, Reply, wait_bind_response, S}.
|
||||
|
||||
active(Event, From, S) ->
|
||||
process_command(S, Event, From).
|
||||
case catch send_command(Event, From, S) of
|
||||
{ok, NewS} ->
|
||||
case Event of
|
||||
{bind, _, _} ->
|
||||
{next_state, active_bind, NewS};
|
||||
_ ->
|
||||
{next_state, active, NewS}
|
||||
end;
|
||||
{error, Reason} ->
|
||||
{reply, {error, Reason}, active, S};
|
||||
{'EXIT', Reason} ->
|
||||
{reply, {error, Reason}, active, S}
|
||||
end.
|
||||
|
||||
active_bind({bind, RootDN, Passwd}, From, #eldap{bind_q=Q} = S) ->
|
||||
NewQ = queue:in({{bind, RootDN, Passwd}, From}, Q),
|
||||
{next_state, active_bind, S#eldap{bind_q=NewQ}};
|
||||
active_bind(Event, From, S) ->
|
||||
case catch send_command(Event, From, S) of
|
||||
{ok, NewS} -> {next_state, active_bind, NewS};
|
||||
{error, Reason} -> {reply, {error, Reason}, active_bind, S};
|
||||
{'EXIT', Reason} -> {reply, {error, Reason}, active_bind, S}
|
||||
end.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: handle_event/3
|
||||
@@ -436,8 +455,21 @@ active(Event, From, S) ->
|
||||
%% {stop, Reason, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_event(close, _StateName, S) ->
|
||||
catch gen_tcp:close(S#eldap.fd),
|
||||
{stop, normal, S};
|
||||
gen_tcp:close(S#eldap.fd),
|
||||
{stop, closed, S};
|
||||
|
||||
handle_event(process_bind_q, active_bind, #eldap{bind_q=Q} = S) ->
|
||||
case queue:out(Q) of
|
||||
{{value, {BindEvent, To}}, NewQ} ->
|
||||
NewStateData = case catch send_command(BindEvent, To, S) of
|
||||
{ok, NewS} -> NewS;
|
||||
{error, Reason} -> gen_fsm:reply(To, {error, Reason}), S;
|
||||
{'EXIT', Reason} -> gen_fsm:reply(To, {error, Reason}), S
|
||||
end,
|
||||
{next_state, active_bind, NewStateData#eldap{bind_q=NewQ}};
|
||||
{empty, Q} ->
|
||||
{next_state, active, S}
|
||||
end;
|
||||
|
||||
handle_event(_Event, StateName, S) ->
|
||||
{next_state, StateName, S}.
|
||||
@@ -452,6 +484,9 @@ handle_event(_Event, StateName, S) ->
|
||||
%% {stop, Reason, NewStateData} |
|
||||
%% {stop, Reason, Reply, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_sync_event({debug_level, N}, _From, StateName, S) ->
|
||||
{reply, ok, StateName, S#eldap{debug_level = N}};
|
||||
|
||||
handle_sync_event(_Event, _From, StateName, S) ->
|
||||
{reply, {StateName, S}, StateName, S}.
|
||||
|
||||
@@ -466,61 +501,52 @@ handle_sync_event(_Event, _From, StateName, S) ->
|
||||
%% Packets arriving in various states
|
||||
%%
|
||||
handle_info({tcp, _Socket, Data}, connecting, S) ->
|
||||
?DEBUG("tcp packet received when disconnected!~n~p", [Data]),
|
||||
log1("eldap. tcp packet received when disconnected!~n~p~n", [Data], S),
|
||||
{next_state, connecting, S};
|
||||
|
||||
handle_info({tcp, _Socket, Data}, wait_bind_response, S) ->
|
||||
cancel_timer(S#eldap.bind_timer),
|
||||
case catch recvd_wait_bind_response(Data, S) of
|
||||
bound ->
|
||||
dequeue_commands(S);
|
||||
{fail_bind, _Reason} ->
|
||||
{next_state, connecting, close_and_retry(S)};
|
||||
{'EXIT', _Reason} ->
|
||||
{next_state, connecting, close_and_retry(S)};
|
||||
{error, _Reason} ->
|
||||
{next_state, connecting, close_and_retry(S)}
|
||||
bound -> {next_state, active, S};
|
||||
{fail_bind, _Reason} -> close_and_retry(S),
|
||||
{next_state, connecting, S#eldap{fd = null}};
|
||||
{'EXIT', _Reason} -> close_and_retry(S),
|
||||
{next_state, connecting, S#eldap{fd = null}};
|
||||
{error, _Reason} -> close_and_retry(S),
|
||||
{next_state, connecting, S#eldap{fd = null}}
|
||||
end;
|
||||
|
||||
handle_info({tcp, _Socket, Data}, StateName, S)
|
||||
when StateName == active orelse StateName == active_bind ->
|
||||
when StateName==active; StateName==active_bind ->
|
||||
case catch recvd_packet(Data, S) of
|
||||
{response, Response, RequestType} ->
|
||||
NewS = case Response of
|
||||
{reply, Reply, To, S1} ->
|
||||
gen_fsm:reply(To, Reply),
|
||||
S1;
|
||||
{ok, S1} ->
|
||||
S1
|
||||
end,
|
||||
if (StateName == active_bind andalso
|
||||
RequestType == bindRequest) orelse
|
||||
(StateName == active) ->
|
||||
dequeue_commands(NewS);
|
||||
true ->
|
||||
{next_state, StateName, NewS}
|
||||
end;
|
||||
_ ->
|
||||
{next_state, StateName, S}
|
||||
{reply, Reply, To, NewS} -> gen_fsm:reply(To, Reply),
|
||||
{next_state, StateName, NewS};
|
||||
{ok, NewS} -> {next_state, StateName, NewS};
|
||||
{'EXIT', _Reason} -> {next_state, StateName, S};
|
||||
{error, _Reason} -> {next_state, StateName, S}
|
||||
end;
|
||||
|
||||
handle_info({tcp_closed, _Socket}, Fsm_state, S) ->
|
||||
?WARNING_MSG("LDAP server closed the connection: ~s:~p~nIn State: ~p",
|
||||
[S#eldap.host, S#eldap.port ,Fsm_state]),
|
||||
{next_state, connecting, close_and_retry(S)};
|
||||
handle_info({tcp_closed, _Socket}, _All_fsm_states, S) ->
|
||||
F = fun(_Id, [{Timer, From, _Name}|_]) ->
|
||||
gen_fsm:reply(From, {error, tcp_closed}),
|
||||
cancel_timer(Timer)
|
||||
end,
|
||||
dict:map(F, S#eldap.dict),
|
||||
retry_connect(),
|
||||
{next_state, connecting, S#eldap{fd = null,
|
||||
dict = dict:new(), bind_q=queue:new()}};
|
||||
|
||||
handle_info({tcp_error, _Socket, Reason}, Fsm_state, S) ->
|
||||
?DEBUG("eldap received tcp_error: ~p~nIn State: ~p", [Reason, Fsm_state]),
|
||||
{next_state, connecting, close_and_retry(S)};
|
||||
|
||||
log1("eldap received tcp_error: ~p~nIn State: ~p~n", [Reason, Fsm_state], S),
|
||||
{next_state, Fsm_state, S};
|
||||
%%
|
||||
%% Timers
|
||||
%%
|
||||
handle_info({timeout, Timer, {cmd_timeout, Id}}, StateName, S) ->
|
||||
handle_info({timeout, Timer, {cmd_timeout, Id}}, active, S) ->
|
||||
case cmd_timeout(Timer, Id, S) of
|
||||
{reply, To, Reason, NewS} -> gen_fsm:reply(To, Reason),
|
||||
{next_state, StateName, NewS};
|
||||
{error, _Reason} -> {next_state, StateName, S}
|
||||
{next_state, active, NewS};
|
||||
{error, _Reason} -> {next_state, active, S}
|
||||
end;
|
||||
|
||||
handle_info({timeout, retry_connect}, connecting, S) ->
|
||||
@@ -528,14 +554,15 @@ handle_info({timeout, retry_connect}, connecting, S) ->
|
||||
{next_state, NextState, NewS};
|
||||
|
||||
handle_info({timeout, _Timer, bind_timeout}, wait_bind_response, S) ->
|
||||
{next_state, connecting, close_and_retry(S)};
|
||||
close_and_retry(S),
|
||||
{next_state, connecting, S#eldap{fd = null}};
|
||||
|
||||
%%
|
||||
%% Make sure we don't fill the message queue with rubbish
|
||||
%%
|
||||
handle_info(Info, StateName, S) ->
|
||||
?DEBUG("eldap. Unexpected Info: ~p~nIn state: ~p~n when StateData is: ~p",
|
||||
[Info, StateName, S]),
|
||||
log1("eldap. Unexpected Info: ~p~nIn state: ~p~n when StateData is: ~p~n",
|
||||
[Info, StateName, S], S),
|
||||
{next_state, StateName, S}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
@@ -557,49 +584,18 @@ code_change(_OldVsn, StateName, S, _Extra) ->
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%%----------------------------------------------------------------------
|
||||
dequeue_commands(S) ->
|
||||
case queue:out(S#eldap.req_q) of
|
||||
{{value, {Event, From}}, Q} ->
|
||||
case process_command(S#eldap{req_q=Q}, Event, From) of
|
||||
{_, active, NewS} ->
|
||||
dequeue_commands(NewS);
|
||||
Res ->
|
||||
Res
|
||||
end;
|
||||
{empty, _} ->
|
||||
{next_state, active, S}
|
||||
end.
|
||||
|
||||
process_command(S, Event, From) ->
|
||||
case send_command(Event, From, S) of
|
||||
{ok, NewS} ->
|
||||
case Event of
|
||||
{bind, _, _} ->
|
||||
{next_state, active_bind, NewS};
|
||||
_ ->
|
||||
{next_state, active, NewS}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
Q = queue:in_r({Event, From}, S#eldap.req_q),
|
||||
NewS = close_and_retry(S#eldap{req_q=Q}),
|
||||
{next_state, connecting, NewS}
|
||||
end.
|
||||
|
||||
send_command(Command, From, S) ->
|
||||
Id = bump_id(S),
|
||||
{Name, Request} = gen_req(Command),
|
||||
Message = #'LDAPMessage'{messageID = Id,
|
||||
protocolOp = {Name, Request}},
|
||||
?DEBUG("~p~n",[{Name, Request}]),
|
||||
log2("~p~n",[{Name, Request}], S),
|
||||
{ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message),
|
||||
case gen_tcp:send(S#eldap.fd, Bytes) of
|
||||
ok ->
|
||||
Timer = erlang:start_timer(?CMD_TIMEOUT, self(), {cmd_timeout, Id}),
|
||||
New_dict = dict:store(Id, [{Timer, Command, From, Name}], S#eldap.dict),
|
||||
{ok, S#eldap{id = Id, dict = New_dict}};
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
ok = gen_tcp:send(S#eldap.fd, Bytes),
|
||||
Timer = erlang:start_timer(?CMD_TIMEOUT, self(), {cmd_timeout, Id}),
|
||||
New_dict = dict:store(Id, [{Timer, From, Name}], S#eldap.dict),
|
||||
{ok, S#eldap{id = Id,
|
||||
dict = New_dict}}.
|
||||
|
||||
gen_req({search, A}) ->
|
||||
{searchRequest,
|
||||
@@ -651,11 +647,10 @@ recvd_packet(Pkt, S) ->
|
||||
case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of
|
||||
{ok,Msg} ->
|
||||
Op = Msg#'LDAPMessage'.protocolOp,
|
||||
?DEBUG("~p",[Op]),
|
||||
log2("~p~n",[Op], S),
|
||||
Dict = S#eldap.dict,
|
||||
Id = Msg#'LDAPMessage'.messageID,
|
||||
{Timer, From, Name, Result_so_far} = get_op_rec(Id, Dict),
|
||||
Answer =
|
||||
case {Name, Op} of
|
||||
{searchRequest, {searchResEntry, R}} when
|
||||
record(R,'SearchResultEntry') ->
|
||||
@@ -703,14 +698,14 @@ recvd_packet(Pkt, S) ->
|
||||
New_dict = dict:erase(Id, Dict),
|
||||
cancel_timer(Timer),
|
||||
Reply = check_bind_reply(Result, From),
|
||||
gen_fsm:send_all_state_event(self(), process_bind_q),
|
||||
{reply, Reply, From, S#eldap{dict = New_dict}};
|
||||
{OtherName, OtherResult} ->
|
||||
New_dict = dict:erase(Id, Dict),
|
||||
cancel_timer(Timer),
|
||||
{reply, {error, {invalid_result, OtherName, OtherResult}},
|
||||
From, S#eldap{dict = New_dict}}
|
||||
end,
|
||||
{response, Answer, Name};
|
||||
end;
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
@@ -730,7 +725,7 @@ check_bind_reply(Other, _From) ->
|
||||
|
||||
get_op_rec(Id, Dict) ->
|
||||
case dict:find(Id, Dict) of
|
||||
{ok, [{Timer, _Command, From, Name}|Res]} ->
|
||||
{ok, [{Timer, From, Name}|Res]} ->
|
||||
{Timer, From, Name, Res};
|
||||
error ->
|
||||
throw({error, unkown_id})
|
||||
@@ -749,7 +744,7 @@ recvd_wait_bind_response(Pkt, S) ->
|
||||
check_tag(Pkt),
|
||||
case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of
|
||||
{ok,Msg} ->
|
||||
?DEBUG("~p", [Msg]),
|
||||
log2("~p", [Msg], S),
|
||||
check_id(S#eldap.id, Msg#'LDAPMessage'.messageID),
|
||||
case Msg#'LDAPMessage'.protocolOp of
|
||||
{bindResponse, Result} ->
|
||||
@@ -791,16 +786,13 @@ check_tag(Data) ->
|
||||
end.
|
||||
|
||||
close_and_retry(S) ->
|
||||
catch gen_tcp:close(S#eldap.fd),
|
||||
Queue = dict:fold(
|
||||
fun(_Id, [{Timer, Command, From, _Name}|_], Q) ->
|
||||
cancel_timer(Timer),
|
||||
queue:in_r({Command, From}, Q);
|
||||
(_, _, Q) ->
|
||||
Q
|
||||
end, S#eldap.req_q, S#eldap.dict),
|
||||
erlang:send_after(?RETRY_TIMEOUT, self(), {timeout, retry_connect}),
|
||||
S#eldap{fd=null, req_q=Queue, dict=dict:new()}.
|
||||
gen_tcp:close(S#eldap.fd),
|
||||
retry_connect().
|
||||
|
||||
retry_connect() ->
|
||||
erlang:send_after(?RETRY_TIMEOUT, self(),
|
||||
{timeout, retry_connect}).
|
||||
|
||||
|
||||
%%-----------------------------------------------------------------------
|
||||
%% Sort out timed out commands
|
||||
@@ -808,7 +800,7 @@ close_and_retry(S) ->
|
||||
cmd_timeout(Timer, Id, S) ->
|
||||
Dict = S#eldap.dict,
|
||||
case dict:find(Id, Dict) of
|
||||
{ok, [{Timer, _Command, From, Name}|Res]} ->
|
||||
{ok, [{Timer, From, Name}|Res]} ->
|
||||
case Name of
|
||||
searchRequest ->
|
||||
{Res1, Ref1} = polish(Res),
|
||||
@@ -851,9 +843,7 @@ polish([], Res, Ref) ->
|
||||
%%-----------------------------------------------------------------------
|
||||
connect_bind(S) ->
|
||||
Host = next_host(S#eldap.host, S#eldap.hosts),
|
||||
TcpOpts = [{packet, asn1}, {active, true}, {keepalive, true},
|
||||
{send_timeout, ?SEND_TIMEOUT}, binary],
|
||||
?INFO_MSG("LDAP connection on ~s:~p", [Host, S#eldap.port]),
|
||||
TcpOpts = [{packet, asn1}, {active, true}, {keepalive, true}, binary],
|
||||
case gen_tcp:connect(Host, S#eldap.port, TcpOpts) of
|
||||
{ok, Socket} ->
|
||||
case bind_request(Socket, S) of
|
||||
@@ -863,17 +853,16 @@ connect_bind(S) ->
|
||||
{ok, wait_bind_response, NewS#eldap{fd = Socket,
|
||||
host = Host,
|
||||
bind_timer = Timer}};
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("LDAP bind failed on ~s:~p~nReason: ~p",
|
||||
[Host, S#eldap.port, Reason]),
|
||||
NewS = close_and_retry(S),
|
||||
{ok, connecting, NewS#eldap{host = Host}}
|
||||
{error, _Reason} ->
|
||||
gen_tcp:close(Socket),
|
||||
erlang:send_after(?RETRY_TIMEOUT, self(),
|
||||
{timeout, retry_connect}),
|
||||
{ok, connecting, S#eldap{host = Host}}
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("LDAP connection failed on ~s:~p~nReason: ~p",
|
||||
[Host, S#eldap.port, Reason]),
|
||||
NewS = close_and_retry(S),
|
||||
{ok, connecting, NewS#eldap{host = Host}}
|
||||
{error, _Reason} ->
|
||||
erlang:send_after(?RETRY_TIMEOUT, self(),
|
||||
{timeout, retry_connect}),
|
||||
{ok, connecting, S#eldap{host = Host}}
|
||||
end.
|
||||
|
||||
bind_request(Socket, S) ->
|
||||
@@ -883,12 +872,10 @@ bind_request(Socket, S) ->
|
||||
authentication = {simple, S#eldap.passwd}},
|
||||
Message = #'LDAPMessage'{messageID = Id,
|
||||
protocolOp = {bindRequest, Req}},
|
||||
?DEBUG("Bind Request Message:~p~n",[Message]),
|
||||
log2("Message:~p~n",[Message], S),
|
||||
{ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message),
|
||||
case gen_tcp:send(Socket, Bytes) of
|
||||
ok -> {ok, S#eldap{id = Id}};
|
||||
Error -> Error
|
||||
end.
|
||||
ok = gen_tcp:send(Socket, Bytes),
|
||||
{ok, S#eldap{id = Id}}.
|
||||
|
||||
%% Given last tried Server, find next one to try
|
||||
next_host(null, [H|_]) -> H; % First time, take first
|
||||
@@ -959,8 +946,8 @@ get_config() ->
|
||||
case file:consult(File) of
|
||||
{ok, Entries} ->
|
||||
case catch parse(Entries) of
|
||||
{ok, Hosts, Port, Rootdn, Passwd} ->
|
||||
{ok, Hosts, Port, Rootdn, Passwd};
|
||||
{ok, Hosts, Port, Rootdn, Passwd, Log} ->
|
||||
{ok, Hosts, Port, Rootdn, Passwd, Log};
|
||||
{error, Reason} ->
|
||||
{error, Reason};
|
||||
{'EXIT', Reason} ->
|
||||
@@ -975,7 +962,8 @@ parse(Entries) ->
|
||||
get_hosts(host, Entries),
|
||||
get_integer(port, Entries),
|
||||
get_list(rootdn, Entries),
|
||||
get_list(passwd, Entries)}.
|
||||
get_list(passwd, Entries),
|
||||
get_log(log, Entries)}.
|
||||
|
||||
get_integer(Key, List) ->
|
||||
case lists:keysearch(Key, 1, List) of
|
||||
@@ -997,6 +985,16 @@ get_list(Key, List) ->
|
||||
throw({error, "No Entry in Config for " ++ atom_to_list(Key)})
|
||||
end.
|
||||
|
||||
get_log(Key, List) ->
|
||||
case lists:keysearch(Key, 1, List) of
|
||||
{value, {Key, Value}} when function(Value) ->
|
||||
Value;
|
||||
{value, {Key, _Else}} ->
|
||||
false;
|
||||
false ->
|
||||
fun(_Level, Format, Args) -> io:format("--- " ++ Format, Args) end
|
||||
end.
|
||||
|
||||
get_hosts(Key, List) ->
|
||||
lists:map(fun({Key1, {A,B,C,D}}) when integer(A),
|
||||
integer(B),
|
||||
@@ -1018,3 +1016,15 @@ bump_id(#eldap{id = Id}) when Id > ?MAX_TRANSACTION_ID ->
|
||||
?MIN_TRANSACTION_ID;
|
||||
bump_id(#eldap{id = Id}) ->
|
||||
Id + 1.
|
||||
|
||||
%%% --------------------------------------------------------------------
|
||||
%%% Log routines. Call a user provided log routine Fun.
|
||||
%%% --------------------------------------------------------------------
|
||||
|
||||
log1(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 1, N).
|
||||
log2(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 2, N).
|
||||
|
||||
log(Fun, Str, Args, This_level, Status) when function(Fun), This_level =< Status ->
|
||||
catch Fun(This_level, Str, Args);
|
||||
log(_, _, _, _, _) ->
|
||||
ok.
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%%% Author: Evgeniy Khramtsov <xramtsov@gmail.com>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -17,7 +17,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Nov 2006 by Evgeniy Khramtsov <xram@jabber.ru>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Oct 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* Workaround for EI encode_string bug
|
||||
*/
|
||||
|
||||
int x_fix_buff(ei_x_buff* x, int szneeded);
|
||||
|
||||
#define put8(s,n) do { \
|
||||
(s)[0] = (char)((n) & 0xff); \
|
||||
(s) += 1; \
|
||||
|
||||
+3
-4
@@ -5,7 +5,7 @@
|
||||
%%% Created : 30 Jul 2004 by Leif Johansson <leifj@it.su.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -30,7 +30,6 @@
|
||||
-export([start/2, stop/1, init/2,
|
||||
check_password/3, set_password/3, is_user_exists/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
start(Host, ExtPrg) ->
|
||||
spawn(?MODULE, init, [Host, ExtPrg]).
|
||||
@@ -77,7 +76,7 @@ loop(Port) ->
|
||||
exit(normal)
|
||||
end;
|
||||
{'EXIT', Port, Reason} ->
|
||||
?CRITICAL_MSG("~p ~n", [Reason]),
|
||||
io:format("~p ~n", [Reason]),
|
||||
exit(port_terminated)
|
||||
end.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 22 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+10
-25
@@ -5,7 +5,7 @@
|
||||
%%% Created : 24 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -30,7 +30,6 @@
|
||||
-export([start/0,
|
||||
start_module/3,
|
||||
stop_module/2,
|
||||
stop_module_keep_config/2,
|
||||
get_opt/2,
|
||||
get_opt/3,
|
||||
get_opt_host/3,
|
||||
@@ -62,47 +61,33 @@ start() ->
|
||||
|
||||
|
||||
start_module(Host, Module, Opts) ->
|
||||
set_module_opts_mnesia(Host, Module, Opts),
|
||||
ets:insert(ejabberd_modules,
|
||||
#ejabberd_module{module_host = {Module, Host},
|
||||
opts = Opts}),
|
||||
case catch Module:start(Host, Opts) of
|
||||
{'EXIT', Reason} ->
|
||||
del_module_mnesia(Host, Module),
|
||||
ets:delete(ejabberd_modules, {Module, Host}),
|
||||
?ERROR_MSG("~p", [Reason]);
|
||||
_ ->
|
||||
set_module_opts_mnesia(Host, Module, Opts),
|
||||
ets:insert(ejabberd_modules,
|
||||
#ejabberd_module{module_host = {Module, Host},
|
||||
opts = Opts}),
|
||||
ok
|
||||
end.
|
||||
|
||||
%% @doc Stop the module in a host, and forget its configuration.
|
||||
stop_module(Host, Module) ->
|
||||
case stop_module_keep_config(Host, Module) of
|
||||
error ->
|
||||
error;
|
||||
ok ->
|
||||
del_module_mnesia(Host, Module)
|
||||
end.
|
||||
|
||||
%% @doc Stop the module in a host, but keep its configuration.
|
||||
%% As the module configuration is kept in the Mnesia local_config table,
|
||||
%% when ejabberd is restarted the module will be started again.
|
||||
%% This function is useful when ejabberd is being stopped
|
||||
%% and it stops all modules.
|
||||
stop_module_keep_config(Host, Module) ->
|
||||
case catch Module:stop(Host) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p", [Reason]),
|
||||
error;
|
||||
?ERROR_MSG("~p", [Reason]);
|
||||
{wait, ProcList} when is_list(ProcList) ->
|
||||
lists:foreach(fun wait_for_process/1, ProcList),
|
||||
del_module_mnesia(Host, Module),
|
||||
ets:delete(ejabberd_modules, {Module, Host}),
|
||||
ok;
|
||||
{wait, Process} ->
|
||||
wait_for_process(Process),
|
||||
del_module_mnesia(Host, Module),
|
||||
ets:delete(ejabberd_modules, {Module, Host}),
|
||||
ok;
|
||||
_ ->
|
||||
del_module_mnesia(Host, Module),
|
||||
ets:delete(ejabberd_modules, {Module, Host}),
|
||||
ok
|
||||
end.
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 10 Apr 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 2 Feb 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+3
-19
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -34,8 +34,6 @@
|
||||
make_correct_from_to_attrs/3,
|
||||
replace_from_to_attrs/3,
|
||||
replace_from_to/3,
|
||||
replace_from_attrs/2,
|
||||
replace_from/2,
|
||||
remove_attr/2,
|
||||
make_jid/3,
|
||||
make_jid/1,
|
||||
@@ -61,8 +59,7 @@
|
||||
now_to_local_string/1,
|
||||
datetime_string_to_timestamp/1,
|
||||
decode_base64/1,
|
||||
encode_base64/1,
|
||||
ip_to_list/1]).
|
||||
encode_base64/1]).
|
||||
|
||||
-include("jlib.hrl").
|
||||
|
||||
@@ -155,13 +152,6 @@ replace_from_to(From, To, {xmlelement, Name, Attrs, Els}) ->
|
||||
Attrs),
|
||||
{xmlelement, Name, NewAttrs, Els}.
|
||||
|
||||
replace_from_attrs(From, Attrs) ->
|
||||
Attrs1 = lists:keydelete("from", 1, Attrs),
|
||||
[{"from", From} | Attrs1].
|
||||
|
||||
replace_from(From, {xmlelement, Name, Attrs, Els}) ->
|
||||
NewAttrs = replace_from_attrs(jlib:jid_to_string(From), Attrs),
|
||||
{xmlelement, Name, NewAttrs, Els}.
|
||||
|
||||
remove_attr(Attr, {xmlelement, Name, Attrs, Els}) ->
|
||||
NewAttrs = lists:keydelete(Attr, 1, Attrs),
|
||||
@@ -686,9 +676,3 @@ e(X) when X>51, X<62 -> X-4;
|
||||
e(62) -> $+;
|
||||
e(63) -> $/;
|
||||
e(X) -> exit({bad_encode_base64_token, X}).
|
||||
|
||||
%% Convert Erlang inet IP to list
|
||||
ip_to_list({IP, _Port}) ->
|
||||
ip_to_list(IP);
|
||||
ip_to_list({A,B,C,D}) ->
|
||||
lists:flatten(io_lib:format("~w.~w.~w.~w",[A,B,C,D])).
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -11,7 +11,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 15 Nov 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 11 Aug 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+17
-93
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Oct 2006 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -31,11 +31,8 @@
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([read_caps/1,
|
||||
get_caps/1,
|
||||
note_caps/3,
|
||||
clear_caps/1,
|
||||
get_features/2,
|
||||
get_user_resources/2,
|
||||
handle_disco_response/3]).
|
||||
|
||||
%% gen_mod callbacks
|
||||
@@ -56,12 +53,9 @@
|
||||
|
||||
-define(PROCNAME, ejabberd_mod_caps).
|
||||
-define(DICT, dict).
|
||||
-define(CAPS_QUERY_TIMEOUT, 60000). % 1mn without answer, consider client never answer
|
||||
|
||||
-record(caps, {node, version, exts}).
|
||||
-record(caps_features, {node_pair, features}).
|
||||
-record(user_caps, {jid, caps}).
|
||||
-record(user_caps_resources, {uid, resource}).
|
||||
-record(state, {host,
|
||||
disco_requests = ?DICT:new(),
|
||||
feature_queries = []}).
|
||||
@@ -94,41 +88,12 @@ read_caps([_ | Tail], Result) ->
|
||||
read_caps([], Result) ->
|
||||
Result.
|
||||
|
||||
%% get_caps reads user caps from database
|
||||
get_caps(JID) ->
|
||||
case catch mnesia:dirty_read({user_caps, list_to_binary(jlib:jid_to_string(JID))}) of
|
||||
[#user_caps{caps=Caps}] ->
|
||||
Caps;
|
||||
_ ->
|
||||
nothing
|
||||
end.
|
||||
|
||||
%% clear_caps removes user caps from database
|
||||
clear_caps(JID) ->
|
||||
{U, S, R} = jlib:jid_tolower(JID),
|
||||
BJID = list_to_binary(jlib:jid_to_string(JID)),
|
||||
BUID = list_to_binary(jlib:jid_to_string({U, S, []})),
|
||||
catch mnesia:dirty_delete({user_caps, BJID}),
|
||||
catch mnesia:dirty_delete_object(#user_caps_resources{uid = BUID, resource = list_to_binary(R)}),
|
||||
ok.
|
||||
|
||||
%% give default user resource
|
||||
get_user_resources(LUser, LServer) ->
|
||||
BUID = list_to_binary(jlib:jid_to_string({LUser, LServer, []})),
|
||||
case catch mnesia:dirty_read({user_caps_resources, BUID}) of
|
||||
{'EXIT', _} ->
|
||||
[];
|
||||
Resources ->
|
||||
lists:map(fun(#user_caps_resources{resource=R}) -> binary_to_list(R) end, Resources)
|
||||
end.
|
||||
|
||||
%% note_caps should be called to make the module request disco
|
||||
%% information. Host is the host that asks, From is the full JID that
|
||||
%% sent the caps packet, and Caps is what read_caps returned.
|
||||
note_caps(Host, From, Caps) ->
|
||||
case Caps of
|
||||
nothing ->
|
||||
ok;
|
||||
nothing -> ok;
|
||||
_ ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
gen_server:cast(Proc, {note_caps, From, Caps})
|
||||
@@ -139,8 +104,7 @@ note_caps(Host, From, Caps) ->
|
||||
%% timeout error.
|
||||
get_features(Host, Caps) ->
|
||||
case Caps of
|
||||
nothing ->
|
||||
[];
|
||||
nothing -> [];
|
||||
#caps{} ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
gen_server:call(Proc, {get_features, Caps})
|
||||
@@ -163,7 +127,8 @@ start(Host, Opts) ->
|
||||
|
||||
stop(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
gen_server:call(Proc, stop).
|
||||
gen_server:call(Proc, stop),
|
||||
supervisor:stop_child(ejabberd_sup, Proc).
|
||||
|
||||
%%====================================================================
|
||||
%% gen_server callbacks
|
||||
@@ -173,14 +138,7 @@ init([Host, _Opts]) ->
|
||||
mnesia:create_table(caps_features,
|
||||
[{ram_copies, [node()]},
|
||||
{attributes, record_info(fields, caps_features)}]),
|
||||
mnesia:create_table(user_caps,
|
||||
[{disc_copies, [node()]},
|
||||
{attributes, record_info(fields, user_caps)}]),
|
||||
mnesia:create_table(user_caps_resources,
|
||||
[{disc_copies, [node()]},
|
||||
{type, bag},
|
||||
{attributes, record_info(fields, user_caps_resources)}]),
|
||||
mnesia:delete_table(user_caps_default),
|
||||
mnesia:add_table_copy(caps_features, node(), ram_copies),
|
||||
{ok, #state{host = Host}}.
|
||||
|
||||
maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) ->
|
||||
@@ -228,21 +186,10 @@ handle_call(stop, _From, State) ->
|
||||
{stop, normal, ok, State}.
|
||||
|
||||
handle_cast({note_caps, From,
|
||||
#caps{node = Node, version = Version, exts = Exts} = Caps},
|
||||
#caps{node = Node, version = Version, exts = Exts}},
|
||||
#state{host = Host, disco_requests = Requests} = State) ->
|
||||
%% XXX: this leads to race conditions where ejabberd will send
|
||||
%% lots of caps disco requests.
|
||||
{U, S, R} = jlib:jid_tolower(From),
|
||||
BJID = list_to_binary(jlib:jid_to_string(From)),
|
||||
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}),
|
||||
case ejabberd_sm:get_user_resources(U, S) of
|
||||
[] ->
|
||||
% only store resources of caps aware external contacts
|
||||
BUID = list_to_binary(jlib:jid_to_string(jlib:jid_remove_resource(From))),
|
||||
mnesia:dirty_write(#user_caps_resources{uid = BUID, resource = list_to_binary(R)});
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
SubNodes = [Version | Exts],
|
||||
%% Now, find which of these are not already in the database.
|
||||
Fun = fun() ->
|
||||
@@ -257,22 +204,22 @@ handle_cast({note_caps, From,
|
||||
end,
|
||||
case mnesia:transaction(Fun) of
|
||||
{atomic, Missing} ->
|
||||
%% For each unknown caps "subnode", we send a disco request.
|
||||
NewRequests = lists:foldl(
|
||||
fun(SubNode, Dict) ->
|
||||
%% For each unknown caps "subnode", we send a disco
|
||||
%% request.
|
||||
NewRequests =
|
||||
lists:foldl(
|
||||
fun(SubNode, Dict) ->
|
||||
ID = randoms:get_string(),
|
||||
Stanza =
|
||||
{xmlelement, "iq",
|
||||
[{"type", "get"},
|
||||
{"id", ID}],
|
||||
[{xmlelement, "query",
|
||||
[{"xmlns", ?NS_DISCO_INFO},
|
||||
{"node", lists:concat([Node, "#", SubNode])}],
|
||||
[{"xmlns", ?NS_DISCO_INFO}],
|
||||
[]}]},
|
||||
ejabberd_local:register_iq_response_handler
|
||||
(Host, ID, ?MODULE, handle_disco_response),
|
||||
ejabberd_router:route(jlib:make_jid("", Host, ""), From, Stanza),
|
||||
timer:send_after(?CAPS_QUERY_TIMEOUT, self(), {disco_timeout, ID}),
|
||||
?DICT:store(ID, {Node, SubNode}, Dict)
|
||||
end, Requests, Missing),
|
||||
{noreply, State#state{disco_requests = NewRequests}};
|
||||
@@ -304,39 +251,16 @@ handle_cast({disco_response, From, _To,
|
||||
?ERROR_MSG("ID '~s' matches no query", [ID])
|
||||
end;
|
||||
{error, _} ->
|
||||
%% XXX: if we get error, we cache empty feature not to probe the client continuously
|
||||
case ?DICT:find(ID, Requests) of
|
||||
{ok, {Node, SubNode}} ->
|
||||
Features = [],
|
||||
mnesia:transaction(
|
||||
fun() ->
|
||||
mnesia:write(#caps_features{node_pair = {Node, SubNode},
|
||||
features = Features})
|
||||
end),
|
||||
gen_server:cast(self(), visit_feature_queries);
|
||||
error ->
|
||||
?ERROR_MSG("ID '~s' matches no query", [ID])
|
||||
end;
|
||||
%gen_server:cast(self(), visit_feature_queries),
|
||||
%?DEBUG("Error IQ reponse from ~s:~n~p", [jlib:jid_to_string(From), SubEls]);
|
||||
gen_server:cast(self(), visit_feature_queries),
|
||||
?ERROR_MSG("Error IQ reponse IQ from ~s:~n~p", [jlib:jid_to_string(From), SubEls]);
|
||||
{result, _} ->
|
||||
?DEBUG("Invalid IQ contents from ~s:~n~p", [jlib:jid_to_string(From), SubEls]);
|
||||
?ERROR_MSG("Invalid IQ contents from ~s:~n~p", [jlib:jid_to_string(From), SubEls]);
|
||||
_ ->
|
||||
%% Can't do anything about errors
|
||||
ok
|
||||
end,
|
||||
NewRequests = ?DICT:erase(ID, Requests),
|
||||
{noreply, State#state{disco_requests = NewRequests}};
|
||||
handle_cast({disco_timeout, ID}, #state{host = Host, disco_requests = Requests} = State) ->
|
||||
%% do not wait a response anymore for this IQ, client certainly will never answer
|
||||
NewRequests = case ?DICT:is_key(ID, Requests) of
|
||||
true ->
|
||||
ejabberd_local:unregister_iq_response_handler(Host, ID),
|
||||
?DICT:erase(ID, Requests);
|
||||
false ->
|
||||
Requests
|
||||
end,
|
||||
{noreply, State#state{disco_requests = NewRequests}};
|
||||
handle_cast(visit_feature_queries, #state{feature_queries = FeatureQueries} = State) ->
|
||||
Timestamp = timestamp(),
|
||||
NewFeatureQueries =
|
||||
|
||||
+38
-62
@@ -5,7 +5,7 @@
|
||||
%%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -307,10 +307,8 @@ adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To,
|
||||
{result, Its} -> Its;
|
||||
empty -> []
|
||||
end,
|
||||
PermLev = get_permission_level(From),
|
||||
%% Recursively get all configure commands
|
||||
Nodes = recursively_get_local_items(PermLev, LServer, "", Server,
|
||||
Lang),
|
||||
Nodes = recursively_get_local_items(LServer, "", Server, Lang),
|
||||
Nodes1 = lists:filter(
|
||||
fun(N) ->
|
||||
Nd = xml:get_tag_attr_s("node", N),
|
||||
@@ -327,15 +325,15 @@ adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To,
|
||||
Acc
|
||||
end.
|
||||
|
||||
recursively_get_local_items(_PermLev, _LServer, "online users", _Server, _Lang) ->
|
||||
recursively_get_local_items(_LServer, "online users", _Server, _Lang) ->
|
||||
[];
|
||||
|
||||
recursively_get_local_items(_PermLev, _LServer, "all users", _Server, _Lang) ->
|
||||
recursively_get_local_items(_LServer, "all users", _Server, _Lang) ->
|
||||
[];
|
||||
|
||||
recursively_get_local_items(PermLev, LServer, Node, Server, Lang) ->
|
||||
recursively_get_local_items(LServer, Node, Server, Lang) ->
|
||||
LNode = tokenize(Node),
|
||||
Items = case get_local_items({PermLev, LServer}, LNode, Server, Lang) of
|
||||
Items = case get_local_items(LServer, LNode, Server, Lang) of
|
||||
{result, Res} ->
|
||||
Res;
|
||||
{error, _Error} ->
|
||||
@@ -350,17 +348,11 @@ recursively_get_local_items(PermLev, LServer, Node, Server, Lang) ->
|
||||
[];
|
||||
true ->
|
||||
[N, recursively_get_local_items(
|
||||
PermLev, LServer, Nd, Server, Lang)]
|
||||
LServer, Nd, Server, Lang)]
|
||||
end
|
||||
end, Items)),
|
||||
Nodes.
|
||||
|
||||
get_permission_level(JID) ->
|
||||
case acl:match_rule(global, configure, JID) of
|
||||
allow -> global;
|
||||
deny -> vhost
|
||||
end.
|
||||
|
||||
%%%-----------------------------------------------------------------------
|
||||
|
||||
-define(ITEMS_RESULT(Allow, LNode, Fallback),
|
||||
@@ -368,8 +360,7 @@ get_permission_level(JID) ->
|
||||
deny ->
|
||||
Fallback;
|
||||
allow ->
|
||||
PermLev = get_permission_level(From),
|
||||
case get_local_items({PermLev, LServer}, LNode,
|
||||
case get_local_items(LServer, LNode,
|
||||
jlib:jid_to_string(To), Lang) of
|
||||
{result, Res} ->
|
||||
{result, Res};
|
||||
@@ -392,8 +383,7 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To, "", Lang) ->
|
||||
deny ->
|
||||
{result, Items};
|
||||
allow ->
|
||||
PermLev = get_permission_level(From),
|
||||
case get_local_items({PermLev, LServer}, [],
|
||||
case get_local_items(LServer, [],
|
||||
jlib:jid_to_string(To), Lang) of
|
||||
{result, Res} ->
|
||||
{result, Items ++ Res};
|
||||
@@ -458,9 +448,6 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To, Node, Lang) ->
|
||||
|
||||
%%%-----------------------------------------------------------------------
|
||||
|
||||
%% @spec ({PermissionLevel, Host}, [string()], Server::string(), Lang)
|
||||
%% -> {result, [xmlelement()]}
|
||||
%% PermissionLevel = global | vhost
|
||||
get_local_items(_Host, [], Server, Lang) ->
|
||||
{result,
|
||||
[?NODE("Configuration", "config"),
|
||||
@@ -497,13 +484,13 @@ get_local_items(_Host, ["user"], Server, Lang) ->
|
||||
get_local_items(_Host, ["http:" | _], _Server, _Lang) ->
|
||||
{result, []};
|
||||
|
||||
get_local_items({_, Host}, ["online users"], _Server, _Lang) ->
|
||||
get_local_items(Host, ["online users"], _Server, _Lang) ->
|
||||
{result, get_online_vh_users(Host)};
|
||||
|
||||
get_local_items({_, Host}, ["all users"], _Server, _Lang) ->
|
||||
get_local_items(Host, ["all users"], _Server, _Lang) ->
|
||||
{result, get_all_vh_users(Host)};
|
||||
|
||||
get_local_items({_, Host}, ["all users", [$@ | Diap]], _Server, _Lang) ->
|
||||
get_local_items(Host, ["all users", [$@ | Diap]], _Server, _Lang) ->
|
||||
case catch ejabberd_auth:get_vh_registered_users(Host) of
|
||||
{'EXIT', _Reason} ->
|
||||
?ERR_INTERNAL_SERVER_ERROR;
|
||||
@@ -527,10 +514,10 @@ get_local_items({_, Host}, ["all users", [$@ | Diap]], _Server, _Lang) ->
|
||||
end
|
||||
end;
|
||||
|
||||
get_local_items({_, Host}, ["outgoing s2s"], _Server, Lang) ->
|
||||
get_local_items(Host, ["outgoing s2s"], _Server, Lang) ->
|
||||
{result, get_outgoing_s2s(Host, Lang)};
|
||||
|
||||
get_local_items({_, Host}, ["outgoing s2s", To], _Server, Lang) ->
|
||||
get_local_items(Host, ["outgoing s2s", To], _Server, Lang) ->
|
||||
{result, get_outgoing_s2s(Host, Lang, To)};
|
||||
|
||||
get_local_items(_Host, ["running nodes"], Server, Lang) ->
|
||||
@@ -539,7 +526,7 @@ get_local_items(_Host, ["running nodes"], Server, Lang) ->
|
||||
get_local_items(_Host, ["stopped nodes"], _Server, Lang) ->
|
||||
{result, get_stopped_nodes(Lang)};
|
||||
|
||||
get_local_items({global, _Host}, ["running nodes", ENode], Server, Lang) ->
|
||||
get_local_items(_Host, ["running nodes", ENode], Server, Lang) ->
|
||||
{result,
|
||||
[?NODE("Database", "running nodes/" ++ ENode ++ "/DB"),
|
||||
?NODE("Modules", "running nodes/" ++ ENode ++ "/modules"),
|
||||
@@ -550,11 +537,6 @@ get_local_items({global, _Host}, ["running nodes", ENode], Server, Lang) ->
|
||||
?NODE("Shut Down Service", "running nodes/" ++ ENode ++ "/shutdown")
|
||||
]};
|
||||
|
||||
get_local_items({vhost, _Host}, ["running nodes", ENode], Server, Lang) ->
|
||||
{result,
|
||||
[?NODE("Modules", "running nodes/" ++ ENode ++ "/modules")
|
||||
]};
|
||||
|
||||
get_local_items(_Host, ["running nodes", _ENode, "DB"], _Server, _Lang) ->
|
||||
{result, []};
|
||||
|
||||
@@ -726,8 +708,8 @@ get_stopped_nodes(_Lang) ->
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
-define(COMMANDS_RESULT(LServerOrGlobal, From, To, Request),
|
||||
case acl:match_rule(LServerOrGlobal, configure, From) of
|
||||
-define(COMMANDS_RESULT(Allow, From, To, Request),
|
||||
case Allow of
|
||||
deny ->
|
||||
{error, ?ERR_FORBIDDEN};
|
||||
allow ->
|
||||
@@ -737,23 +719,24 @@ get_stopped_nodes(_Lang) ->
|
||||
adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To,
|
||||
#adhoc_request{node = Node} = Request) ->
|
||||
LNode = tokenize(Node),
|
||||
Allow = acl:match_rule(LServer, configure, From),
|
||||
case LNode of
|
||||
["running nodes", _ENode, "DB"] ->
|
||||
?COMMANDS_RESULT(global, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["running nodes", _ENode, "modules", _] ->
|
||||
?COMMANDS_RESULT(LServer, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["running nodes", _ENode, "backup", _] ->
|
||||
?COMMANDS_RESULT(global, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["running nodes", _ENode, "import", _] ->
|
||||
?COMMANDS_RESULT(global, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["running nodes", _ENode, "restart"] ->
|
||||
?COMMANDS_RESULT(global, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["running nodes", _ENode, "shutdown"] ->
|
||||
?COMMANDS_RESULT(global, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
["config", _] ->
|
||||
?COMMANDS_RESULT(LServer, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
?NS_ADMINL(_) ->
|
||||
?COMMANDS_RESULT(LServer, From, To, Request);
|
||||
?COMMANDS_RESULT(Allow, From, To, Request);
|
||||
_ ->
|
||||
Acc
|
||||
end.
|
||||
@@ -1265,7 +1248,7 @@ get_form(Host, ?NS_ADMINL("get-registered-users-num"), Lang) ->
|
||||
[?HFIELD(),
|
||||
{xmlelement,
|
||||
"field",
|
||||
[{"type", "text-single"},
|
||||
[{"type", "jid-single"},
|
||||
{"label", ?T(Lang, "Number of registered users")},
|
||||
{"var", "registeredusersnum"}],
|
||||
[{xmlelement, "value", [], [{xmlcdata, Num}]}]
|
||||
@@ -1279,7 +1262,7 @@ get_form(Host, ?NS_ADMINL("get-online-users-num"), Lang) ->
|
||||
[?HFIELD(),
|
||||
{xmlelement,
|
||||
"field",
|
||||
[{"type", "text-single"},
|
||||
[{"type", "jid-single"},
|
||||
{"label", ?T(Lang, "Number of online users")},
|
||||
{"var", "onlineusersnum"}],
|
||||
[{xmlelement, "value", [], [{xmlcdata, Num}]}]
|
||||
@@ -1433,7 +1416,7 @@ set_form(_From, _Host, ["running nodes", ENode, "backup", "textfile"], _Lang, XD
|
||||
false ->
|
||||
{error, ?ERR_BAD_REQUEST};
|
||||
{value, {_, [String]}} ->
|
||||
case rpc:call(Node, ejabberd_ctl, dump_to_textfile, [String]) of
|
||||
case rpc:call(Node, mnesia, dump_to_textfile, [String]) of
|
||||
{badrpc, _Reason} ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||
{error, _Reason} ->
|
||||
@@ -1557,7 +1540,7 @@ set_form(_From, Host, ["config", "access"], _Lang, XData) ->
|
||||
{error, ?ERR_BAD_REQUEST}
|
||||
end;
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
Password = get_value("password", XData),
|
||||
Password = get_value("password-verify", XData),
|
||||
@@ -1565,11 +1548,10 @@ set_form(From, Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
|
||||
User = AccountJID#jid.luser,
|
||||
Server = AccountJID#jid.lserver,
|
||||
true = lists:member(Server, ?MYHOSTS),
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
ejabberd_auth:try_register(User, Server, Password),
|
||||
{result, []};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
|
||||
AccountStringList = get_values("accountjids", XData),
|
||||
[_|_] = AccountStringList,
|
||||
ASL2 = lists:map(
|
||||
@@ -1577,8 +1559,7 @@ set_form(From, Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
User = JID#jid.luser,
|
||||
Server = JID#jid.lserver,
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
Server = JID#jid.lserver,
|
||||
true = ejabberd_auth:is_user_exists(User, Server),
|
||||
{User, Server}
|
||||
end,
|
||||
@@ -1586,13 +1567,12 @@ set_form(From, Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
|
||||
[ejabberd_auth:remove_user(User, Server) || {User, Server} <- ASL2],
|
||||
{result, []};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
LUser = JID#jid.luser,
|
||||
LServer = JID#jid.lserver,
|
||||
true = (LServer == Host) orelse (get_permission_level(From) == global),
|
||||
%% Code copied from ejabberd_sm.erl
|
||||
case JID#jid.lresource of
|
||||
[] ->
|
||||
@@ -1606,13 +1586,12 @@ set_form(From, Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
|
||||
end,
|
||||
{result, []};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
User = JID#jid.luser,
|
||||
Server = JID#jid.lserver,
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
Password = ejabberd_auth:get_password(User, Server),
|
||||
true = is_list(Password),
|
||||
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||
@@ -1621,25 +1600,23 @@ set_form(From, Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
|
||||
?XFIELD("text-single", "Password", "password", Password)
|
||||
]}]};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("change-user-password"), _Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("change-user-password"), _Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
Password = get_value("password", XData),
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
User = JID#jid.luser,
|
||||
Server = JID#jid.lserver,
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
true = ejabberd_auth:is_user_exists(User, Server),
|
||||
ejabberd_auth:set_password(User, Server, Password),
|
||||
{result, []};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
User = JID#jid.luser,
|
||||
Server = JID#jid.lserver,
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
|
||||
%% Code copied from web/ejabberd_web_admin.erl
|
||||
%% TODO: Update time format to XEP-0202: Entity Time
|
||||
@@ -1671,13 +1648,12 @@ set_form(From, Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
|
||||
?XFIELD("text-single", "Last login", "lastlogin", FLast)
|
||||
]}]};
|
||||
|
||||
set_form(From, Host, ?NS_ADMINL("user-stats"), Lang, XData) ->
|
||||
set_form(_From, _Host, ?NS_ADMINL("user-stats"), Lang, XData) ->
|
||||
AccountString = get_value("accountjid", XData),
|
||||
JID = jlib:string_to_jid(AccountString),
|
||||
[_|_] = JID#jid.luser,
|
||||
User = JID#jid.luser,
|
||||
Server = JID#jid.lserver,
|
||||
true = (Server == Host) orelse (get_permission_level(From) == global),
|
||||
|
||||
Resources = ejabberd_sm:get_user_resources(User, Server),
|
||||
IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource) || Resource <- Resources],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 26 Oct 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
%%% Created : 1 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
|
||||
+6
-9
@@ -5,7 +5,7 @@
|
||||
%%% Created : 15 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2008 Process-one
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -16,7 +16,7 @@
|
||||
%%% 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
@@ -121,7 +121,7 @@ handle_info({route, From, To, Packet}, State) ->
|
||||
"" -> jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST);
|
||||
_ -> Packet
|
||||
end,
|
||||
do_client_version(disabled, To, From), % Put 'enabled' to enable it
|
||||
%%do_client_version(To, From),
|
||||
ejabberd_router:route(To, From, Packet2),
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) ->
|
||||
@@ -149,9 +149,8 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%% Example of routing XMPP packets using Erlang's message passing
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% To enable this educational example, edit the function handle_info:
|
||||
%% replace the argument 'disabled' with 'enabled' in the call to the
|
||||
%% function do_client_version.
|
||||
%% To enable this educational example, uncomment the call to the
|
||||
%% function do_client_version in handle_info.
|
||||
|
||||
%% ejabberd provides a method to receive XMPP packets using Erlang's
|
||||
%% message passing mechanism.
|
||||
@@ -168,9 +167,7 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%% using exactly the same JID. We add a (mostly) random resource to
|
||||
%% try to guarantee that the received response matches the request sent.
|
||||
%% Finally, the received response is printed in the ejabberd log file.
|
||||
do_client_version(disabled, _From, _To) ->
|
||||
ok;
|
||||
do_client_version(enabled, From, To) ->
|
||||
do_client_version(From, To) ->
|
||||
ToS = jlib:jid_to_string(To),
|
||||
%% It is important to identify this process and packet
|
||||
Random_resource = integer_to_list(random:uniform(100000)),
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : mod_ip_blacklist.erl
|
||||
%%% Author : Mickael Remond <mremond@process-one.net>
|
||||
%%% Purpose : Download blacklists from ProcessOne
|
||||
%%% Created : 5 May 2008 by Mickael Remond <mremond@process-one.net>
|
||||
%%% Usage : Add the following line in modules section of ejabberd.cfg:
|
||||
%%% {mod_ip_blacklist, []}
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2009 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
%%% 02111-1307 USA
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(mod_ip_blacklist).
|
||||
-author('mremond@process-one.net').
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
%% API:
|
||||
-export([start/2,
|
||||
init/1,
|
||||
stop/1]).
|
||||
-export([update_bl_c2s/0]).
|
||||
%% Hooks:
|
||||
-export([is_ip_in_c2s_blacklist/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
-define(PROCNAME, ?MODULE).
|
||||
-define(BLC2S, "http://xaai.process-one.net/bl_c2s.txt").
|
||||
-define(UPDATE_INTERVAL, 6). %% in hours
|
||||
|
||||
-record(state, {timer}).
|
||||
-record(bl_c2s, {ip}).
|
||||
|
||||
%% Start once for all vhost
|
||||
start(Host, Opts) ->
|
||||
case whereis(?PROCNAME) of
|
||||
undefined ->
|
||||
?DEBUG("Starting mod_ip_blacklist ~p ~p~n", [Host, Opts]),
|
||||
register(?PROCNAME,
|
||||
spawn(?MODULE, init, [#state{}]));
|
||||
_ ->
|
||||
ok
|
||||
end.
|
||||
|
||||
%% TODO:
|
||||
stop(_Host) ->
|
||||
ok.
|
||||
|
||||
init(State)->
|
||||
inets:start(),
|
||||
ets:new(bl_c2s, [named_table, public, {keypos, #bl_c2s.ip}]),
|
||||
update_bl_c2s(),
|
||||
%% Register hooks for blacklist
|
||||
ejabberd_hooks:add(check_bl_c2s, ?MODULE, is_ip_in_c2s_blacklist, 50),
|
||||
%% Set timer: Download the blacklist file every 6 hours
|
||||
timer:apply_interval(timer:hours(?UPDATE_INTERVAL), ?MODULE, update_bl_c2s, []),
|
||||
loop(State).
|
||||
|
||||
%% Remove timer when stop is received.
|
||||
loop(_State) ->
|
||||
receive
|
||||
stop ->
|
||||
ok
|
||||
end.
|
||||
|
||||
%% Download blacklist file from ProcessOne XAAI
|
||||
%% and update the table internal table
|
||||
%% TODO: Support comment lines starting by %
|
||||
update_bl_c2s() ->
|
||||
?INFO_MSG("Updating C2S Blacklist", []),
|
||||
case http:request(?BLC2S) of
|
||||
{ok, {{_Version, 200, _Reason}, _Headers, Body}} ->
|
||||
IPs = string:tokens(Body,"\n"),
|
||||
ets:delete_all_objects(bl_c2s),
|
||||
lists:foreach(
|
||||
fun(IP) ->
|
||||
ets:insert(bl_c2s, #bl_c2s{ip=list_to_binary(IP)})
|
||||
end, IPs);
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("Cannot download C2S blacklist file. Reason: ~p",
|
||||
[Reason])
|
||||
end.
|
||||
|
||||
%% Hook is run with:
|
||||
%% ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]),
|
||||
%% Return: false: IP not blacklisted
|
||||
%% true: IP is blacklisted
|
||||
%% IPV4 IP tuple:
|
||||
is_ip_in_c2s_blacklist(_Val, IP) when is_tuple(IP) ->
|
||||
BinaryIP = list_to_binary(jlib:ip_to_list(IP)),
|
||||
case ets:lookup(bl_c2s, BinaryIP) of
|
||||
[] -> %% Not in blacklist
|
||||
false;
|
||||
[_] -> %% Blacklisted!
|
||||
{stop, true}
|
||||
end;
|
||||
is_ip_in_c2s_blacklist(_Val, _IP) ->
|
||||
false.
|
||||
|
||||
%% TODO:
|
||||
%% - For now, we do not kick user already logged on a given IP after
|
||||
%% we update the blacklist.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user