Compare commits

..

2 Commits

Author SHA1 Message Date
Alexey Shchepin e91952449b Added ejabberd-1.0.0 tag
SVN Revision: 466
2005-12-13 17:30:04 +00:00
Alexey Shchepin 6f5d2be577 Added ejabberd-1.0.0 branch
SVN Revision: 465
2005-12-13 17:29:27 +00:00
375 changed files with 42207 additions and 140942 deletions
-38
View File
@@ -1,38 +0,0 @@
#
# You can add personal rules in your file .git/info/exclude
*.swp
*~
/doc/*.aux
/doc/*.haux
/doc/*.html
/doc/*.htoc
/doc/*.idx
/doc/*.ilg
/doc/*.ind
/doc/*.log
/doc/*.out
/doc/*.pdf
/doc/*.toc
/doc/contributed_modules.tex
/doc/version.tex
/src/*.beam
/src/*.so
/src/*.so.dSYM
/src/*/*.beam
/src/*/Makefile
/src/Makefile
/src/XmppAddr.asn1db
/src/XmppAddr.erl
/src/XmppAddr.hrl
/src/aclocal.m4
/src/autom4te.cache
/src/config.log
/src/config.status
/src/configure
/src/ejabberd.init
/src/ejabberdctl.example
/src/eldap/ELDAPv3.asn1db
/src/eldap/ELDAPv3.erl
/src/eldap/ELDAPv3.hrl
/src/eldap/eldap_filter_yecc.erl
/src/epam
+2509
View File
File diff suppressed because it is too large Load Diff
-58
View File
@@ -1,58 +0,0 @@
ejabberd - High-Performance Enterprise Instant Messaging Server
Quickstart guide
0. Requirements
To compile ejabberd you need:
- GNU Make
- GCC
- Erlang/OTP R12B-5 or higher. Recommended: R12B-5, R13B04 and R14B01.
Avoid R14A and R14B.
- exmpp 0.9.6 or higher
- OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
- Zlib 1.2.3 or higher, for Stream Compression support
(XEP-0138). Optional.
- Erlang mysql library. Optional. MySQL authentication/storage.
- Erlang pgsql library. Optional. PostgreSQL authentication/storage.
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
- ESASL library. Optional. For SASL GSSAPI authentication.
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
1. Compile and install on *nix systems
To compile ejabberd, go to the directory src/ and execute the commands:
./configure
make
If you get an error like:
./configure: No such file or directory
the solution is to first execute:
aclocal
autoconf
To install ejabberd, run this command with system administrator rights
(root user):
sudo make install
These commands will:
- Install the configuration files in /etc/ejabberd/
- Install ejabberd binary, header and runtime files in /lib/ejabberd/
- Install the administration script: /sbin/ejabberdctl
- Install ejabberd documentation in /share/doc/ejabberd/
- Create a spool directory: /var/lib/ejabberd/
- Create a directory for log files: /var/log/ejabberd/
2. Start ejabberd
You can use the ejabberdctl command line administration script to
start and stop ejabberd. For example:
ejabberdctl start
For detailed information please refer to the
ejabberd Installation and Operation Guide
+17
View File
@@ -0,0 +1,17 @@
Win32 build: Make it possible to compile with +debug_info flag.
mod_muc logging
admin interface
users management
statistics about each user
statistics about each connection
S2S:
check "id" attributes in db:verify packets
more correctly work with SRV DNS records (priority, weight, etc...)
make roster set to work in one transaction
add traffic shapers to c2s connection before authentification
more traffic shapers
SNMP
-5
View File
@@ -1,5 +0,0 @@
% List of ejabberd-modules to add for ejabberd packaging (source archive and installer)
%
% HTTP-binding:
%https://svn.process-one.net/ejabberd-modules/http_bind/trunk
%https://svn.process-one.net/ejabberd-modules/mod_http_fileserver/trunk
@@ -0,0 +1,190 @@
%%%----------------------------------------------------------------------
%%% File : extract_translations.erl
%%% Author : Sergei Golovan <sgolovan@nes.ru>
%%% Purpose : Auxiliary tool for interface/messages translators
%%% Created : 23 Apr 2005 by Sergei Golovan <sgolovan@nes.ru>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(extract_translations).
-author('sgolovan@nes.ru').
-export([start/0]).
-define(STATUS_SUCCESS, 0).
-define(STATUS_ERROR, 1).
-define(STATUS_USAGE, 2).
-include_lib("kernel/include/file.hrl").
start() ->
ets:new(translations, [named_table, public]),
ets:new(files, [named_table, public]),
ets:new(vars, [named_table, public]),
case init:get_plain_arguments() of
["-unused", Dir, File] ->
Status = process(Dir, File, unused),
halt(Status);
[Dir, File] ->
Status = process(Dir, File, used),
halt(Status);
_ ->
print_usage(),
halt(?STATUS_USAGE)
end.
process(Dir, File, Used) ->
case load_file(File) of
{error, Reason} ->
io:format("~s: ~s~n", [File, file:format_error(Reason)]),
?STATUS_ERROR;
_ ->
FileList = find_src_files(Dir),
lists:foreach(
fun(F) ->
parse_file(Dir, F, Used)
end, FileList),
case Used of
unused ->
ets:foldl(fun({Key, _}, _) ->
io:format("~p~n", [Key])
end, ok, translations);
_ ->
ok
end,
?STATUS_SUCCESS
end.
parse_file(Dir, File, Used) ->
ets:delete_all_objects(vars),
case epp:parse_file(File, [Dir, filename:dirname(File)], []) of
{ok, Forms} ->
lists:foreach(
fun(F) ->
parse_form(Dir, File, F, Used)
end, Forms);
_ ->
ok
end.
parse_form(Dir, File, Form, Used) ->
case Form of
{call,
_,
{remote, _, {atom, _, translate}, {atom, _, translate}},
[_, {string, _, Str}]
} ->
process_string(Dir, File, Str, Used);
{call,
_,
{remote, _, {atom, _, translate}, {atom, _, translate}},
[_, {var, _, Name}]
} ->
case ets:lookup(vars, Name) of
[{_Name, Value}] ->
process_string(Dir, File, Value, Used);
_ ->
ok
end;
{match,
_,
{var, _, Name},
{string, _, Value}
} ->
ets:insert(vars, {Name, Value});
L when is_list(L) ->
lists:foreach(
fun(F) ->
parse_form(Dir, File, F, Used)
end, L);
T when is_tuple(T) ->
lists:foreach(
fun(F) ->
parse_form(Dir, File, F, Used)
end, tuple_to_list(T));
_ ->
ok
end.
process_string(Dir, File, Str, Used) ->
case {ets:lookup(translations, Str), Used} of
{[{_Key, _Trans}], unused} ->
ets:delete(translations, Str);
{[{_Key, _Trans}], used} ->
ok;
{_, used} ->
case ets:lookup(files, File) of
[{_}] ->
ok;
_ ->
io:format("~n% ~s~n", [File]),
ets:insert(files, {File})
end,
io:format("{~p, \"\"}.~n", [Str]),
ets:insert(translations, {Str, ""});
_ ->
ok
end.
load_file(File) ->
case file:consult(File) of
{ok, Terms} ->
lists:foreach(
fun({Orig, Trans}) ->
case Trans of
"" ->
ok;
_ ->
ets:insert(translations, {Orig, Trans})
end
end, Terms);
Err ->
Err
end.
find_src_files(Dir) ->
case file:list_dir(Dir) of
{ok, FileList} ->
recurse_filelist(
lists:map(
fun(F) ->
filename:join(Dir, F)
end, FileList));
_ ->
[]
end.
recurse_filelist(FileList) ->
recurse_filelist(FileList, []).
recurse_filelist([], Acc) ->
lists:reverse(Acc);
recurse_filelist([H | T], Acc) ->
case file:read_file_info(H) of
{ok, #file_info{type = directory}} ->
recurse_filelist(T, lists:reverse(find_src_files(H)) ++ Acc);
{ok, #file_info{type = regular}} ->
case string:substr(H, string:len(H) - 3) of
".erl" ->
recurse_filelist(T, [H | Acc]);
".hrl" ->
recurse_filelist(T, [H | Acc]);
_ ->
recurse_filelist(T, Acc)
end;
_ ->
recurse_filelist(T, Acc)
end.
print_usage() ->
io:format(
"Usage: extract_translations [-unused] dir file~n"
"~n"
"Example:~n"
" extract_translations . ./msgs/ru.msg~n"
).
+101
View File
@@ -0,0 +1,101 @@
#!/bin/bash
# Frontend for ejabberd's extract_translations.erl
# by Badlop
# last updated: 8 December 2005
while [ "$1" != "" ]
do
case "$1" in
-help)
echo "Options:"
echo " -lang LANGUAGE"
echo " -src FULL_PATH_EJABBERD"
echo ""
echo "Example:"
echo " ./prepare-translation.sh -lang es -src /home/admin/ejabberd"
exit 0
;;
-lang)
# This is the language to be extracted
LANGU=$2
shift
shift
;;
-src)
# This is the path to the ejabberd source dir
EJA_DIR=$2
shift
shift
;;
*)
echo "unknown option: '$1 $2'"
shift
shift
;;
esac
done
# Where is Erlang binary
ERL=`which erl`
EXTRACT_DIR=$EJA_DIR/contrib/extract_translations/
EXTRACT_ERL=extract_translations.erl
EXTRACT_BEAM=extract_translations.beam
SRC_DIR=$EJA_DIR/src
MSGS_DIR=$SRC_DIR/msgs
MSGS_FILE=$LANGU.msg
MSGS_FILE2=$LANGU.msg.translate
MSGS_PATH=$MSGS_DIR/$MSGS_FILE
MSGS_PATH2=$MSGS_DIR/$MSGS_FILE2
if !([[ -n $EJA_DIR ]])
then
echo "ejabberd dir does not exist: $EJA_DIR"
fi
if !([[ -x $EXTRACT_BEAM ]])
then
echo -n "Compiling extract_translations.erl: "
sh -c "cd $EXTRACT_DIR; $ERL -compile $EXTRACT_ERL"
fi
echo ""
echo -n "Extracting language strings for '$LANGU':"
echo -n " new..."
$ERL -pa $EXTRACT_DIR -noinput -noshell -s extract_translations -s init stop -extra $SRC_DIR $MSGS_PATH >$MSGS_PATH.new
echo -n " old..."
$ERL -pa $EXTRACT_DIR -noinput -noshell -s extract_translations -s init stop -extra -unused $SRC_DIR $MSGS_PATH >$MSGS_PATH.unused
cat $MSGS_PATH >$MSGS_PATH2
echo "" >>$MSGS_PATH2
cat $MSGS_PATH.new >>$MSGS_PATH2
rm $MSGS_PATH.new
echo "" >>$MSGS_PATH2
cat $MSGS_PATH.unused >>$MSGS_PATH2
rm $MSGS_PATH.unused
echo " ok"
echo ""
echo "Process completed."
echo ""
echo " A new file has been created for you, with the current, the new and the deprecated strings:"
echo " $MSGS_PATH2"
echo ""
echo " At the end of that file you will find the strings you must update:"
echo " - Untranslated strings are like this: {"March", ""}."
echo " To translate the string, add the text inside the commas. Example:"
echo " {"March", "Marzo"}."
echo " - Old strings that are not used: "Woowoa""
echo " Search the entire file for those strings and remove them"
echo ""
echo " Once you have translated all the strings and removed all the old ones,"
echo " rename the file to overwrite the previous one:"
echo " $MSGS_PATH"
+4 -54
View File
@@ -1,61 +1,11 @@
SHELL = /bin/bash
# $Id$
CONTRIBUTED_MODULES = ""
#ifeq ($(shell ls mod_http_bind.tex),mod_http_bind.tex)
# CONTRIBUTED_MODULES += "\\n\\setboolean{modhttpbind}{true}"
#endif
all: release pdf html
release:
@echo "Notes for the releaser:"
@echo "* Do not forget to add a link to the release notes in guide.tex"
@echo "* Do not forget to update the version number in src/ejabberd.app!"
@echo "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)."
@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 -n "% Contributed modules (automatically generated)." > contributed_modules.tex
@echo -e "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex
html: guide.html dev.html features.html
pdf: guide.pdf features.pdf
clean:
rm -f *.aux
rm -f *.haux
rm -f *.htoc
rm -f *.idx
rm -f *.ilg
rm -f *.ind
rm -f *.log
rm -f *.out
rm -f *.pdf
rm -f *.toc
rm -f version.tex
[ ! -f contributed_modules.tex ] || rm contributed_modules.tex
distclean: clean
rm -f *.html
all: guide.html dev.html
guide.html: guide.tex
hevea -fix -pedantic guide.tex
hevea -charset ISO8859-1 guide.tex
dev.html: dev.tex
hevea -fix -pedantic dev.tex
hevea -charset ISO8859-1 dev.tex
features.html: features.tex
hevea -fix -pedantic features.tex
guide.pdf: guide.tex
pdflatex guide.tex
pdflatex guide.tex
pdflatex guide.tex
makeindex guide.idx
pdflatex guide.tex
features.pdf: features.tex
pdflatex features.tex
+383
View File
@@ -0,0 +1,383 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>Ejabberd Developers Guide</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<META name="GENERATOR" content="hevea 1.07">
</HEAD>
<BODY >
<!--HEVEA command line is: /usr/bin/hevea -charset ISO8859-1 dev.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<H1 ALIGN=center>Ejabberd Developers Guide</H1>
<H3 ALIGN=center>Alexey Shchepin<BR>
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3>
<H3 ALIGN=center>August 21, 2005</H3><DIV ALIGN=center>
<IMG SRC="logo.png">
</DIV><BR>
<BR>
<!--TOC section Table of Contents-->
<H2>Table of Contents</H2><!--SEC END -->
<UL><LI>
<A HREF="#htoc1">1&nbsp;&nbsp;Introduction</A>
<UL><LI>
<A HREF="#htoc2">1.1&nbsp;&nbsp;How it works</A>
<UL><LI>
<A HREF="#htoc3">1.1.1&nbsp;&nbsp;Router</A>
<LI><A HREF="#htoc4">1.1.2&nbsp;&nbsp;Local Router</A>
<LI><A HREF="#htoc5">1.1.3&nbsp;&nbsp;Session Manager</A>
<LI><A HREF="#htoc6">1.1.4&nbsp;&nbsp;S2S Manager</A>
</UL>
</UL>
<LI><A HREF="#htoc7">2&nbsp;&nbsp;XML representation</A>
<LI><A HREF="#htoc8">3&nbsp;&nbsp;Module <TT>xml</TT></A>
<LI><A HREF="#htoc9">4&nbsp;&nbsp;Module <TT>xml_stream</TT></A>
<LI><A HREF="#htoc10">5&nbsp;&nbsp;<TT>ejabberd</TT> modules</A>
<UL><LI>
<A HREF="#htoc11">5.1&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</A>
<LI><A HREF="#htoc12">5.2&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></A>
<LI><A HREF="#htoc13">5.3&nbsp;&nbsp;Services</A>
</UL>
</UL>
<!--TOC section Introduction-->
<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="sec:intro"></A>
<TT>ejabberd</TT> is a Free and Open Source fault-tolerant distributed Jabber
server. It is written mostly in Erlang.<BR>
<BR>
The main features of <TT>ejabberd</TT> are:
<UL><LI>
Works on most of popular platforms: *nix (tested on Linux, FreeBSD and
NetBSD) and Win32
<LI>Distributed: You can run <TT>ejabberd</TT> on a cluster of machines to let all of
them serve one Jabber domain.
<LI>Fault-tolerance: You can setup an <TT>ejabberd</TT> cluster so that all the
information required for a properly working service will be stored
permanently on more than one node. This means that if one of the nodes
crashes, then the others will continue working without disruption.
You can also add or replace nodes ``on the fly''.
<LI>Support for virtual hosting
<LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User Chat</A> service
<LI>Built-in IRC transport
<LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0060.html">Publish-Subscribe</A> service
<LI>Built-in Jabber Users Directory service based on users vCards
<LI>Built-in web-based administration interface
<LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> service
<LI>SSL support
<LI>Support for LDAP authentication
<LI>Ability to interface with external components (JIT, MSN-t, Yahoo-t, etc.)
<LI>Migration from jabberd14 is possible
<LI>Mostly XMPP-compliant
<LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0030.html">Service Discovery</A>.
<LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0039.html">Statistics Gathering</A>.
<LI>Support for <TT>xml:lang</TT>
</UL>
<!--TOC subsection How it works-->
<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;How it works</H3><!--SEC END -->
<A NAME="sec:howitworks"></A>
A Jabber domain is served by one or more <TT>ejabberd</TT> nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
<TT>~ejabberd/.erlang.cookie</TT> must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc...<BR>
<BR>
Each <TT>ejabberd</TT> node have following modules:
<UL><LI>
router;
<LI>local router.
<LI>session manager;
<LI>S2S manager;
</UL>
<!--TOC subsubsection Router-->
<H4><A NAME="htoc3">1.1.1</A>&nbsp;&nbsp;Router</H4><!--SEC END -->
This module is the main router of Jabber packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate <TT>ejabberd</TT> node or
process. If it does not exists in either tables, then it sent to the S2S
manager.<BR>
<BR>
<!--TOC subsubsection Local Router-->
<H4><A NAME="htoc4">1.1.2</A>&nbsp;&nbsp;Local Router</H4><!--SEC END -->
This module routes packets which have a destination domain equal to this server
name. If destination JID has a non-empty user part, then it routed to the
session manager, else it is processed depending on it's content.<BR>
<BR>
<!--TOC subsubsection Session Manager-->
<H4><A NAME="htoc5">1.1.3</A>&nbsp;&nbsp;Session Manager</H4><!--SEC END -->
This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.<BR>
<BR>
<!--TOC subsubsection S2S Manager-->
<H4><A NAME="htoc6">1.1.4</A>&nbsp;&nbsp;S2S Manager</H4><!--SEC END -->
This module routes packets to other Jabber servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.<BR>
<BR>
<!--TOC section XML representation-->
<H2><A NAME="htoc7">2</A>&nbsp;&nbsp;XML representation</H2><!--SEC END -->
<A NAME="sec:xmlrepr"></A>
Each XML stanza is represented as the following tuple:
<PRE>
XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string()
Attrs = [Attr]
Attr = {Key, Val}
Key = string()
Val = string()
ElementOrCDATA = XMLElement | CDATA
CDATA = {xmlcdata, string()}
</PRE>E.&nbsp;g. this stanza:
<PRE>
&lt;message to='test@conference.example.org' type='groupchat'&gt;
&lt;body&gt;test&lt;/body&gt;
&lt;/message&gt;
</PRE>is represented as the following structure:
<PRE>
{xmlelement, "message",
[{"to", "test@conference.example.org"},
{"type", "groupchat"}],
[{xmlelement, "body",
[],
[{xmlcdata, "test"}]}]}}
</PRE>
<!--TOC section Module <TT>xml</TT>-->
<H2><A NAME="htoc8">3</A>&nbsp;&nbsp;Module <TT>xml</TT></H2><!--SEC END -->
<A NAME="sec:xmlmod"></A>
<DL COMPACT=compact><DT>
<CODE><B>element_to_string(El) -&gt; string()</B></CODE><DD>
<PRE>
El = XMLElement
</PRE>Returns string representation of XML stanza <TT>El</TT>.<BR>
<BR>
<DT><CODE><B>crypt(S) -&gt; string()</B></CODE><DD>
<PRE>
S = string()
</PRE>Returns string which correspond to <TT>S</TT> with encoded XML special
characters.<BR>
<BR>
<DT><CODE><B>remove_cdata(ECList) -&gt; EList</B></CODE><DD>
<PRE>
ECList = [ElementOrCDATA]
EList = [XMLElement]
</PRE><TT>EList</TT> is a list of all non-CDATA elements of ECList.<BR>
<BR>
<DT><CODE><B>get_path_s(El, Path) -&gt; Res</B></CODE><DD>
<PRE>
El = XMLElement
Path = [PathItem]
PathItem = PathElem | PathAttr | PathCDATA
PathElem = {elem, Name}
PathAttr = {attr, Name}
PathCDATA = cdata
Name = string()
Res = string() | XMLElement
</PRE>If <TT>Path</TT> is empty, then returns <TT>El</TT>. Else sequentially
consider elements of <TT>Path</TT>. Each element is one of:
<DL COMPACT=compact><DT>
<CODE><B>{elem, Name}</B></CODE><DD> <TT>Name</TT> is name of subelement of
<TT>El</TT>, if such element exists, then this element considered in
following steps, else returns empty string.
<DT><CODE><B>{attr, Name}</B></CODE><DD> If <TT>El</TT> have attribute <TT>Name</TT>, then
returns value of this attribute, else returns empty string.
<DT><CODE><B>cdata</B></CODE><DD> Returns CDATA of <TT>El</TT>.
</DL><BR>
<BR>
<DT><B>TODO:</B><DD>
<PRE>
get_cdata/1, get_tag_cdata/1
get_attr/2, get_attr_s/2
get_tag_attr/2, get_tag_attr_s/2
get_subtag/2
</PRE></DL>
<!--TOC section Module <TT>xml_stream</TT>-->
<H2><A NAME="htoc9">4</A>&nbsp;&nbsp;Module <TT>xml_stream</TT></H2><!--SEC END -->
<A NAME="sec:xmlstreammod"></A>
<DL COMPACT=compact><DT>
<CODE><B>parse_element(Str) -&gt; XMLElement | {error, Err}</B></CODE><DD>
<PRE>
Str = string()
Err = term()
</PRE>Parses <TT>Str</TT> using XML parser, returns either parsed element or error
tuple.
</DL>
<!--TOC section <TT>ejabberd</TT> modules-->
<H2><A NAME="htoc10">5</A>&nbsp;&nbsp;<TT>ejabberd</TT> modules</H2><!--SEC END -->
<A NAME="sec:emods"></A>
<!--TOC subsection <CODE>gen_mod</CODE> behaviour-->
<H3><A NAME="htoc11">5.1</A>&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</H3><!--SEC END -->
<A NAME="sec:genmod"></A>
TBD<BR>
<BR>
<!--TOC subsection Module <CODE>gen_iq_handler</CODE>-->
<H3><A NAME="htoc12">5.2</A>&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></H3><!--SEC END -->
<A NAME="sec:geniqhandl"></A>
The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets
of particular XML namespaces that addressed to server or to users bare JIDs.<BR>
<BR>
In this module the following functions are defined:
<DL COMPACT=compact><DT>
<CODE><B>add_iq_handler(Component, Host, NS, Module, Function, Type)</B></CODE><DD>
<PRE>
Component = Module = Function = atom()
Host = NS = string()
Type = no_queue | one_queue | parallel
</PRE>Registers function <CODE>Module:Function</CODE> as handler for IQ packets on
virtual host <CODE>Host</CODE> that contain child of namespace <CODE>NS</CODE> in
<CODE>Component</CODE>. Queueing discipline is <CODE>Type</CODE>. There are at least
two components defined:
<DL COMPACT=compact><DT>
<CODE><B>ejabberd_local</B></CODE><DD> Handles packets that addressed to server JID;
<DT><CODE><B>ejabberd_sm</B></CODE><DD> Handles packets that addressed to users bare JIDs.
</DL>
<DT><CODE><B>remove_iq_handler(Component, Host, NS)</B></CODE><DD>
<PRE>
Component = atom()
Host = NS = string()
</PRE>Removes IQ handler on virtual host <CODE>Host</CODE> for namespace <CODE>NS</CODE> from
<CODE>Component</CODE>.
</DL>
Handler function must have the following type:
<DL COMPACT=compact><DT>
<CODE><B>Module:Function(From, To, IQ)</B></CODE><DD>
<PRE>
From = To = jid()
</PRE></DL>
<PRE>
-module(mod_cputime).
-behaviour(gen_mod).
-export([start/2,
stop/1,
process_local_iq/3]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(NS_CPUTIME, "ejabberd:cputime").
start(Host, Opts) -&gt;
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc).
stop(Host) -&gt;
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
case Type of
set -&gt;
{iq, ID, error, XMLNS,
[SubEl, ?ERR_NOT_ALLOWED]};
get -&gt;
CPUTime = element(1, erlang:statistics(runtime))/1000,
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
{iq, ID, result, XMLNS,
[{xmlelement, "query",
[{"xmlns", ?NS_CPUTIME}],
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
end.
</PRE>
<!--TOC subsection Services-->
<H3><A NAME="htoc13">5.3</A>&nbsp;&nbsp;Services</H3><!--SEC END -->
<A NAME="sec:services"></A>
TBD<BR>
<BR>
TODO: use <CODE>proc_lib</CODE>
<PRE>
-module(mod_echo).
-behaviour(gen_mod).
-export([start/2, init/1, stop/1]).
-include("ejabberd.hrl").
-include("jlib.hrl").
start(Host, Opts) -&gt;
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) -&gt;
ejabberd_router:register_local_route(Host),
loop(Host).
loop(Host) -&gt;
receive
{route, From, To, Packet} -&gt;
ejabberd_router:route(To, From, Packet),
loop(Host);
stop -&gt;
ejabberd_router:unregister_route(Host),
ok;
_ -&gt;
loop(Host)
end.
stop(Host) -&gt;
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop,
{wait, Proc}.
</PRE>
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2>
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>
+97 -169
View File
@@ -1,20 +1,14 @@
\documentclass[a4paper,10pt]{article}
\documentclass[10pt]{article}
%% Packages
\usepackage{graphics}
\usepackage{hevea}
\usepackage{makeidx}
\usepackage{verbatim}
%% Index
\makeindex
% Remove the index anchors from the HTML version to save size and bandwith.
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
%% Images
\newcommand{\logoscale}{0.7}
\newcommand{\imgscale}{0.58}
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
\newcommand{\insscaleimg}[2]{
\imgsrc{#2}{}
\begin{latexonly}
@@ -22,82 +16,87 @@
\end{latexonly}
}
%% Various
\newcommand{\ns}[1]{\texttt{#1}}
\newcommand{\ejabberd}{\texttt{ejabberd}}
\newcommand{\Jabber}{Jabber}
\newcommand{\XMPP}{XMPP}
%% Modules
\newcommand{\module}[1]{\texttt{#1}}
\newcommand{\modadhoc}{\module{mod\_adhoc}}
\newcommand{\modannounce}{\module{mod\_announce}}
\newcommand{\modconfigure}{\module{mod\_configure}}
\newcommand{\moddisco}{\module{mod\_disco}}
\newcommand{\modecho}{\module{mod\_echo}}
\newcommand{\modirc}{\module{mod\_irc}}
\newcommand{\modlast}{\module{mod\_last}}
\newcommand{\modmuc}{\module{mod\_muc}}
\newcommand{\modmuclog}{\module{mod\_muc\_log}}
\newcommand{\modoffline}{\module{mod\_offline}}
\newcommand{\modprivacy}{\module{mod\_privacy}}
\newcommand{\modprivate}{\module{mod\_private}}
\newcommand{\modpubsub}{\module{mod\_pubsub}}
\newcommand{\modregister}{\module{mod\_register}}
\newcommand{\modroster}{\module{mod\_roster}}
\newcommand{\modservicelog}{\module{mod\_service\_log}}
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
\newcommand{\modstats}{\module{mod\_stats}}
\newcommand{\modtime}{\module{mod\_time}}
\newcommand{\modvcard}{\module{mod\_vcard}}
\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
\newcommand{\modversion}{\module{mod\_version}}
\newcommand{\modregister}{\texttt{mod\_register}}
\newcommand{\modroster}{\texttt{mod\_roster}}
\newcommand{\modconfigure}{\texttt{mod\_configure}}
\newcommand{\moddisco}{\texttt{mod\_disco}}
\newcommand{\modstats}{\texttt{mod\_stats}}
\newcommand{\modvcard}{\texttt{mod\_vcard}}
\newcommand{\modoffline}{\texttt{mod\_offline}}
\newcommand{\modecho}{\texttt{mod\_echo}}
\newcommand{\modprivate}{\texttt{mod\_private}}
\newcommand{\modtime}{\texttt{mod\_time}}
\newcommand{\modversion}{\texttt{mod\_version}}
%% Title page
\include{version}
\title{Ejabberd \version\ Developers Guide}
\newcommand{\tjepref}[2]{\footahref{http://www.jabber.org/jeps/jep-#1.html}{#2}}
\newcommand{\jepref}[1]{\tjepref{#1}{JEP-#1}}
%\setcounter{tocdepth}{3}
\title{Ejabberd Developers Guide}
\author{Alexey Shchepin \\
\ahrefurl{mailto:alexey@sevcom.net} \\
\ahrefurl{xmpp:aleksey@jabber.ru}}
%% Options
\newcommand{\marking}[1]{#1} % Marking disabled
\newcommand{\quoting}[2][yozhik]{} % Quotes disabled
\newcommand{\new}{\begin{latexonly}\marginpar{\textsc{new}}\end{latexonly}} % Highlight new features
\newcommand{\improved}{\begin{latexonly}\marginpar{\textsc{improved}}\end{latexonly}} % Highlight improved features
\newcommand{\moreinfo}[1]{} % Hide details
%% Footnotes
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
\date{August 21, 2005}
\begin{document}
\label{titlepage}
\begin{titlepage}
\maketitle{}
\begin{center}
{\insscaleimg{\logoscale}{logo.png}
{\centering
\insscaleimg{\logoscale}{logo.png}
\par
}
\end{center}
\begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup --
Kevin Smith, Current maintainer of the Psi project}\end{quotation}
\end{titlepage}
%\newpage
\tableofcontents{}
% Input introduction.tex
\input{introduction}
\newpage
\section{Introduction}
\label{sec:intro}
\section{How it Works}
\label{howitworks}
\ejabberd{} is a Free and Open Source fault-tolerant distributed \Jabber{}
server. It is written mostly in Erlang.
The main features of \ejabberd{} are:
\begin{itemize}
\item Works on most of popular platforms: *nix (tested on Linux, FreeBSD and
NetBSD) and Win32
\item Distributed: You can run \ejabberd{} on a cluster of machines to let all of
them serve one Jabber domain.
\item Fault-tolerance: You can setup an \ejabberd{} cluster so that all the
information required for a properly working service will be stored
permanently on more than one node. This means that if one of the nodes
crashes, then the others will continue working without disruption.
You can also add or replace nodes ``on the fly''.
\item Support for virtual hosting
\item Built-in \tjepref{0045}{Multi-User Chat} service
\item Built-in IRC transport
\item Built-in \tjepref{0060}{Publish-Subscribe} service
\item Built-in Jabber Users Directory service based on users vCards
\item Built-in web-based administration interface
\item Built-in \tjepref{0025}{HTTP Polling} service
\item SSL support
\item Support for LDAP authentication
\item Ability to interface with external components (JIT, MSN-t, Yahoo-t, etc.)
\item Migration from jabberd14 is possible
\item Mostly XMPP-compliant
\item Support for \tjepref{0030}{Service Discovery}.
\item Support for \tjepref{0039}{Statistics Gathering}.
\item Support for \ns{xml:lang}
\end{itemize}
A \XMPP{} domain is served by one or more \ejabberd{} nodes. These nodes can
\subsection{How it works}
\label{sec:howitworks}
A \Jabber{} domain is served by one or more \ejabberd{} nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
@@ -116,9 +115,9 @@ Each \ejabberd{} node have following modules:
\end{itemize}
\subsection{Router}
\subsubsection{Router}
This module is the main router of \XMPP{} packets on each node. It routes
This module is the main router of \Jabber{} packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
@@ -127,14 +126,14 @@ process. If it does not exists in either tables, then it sent to the S2S
manager.
\subsection{Local Router}
\subsubsection{Local Router}
This module routes packets which have a destination domain equal to this server
name. If destination JID has a non-empty user part, then it routed to the
session manager, else it is processed depending on it's content.
\subsection{Session Manager}
\subsubsection{Session Manager}
This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
@@ -142,9 +141,9 @@ this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.
\subsection{S2S Manager}
\subsubsection{S2S Manager}
This module routes packets to other \XMPP{} servers. First, it checks if an
This module routes packets to other \Jabber{} servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
@@ -152,81 +151,10 @@ it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.
\section{Authentication}
\subsubsection{External}
\label{externalauth}
\ind{external authentication}
The external authentication script follows
\footahref{http://www.erlang.org/doc/tutorial/c_portdriver.html}{the erlang port driver API}.
That script is supposed to do theses actions, in an infinite loop:
\begin{itemize}
\item read from stdin: AABBBBBBBBB.....
\begin{itemize}
\item A: 2 bytes of length data (a short in network byte order)
\item B: a string of length found in A that contains operation in plain text
operation are as follows:
\begin{itemize}
\item auth:User:Server:Password (check if a username/password pair is correct)
\item isuser:User:Server (check if it's a valid user)
\item setpass:User:Server:Password (set user's password)
\item tryregister:User:Server:Password (try to register an account)
\item removeuser:User:Server (remove this account)
\item removeuser3:User:Server:Password (remove this account if the password is correct)
\end{itemize}
\end{itemize}
\item write to stdout: AABB
\begin{itemize}
\item A: the number 2 (coded as a short, which is bytes length of following result)
\item B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
\end{itemize}
\end{itemize}
Example python script
\begin{verbatim}
#!/usr/bin/python
import sys
from struct import *
def from_ejabberd():
input_length = sys.stdin.read(2)
(size,) = unpack('>h', input_length)
return sys.stdin.read(size).split(':')
def to_ejabberd(bool):
answer = 0
if bool:
answer = 1
token = pack('>hh', 2, answer)
sys.stdout.write(token)
sys.stdout.flush()
def auth(username, server, password):
return True
def isuser(username, server):
return True
def setpass(username, server, password):
return True
while True:
data = from_ejabberd()
success = False
if data[0] == "auth":
success = auth(data[1], data[2], data[3])
elif data[0] == "isuser":
success = isuser(data[1], data[2])
elif data[0] == "setpass":
success = setpass(data[1], data[2], data[3])
to_ejabberd(success)
\end{verbatim}
\section{XML Representation}
\label{xmlrepr}
\section{XML representation}
\label{sec:xmlrepr}
Each XML stanza is represented as the following tuple:
\begin{verbatim}
@@ -258,23 +186,23 @@ is represented as the following structure:
\section{Module \texttt{xml}}
\label{xmlmod}
\label{sec:xmlmod}
\begin{description}
\item{\verb|element_to_string(El) -> string()|}
\item[\verb|element_to_string(El) -> string()|]
\begin{verbatim}
El = XMLElement
\end{verbatim}
Returns string representation of XML stanza \texttt{El}.
\item{\verb|crypt(S) -> string()|}
\item[\verb|crypt(S) -> string()|]
\begin{verbatim}
S = string()
\end{verbatim}
Returns string which correspond to \texttt{S} with encoded XML special
characters.
\item{\verb|remove_cdata(ECList) -> EList|}
\item[\verb|remove_cdata(ECList) -> EList|]
\begin{verbatim}
ECList = [ElementOrCDATA]
EList = [XMLElement]
@@ -283,7 +211,7 @@ EList = [XMLElement]
\item{\verb|get_path_s(El, Path) -> Res|}
\item[\verb|get_path_s(El, Path) -> Res|]
\begin{verbatim}
El = XMLElement
Path = [PathItem]
@@ -297,15 +225,15 @@ Res = string() | XMLElement
If \texttt{Path} is empty, then returns \texttt{El}. Else sequentially
consider elements of \texttt{Path}. Each element is one of:
\begin{description}
\item{\verb|{elem, Name}|} \texttt{Name} is name of subelement of
\item[\verb|{elem, Name}|] \texttt{Name} is name of subelement of
\texttt{El}, if such element exists, then this element considered in
following steps, else returns empty string.
\item{\verb|{attr, Name}|} If \texttt{El} have attribute \texttt{Name}, then
\item[\verb|{attr, Name}|] If \texttt{El} have attribute \texttt{Name}, then
returns value of this attribute, else returns empty string.
\item{\verb|cdata|} Returns CDATA of \texttt{El}.
\item[\verb|cdata|] Returns CDATA of \texttt{El}.
\end{description}
\item{TODO:}
\item[TODO:]
\begin{verbatim}
get_cdata/1, get_tag_cdata/1
get_attr/2, get_attr_s/2
@@ -316,10 +244,10 @@ Res = string() | XMLElement
\section{Module \texttt{xml\_stream}}
\label{xmlstreammod}
\label{sec:xmlstreammod}
\begin{description}
\item{\verb!parse_element(Str) -> XMLElement | {error, Err}!}
\item[\verb!parse_element(Str) -> XMLElement | {error, Err}!]
\begin{verbatim}
Str = string()
Err = term()
@@ -329,24 +257,24 @@ Err = term()
\end{description}
\section{Modules}
\label{emods}
\section{\ejabberd{} modules}
\label{sec:emods}
%\subsection{gen\_mod behaviour}
%\label{genmod}
\subsection{\verb|gen_mod| behaviour}
\label{sec:genmod}
%TBD
TBD
\subsection{Module gen\_iq\_handler}
\label{geniqhandl}
\subsection{Module \verb|gen_iq_handler|}
\label{sec:geniqhandl}
The module \verb|gen_iq_handler| allows to easily write handlers for IQ packets
of particular XML namespaces that addressed to server or to users bare JIDs.
In this module the following functions are defined:
\begin{description}
\item{\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|}
\item[\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|]
\begin{verbatim}
Component = Module = Function = atom()
Host = NS = string()
@@ -357,10 +285,10 @@ Type = no_queue | one_queue | parallel
\verb|Component|. Queueing discipline is \verb|Type|. There are at least
two components defined:
\begin{description}
\item{\verb|ejabberd_local|} Handles packets that addressed to server JID;
\item{\verb|ejabberd_sm|} Handles packets that addressed to users bare JIDs.
\item[\verb|ejabberd_local|] Handles packets that addressed to server JID;
\item[\verb|ejabberd_sm|] Handles packets that addressed to users bare JIDs.
\end{description}
\item{\verb|remove_iq_handler(Component, Host, NS)|}
\item[\verb|remove_iq_handler(Component, Host, NS)|]
\begin{verbatim}
Component = atom()
Host = NS = string()
@@ -371,7 +299,7 @@ Host = NS = string()
Handler function must have the following type:
\begin{description}
\item{\verb|Module:Function(From, To, IQ)|}
\item[\verb|Module:Function(From, To, IQ)|]
\begin{verbatim}
From = To = jid()
\end{verbatim}
@@ -418,12 +346,12 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
\subsection{Services}
\label{services}
\label{sec:services}
%TBD
TBD
%TODO: use \verb|proc_lib|
TODO: use \verb|proc_lib|
\begin{verbatim}
-module(mod_echo).
-18
View File
@@ -1,18 +0,0 @@
APPNAME = ejabberd
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../../src/ejabberd.app)
DOCDIR=.
SRCDIR=../../src
.PHONY = all
all: docs
clean:
rm -f *.html
rm edoc-info
rm erlang.png
docs:
erl -noshell -run edoc_run application \
"'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,false},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 B

-19
View File
@@ -1,19 +0,0 @@
.comment {color: brown}
.export {color: darkorchid}
.import {color: darkorchid}
.string {color: maroon}
.builtin {color: dodgerblue}
.guard {color: mediumturquoise}
.function {color: blue}
.variable {color: green}
.macro {color: mediumpurple}
.record {color: orangered}
.call {color: purple}
.attribute {color: firebrick}
.error{color: red}
.l {
font-style: normal;
font-weight: normal;
text-decoration: none;
color: gray;
}
-356
View File
@@ -1,356 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : escobar_hiliter.erl
%%% Author : Mats Cronqvist <mats.cronqvist@gmail.com>
%%% Description :
%%%
%%% Created : 6 Jun 2005 by Mats Cronqvist <mats.cronqvist@gmail.com>
%%%
%%%
%%% Escobar, Copyright (c) 2005-2009 Mats Cronqvist
%%%
%%% MIT License:
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in
%%% all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%%% THE SOFTWARE.
%%%
%%%-------------------------------------------------------------------
-module(escobar_hilite).
-export([file/1,tree/1,string/1,out/2]).
-define(LOG(T),escobar:log(process_info(self()),T)).
-import(erl_syntax,
[get_ann/1,add_ann/2,subtrees/1,update_tree/2,type/1,get_pos/1,
application/2,application_arguments/1,application_operator/1,
arity_qualifier_argument/1,arity_qualifier_body/1,
atom_name/1,atom_value/1,
attribute/2,attribute_name/1,attribute_arguments/1,
clause/3,clause_patterns/1,clause_guard/1,clause_body/1,
comment/2,comment_text/1,comment_padding/1,
function/2,function_name/1,function_clauses/1,function_arity/1,
integer_literal/1,
list/1,list_elements/1,
macro/2,macro_name/1,macro_arguments/1,
module_qualifier_body/1, module_qualifier_argument/1,
string_value/1,string_literal/1,
variable_literal/1,variable_name/1,
record_access/3, record_access_argument/1,
record_access_field/1,record_access_type/1,
record_expr/3, record_expr_argument/1,
record_expr_fields/1, record_expr_type/1,
record_index_expr/2, record_index_expr_field/1,
record_index_expr_type/1,
form_list/1,
get_precomments/1,get_postcomments/1,has_comments/1,
copy_comments/2,remove_comments/1]).
-import(prettypr,
[above/2,follow/2,beside/2,empty/0,
null_text/1,break/1,floating/3,text/1,floating/1]).
-import(lists,[flatten/1,duplicate/2,keysearch/3,member/2,usort/1,reverse/1]).
-import(filename,[join/1,basename/1]).
out(File,HtmlString) ->
{ok,FD}=file:open(File,[write]),
try
io:fwrite(FD,"<html>",[]),
io:fwrite(FD,"<link rel=\"stylesheet\" type=\"text/css\"",[]),
io:fwrite(FD,"href=\"escobar.css\"></link><body><pre>",[]),
io:fwrite(FD,"~s",[HtmlString]),
io:fwrite(FD,"</pre></body></html>",[])
after
file:close(FD)
end.
string(Str) ->
tree(form_list(scan_and_parse(Str,1,[]))).
scan_and_parse([],_Line,Forms) -> reverse(Forms);
scan_and_parse(Text,Line,Forms) ->
{done,{ok,Toks,NLine},Cont} = erl_scan:tokens([],Text,Line),
{ok,Form} = erl_parse:parse_form(Toks),
scan_and_parse(Cont,NLine,[Form|Forms]).
file(FileName) ->
case filelib:is_regular(FileName) of
true ->
case filename:extension(FileName) of
".beam"-> tree(get_tree_beam(FileName));
".erl" -> tree(get_comm_tree_erl(FileName));
".hrl" -> tree(get_comm_tree_erl(FileName));
X -> erlang:error({unknown_extension,X})
end;
false->
erlang:error({no_file,FileName})
end.
get_comm_tree_erl(Filename) ->
Comms = erl_comment_scan:file(Filename),
Forms = get_forms_erl(Filename),
erl_recomment:recomment_forms(Forms,Comms).
get_tree_beam(Filename) ->
case beam_lib:chunks(Filename,["Abst"]) of
{ok,{_,[{"Abst",AChunk}]}} ->
{_,Forms} = binary_to_term(AChunk),
form_list(Forms);
_ ->
erlang:error({no_debuginfo,Filename})
end.
get_forms_erl(Filename) ->
{ok,Fs} = epp_dodger:parse_file(Filename,[{no_fail, true}]),
Fs.
%%% # tree
%%% turn a syntax tree into html by annotating and pretty-printing
%%% with a hook function
tree(Tree) ->
pout(ann(type(Tree),Tree)).
%%lists:foldl(fun(Form,Acc) -> [pout(ann(Form))|Acc] end, [], Tree).
pout(Form) ->
erl_prettypr:format(Form,[{hook,fun tag/3},{paper,90},{ribbon,650}]).
%%% ## formatting
%%% ### 'tag' - the format hook function
tag(Node,Ctxt,Cont) ->
Tags = get_ann(Node),
case member(has_comment,Tags) of
true ->
PreC = get_precomments(Node),
PostC = get_postcomments(Node),
Nod = remove_comments(Node),
Doc0 = tagit(Tags--[has_comment],Cont(Nod,Ctxt)),
postcomment(precomment(Doc0,PreC),PostC);
false ->
Doc0 = Cont(Node,Ctxt),
tagit(Tags,Doc0)
end.
tagit([],Doc0) ->
Doc0;
tagit(["binary"],{beside,_,{beside,Doc,_}}) ->
beside(floating(text("&lt;&lt;")),beside(Doc,floating(text("&gt;&gt;"))));
tagit([Tag],Doc0) ->
beside(null_text(Tag),beside(Doc0,null_text(etag(Tag)))).
etag("<"++Tag) -> "</"++hd(string:tokens(Tag," "))++">".
%%%### comment stuff
precomment(Doc,PreC) ->
above(floating(break(stack(PreC)), -1, -1), Doc).
postcomment(Doc,PostC) ->
beside(Doc, floating(break(stack(PostC)), 1, 0)).
stack([]) -> empty();
stack([Comm|Comms]) ->
Doc = maybe_pad(stack_comment_lines(comment_text(Comm)),Comm),
case Comms of
[] -> Doc;
_ -> above(Doc, stack(Comms))
end.
maybe_pad(Doc,Comm) ->
case comment_padding(Comm) of
I when is_integer(I), 0 < I -> beside(text(duplicate(I,$ )), Doc);
_ -> Doc
end.
%%% stolen with pride from erl_prettypr
%%% Stack lines of text above each other and prefix each string in
%%% the list with a single `%' character.
stack_comment_lines([S | Ss]) ->
D = tagit([dehtml('span', [{class,comment}])],text("%"++debracket(S))),
case Ss of
[] -> D;
_ -> above(D, stack_comment_lines(Ss))
end;
stack_comment_lines([]) ->
empty().
%%% annotate nodes that should be hilited
%%% the annotation is put on the subtree that should be marked up
%%% the annotation is;
%%% has_comments|Markup
%%% if a node already has an annotation the new one is dropped, except
%%% if either the new or the old one is has_comments
ann(binary,Tree) ->
new_tree(Tree,add_anno("binary",Tree));
ann(application,Tree) ->
Op = application_operator(Tree),
Args = application_arguments(Tree),
new_tree(Tree,application(add_anno(mu(application,Tree),Op),Args));
ann(attribute,Tree) ->
Name = attribute_name(Tree),
case atom_value(Name) of
export ->
AQs = list_elements(hd(attribute_arguments(Tree))),
Args = [list([add_anno(mu(export,Tree),AQ) || AQ <- AQs])];
import ->
[ImportMod,ImportFAs] = attribute_arguments(Tree),
AQs = list_elements(ImportFAs),
Args = [ImportMod,list([add_anno(mu(import,Tree),AQ) || AQ <- AQs])];
define ->
[Macro|Rest] = attribute_arguments(Tree),
case type(Macro) of
application ->
Op = application_operator(Macro),
As = application_arguments(Macro),
Args = [application(add_anno(mu(macro,Tree),Op),As)|Rest];
_ ->
Args = [add_anno(mu(macro,Tree),Macro)|Rest]
end;
record ->
[Rec|Rest] = attribute_arguments(Tree),
Args = [add_anno(mu(record,Tree),Rec)|Rest];
_ ->
Args = attribute_arguments(Tree)
end,
new_tree(Tree,attribute(add_anno(mu(attribute,Tree),Name),Args));
ann(record_access,Tree) ->
Arg = record_access_argument(Tree),
Type = record_access_type(Tree),
Field = record_access_field(Tree),
new_tree(Tree,record_access(Arg,add_anno(mu(record,Tree),Type),Field));
ann(record_expr,Tree) ->
Arg = record_expr_argument(Tree),
Type = record_expr_type(Tree),
Fields = record_expr_fields(Tree),
new_tree(Tree,record_expr(Arg,add_anno(mu(record,Tree),Type),Fields));
ann(record_index_expr,Tree) ->
Type = record_index_expr_type(Tree),
Field = record_index_expr_field(Tree),
new_tree(Tree,record_index_expr(add_anno(mu(record,Tree),Type),Field));
ann(function,Tree) ->
Name = function_name(Tree),
Clauses = function_clauses(Tree),
new_tree(Tree,function(add_anno(mu(function,Tree),Name),Clauses));
ann(macro,Tree) ->
Name = macro_name(Tree),
Args = macro_arguments(Tree),
new_tree(Tree,macro(add_anno(mu(macro,Tree),Name), Args));
ann(string,OTree) ->
Tree = erl_syntax:string(debracket(string_value(OTree))),
new_tree(OTree,add_anno(mu(string,OTree),Tree));
ann(variable,Tree) ->
new_tree(Tree,add_anno(mu(variable,Tree),Tree));
ann(text,Tree) ->
new_tree(Tree,add_anno(mu(error,Tree),Tree));
ann(comment,OTree) ->
Pad = comment_padding(OTree),
Text = [debracket(S) || S <- comment_text(OTree)],
Tree = comment(Pad,Text),
new_tree(OTree,add_anno(mu(comment,OTree),Tree));
ann(_Typ,Tree) ->
new_tree(Tree,Tree).
new_tree(OTree,NTree) ->
Tree =
case has_comments(OTree) of
true -> add_ann(has_comment,copy_comments(OTree,NTree));
false -> NTree
end,
SubTrees = subtrees(Tree),
case [[ann(type(SubT),SubT) || SubT<-Group] || Group<-SubTrees] of
[] -> Tree;
NSubtrees -> update_tree(Tree,NSubtrees)
end.
debracket([]) -> [];
debracket([$>|Str]) -> "&gt;"++debracket(Str);
debracket([$<|Str]) -> "&lt;"++debracket(Str);
debracket([C|Str]) -> [C|debracket(Str)].
add_anno(nil,Tree) -> Tree;
add_anno(Ann,Tree) ->
case get_ann(Tree) of
[] -> add_ann(Ann,Tree);
[has_comment] -> add_ann(Ann,Tree);
_OAnn -> Tree
end.
%%%### the markups
mu(application,Node) ->
Op = application_operator(Node),
Ar = length(application_arguments(Node)),
case type(Op) of
%% variable ->
%% dehtml('span', [{class,variable}]);
atom ->
case is_guard_or_builtin(atom_value(Op),Ar) of
guard -> dehtml('span', [{class,guard}]);
builtin->dehtml('span', [{class,builtin}]);
neither->dehtml('span', [{class,call}])
end;
module_qualifier ->
Mod = module_qualifier_argument(Op),
Fun = module_qualifier_body(Op),
case {type(Mod),type(Fun)} of
{atom,atom} ->
case atom_value(Mod) of
erlang -> dehtml('span', [{class,builtin}]);
_ -> dehtml('span', [{class,call}])
end;
_ ->
nil
end;
_ ->
nil
end;
mu(function = Class, {tree, function, _, {function, _, [{tree, clause, _, {clause, Vars, _, _}} | _]}}) ->
dehtml('span', [{class,Class}, {arity,length(Vars)}]);
mu(Class,_Node) ->
dehtml('span', [{class,Class}]).
dehtml(Tag,Atts) ->
flatten([$<,str(Tag),$ ,[[str(A),"=\"",str(V),"\" "]||{A,V}<-Atts],$>]).
str(I) when is_integer(I) -> integer_to_list(I);
str(A) when is_atom(A) -> atom_to_list(A);
str(L) when is_list(L) -> L.
is_guard_or_builtin(atom,1) ->guard;
is_guard_or_builtin(binary,1) ->guard;
is_guard_or_builtin(constant,1) ->guard;
is_guard_or_builtin(float,1) ->guard;
is_guard_or_builtin(function,1) ->guard;
is_guard_or_builtin(function,2) ->guard;
is_guard_or_builtin(integer,1) ->guard;
is_guard_or_builtin(list,1) ->guard;
is_guard_or_builtin(number,1) ->guard;
is_guard_or_builtin(pid,1) ->guard;
is_guard_or_builtin(port,1) ->guard;
is_guard_or_builtin(reference,1) ->guard;
is_guard_or_builtin(tuple,1) ->guard;
is_guard_or_builtin(record,2) ->guard;
is_guard_or_builtin(record,3) ->guard;
is_guard_or_builtin(F,A) ->
case erlang:function_exported(erlang,F,A) orelse
erlang:is_builtin(erlang,F,A) of
true -> builtin;
false-> neither
end.
-54
View File
@@ -1,54 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : escobar_run.erl
%%% Author : Badlop <badlop@process-one.net>
%%% Purpose : Frontend to run Escobar
%%% Created : 16 Apr 2008 by Badlop <badlop@process-one.net>
%%%-------------------------------------------------------------------
-module(escobar_run).
%%% Download ejabberd_hilite.erl from http://code.google.com/p/erl-escobar/
%%% Example calls:
%%% escobar_run:file("escobar_run.erl", "../ejascobar/").
%%% escobar_run:dir(".", "../ejascobar/").
%%% escobar_run:dir(".", "../doc/api/").
%%% find ./ -type f -name '*.html' -exec sed -i 's/class="function" >\([a-z0-9]*\)</class="function" id="\1">\1</;' {} \;
-export([file/2, file/1, dir/1]).
file([F, OutDir]) ->
file(F, OutDir).
file(F, OutDir) ->
String = escobar_hilite:file(F),
FB = filename:basename(F),
FilenameHTML = filename:join(OutDir, FB ++ ".html"),
escobar_hilite:out(FilenameHTML, String).
dir([SrcDir, OutDir]) ->
SrcDirAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
Files = get_files([SrcDirAbs]),
lists:foreach(
fun(F) ->
case filename:extension(F) of
".erl" ->
file(F, OutDirAbs);
".hrl" ->
file(F, OutDirAbs);
_ ->
ok
end
end,
Files).
get_files([]) ->
[];
get_files([FHead | FTail]) ->
case catch file:list_dir(FHead) of
{ok, Files} ->
FilesHead = [filename:join(FHead, FilesN) || FilesN <- Files],
get_files(FilesHead ++ FTail);
{error, enotdir} ->
[FHead] ++ get_files(FTail)
end.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

-522
View File
@@ -1,522 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : funrelg.erl
%%% Author : Badlop <badlop@process-one.net>
%%% Purpose : Function Relation Graph
%%% Created : 3 Apr 2007 by Badlop <badlop@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(funrelg).
-author('badlop@process-one.net').
-export([dir/1, file/1, g/0, g/1, gc/0, gc/1, d/0]).
-record(mfa, {mod, func, arity}).
-record(arcs, {id, from, to, occ}).
%% The functions that are not in export and don't call anybody are not drawn
%% The calls to this module that use Mod:Func are drawn as external calls
%%-----------------------------
%% Module handlers
%%-----------------------------
dir([SrcDir, OutDir]) ->
SrcDirAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
Files = get_files([SrcDirAbs]),
lists:foreach(
fun(F) ->
file(F, OutDirAbs)
end,
Files).
file([SrcDir, OutDir]) ->
SrcFilAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
file(SrcFilAbs, OutDirAbs).
file(SrcFile, OutDir) ->
case {filename:extension(SrcFile), filename:basename(SrcFile)} of
%% The file must by *.erl, and the first character must be a-z
{".erl", [FirstChar | _]} when (FirstChar >= 97) and (FirstChar =< 122) ->
make_file(SrcFile, OutDir),
d();
_ ->
ok
end.
get_files([]) ->
[];
get_files([FHead | FTail]) ->
case catch file:list_dir(FHead) of
{ok, Files} ->
FilesHead = [filename:join(FHead, FilesN) || FilesN <- Files],
get_files(FilesHead ++ FTail);
{error, enotdir} ->
[FHead] ++ get_files(FTail)
end.
make_file(File, OutDir) ->
FB = filename:basename(File),
FileDot = filename:join(OutDir, FB ++ ".dot"),
Text = gc(File),
{ok,FO}=file:open(FileDot,[write]),
try
io:fwrite(FO,"~s",[Text])
after
file:close(FO)
end,
FileSvg = filename:join(OutDir, filename:basename(File, ".erl") ++ ".svg"),
case os:cmd("dot -Tsvg " ++ FileDot ++ " -o " ++ FileSvg) of
"" -> ok;
ShellResult ->
io:format("Trying to run 'dot', we got this result:~n ~s~n"
"Remember that you need to have Graphviz 'dot' installed.~n", [ShellResult])
end,
ok.
%%====================================================================
%% Internal functions
%%====================================================================
g() ->
g("a.erl").
g(Filename) ->
gc(Filename),
halt().
gc() ->
gc("a.erl").
gc(Filename) ->
{ok, File} = epp_dodger:parse_file(Filename),
ets:new(arcs, [set, public, named_table, {keypos, 2}]),
ets:new(mfa_conversion, [set, public, named_table, {keypos, 1}]),
ets:new(counters, [set, public, named_table]),
ets:insert(counters, {arcs_id, 0}),
ModuleName = get_module_name(File),
Exports = lists:usort(get_exports(File)),
Functions = get_functions(File),
FunctionsParsed = lists:usort(parse_functions(Functions)), % side effects: stores on ets
Privates = FunctionsParsed -- Exports,
%%Externals = get_externals(),
MFAs = get_func_calls(),
AppModules1 = os:cmd("ls -1 ../doc/devdoc/*.html | tr \".\" \" \" | tr \"/\" \" \" | awk '{print $3}'"),
AppModules = [list_to_atom(Str) || Str <- string:tokens(AppModules1, [10])],
ExternalTypes1 = [mfa_to_externaltype(MFA, ModuleName, AppModules, FunctionsParsed) || MFA <- MFAs],
ExternalTypes = lists:usort(ExternalTypes1),
AppExternals = [Function || {Type, Function} <- ExternalTypes, Type == app],
ExmppExternals = [Function || {Type, Function} <- ExternalTypes, Type == exmpp],
OTPExternals = [Function || {Type, Function} <- ExternalTypes, Type == other],
textize(ModuleName, Exports, Privates, AppExternals, ExmppExternals, OTPExternals).
get_arcs_id() ->
ets:update_counter(counters, arcs_id, 1).
insert_arc_normal(FromFunc, FromArity, ToFunc, ToArity) ->
From = #mfa{mod = -1, func = FromFunc, arity = FromArity},
To = #mfa{mod = -1, func = ToFunc, arity = ToArity},
insert_arc(From, To).
insert_arc_external(FromFunc, FromArity, ToMod, ToFunc, ToArity) ->
From = #mfa{mod = -1, func = FromFunc, arity = FromArity},
To = #mfa{mod = ToMod, func = ToFunc, arity = ToArity},
insert_arc(From, To).
insert_arc(From, To) ->
Match = #arcs{
from = From,
to = To,
id='$1',
_='_'},
Select = [{Match, [], ['$1']}],
Ids = ets:select(arcs, Select),
case Ids of
[] ->
ets:insert(arcs,
#arcs{
id = get_arcs_id(),
from = From,
to = To,
occ = 1
}
);
[Id] ->
[Arc] = ets:lookup(arcs, Id),
Arc2 = Arc#arcs{occ = Arc#arcs.occ+1},
ets:insert(arcs, Arc2)
end.
read_arc(Id) ->
ets:lookup(arcs, Id).
d() ->
ets:delete(arcs),
ets:delete(mfa_conversion),
ets:delete(counters).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Get
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_module_name(File) ->
Attributes = get_elements(attribute, File),
get_attribute(module, Attributes).
get_exports(File) ->
Attributes = get_elements(attribute, File),
Exports = get_attribute(export, Attributes),
parse_export(Exports).
get_functions(File) ->
get_elements(function, File).
get_elements(Type, L) -> get_elements(Type, L, []).
get_elements(_, [], Res) -> Res;
get_elements(Type, [{tree, Type, _, A} | L], Res) ->
get_elements(Type, L, Res++[A]);
get_elements(Type, [_ | L], Res) ->
get_elements(Type, L, Res).
get_attribute(_, []) -> [];
get_attribute(Name, [{attribute, {tree, atom, _, Name}, [Al]} | As]) ->
case Name of
module ->
{tree, atom, _, Mn} = Al,
Mn;
export ->
{tree, list, _, {list, Exports, _}} = Al,
Exports++get_attribute(Name, As);
_ -> ok
end;
get_attribute(Name, [_ | As]) ->
get_attribute(Name, As).
parse_export(Ex) ->
lists:foldl(
fun(Aq, Res) ->
{tree, arity_qualifier, _, {arity_qualifier, Atom, Inte}} = Aq,
{tree, atom, _, An} = Atom,
{tree, integer, _, In} = Inte,
Res++[{An, In}]
end,
[],
Ex).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Parse
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_functions(Functions) ->
lists:map(
fun(E) ->
{function, {_, _, _, Fn}, Clauses} = E,
Arity = get_function_arity(Clauses),
parse_clauses(Fn, Clauses),
{Fn, Arity}
end,
Functions).
parse_clauses(Fn, Clauses) ->
lists:foreach(
fun(E) ->
{tree, clause, L, C} = E,
{attr, _Ln, _, _} = L,
{clause, Parameters, _, Contents} = C,
Fa = length(Parameters),
parse_contents({Fn, Fa}, Contents)
end,
Clauses).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% OLD
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_contents(F, Contents) ->
{_, Res} = lists:foldl(
fun(C, {Fu, R}) ->
{Fu, R++parse_content(F, C)}
end,
{F, []},
Contents),
Res.
parse_content(F, {tree, application, L, A}) ->
{attr, _Ln, _, _} = L,
parse_application(F, A);
parse_content(F, {tree, list, _, {list, [L], Ls}}) ->
RL = parse_content(F, L),
RL++parse_content(F, Ls);
parse_content(F, {tree, tuple, _, T}) ->
parse_contents(F, T);
parse_content(F, {tree, match_expr, _, M}) ->
{match_expr, _, Value} = M,
parse_content(F, Value);
parse_content(F, {tree, try_expr, _, T}) ->
{try_expr, As, Bs, Cs, Ds} = T,
RAs = parse_contents(F, As),
RBs = parse_contents(F, Bs),
RDs = parse_contents(F, Ds),
RAs++RBs++RDs++parse_contents(F, Cs);
parse_content(F, {tree, block_expr, _, Ts}) ->
parse_contents(F, Ts);
parse_content(F, {tree, catch_expr, _, C}) ->
parse_content(F, C);
parse_content(F, {tree, case_expr, _, C}) ->
{case_expr, Case, Cases} = C,
R2 = parse_content(F, Case),
R2++parse_contents(F, Cases);
parse_content(F, {tree, if_expr, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, disjunction, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, conjunction, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, list_comp, _, L}) ->
{list_comp, A, Bs} = L,
RA = parse_content(F, A),
RA++parse_contents(F, Bs);
parse_content(F, {tree, generator, _, G}) ->
{generator, _, Gen} = G,
parse_content(F, Gen);
parse_content(F, {tree, clause, _, C}) ->
{clause, Clause, When, Second} = C,
R2 = parse_contents(F, Clause),
R3 = parse_content(F, When),
R2++R3++parse_contents(F, Second);
parse_content(F, {tree, fun_expr, _, E}) ->
parse_contents(F, E);
parse_content(F, {tree, record_expr, _, E}) ->
{record_expr, _, _, Records} = E,
parse_contents(F, Records);
parse_content(F, {tree, record_field, _, R}) ->
{record_field, F1, F2} = R,
R2 = parse_content(F, F1),
R2++parse_content(F, F2);
parse_content(F, {tree, receive_expr, _, E}) ->
{receive_expr, E1, _, _} = E,
parse_contents(F, E1);
parse_content(F, {tree, infix_expr, _, I}) ->
{infix_expr, _Operator, T1, T2} = I,
R = parse_content(F, T1),
R++parse_content(F, T2);
parse_content(_F, {tree, prefix_expr, _, _P}) ->
[];
parse_content(_F, {tree, class_qualifier, _, _}) -> [];
parse_content(_F, {tree, implicit_fun, _, _}) -> [];
parse_content(_F, {tree, record_access, _, _}) -> [];
parse_content(_F, {tree, record_index_expr, _, _}) -> [];
parse_content(_F, {tree, macro, _, _}) -> [];
parse_content(_F, {tree, binary, _, _}) -> [];
parse_content(_F, {tree, binary_generator, _, _}) -> [];
parse_content(_F, {tree, binary_comp, _, _}) -> [];
parse_content(_F, {integer, _, _I}) -> [];
parse_content(_F, {float, _, _I}) -> [];
parse_content(_F, {string, _, _S}) -> [];
parse_content(_F, {char, _, _S}) -> [];
parse_content(_F, {atom, _, _A}) -> [];
parse_content(_F, {var, _, _V}) -> [];
parse_content(_F, {nil, _}) -> [];
parse_content(_F, none) -> [];
parse_content(_F, C) -> io:format("Unknown content: ~p~n", [C]), [].
parse_application({Fn, Fa}, {application, {atom, _, Name}, Valores}) ->
Arity = length(Valores),
insert_arc_normal(Fn, Fa, Name, Arity),
Ra = [{arc_normal, Fn, Name}],
Ra++parse_contents({Fn, Fa}, Valores);
parse_application({Fn, Fa}, {application, {tree, module_qualifier, _, M}, Tree2}) ->
case M of
{module_qualifier, {_, _, Tf1}, {_, _, Tf2}} ->
ToArity = length(Tree2),
insert_arc_external(Fn, Fa, Tf1, Tf2, ToArity),
parse_contents({Fn, Fa}, Tree2);
_Other ->
%%io:format("Unknown application module_qualifier: ~p~n", [M]),
parse_contents({Fn, Fa}, Tree2)
end;
parse_application({Fn, Fa}, {application, {tree, record_access, _, _}, Tree2}) ->
parse_contents({Fn, Fa}, Tree2);
parse_application({Fn, Fa}, {application, {var, _, _}, Tree2}) ->
parse_contents({Fn, Fa}, Tree2);
parse_application({Fn, Fa}, {application, Other, Tree2}) ->
io:format("Unknown application tree: ~p~n", [Other]),
parse_contents({Fn, Fa}, Tree2).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Textize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
textize(ModuleName, Exports, Privates, AppExternals, ExmppExternals, OTPExternals) ->
ExportsS = textize_exports(Exports),
PrivatesS = textize_exports(Privates),
AppExternalsS = textize_externals(AppExternals),
ExmppExternalsS = textize_externals(ExmppExternals),
OTPExternalsS = textize_externals(OTPExternals),
Arcs = textize_arcs(),
io_lib:format(
"digraph ~p {~n"++
" label = \"Module ~p\";~n"++
" labelloc = \"t\";~n"++
" fontname = Helvetica;~n"++
" rankdir = LR;~n"++
" ratio = fill;~n"++
%%" node [shape = box, style = filled, color = olivedrab1, fontsize=40];~s~n"++
%%" node [shape = parallelogram, style = filled, color = rosybrown1, fontsize=40];~s~n"++
%%" node [shape = ellipse, style = filled, color = slategray1, peripheries=3, fontsize=40];~n"++
" node [shape = box, color=darkgreen, fillcolor=Honeydew, style=filled, href=\"PRI~p.html#\\N\"];~s~n"++
" node [shape = box, color=darkgreen, fillcolor=PaleGreen, style=filled, href=\"EXP~p.html#\\N\"];~s~n"++
" node [shape = box, color=darkgreen, fillcolor=Aquamarine, style=filled, href=\"APP\\N\"];~s~n"++
" node [shape = box, color=darkblue, fillcolor=LightSkyBlue,style=filled, href=\"EXM\\N\"];~s~n"++
" node [shape = box, color=darkred, fillcolor=PeachPuff, style=filled, href=\"OTP\\N\"];~s~n"++
" node [shape = box];~n"++
"~s"++
"}~n",
[ModuleName, ModuleName,
ModuleName, PrivatesS,
ModuleName, ExportsS,
AppExternalsS,
ExmppExternalsS,
OTPExternalsS,
Arcs]).
textize_exports(Exports) ->
lists:foldl(
fun({Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p/~p\";", [Func, Arity]))
end,
"",
Exports).
textize_externals(Externals) ->
lists:foldl(
fun({Mod, Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p:~p/~p\";", [Mod, Func, Arity]));
({Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p/~p\";", [Func, Arity]))
end,
"",
Externals).
textize_arcs() ->
Id = ets:first(arcs),
textize_arcs(Id, []).
textize_arcs('$end_of_table', Res) -> Res;
textize_arcs(Id, Res) ->
[Arc] = read_arc(Id),
From = mfa_prepare(Arc#arcs.from),
To = mfa_prepare(Arc#arcs.to),
Edge_attrs = check_loop(From, To)++check_occu(Arc#arcs.occ)++check_external(Arc#arcs.to),
Res2 = io_lib:format(" ~s -> ~s~s;~n", [From, To, Edge_attrs]),
Id_next = ets:next(arcs, Id),
textize_arcs(Id_next, string:concat(Res2, Res)).
get_func_calls() ->
Id = ets:first(arcs),
get_func_calls(Id, []).
get_func_calls('$end_of_table', Res) -> Res;
get_func_calls(Id, Res) ->
[Arc] = read_arc(Id),
MFA = Arc#arcs.to,
Call = MFA,
Id_next = ets:next(arcs, Id),
get_func_calls(Id_next, [Call | Res]).
mfa_prepare(MFAinitial) ->
MFA = try_mfa_conversion(MFAinitial),
Mod = case MFA#mfa.mod of
-1 -> "\"";
M -> io_lib:format("\"~p:", [M])
end,
Func = io_lib:format("~p", [MFA#mfa.func]),
Arity = case MFA#mfa.arity of
-1 -> "\"";
A -> io_lib:format("/~p\"", [A])
end,
string:concat(Mod, string:concat(Func, Arity)).
%% noexternal | app | exmpp | other
mfa_to_externaltype(MFA, ModuleName, AppModules, Functions) ->
case MFA of
{mfa, -1, Fu, Ar} ->
case {is_internal, lists:member({Fu, Ar}, Functions)} of
{is_internal, true} ->
{noexternal, {Fu, Ar}};
{is_internal, false} ->
store_mfa_conversion(MFA, {mfa, -1, Fu, Ar}),
{other, {Fu, Ar}}
end;
{mfa, Mo, Fu, Ar} when Mo == ModuleName ->
store_mfa_conversion(MFA, {mfa, -1, Fu, Ar}),
{noexternal, {Fu, Ar}};
{mfa, Mo, Fu, Ar} ->
Type = case {is_app, lists:member(Mo, AppModules)} of
{is_app, true} -> app;
{is_app, false} ->
case string:str(atom_to_list(Mo), "exmpp") of
0 -> other;
N when is_integer(N) -> exmpp
end
end,
{Type, {Mo, Fu, Ar}}
end.
get_function_arity([{tree, clause, _, {clause, Vars, _, _}} | _]) ->
length(Vars);
get_function_arity(E) ->
io:format("Unknown function arity: ~p~n", [E]).
store_mfa_conversion(MFA1, MFA2) ->
ets:insert(mfa_conversion, {MFA1, MFA2}).
try_mfa_conversion(MFA) ->
case ets:lookup(mfa_conversion, MFA) of
[{MFA,MFA2}] ->
MFA2;
[] ->
MFA
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Utils
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%check_loop(I, I) -> " [color = sandybrown]";
check_loop(I, I) -> "";
check_loop(_, _) -> "".
check_occu(1) -> "";
check_occu(Occ) -> io_lib:format(" [label=\"~p\"]", [Occ]).
check_external(To) ->
case To#mfa.mod of
-1 -> " [style = bold]";
_ -> ""
end.
-115
View File
@@ -1,115 +0,0 @@
div.navbar table tr td a[target="_parent"] {
background: transparent url("ejabberd-devdoc.png") no-repeat;
display: block;
font-size: 0%;
top: 0;
left: 0;
padding: 0;
margin: 0;
width: 192px;
height: 42px;
}
div.navbar table tr td a img {
border: 0;
padding: 0 0 0 10;
float: right;
}
p i {
display: none;
}
html, body {
font-family: Verdana, sans-serif;
color: #000;
background-color: #fff;
}
h1 {
font-size: 20px;
color: #4a5389;
border-bottom: solid 1px #000;
}
h2 {
font-size: 18px;
text-align: right;
color: #4a5389;
border-bottom: 1px solid #000;
}
h3 {
font-size: 16px;
color: #900;
}
h4 {
font-size: 14px;
color: #000;
}
a[href] {
color: #4a5389;
}
a[href]:hover {
background-color: #ecefff;
}
p, li, dd {
text-align: justify;
}
li {
margin-top: 0.3em;
}
li:first-child {
margin-top: 0px;
}
blockquote {
color: #555;
}
caption {
font-style: italic;
color: #009;
text-align: left;
margin-left: 20px;
}
table[border="1"] {
border-collapse: collapse;
margin-bottom: 1em;
}
table[border="1"] td {
border: 1px solid #ddd;
}
pre, tt, code {
color: #461b7e;
}
pre {
margin:1ex 2ex;
border:1px dashed lightgrey;
background-color:#f9f9f9;
padding:0.5ex;
}
pre em {
font-style: normal;
font-weight: bold;
}
dt {
margin:0ex 2ex;
font-weight:bold;
}
dd {
margin:0ex 0ex 1ex 4ex;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

-136
View File
@@ -1,136 +0,0 @@
\documentclass[a4paper,10pt]{article}
%% Packages
\usepackage{epsfig}
\usepackage{fancyhdr}
\usepackage{graphics}
\usepackage{hevea}
\usepackage[pdftex,colorlinks,unicode,urlcolor=blue,linkcolor=blue,pdftitle=Ejabberd\
Feature\ Sheet,pdfauthor=Sander\
Devrieze,pdfsubject=ejabberd,pdfkeywords=ejabberd]{hyperref}
\usepackage{verbatim}
\usepackage{color}
%% Index
% Remove the index anchors from the HTML version to save size and bandwith.
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
%% Images
\newcommand{\logoscale}{0.7}
\newcommand{\imgscale}{0.58}
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
\newcommand{\insscaleimg}[2]{
\imgsrc{#2}{}
\begin{latexonly}
\scalebox{#1}{\includegraphics{#2}}
\end{latexonly}
}
%% Various
\newcommand{\bracehack}{\def\{{\char"7B}\def\}{\char"7D}}
\newcommand{\titem}[1]{\item[\bracehack\texttt{#1}]}
\newcommand{\ns}[1]{\texttt{#1}}
\newcommand{\jid}[1]{\texttt{#1}}
\newcommand{\option}[1]{\texttt{#1}}
\newcommand{\poption}[1]{{\bracehack\texttt{#1}}}
\newcommand{\node}[1]{\texttt{#1}}
\newcommand{\term}[1]{\texttt{#1}}
\newcommand{\shell}[1]{\texttt{#1}}
\newcommand{\ejabberd}{\texttt{ejabberd}}
\newcommand{\Jabber}{Jabber}
%% Title page
\include{version}
\title{Ejabberd \version\ Feature Sheet}
\author{Sander Devrieze \\
\ahrefurl{mailto:s.devrieze@pandora.be} \\
\ahrefurl{xmpp:sander@devrieze.dyndns.org}}
% Options
\newcommand{\marking}[1]{\textbf{\begin{large}\textcolor{ejblue}{#1}\end{large}}} % Marking enabled
\newcommand{\quoting}[2][yozhik]{\begin{quotation}\textcolor{#1}{\textit{#2}}\end{quotation}} % Quotes enabled
\newcommand{\new}{\marginpar{\textcolor{red}{\textsc{new}}}} % Highlight new features
\newcommand{\improved}{\marginpar{\textcolor{orange}{\textsc{improved}}}} % Highlight improved features
\setcounter{secnumdepth}{-1} % Disable section numbering
%% To by-pass errors in the HTML version.
\newstyle{SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;}
\definecolor{orange} {cmyk}{0.000,0.333,1.000,0.000}
%% Footnotes
\begin{latexonly}
\global\parskip=9pt plus 3pt minus 1pt
\global\parindent=0pt
\gdef\ahrefurl#1{\href{#1}{\texttt{#1}}}
\gdef\footahref#1#2{#2\footnote{\href{#1}{\texttt{#1}}}}
\end{latexonly}
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
%% Fancy header
\fancyhf{}
\pagestyle{fancy}
\rhead{\textcolor{ejblue}{The Expandable Jabber/XMPP Daemon.}}
\renewcommand{\headrule}{{\color{ejblue}%
\hrule width\headwidth height\headrulewidth \vskip-\headrulewidth}}
\lhead{\setlength{\unitlength}{-6mm}
\begin{picture}(0,0)
\put(5.8,3.25){\includegraphics[width=1.3\textwidth]{yozhikheader.png}}
\end{picture}}
% Official ejabberd colours
\definecolor{ejblue} {cmyk}{1.000,0.831,0.000,0.537} %RGB: 0,0,118 HTML: 000076
\definecolor{ejgreenyellow}{cmyk}{0.079,0.000,0.275,0.102} %RGB: 209,229,159 HTML: d1e59f
\definecolor{ejgreendark} {cmyk}{0.131,0.000,0.146,0.220} %RGB: 166,199,162 HTML: a6c7a2
\definecolor{ejgreen} {cmyk}{0.077,0.000,0.081,0.078} %RGB: 216,236,215 HTML: d8ecd7
\definecolor{ejgreenwhite} {cmyk}{0.044,0.000,0.048,0.020} %RGB: 239,250,238 HTML: effaee
\definecolor{yozhik} {cmyk}{0.000,0.837,1.000,0.424} %RGB: 147,0,0 HTML: 930000
\begin{document}
\label{titlepage}
\begin{titlepage}
\maketitle{}
\thispagestyle{empty}
\begin{center}
{\insscaleimg{\logoscale}{logo.png}
\par
}
\end{center}
\quoting{I can thoroughly recommend ejabberd for ease of setup --
Kevin Smith, Current maintainer of the Psi project}
\end{titlepage}
\newpage
% Set the page counter to 2 so that the titlepage and the second page do not
% have the same page number. This fixes the PDFLaTeX warning "destination with
% the same identifier".
\begin{latexonly}
\setcounter{page}{2}
\pagecolor{ejgreenwhite}
\end{latexonly}
% Input introduction.tex
\input{introduction}
\end{document}
%% TODO
% * illustrations (e.g. screenshot from web interface)
% * commented parts
% * slides, guide and html version
% * cleaning and improving LaTeX code
% * key features: something like this (shorter)? (more focussed on Erlang now): "To reach the goal of high
% availability, performance and clustering, ejabberd is written in Erlang, a programming language perfectly
% suited for this. Besides that, some parts are written in C to also incude the advantages of this language. In
% short, ejabberd is a perfect mix of mainly Erlang code, peppered with some C code to get the final touch!"
% <picture of a cocktail>
% * key features: saying that ejabberd the only XMPP server is that can do real clustering:
% http://www.jivesoftware.org/forums/thread.jspa?threadID=14602
% "What I find interesting is that *no* XMPP servers truly provide clustering. This includes all the commercial
% servers. The one partial exception appears to be ejabberd, which can cluster certain data such as sessions,
% but not all services such as MUC."
% * try it today: links to migration tutorials
+2438
View File
File diff suppressed because it is too large Load Diff
+1273 -5149
View File
File diff suppressed because it is too large Load Diff
+58 -59
View File
@@ -1,33 +1,25 @@
\chapter{Introduction}
\label{intro}
\section{Introduction}
\label{sec:intr}
%% TODO: improve the feature sheet with a nice table to highlight new features.
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. ---
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. --
Joeri}
%ejabberd is a free and open source instant messaging server written in Erlang. ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication (Jabber/XMPP).
\ejabberd{} is a free (GPL) distributed fault-tolerant \Jabber{}/XMPP server and is mainly written in \footahref{http://www.erlang.org/}{Erlang}.
\ejabberd{} is a \marking{free and open source} instant messaging server written in \footahref{http://www.erlang.org/}{Erlang/OTP}.
\ejabberd{} is designed to be a \marking{stable} and \marking{feature rich} \Jabber{}/XMPP server.
\ejabberd{} is \marking{cross-platform}, distributed, fault-tolerant, and based on open standards to achieve real-time communication.
\ejabberd{} is designed to be a \marking{rock-solid and feature rich} XMPP server.
\ejabberd{} is suitable for small deployments, whether they need to be \marking{scalable} or not, as well as extremely big deployments.
\ejabberd{} is suitable for small servers, whether they need to be scalable or not, as well as extremely big servers.
%\subsection{Layout with example deployment (title needs a better name)}
%\label{layout}
%In this section there will be a graphical overview like these:\\
%\verb|http://www.tipic.com/var/timp/timp_dep.gif| \\
%\verb|http://www.jabber.com/images/jabber_Com_Platform.jpg| \\
%\verb|http://www.antepo.com/files/OPN45systemdatasheet.pdf| \\
%A page full with names of Jabber client that are known to work with ejabberd. \begin{tiny}tiny font\end{tiny}
%Some small images of Jabber clients that are known to work greatly with ejabberd. Less text!!!
%\subsection{Try It Today}
%\label{trytoday}
%(Not sure if I will include/finish this section for the next version.)
@@ -40,93 +32,100 @@ Joeri}
%\end{itemize}
\newpage
\section{Key Features}
\label{keyfeatures}
\subsection{Key Features}
\label{sec:keyfeatures}
\ind{features!key features}
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. ---
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. --
Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
\ejabberd{} is:
\begin{itemize}
\item \marking{Cross-platform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
\item \marking{Multiplatform:} \ejabberd{} runs under Windows NT/2000/XP and Unix derived systems such as Linux, FreeBSD and NetBSD.
\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve the same \Jabber{} domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.
\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve one \Jabber{} domain. When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support hundreds of concurrent users.
\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'.
\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ``on the fly''.
\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already installed, and ready to run out of the box. Other benefits for administrators include:
\begin{itemize}
\item Comprehensive documentation.
\item Straightforward installers for Linux, Mac OS X, and Windows. %%\improved{}
\item Web Administration.
\item Shared Roster Groups.
\item Command line administration tool. %%\improved{}
\item Comprehensive documentation.\moreinfo{ --- You can start in the \footahref{http://ejabberd.jabber.ru/book}{ejabberd Book}.}
\item Straightforward installers for Windows and Linux.\moreinfo{ --- (\footahref{http://ejabberd.jabber.ru/screenshots-linux-installer}{Screenshots}).}
\item Web interface for administration tasks.\moreinfo{ --- With HTTPS secure access. \footahref{http://ejabberd.jabber.ru/online-demo-webadmin}{Demo}.}
\item Shared Roster groups.\improved{}\moreinfo{ --- The administrator can setup a common list of \Jabber{} users for all users on the server. Those users are virtually added to all rosters. They cannot be removed, but can be renamed or moved into different roster groups. Does not require client implementation. Not related to \jepref{0144} (Roster Item Exchange).\footahref{http://ejabberd.jabber.ru/screenshots-shared-roster-groups}{Screenshots})}
\item Command line administration tool.\moreinfo{ --- Some basic administration tasks can be acomplished using the command line: register/remove users, backup/restore database, amongst others (\footahref{http://ejabberd.jabber.ru/screenshots-administration#ejabberdctl}{Screenshots}).}
\item Can integrate with existing authentication mechanisms.
\item Capability to send announce messages.
\item Statistics via \jepref{0039} (Statistics Gathering).
\end{itemize}
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
\begin{itemize}
\item Translated to 24 languages. %%\improved{}
\item Translated in 11 languages.\moreinfo{ --- More information is available \footahref{http://ejabberd.jabber.ru/localization}{here}.}
\item Support for \footahref{http://www.ietf.org/rfc/rfc3490.txt}{IDNA}.
\item Support for \ns{xml:lang}.
\end{itemize}
\item \marking{Open Standards:} \ejabberd{} is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
\item \marking{Modular:} \ejabberd{}'s modular architecture allows easy customization:
\begin{itemize}
\item Fully XMPP compliant.
\item XML-based protocol.
\item \footahref{http://www.ejabberd.im/protocols}{Many protocols supported}.
\item Load only the modules you want.
\item Extend \ejabberd{} with your own custom modules.\moreinfo{ --- A list of contributed modules and patches is available on the \footahref{http://ejabberd.jabber.ru/contributions}{contributions page}.}
\end{itemize}
\end{itemize}
\newpage
\section{Additional Features}
\label{addfeatures}
\subsection{Additional Features}
\label{sec:addfeatures}
\ind{features!additional features}
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem ---
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem --
Justin Karneges, Founder of the Psi and the Delta projects}
Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features:
Besides common \Jabber{} server features, \ejabberd{} comes with a wide range of other features:
\begin{itemize}
\item Modular
\item The ability to interface via external components with networks such as:
\begin{itemize}
\item Load only the modules you want.
\item Extend \ejabberd{} with your own custom modules.
\item AIM
\item ICQ
\item MSN
\item Yahoo!
\end{itemize}
\item Open Standards
\begin{itemize}
\item \footahref{http://ejabberd.jabber.ru/protocols}{Many JEPs supported}.
\item XML-based protocol
\item Fully XMPP compliant for c2s connections (Core \& IM) \moreinfo{ --- ejabberd supports all XMPP Core 1.0 and XMPP IM 1.0, or is close to it. Check the \footahref{http://ejabberd.jabber.ru/protocols}{supported protocols}.}
\end{itemize}
\item Security
\begin{itemize}
\item SASL and STARTTLS for c2s and s2s connections.
\item STARTTLS and Dialback s2s connections.
\item Web Admin accessible via HTTPS secure access.
\item SASL and STARTTLS for c2s connections.
\item STARTTLS and Dialback s2s connections.\new{}
\item Obsolete SSL for c2s connections also supported.
\item Web interface accessible via HTTPS secure access.
\end{itemize}
\item Databases
\begin{itemize}
\item Internal database for fast deployment (Mnesia).
\item Native MySQL support.
\item Native PostgreSQL support.
\item ODBC data storage support.
\item Microsoft SQL Server support. %%\new{}
\item Mnesia.
\item ODBC data storage support (tested against PostgreSQL). \moreinfo{ --- ODBC requests can be load balanced between several connections.}
\end{itemize}
\item Authentication
\begin{itemize}
\item Internal Authentication.
\item PAM, LDAP and ODBC. %%\improved{}
\item LDAP. \moreinfo{ --- Accounts can authenticate in a LDAP server.}
\item External Authentication script.
\item Internal Authentication.
\end{itemize}
\item Others
\begin{itemize}
\item Support for virtual hosting.
\item Compressing XML streams with Stream Compression (\xepref{0138}).
\item Statistics via Statistics Gathering (\xepref{0039}).
\item IPv6 support both for c2s and s2s connections.
\item \txepref{0045}{Multi-User Chat} module with support for clustering and HTML logging. %%\improved{}
\item IPv6 support both for c2s and s2s connections.
\item Support for virtual hosting. \moreinfo{ --- Several \Jabber{} hosts can be hosted on the same \ejabberd{} instance. As simple as adding a new domain name to the list of hosts in the configuration file.}
\item \tjepref{0025}{HTTP Polling} service
\item \tjepref{0045}{Multi-User Chat} module.
\item IRC transport.
\item \tjepref{0060}{Publish-Subscribe} component.
\item Users Directory based on users vCards.
\item \txepref{0060}{Publish-Subscribe} component with support for \txepref{0163}{Personal Eventing via Pubsub}.
\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services.
\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
\end{itemize}
\end{itemize}
\end{itemize}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

+65 -66
View File
@@ -1,113 +1,112 @@
Release Notes
Release notes
ejabberd 1.0.0
14 December 2005
2005-12-13
This document describes the main changes in ejabberd 1.0.0. Unique in this
version is the compliancy with the XMPP (eXtensible Messaging and Presence
Protocol) standard. ejabberd is the first Open Source Jabber server claiming
to fully comply to the XMPP standard.
This document describes the main changes in ejabberd 1.0.0. This version is
compliant with the XMPP (eXtensible Messaging and Presence Protocol)
standard. ejabberd is the first Open Source server claiming to fully
comply to the XMPP standard.
ejabberd can be downloaded from the Process-one website:
The code can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
Detailed information can be found in the ejabberd Feature Sheet and User
Guide which are available on the Process-one website:
For more detailed information, please refer to ejabberd User Guide
on the Process-one website:
http://www.process-one.net/en/projects/ejabberd/docs.html
Recent changes include:
Recent changes include....
Server-to-server Encryption for Enhanced Security
Encrypted server-to-server connections
- Support for STARTTLS and SASL EXTERNAL to secure server-to-server traffic
has been added.
- Also, STARTTLS and Dialback has been implemented for server-to-server (s2s)
connections. Detailed information about these new features can be found on
http://ejabberd.jabber.ru/s2s-encryption
- commonName and dNSName fields matching were introduced to ease the process
of retrieving certificates.
- Different certificates can be defined for each virtual host.
- Support for STARTTLS+SASL EXTERNAL for Server-to-Server connections.
- STARTTLS+Dialback has been implemented for Server-to-Server (s2s)
connections. Those options are handled with two new config file options
(s2s_use_starttls and s2s_certfile). See ejabberd.cfg.example for usage
examples.
- DNSName certificate field and DNS name matching are supported.
- Per virtual host certificate can be defined.
ODBC Support
- ODBC support has been improved to allow production use of ejabberd with
relational databases.
- Support for vCard storage in ODBC has been added.
- ejd2odbc.erl is a tool to convert an installation from Erlang's database
Mnesia to an ODBC compatible relational database.
- Support for VCard storage in ODBC has been added.
- ejd2odbc.erl: is a program that convert an installation from Erlang Mnesia
database to an ODBC relational database.
Native PostgreSQL Support
Native PostgreSQL support
- Native PostgreSQL support gives you a better performance when you use
PostgreSQL.
- Native postgreSQL support has been added: You can now use a PostgreSQL
database without the need to go through the ODBC driver.
Shared Roster groups
Shared roster
- Shared Roster groups support has been enhanced. New is the ability to add
all registered users to everyone's roster. Detailed information about this
new feature can be found on http://ejabberd.jabber.ru/shared-roster-all
- Shared roster support have been improved: You can specify all users in a
virtual host for addition in a group.
Web Interface
Web interface
- The web interface internal code has been modified for better integration
and compliancy with J-EAI, an ejabberd-based Enterprise Application
Integration platform.
- More XHTML 1.0 Transitional compliancy work was done.
- The Web interface internal code has been modified for better integration
and compliance with J-EAI.
- The Web interface is now compliant to XHTML 1.0 Transitional.
- Several bugs have been fixed.
Transports
- A transport workaround can be enabled during compilation. To do this, you
- A transport workaround can be enabled with the compile time option. You
can pass the "--enable-roster-gateway-workaround" option to the configure
script. (./configure --enable-roster-gateway-workaround)
This option allows transports to add items with subscription "to" in the
roster by sending <presence type='subscribed'/> stanza to user. This option
is only needed for JIT ICQ transport.
Warning: by enabling this option, ejabberd will not be fully XMPP compliant
anymore.
script. For example:
./configure --enable-roster-gateway-workaround
This option allows to add items with subscription "to" in roster by
sending <presence type='subscribed'/> stanza to user. This option is
needed for JIT ICQ transport.
Warning: By using this option, ejabberd is not fully XMPP compliant.
Documentation and Internationalization
Documentation and translations
- Documentation has been extended to cover more topics.
- Translations have been updated.
- Documentation has been improved to cover more topics.
- Translations have been updated to support the new features.
Bugfixes
- This release contains several bugfixes.
- Among other bugfixes include improvements to the client-to-server (c2s)
connection management module.
- Please refer to the ChangeLog file supplied
Among other bugfixes include improvements to the Client-to-Server
connection management module. Please refer to the ChangeLog file supplied
with this release regarding all improvements in ejabberd.
Erlang version supported
Installation Notes
- You now need at least Erlang/OTP R9C to be able to run ejabberd 1.0.0.
Installers
Supported Erlang Version
- You need at least Erlang/OTP R9C to run ejabberd 1.0.0.
Installation
Installers are provided for Microsoft Windows and Linux/x86.
Installers can be retrieved from:
Installers are provided for Microsoft Windows and Linux/x86. The Linux
installer includes Erlang ASN.1 modules for LDAP authentication support.
Installers are available from:
http://www.process-one.net/en/projects/ejabberd/download.html
Migration Notes
Migration
- Before any migration, ejabberd system and database must be properly
backed up.
- When upgrading an ODBC-based installation, you will need to change the
relational database schema. The following SQL commands must be run on the
database:
CREATE SEQUENCE spool_seq_seq;
ALTER TABLE spool ADD COLUMN seq integer;
ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
UPDATE spool SET seq = DEFAULT;
ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
backed-up.
- System migrating from a previous ODBC based install will need to change
their relational database schema. The following SQL commands must be run
on the database:
CREATE SEQUENCE spool_seq_seq;
ALTER TABLE spool ADD COLUMN seq integer;
ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
UPDATE spool SET seq = DEFAULT;
ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
References
The ejabberd feature sheet helps comparing with other Jabber/XMPP
servers:
http://www.process-one.net/en/projects/ejabberd/docs/features.pdf
Contributed tutorials of interest are:
- Migration from Jabberd1.4 to ejabberd:
http://ejabberd.jabber.ru/jabberd1-to-ejabberd
-115
View File
@@ -1,115 +0,0 @@
Release Notes
ejabberd 1.1.0
24 April 2006
This document describes the main changes in ejabberd 1.1.0. This version
introduce new features including support for new Jabber Enhancement
Proposals and several performance improvements enabling deployments on an
even larger scale than already possible.
ejabberd can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
Detailed information can be found in the ejabberd Feature Sheet and User
Guide which are available on the Process-one website:
http://www.process-one.net/en/projects/ejabberd/docs.html
A complete list of changes is available from:
http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025
Recent changes include:
New Jabber Enhancement Proposal support:
- JEP-0050: Ad-Hoc Commands.
- JEP-0138: Stream Compression.
- JEP-0175: SASL anonymous.
Anonymous login
- SASL anonymous.
- Anonymous login for clients that do not yet support SASL Anonymous.
Relational database Support
- MySQL is now fully supported through ODBC and in native mode.
- Various improvements to the native database interfaces.
- The migration tool can use relational databases.
Multi-User Chat improvements
- Logging of room discussion to text file is now supported.
- Better reconfiguration support.
- Security oriented fixes.
- Several improvements and updates to latest JEP-0045.
Performance scalability improvements for large clusters
- Improved session synchronisation management between cluster nodes.
- Internal architecture has been reworked to use generalize Erlang/OTP
framework usage.
- Speed improvement on logger.
- TCP/IP packet reception change for better network throttling and
regulation.
As a result, these improvements will reduce load on large scale deployments.
XMPP Protocol related improvements
- XML stanza size can be limited.
- Messages are send to all resources with the same highest priority.
Documentation and Internationalization
- Documentation has been extended to cover more topics.
- Translations have been updated.
Web interface
- XHTML 1.0 compliance.
Bugfixes
- This release contains many bugfixes on various areas such as Publish-Subscribe, build
chain, installers, IRC gateway, ejabberdctl, amongst others.
- Please refer to the ChangeLog file supplied with this release regarding
all improvements in ejabberd.
Installation Notes
Supported Erlang Version
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0.
Installation
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
Installers can be retrieved from:
http://www.process-one.net/en/projects/ejabberd/download.html
Migration Notes
- Before any migration, ejabberd system and database must be properly
backed up.
- The database schema has not been changed comparing to version 1.0.0 and
consequently it does not require any migration.
References
Contributed tutorials and documents of interest are:
- Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd:
http://ejabberd.jabber.ru/migrate-to-ejabberd
- Transport configuration for connecting to other networks:
http://ejabberd.jabber.ru/tutorials-transports
- Using ejabberd with MySQL native driver:
http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver
- Anonymous User Support:
http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support
- Frequently Asked Questions:
http://ejabberd.jabber.ru/faq
END
-119
View File
@@ -1,119 +0,0 @@
Release Notes
ejabberd 1.1.1
28 April 2006
This document describes the main changes in ejabberd 1.1.x. This version
introduce new features including support for new Jabber Enhancement
Proposals and several performance improvements enabling deployments on an
even larger scale than already possible.
This release fix a security issue introduced in ejabberd 1.1.0. In SASL
mode, anonymous login was enabled as a default. Upgrading ejabberd 1.1.0 to
ejabberd 1.1.1 is highly recommended.
ejabberd can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
Detailed information can be found in the ejabberd Feature Sheet and User
Guide which are available on the Process-one website:
http://www.process-one.net/en/projects/ejabberd/docs.html
A complete list of changes is available from:
http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025
Recent changes include:
New Jabber Enhancement Proposal support:
- JEP-0050: Ad-Hoc Commands.
- JEP-0138: Stream Compression.
- JEP-0175: SASL anonymous.
Anonymous login
- SASL anonymous.
- Anonymous login for clients that do not yet support SASL Anonymous.
Relational database Support
- MySQL is now fully supported through ODBC and in native mode.
- Various improvements to the native database interfaces.
- The migration tool can use relational databases.
Multi-User Chat improvements
- Logging of room discussion to text file is now supported.
- Better reconfiguration support.
- Security oriented fixes.
- Several improvements and updates to latest JEP-0045.
Performance scalability improvements for large clusters
- Improved session synchronisation management between cluster nodes.
- Internal architecture has been reworked to use generalize Erlang/OTP
framework usage.
- Speed improvement on logger.
- TCP/IP packet reception change for better network throttling and
regulation.
As a result, these improvements will reduce load on large scale deployments.
XMPP Protocol related improvements
- XML stanza size can be limited.
- Messages are send to all resources with the same highest priority.
Documentation and Internationalization
- Documentation has been extended to cover more topics.
- Translations have been updated.
Web interface
- XHTML 1.0 compliance.
Bugfixes
- This release contains many bugfixes on various areas such as Publish-Subscribe, build
chain, installers, IRC gateway, ejabberdctl, amongst others.
- Please refer to the ChangeLog file supplied with this release regarding
all improvements in ejabberd.
Installation Notes
Supported Erlang Version
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0.
Installation
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
Installers can be retrieved from:
http://www.process-one.net/en/projects/ejabberd/download.html
Migration Notes
- Before any migration, ejabberd system and database must be properly
backed up.
- The database schema has not been changed comparing to version 1.0.0 and
consequently it does not require any migration.
References
Contributed tutorials and documents of interest are:
- Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd:
http://ejabberd.jabber.ru/migrate-to-ejabberd
- Transport configuration for connecting to other networks:
http://ejabberd.jabber.ru/tutorials-transports
- Using ejabberd with MySQL native driver:
http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver
- Anonymous User Support:
http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support
- Frequently Asked Questions:
http://ejabberd.jabber.ru/faq
END
-119
View File
@@ -1,119 +0,0 @@
Release Notes
ejabberd 1.1.2
27 September 2006
This document describes the main changes in ejabberd 1.1.2.
This version is a major improvement over ejabberd 1.1.1, improving the
overall behaviour of the server in many areas. Users of ejabberd 1.1.1
should upgrade to this new release for improved robustness and compliance.
ejabberd can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
Detailed information can be found in the Feature Sheet and in the
Installation and Operation Guide which are both available on the
Process-one website:
http://www.process-one.net/en/projects/ejabberd/docs.html
ejabberd includes 44 improvements. A complete list of changes can be
retrieved from:
http://redir.process-one.net/ejabberd-1.1.2
Recent changes include:
LDAP Improvements
- Major improvements have been made on the LDAP module. It is now more
flexible and more robust.
HTTP Polling Fixes
- The HTTP polling modules have been fixed and improved: the connections are
closed properly and polled messages cannot be lost anymore.
Roster Management Improvement
- Roster management improvements increase reliability, especially in cases
where users are on different servers.
- Shared rosters are more reliable.
Improved Robustness
- It is now possible to limit the number of opened connections for a single
user.
Relational databases
- Database support: Microsoft SQL Server is now officially supported in ODBC
mode.
Publish-Subscribe Improvement
- Restricting node creation with a dedicated ACL rule is now possible.
Localization
- A Czech translation has been added.
- Translations have been updated.
Binary Installer
- New binary installer for Windows including all requirements.
- Improved installers for Linux and MacOSX (PowerPC)
XMPP Compliancy
- Some protocol compliance fix have been added, after the Portland XMPP
Interop Meeting in July.
Miscelanous
- MUC have been improved (logging rendering).
- The command line tool ejabberdctl has been improved.
- The build chain has been improved, including MacOSX support.
- The documentation has been improved and updated to describe the new
features.
Bugfixes
- Anonymous login bugfixes.
- Please refer to the ChangeLog file supplied with this release regarding
all improvements in ejabberd.
Installation Notes
Supported Erlang Version
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.2.
- The recommanded version is Erlang/OTP R10B-10.
- Erlang/OTP R11B has not yet been fully certified for ejabberd.
Installation
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
They can be retrieved from:
http://www.process-one.net/en/projects/ejabberd/download.html
Migration Notes
- Before any migration, ejabberd system and database must be properly
backed up.
- The relational database schema has changed between version 1.1.1 and
1.1.2. An "askmessage" column needs to be added in the "rosterusers" table
to perform the migration.
References
Contributed tutorials and documents of interest are:
- Migration from other XMPP servers to ejabberd:
http://ejabberd.jabber.ru/migrate-to-ejabberd
- Transport configuration for connecting to other networks:
http://ejabberd.jabber.ru/tutorials-transports
- Frequently Asked Questions:
http://ejabberd.jabber.ru/faq
END
-14
View File
@@ -1,14 +0,0 @@
Release Notes
ejabberd 1.1.3
2 February 2007
ejabberd 1.1.3 is a security fix release for ejabberd roster ODBC
module.
The upgrade is only necessary if you are using ejabberd with the
mod_roster_odbc.
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/projects/ejabberd/
END
-31
View File
@@ -1,31 +0,0 @@
Release Notes
ejabberd 1.1.4
3 september 2007
ejabberd 1.1.4 is a bugfix release for ejabberd 1.1.x branch.
ejabberd 1.1.4 includes 10 improvements. A complete list of changes
can be retrieved from:
http://redir.process-one.net/ejabberd-1.1.4
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/projects/ejabberd/
Recent changes include:
- Better LDAP support.
- Support for UTF-8 with MySQL 5.
- Roster migration script bugfixes.
- Performance improvements on user removal.
- Traffic shapers bugfix.
- Configuration: host value is now case insensitive.
- Build: ejabberd.cfg file is not overwritten with 'make install' command.
Bugs report
You can officially report bugs on Process-one support site:
http://support.process-one.net/
END
-208
View File
@@ -1,208 +0,0 @@
Release Notes
ejabberd 2.0.0
21 February 2008
ejabberd 2.0.0 is a major new version for ejabberd adding plenty of
new features, performance and scalability improvements and
architectural changes.
ejabberd 2.0.0 includes more than 200 improvements over ejabberd
1.1.x. A complete list of changes can be retrieved from:
http://redir.process-one.net/ejabberd-2.0.0
The new code can be downloaded from ejabberd downloads page:
http://www.process-one.net/en/ejabberd/
Recent changes include:
* Clustering and Architecture
- New front-end and back-end cluster architecture for better
scalability and robustness. Back-end nodes are able to run a fully
fault-tolerant XMPP router and services, but you can now deploy
many front-end nodes to share the load without needing to synchronize
any state with the back-ends.
- All components now run in cluster mode (For example, Multi-User chat
service and file transfer proxy).
- New load balancing algorithm to support Multi-User chat and gateways
clustering. More generally it supports any external component load
balancing.
- ejabberd watchdog to receive warning on suspicious resources consumption.
- Traffic shapers are now supported on components. This protect
ejabberd from components and gateways abuses.
* Publish and Subscribe
- Complete rewrite of the PubSub module. The new PubSub module is
plugin-based, allowing developers to create new nodes type. Any
application can be plugged to ejabberd and can provide rich presence
as a pubsub plugin.
- Personal Eventing via Pubsub support (XEP-0163). This module is
implemented as a PubSub service. It supports user mood (XEP-107),
User Tune (XEP-118), user location (XEP-0080) or user avatar
(XEP-0084) for example.
* Server to Server (s2s)
- More robust code with connection timeout implementation.
- Support for multiple s2s connections per domain.
- s2s whitelist and blacklist support.
- s2s retrial interval.
* LDAP
- Many enterprise-class enhancements such as better behaviour under
heavy load.
- Support for LDAP servers pool.
- Simplified use of virtual hosting with LDAP with domain substitution
in config.
- Ability to match on several userid attributes.
* Multi-User Chat
- Clustering and load balancing support.
- Ability to define default room configuration in ejabberd config file.
- Many anti abuse features have been added:
. New ACL to limit the creation of persistent room to authorized users.
. Ability to define the maximum number of users per room.
. Limitation of the rate of message and presence packets.
. Limitation of the maximum number of room a user can join at the same time.
* File Transfer
- XEP-0065 - Proxy65 file transfer proxy. The proxy can run in
cluster mode.
* Authentication
- PAM (Pluggable Authentication Modules) support on *nix systems.
- External Authentication protocol is now fully documented.
* Web Client Support
- XEP-0124 - BOSH support: BOSH (Bidirectional-streams Over
Synchronous HTTP) was formerly known as "HTTP binding". It provides
an efficient alternative to HTTP polling for scalable Web based chat
solutions.
- HTTP module can now serve static documents (with
mod_http_fileserver). It is needed for high-performance Web 2.0 chat
/ IM application. System administrators can now avoid using a proxy
(like Apache) that handles much less simultaneous than ejabberd HTTP
module.
- Added limitations enforcement on HTTP poll and HTTP bind modules
(bandwidth, packet size).
* System Administration
- XEP-0133 - Service administration support. System administrators can
now perform lot of ejabberd related admin tasks from their XMPP
client, through adhoc commands.
- Dynamic log levels: Improved logging with more log levels. You can
now change the loglevel at run time. No performance penalty is
involved when less verbose levels are used.
- The ejabberdctl command-line administration script now can start
and stop ejabberd. It also includes other useful options.
* Localization
- ejabberd is now translated to 24 languages: Catalan, Chinese, Czech,
Dutch, English, Esperanto, French, Galician, German, Italian, Japanese,
Norwegian, Polish, Portuguese, Portuguese (Brazil), Russian, Slovak,
Spanish, Swedish, Thai, Turkish, Ukrainian, Vietnamese, Walloon.
* Build and Installer
- Many launch script improvements.
- New translations. The binary installer is now available in Chinese,
Dutch, English, French, German, Spanish, Russian.
- Makefile now implements uninstall command.
- Full MacOSX compliance in Makefile.
- Configure script is clever at finding libraries in unusual places.
* Development API
- Several hooks have been added for module developers (most notably
presence related hooks).
- HTTP request handler to write HTTP based plugins.
- Manage connections IP address.
* Bugfixes
- ejabberd 2.0.0 also fixes numerous small bugs :) Read the full
changelog for details.
Important Note:
- Since this release, ejabberd requires Erlang R10B-5 or higher.
R11B-5 is the recommended version. R12 is not yet officially
supported, and is not recommended for production servers.
Upgrading From ejabberd 1.x:
- If you upgrade from a version older than 1.1.4, please check the
Release Notes of the intermediate versions for additional
information about database or configuration changes.
- The database schemas didn't change since ejabberd 1.1.4. Of course,
you are encouraged to make a database backup of your SQL database,
or your Mnesia spool directory before upgrading ejabberd.
- The ejabberdctl command line administration script is improved in
ejabberd 2.0.0, and now it can start and stop ejabberd. If you
already wrote your own start script for ejabberd 1.x, you can
continue using it, or try ejabberdctl. For your convenience, the
ejabberd Guide describes all the ejabberd and Erlang options used by
ejabberdctl.
- The example ejabberd.cfg file has been reorganized, but its format
and syntax rules are the same. So, you can continue using your
ejabberd.cfg file from 1.x if you want. The most important changes
are described now.
- The 'ssl' option is no longer available in the listening ports. For
legacy SSL encryption use the option 'tls'. For STARTTLS encryption
as defined in RFC 3920 XMPP-CORE use the option 'starttls'. Check
the ejabberd Guide for more information about configuring listening
ports.
- The options 'welcome_message' and 'registration_watchers' are now
options of the module mod_register. Check in the ejabberd Guide how
to configure that module.
- To enable PEP support in mod_pubsub, you need to enable it in the
mod_pubsub configuration, and also enable the new module
mod_caps. Check the section about mod_pubsub in the ejabberd Guide.
- Other new features and improvements also require changes in the
ejabberd.cfg, like mod_http_bind, mod_http_fileserver, mod_proxy65,
loglevel, pam_service, and watchdog_admins. Search for those words
in the ejabberd Guide and the example ejabberd.cfg.
Bug Reports
You can officially report bugs on Process-one support site:
https://support.process-one.net/
END
-30
View File
@@ -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
-34
View File
@@ -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
-35
View File
@@ -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
-44
View File
@@ -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
-33
View File
@@ -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
-281
View File
@@ -1,281 +0,0 @@
Release Notes
ejabberd 2.1.0
ejabberd 2.1.0 is a major new version for ejabberd adding many
new features, performance and scalability improvements.
ejabberd 2.1.0 includes many new features, improvements and bug fixes.
A complete list of changes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.0
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
New features and improvements:
* Anti-abuse
- Captcha support (XEP-0158). The example script uses ImageMagick.
- New option: registration_timeout to limit registrations by time
- Use send timeout to avoid locking on gen_tcp:send
- mod_ip_blacklist: client blacklist support by IP
* API
- ejabberd_http provides Host, Port, Headers and Protocol in HTTP requests
- Export function to create MUC room
- New events: s2s_send_packet and s2s_receive_packet
- New event: webadmin_user_parse_query when POST in web admin user page
- Support distributed hooks over the cluster
* Authentification
- Extauth responses: log strange responses and add timeout
* Binary Installer
- Includes exmpp library to support import/export XML files
* Caps
- Remove useless caps tables entries
- mod_caps must handle correctly external contacts with several resources
- Complain if mod_caps disabled and mod_pubsub has PEP plugin enabled
* Clustering and Architecture
* Configuration
- Added option access_max_user_messages for mod_offline
- Added option backlog for ejabberd_listener to increase TCP backlog
- Added option define_macro and use_macro
- Added option include_config_file to include additional configuration files
- Added option max_fsm_queue
- Added option outgoing_s2s_options to define IP address families and timeout
- Added option registration_timeout to ejabberd.cfg.example
- Added option s2s_dns_options to define DNS timeout and retries
- Added option ERL_OPTIONS to ejabberdctl.cfg
- Added option FIREWALL_WINDOW to ejabberdctl.cfg
- Added option EJABBERD_PID_PATH to ejabberdctl.cfg
- Deleted option user_max_messages of mod_offline
- Check certfiles are readable on server start and listener start
- Config file management mix file reading and sanity check
- Include example PAM configuration file: ejabberd.pam
- New ejabberd listener: ejabberd_stun
- Support to bind the same port to multiple interfaces
- New syntax to specify the IP address and IPv6 in listeners
configuration. The old options {ip,{1,2,3,4}} and inet6 are
supported even if they aren't documented.
- New syntax to specify the network protocol: tcp or udp
- Report error at startup if a listener module isn't available
- Only listen in a port when actually ready to serve requests
- In default config, only local accounts can create rooms and PubSub nodes
* Core architecture
- More verbose error reporting for xml:element_to_string
- Deliver messages when first presence is Invisible
- Better log message when config file is not found
- Include original timestamp on delayed presences
* Crypto
- Do not ask certificate for client (c2s)
- SSL code remove from ejabberd in favor of TLS
- Support Zlib compression after STARTTLS encryption
- tls v1 client hello
* Documentation
- Document possible default MUC room options
- Document service_check_from in the Guide
- Document s2s_default_policy and s2s_host in the Guide
- new command and guide instructions to change node name in a Mnesia database
* ejabberd commands
- ejabberd commands: separate command definition and calling interface
- access_commands restricts who can execute what commands and arguments
- ejabberdctl script now displays help and categorization of commands
* HTTP Binding and HTTP Polling
- HTTP-Bind: module optimization and clean-up
- HTTP-Bind: allow configuration of max_inactivity timeout
- HTTP-Poll: turn session timeout into a config file parameter
* Jingle
- STUN server that facilitates the client-to-client negotiation process
* LDAP
- Faster reconnection to LDAP servers
- LDAP filter optimisation: Add ability to filter user in ejabberd and not LDAP
- LDAP differentiates failed auth and unavailable auth service
- Improve LDAP logging
- LDAPS support using TLS.
* Localization
- Use Gettext PO for translators, export to ejabberd MSG
- Support translation files for additional projects
- Most translations are updated to latest code
- New translation to Greek language
* Multi-User Chat (MUC)
- Allow admins to send messages to rooms
- Allow to store room description
- Captcha support in MUC: the admin of a room can configure it to
require participants to fill a captcha to join the room.
- Limit number of characters in Room ID, Name and Description
- Prevent unvoiced occupants from changing nick
- Support Result Set Management (XEP-0059) for listing rooms
- Support for decline of invitation to MUC room
- mod_muc_log options: plaintext format; filename with only room name
* Performance
- Run roster_get_jid_info only if privacy list has subscription or group item
- Significant PubSub performance improvements
* Publish-Subscribe
- Add nodetree filtering/authorization
- Add subscription option support for collection nodes
- Allow Multiple Subscriptions
- Check option of the nodetree instead of checking configuration
- Implement whitelist authorize and roster access model
- Implicit item deletion is not notified when deleting node
- Make PubSub x-data configuration form handles list value
- Make default node name convention XEP-compatible, document usage of hierarchy
- Node names are used verbatim, without separating by slash, unless a
node plugin uses its own separator
- Send authorization update event (XEP-0060, 8.6)
- Support of collection node subscription options
- Support ODBC storage. Experimental, needs more testing.
* Relational databases:
- Added MSSQL 2000 and 2005
- Privacy rules storage in MySQL
- Implement reliable ODBC transaction nesting
* Source Package
- Default installation directories changed. Please see the upgrade notes below.
- Allow more environment variable overrides in ejabberdctl
- ChangeLog is not edited manually anymore; it's generated automatically.
- Install the ejabberd Guide
- Install the ejabberd include files
- New option for the 'configure' script: --enable-user which installs
ejabberd granting permission to manage it to a regular system user;
no need to use root account to.
- Only try to install epam if pam was enabled in configure script
- Spool, config and log dirs: owner writes, group reads, others do nothing.
- Provides an example ejabberd.init file
* S2S
- Option to define s2s outgoing behaviour: IPv4, IPv6 and timeout
- DNS timeout and retries, configurable with s2s_dns_options.
* Shared rosters
- When a member is added/removed to group, send roster upgrade to group members
* Users management
- When account is deleted, cancel presence subscription for all roster items
* XEP Support
- Added XEP-0059 Result Set Management (for listing rooms)
- Added XEP-0082 Date Time
- Added XEP-0085 Chat State Notifications
- Added XEP-0157 Contact Addresses for XMPP Services
- Added XEP-0158 CAPTCHA Forms (in MUC rooms)
- Added STUN server, for XEP-0176: Jingle ICE-UDP Transport Method
- Added XEP-0199 XMPP Ping
- Added XEP-0202 Entity Time
- Added XEP-0203 Delayed Delivery
- Added XEP-0227 Portable Import/Export Format for XMPP-IM Servers
- Added XEP-0237 Roster Versioning
* Web Admin
- Display the connection method of user sessions
- Cross link of ejabberd users in the list of users and rosters
- Improved the browsing menu: don't disappear when browsing a host or node
- Include Last-Modified HTTP header in responses to allow caching
- Make some Input areas multiline: options of listening ports and modules
- Support PUT and DELETE methods in ejabberd_http
- WebAdmin serves Guide and links to related sections
* Web plugins
- mod_http_fileserver: new option directory_indices, and improve logging
Important Notes:
- ejabberd 2.1.0 requires Erlang R10B-9 or higher.
R12B-5 is the recommended version. Support for R13B is experimental.
Upgrading From ejabberd 1.x.x:
- Check the Release Notes of the intermediate versions for additional
information about database or configuration changes.
Upgrading From ejabberd 2.0.x:
- The database schemas have three changes since ejabberd 2.0.x.
Check the database creation SQL files and update your database.
1) New table roster_version to support roster versioning.
2) Six new tables for optional pubsub ODBC storage.
3) Some tables in the MySQL database have a new created_at column.
- As usual, it is recommended to backup the Mnesia spool directory and
your SQL database (if used) before upgrading ejabberd.
- Between ejabberd 2.0.0 and 2.0.5, mod_pubsub used "default" as the
default node plugin. But in 2.1.0 this is renamed to "hometree".
You have to edit your ejabberd config file and replace those names.
If you used ejabberd 2.0.5 or older, the database will be updated
automatically. But if you were using ejabberd from SVN, you must
manually run ejabberdctl with the command: rename_default_nodeplugin.
Running this command on already updated database does nothing.
- The listener options 'ip' and 'inet6' are not documented anymore
but they are supported and you can continue using them.
There is a new syntax to define IP address and IP version.
As usual, check the ejabberd Guide for more information.
- The log file sasl.log is now called erlang.log
- ejabberdctl commands now have _ characters instead of -.
For backwards compatibility, it is still supported -.
- mod_offline has a new option: access_max_user_messages.
The old option user_max_messages is no longer supported.
- If you upgrade from ejabberd trunk SVN, you must execute this:
$ ejabberdctl rename_default_nodeplugin
- Default installation directories changed a bit:
* The Mnesia spool files that were previously stored in
/var/lib/ejabberd/db/NODENAME/*
are now stored in
/var/lib/ejabberd/*
* The directories
/var/lib/ejabberd/ebin
/var/lib/ejabberd/priv
and their content is now installed as
/lib/ejabberd/ebin
/lib/ejabberd/priv
* There is a new directory with Erlang header files:
/lib/ejabberd/include
* There is a new directory for ejabberd documentation,
which includes the Admin Guide and the release notes::
/share/doc/ejabberd
- How to upgrade from previous version to ejabberd 2.1.0:
1. Stop the old instance of ejabberd.
2. Run 'make install' of new ejabberd 2.1.0 to create the new directories.
3. Copy the content of your old directory:
/var/lib/ejabberd/db/NODENAME/
to the new location:
/var/lib/ejabberd/
so you will have the files like this:
/var/lib/ejabberd/acl.DCD ...
4. You can backup the content of those directories and delete them:
/var/lib/ejabberd/ebin
/var/lib/ejabberd/priv
/var/lib/ejabberd/db
5. Now try to start your new ejabberd 2.1.0.
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-47
View File
@@ -1,47 +0,0 @@
Release Notes
ejabberd 2.1.1
ejabberd 2.1.1 is the first bugfix release in ejabberd 2.1.x branch.
ejabberd 2.1.1 includes several important bugfixes.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.1
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
The changes are:
* Core
- Call ejabberd_router:route/3 instead of sending a message
- Can't connect if starttls_required and zlib are set
- Routes vCard request to the occupant full JID, but should to bare JID
- S2S: fix allow_host/2 on subdomains. added hook s2s_allow_host
* MUC
- Support converting one-to-one chat to MUC
- Add support for serving a Unique Room Name
* Publish Subscribe
- Receive same last published PEP items at reconnect if several resources online
- Typo in mod_pubsub_odbc breaks Service Discovery and more
* Web
- Fix memory and port leak when TLS is enabled in HTTP
- WebAdmin doesn't report correct last activity with postgresql backend
- Option to define custom HTTP headers in mod_http_fileserver
- Show informative webpage when browsing the HTTP-Poll page
* Other
- Change captcha.sh to not depend on bash
- Generate main XML file also when exporting only a vhost
- Fix last newline in ejabberdctl result
- Guide: fix -setcookie, mod_pubsub_odbc host, content_types
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-51
View File
@@ -1,51 +0,0 @@
Release Notes
ejabberd 2.1.2
ejabberd 2.1.2 is the second bugfix release in ejabberd 2.1.x branch.
ejabberd 2.1.2 includes several bugfixes.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.2
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
The major changes are:
* Core
- Close sessions that were half connected
- Fix SASL PLAIN authentication message for RFC4616 compliance
- Fix support for old Erlang/OTP R10 and R11
- Return proper error (not 'conflict') when register is forbidden by ACL
- When ejabberd stops, send stream close to clients
* ejabberdctl
- Check for EGID in ejabberdctl command
- Command to stop ejabberd informing users, with grace period
- If there's a problem in config file, display config lines and stop node
* MUC
- Kick occupants with reason when room is stopped due to MUC shutdown
- Write in room log when a room is created, destroyed, started, stopped
* PubSub and PEP
- Don't call gen_server on internal event (improves performance and scalability)
- Fix duplicate SHIM header in Pubsub message
- Notification messages of Pubsub node config change contained a SHIM header
- SubID SHIM header missing in Pubsub message with multiple
subscriptions on the same node
- PEP: last published item not sent from unavailable users when the
subscription is implicit (XEP-0115)
- pep_mapping not working due to Node type mismatch
* WebAdmin
- If big offline message queue, show only subset on WebAdmin
- Support in user list page of WebAdmin when mod_offline is disabled
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-91
View File
@@ -1,91 +0,0 @@
Release Notes
ejabberd 2.1.3
ejabberd 2.1.3 is the third release in ejabberd 2.1.x branch.
ejabberd 2.1.3 includes many bugfixes, and some improvements.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.3
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Client connections
- Avoid 'invalid' value in iq record
- Avoid resending stream:error stanzas on terminate (EJAB-1180)
- Close also legacy sessions that were half connected (EJAB-1165)
- iq_query_info/1 now returns 'invalid' if XMLNS is invalid
- New ejabberd_c2s option support: max_fsm_queue
- Rewrite mnesia counter functions to use dirty_update_counter (EJAB-1177)
- Run user_receive_packet also when sending offline messages (EJAB-1193)
- Use p1_fsm behaviour in c2s FSM (EJAB-1173)
* Clustering
- Fix cluster race condition in route read
- New command to set master Mnesia node
- Use mnesia:async_dirty when cleaning table from failed node
* Documentation
- Add quotes in documentation of some erl arguments (EJAB-1191)
- Add option access_from (EJAB-1187)
- Add option max_fsm_queue (EJAB-1185)
- Fix documentation installation, no need for executable permission (EJAB-1170)
- Fix typo in EJABBERD_BIN_PATH (EJAB-891)
- Fix typos in example config comments (EJAB-1192)
* ejabberdctl
- Support concurrent connections with bound connection names
- Add support for Jot in ctl and TTY in debug
- Support help command names with old - characters
- Fix to really use the variable ERL_PROCESSES
* Erlang compatibility
- Don't call queue:filter/2 to keep compatibility with older Erlang versions
- Use alternative of file:read_line/1 to not require R13B02
* HTTP
- Add new debugging hook to the http receiving process
- Allow a request_handler to serve a file in root of HTTP
* HTTP-Bind (BOSH)
- Cross-domain HTTP-Bind support (EJAB-1168)
- Hibernate http-bind process after handling a request
- Reduce verbosity of HTTP Binding log messages
* LDAP
- Document ldap_dn_filter, fetch only needed attributes in search (EJAB-1204)
- Use "%u" pattern as default for ldap_uids (EJAB-1203)
* Localization
- Fix German translation (EJAB-1195)
- Fix Russian translation
* ODBC
- Fix MSSQL support, which was broken (EJAB-1201)
- Improved SQL reconnect behaviour
* Pubsub, PEP and Caps
- Add extended stanza addressing 'replyto' on PEP (EJAB-1198)
- Add pubsub#purge_offline (EJAB-1186)
- Fix pubsub#title option (EJAB-1190)
- Fix remove_user for node subscriptions (EJAB-1172)
- Optimizations in mod_caps
* Other
- mod_register: Add new acl access_from, default is to deny
- mod_sic: new module for the experimental XEP-0279 Server IP Check (EJAB-1205)
- PIEFXIS: Catch errors when exporting to PIEFXIS file (EJAB-1178)
- Proxy65: new option "hostname" (EJAB-838)
- Roster: Fix resending authorization problem
- Shared Roster Groups: get contacts nickname from vcard (EJAB-114)
- S2S: Improved s2s connections clean up (EJAB-1202)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-80
View File
@@ -1,80 +0,0 @@
Release Notes
ejabberd 2.1.4
ejabberd 2.1.4 is the fourth release in ejabberd 2.1.x branch,
and includes many small bugfixes and improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.4
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Authentication
- Extauth: Optionally cache extauth users in mnesia (EJAB-641)
- LDAP: Allow inband password change (EJAB-199)
- LDAP: Extensible match support (EJAB-722)
- LDAP: New option ldap_tls_verify is added (EJAB-1229)
- PAM: New option pam_userinfotype to provide username or JID (EJAB-652)
* HTTP
- Add xml default content type
- Don't show HTTP request in logs, because reveals password (EJAB-1231)
- Move HTTP session timeout log from warning level to info
- New Access rule webadmin_view for read-only
* HTTP-Bind (BOSH)
- Change max inactivity from 30 to 120 seconds
- Export functions to facilitate prebinding methods
- Use dirty_delete when removing the session
- Remove an unneeded delay of 100 milliseconds
* Pubsub, PEP and Caps
- Enforce pubsub#presence_based_delivery (EJAB-1221)
- Enforce pubsub#show_values subscription option (EJAB-1096)
- Fix error code when unsubscribing from a non-existent node
- Fix to send node notifications (EJAB-1225)
- Full support for XEP-0115 v1.5 (EJAB-1223)(EJAB-1189)
- Make last_item_cache feature to be cluster aware
- Prevent orphaned pubsub node (EJAB-1233)
- Send created node notifications
* Other
- Bounce messages when closing c2s session
- Bugfixes when handling Service Discovery to contacts (EJAB-1207)
- Compilation of ejabberd_debug.erl is now optional
- Don't send error stanza as reply to error stanza (EJAB-930)
- Don't store blocked messages in offline queue
- Reduce verbosity of log when captcha_cmd is checked but not configured
- Use a standard method to get a random seed (EJAB-1229)
- Commands: new update_list and update to update modified modules (EJAB-1237)
- Localization: Updated most translations
- MUC: Refactor code to reduce calls to get_affiliation and get_role
- ODBC: Add created_at column also to PostgreSQL schema
- Vcard: Automatic vcard avatar addition in presence
Upgrading From previous ejabberd releases:
- If you use PostgreSQL, maybe you want to add the column created_at
to several tables. This is only a suggestion; ejabberd doesn't use
that column. Add it to your existing database executing those SQL
statements:
ALTER TABLE users ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE rosterusers ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE spool ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE vcard ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE privacy_list ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE privacy_storage ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-70
View File
@@ -1,70 +0,0 @@
Release Notes
ejabberd 2.1.5
ejabberd 2.1.5 is the fifth release in ejabberd 2.1.x branch,
and includes several minor bugfixes and a few improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.5
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Authentication
- Extauth: Support parallel script running (EJAB-1280)
- mod_register: Return Registered element when account exists
* ejabberdctl
- Fix print of command result that contains ~
- Fix problem when FIREWALL_WINDOW options for erl kernel were used
- Fix typo in update_list command (EJAB-1237)
- Some systems delete the lock dir; in such case don't use flock at all
- The command Update now returns meaningful message and exit-status (EJAB-1237)
* HTTP-Bind (BOSH)
- Don't say v1.2 in the Bind HTTP page
- New optional BOSH connection attribute process-delay (EJAB-1257)
* MUC
- Document the mod_muc option captcha_protected
- Now admins are able to see private rooms in disco (EJAB-1269)
- Show some more room options in the log file
* ODBC
- Correct handling of SQL boolean types (EJAB-1275)
- Discard too old queued requests (the caller has already got a timeout)
- Fixes wrong SQL escaping when --enable-full-xml is set
- Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1
* Pubsub, PEP and Caps
- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238)
- Support all the hash functions required by Caps XEP-0115
* Requirements
- Fixed support for Erlang R12; which doesn't support: true andalso ok
- Support OTP R14A by using public_key library instead of old ssl (EJAB-953)
- Requirement of OpenSSL increased from 0.9.6 to 0.9.8
- OpenSSL is now required, not optional
* Other
- Don't ask for client certificate when using tls (EJAB-1267)
- Fix typo in --enable-transient_supervisors
- Fix privacy check when serving local Last (EJAB-1271)
- Inform client that SSL session caching is disabled
- New configure option: --enable-nif
- Use driver allocator in C files for reflecting memory in erlang:memory(system)
- Debug: New p1_prof compiled with: make debugtools=true
- Debug: Added functions to collect stats about queues, memory, reductions etc
- HTTP: Log error if request has ambiguous Host header (EJAB-1261)
- Logs: When logging s2s out connection attempt or success, log if TLS is used
- Shared Rosters: When account is deleted, delete also member of stored rosters
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-67
View File
@@ -1,67 +0,0 @@
Release Notes
ejabberd 2.1.6
ejabberd 2.1.6 is the sixth release in ejabberd 2.1.x branch,
and includes a lot of bugfixes and improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.6
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
Some of the changes are:
* Account register
- mod_register: New ip_access option restricts which IPs can register (EJAB-915)
- mod_register: Default configuration allows registrations only from localhost
- mod_register: New password_strength for entropy check (EJAB-1326)
- mod_register: New captcha_protected option to require CAPTCHA (EJAB-1262)
- mod_register_web: New module, with CAPTCHA support (EJAB-471)
* BOSH
- Don't loop when there is nothing after a stream start (EJAB-1358)
- Fix http-bind supervisor to support multiple vhosts (EJAB-1321)
- Support to restart http-bind (EJAB-1318)
- Support for X-Forwarded-For HTTP header (EJAB-1356)
* Erlang/OTP compatibility
- R11: Fix detection of Erlang R11 and older (EJAB-1287)
- R12B5: Fix compatibility in ejabberd_http_bind.erl (EJAB-1343)
- R14A: Make xml.c correctly compile (EJAB-1288)
- R14A, R14B: Disapprove the use of R14A and R14B due to the rwlock bug
- R14B: Use pg2 from this version in systems with older ones (EJAB-1349)
* Listeners
- Bind listener ports early and start accepting connections later
- Fix a leak of ejabberd_receiver processes
- Speed up ejabberd_s2s:is_service/2, allow_host/2 (EJAB-1319)
- S2S: New option to require encryption (EJAB-495)
- S2S: New option to reject connection if untrusted certificate (EJAB-464)
- S2S: Include From attribute in the stream header of outgoing S2S connections
- S2S: Fix domain_certfile tlsopts modifications for S2S connections (EJAB-1086)
* Pubsub/PEP/Caps
- Fix pubsub cross domain eventing (EJAB-1340)
- Use one_queue IQ discipline by default
- Implement lifetime for broken hashes
- New CAPS processing
* ODBC
- Increase maximum restart strategy to handle some SQL timeouts
- Support PostgreSQL 9.0 (EJAB-1359)
- Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252)
* Miscellanea:
- mod_shared_roster_ldap: New Shared Roster Groups using LDAP information
- mod_privacy: Fix to allow block by group and subscription again
- Support timezone West of UTC (EJAB-1301)
- Support to change loglevel per module at runtime (EJAB-225)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-104
View File
@@ -1,104 +0,0 @@
******************************************************************************
* These are the preliminary release notes of ejabberd 3.0.0.
*
* The download page for preliminary releases is:
* http://download.process-one.net/ejabberd/
*
* WARNING!!! PRELIMINARY DATABASE SCHEMA !!!
* The database schema may change before ejabberd 3.0.0 is released,
* and no migration code will be developed for this preliminary schema.
* The only supported migrations are
* from any ejabberd 0.9.0 ... 2.1.x to the final 3.0.0.
* Don't use this preliminary ejabberd release for a production server.
* You can test this release with a blank database or with a copy of your
* production database, but don't let your users connect to this copy
* because their changes may get lost when you upgrade to the final 3.0.0.
******************************************************************************
Release Notes
ejabberd 3.0.0
ejabberd 3.0.0 is the first release in the brand new 3.x.x branch,
and includes several minor bugfixes and a few improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-3.0.0
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
ejabberd 3.0.0 includes three major changes:
* exmpp is now extensively used in ejabberd for parsing stanzas, and many more.
* gen_storage (abbreviated GS) provides a database abstraction layer,
which supports storage in Mnesia and in ODBC databases.
Several ejabberd modules use GS, like mod_roster and ejabberd_auth_storage.
The schema of the tables stored by those modules have changed.
ejabberd automatically creates mnesia and ODBC tables,
and migrates them from a previous ejabberd version.
* Massive Hosting (abbreviated MH) is preliminary implemented in ejabberd,
but it is still incomplete, untested and undocumented.
This is a more detailed list of changes since ejabberd 2.1.x releases:
* Requirements
- Erlang/OTP R12B-5 or higher is required
- exmpp 0.9.6 or higher is required, not optional
- ESASL library is optional, for SASL GSSAPI authentication
- Libexpat not required by ejabberd, it uses exmpp now (EJAB-1111)
- GNU Iconv not required, because mod_irc isn't included anymore (EJAB-954)
- Only database migration from ejabberd 0.9.0 up to 2.1.x is supported
- ejabberd modules developed for previous releases need to be upgraded to exmpp
* Configuration
- New option clusterid
- New option that can't be used yet: static_modules
- ejabberd_auth_storage: new option auth_storage
- mod_muc_log: option spam_prevention is now link_nofollow (EJAB-1141)
- mod_roster: new access option (EJAB-72)
- S2S: allow definition of local address for outgoing connections (EJAB-418)
* Database
- New gen_storage that provides a database storage abstraction layer (EJAB-1102)
- mod_*_odbc are obsolete, use the normal ones with the option {backend, odbc}
- New ejabberd_auth_storage that supports internal and odbc databases
* XEP support
- Removed support for the deprecated XEP-0018 Invisible Presence (EJAB-810)
- mod_multicast: service for XEP-0033: Extended Stanza Addressing (EJAB-265)
- New ejabberd router for multicast packets (XEP-0033) (EJAB-329)
- ejabberd_c2s uses XEP-0033 if mod_multicast is enabled (EJAB-267)
- mod_muc uses XEP-0033 if mod_multicast is enabled (EJAB-266)
* Pubsub/PEP/Caps
- Allow distinguish between leafs and items (EJAB-1027)
- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238)
- Enforce pubsub#presence_based_delivery (EJAB-1221)
- Improve get_caps while still waiting for initial presence (EJAB-934)
- Make nodetree_tree implicitly create parent node if required (EJAB-944)
- Only use binary() instead of string() in Host and ServerHost (EJAB-1244)
- Rename NodeId (pubsub_node.id) bindings to Nidx (EJAB-1000)
- node_flat becomes default; it has the code instead of hometree (EJAB-1077)
- pubsub#notify_sub node option (EJAB-1230)
- pubsub#type node config and payload namespace (EJAB-1083)
* Miscellanea
- Bugfix handling Service Discovery to contacts (EJAB-1207)
- Bugfix: external contacts were offline after unavailable presence (EJAB-943)
- Don't offer SASL auth before doing TLS if TLS is required
- Experimental support for GSSAPI auth, requires esasl library (EJAB-831)
- Use binaries instead of lists where possible (EJAB-17)
- Windows ejabberdctl.cmd only handles up to 4 arguments (EJAB-1216)
- ejabberdctl: when starting, check it isn't already running
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+2
View File
@@ -0,0 +1,2 @@
% Define ejabberd version here.
\newcommand{\version}{1.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

+2 -18
View File
@@ -1,4 +1,4 @@
#!/usr/bin/perl
#!/usr/local/bin/perl
use Unix::Syslog qw(:macros :subs);
@@ -18,7 +18,7 @@ while(1)
my $len = unpack "n",$buf;
my $nread = sysread STDIN,$buf,$len;
my ($op,$user,$host,$password) = split /:/,$buf;
my ($op,$user,$password) = split /:/,$buf;
#$user =~ s/\./\//og;
my $jid = "$user\@$domain";
my $result;
@@ -42,22 +42,6 @@ while(1)
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'tryregister' and do
{
$result = 1;
},last SWITCH;
$op eq 'removeuser' and do
{
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'removeuser3' and do
{
$result = 1;
},last SWITCH;
};
my $out = pack "nn",2,$result ? 1 : 0;
syswrite STDOUT,$out;
+75
View File
@@ -0,0 +1,75 @@
#!/bin/sh
#
# PROVIDE: ejabberd
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
HOME=/usr/pkg/jabber D=/usr/pkg/jabber/ejabberd export HOME
name="ejabberd"
rcvar=$name
if [ -r /etc/rc.conf ]
then
. /etc/rc.conf
else
eval ${rcvar}=YES
fi
# $flags from environment overrides ${rcvar}_flags
if [ -n "${flags}" ]
then
eval ${rcvar}_flags="${flags}"
fi
checkyesno()
{
eval _value=\$${1}
case $_value in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0 ;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1 ;;
*)
echo "\$${1} is not set properly."
return 1
;;
esac
}
cmd=${1:-start}
case ${cmd} in
force*)
cmd=${cmd#force}
eval ${rcvar}=YES
;;
esac
if checkyesno ${rcvar}
then
else
exit 0
fi
case ${cmd} in
start)
if [ -x $D/src ]; then
echo "Starting ${name}."
cd $D/src
ERL_MAX_PORTS=32000 export ERL_MAX_PORTS
ulimit -n $ERL_MAX_PORTS
su jabber -c "/usr/pkg/bin/erl -sname ejabberd -s ejabberd -heart -detached -sasl sasl_error_logger '{file, \"ejabberd-sasl.log\"}' &" \
1>/dev/null 2>&1
fi
;;
stop)
echo "rpc:call('ejabberd@`hostname -s`', init, stop, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdstop"
;;
restart)
echo "rpc:call('ejabberd@`hostname -s`', init, restart, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdrestart"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
+81
View File
@@ -0,0 +1,81 @@
#!/bin/sh
echo '1. fetch, compile, and install erlang'
if [ ! pkg_info erlang 1>/dev/null 2>&1 ]; then
cd /usr/pkgsrc/lang/erlang
make fetch-list|sh
make
make install
fi
if pkg_info erlang | grep -q erlang-9.1nb1; then
else
echo "erlang-9.1nb1 not installed" 1>&2
exit 1
fi
echo '2. install crypt_drv.so'
if [ ! -d /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib ] ; then
mkdir -p /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/crypto_drv.so ]; then
cp work/otp*/lib/crypto/priv/*/*/crypto_drv.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '3. compile and install elibcrypto.so'
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/elibcrypto.so ]; then
cd /usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/crypto/c_src
ld -r -u CRYPTO_set_mem_functions -u MD5 -u MD5_Init -u MD5_Update \
-u MD5_Final -u SHA1 -u SHA1_Init -u SHA1_Update -u SHA1_Final \
-u des_set_key -u des_ncbc_encrypt -u des_ede3_cbc_encrypt \
-L/usr/lib -lcrypto -o ../priv/obj/i386--netbsdelf/elibcrypto.o
cc -shared \
-L/usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/erl_interface/obj/i386--netbsdelf \
-o ../priv/obj/i386--netbsdelf/elibcrypto.so \
../priv/obj/i386--netbsdelf/elibcrypto.o -L/usr/lib -lcrypto
cp ../priv/obj/i386--netbsdelf/elibcrypto.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '4. compile and install ssl_esock'
if [ ! -f /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/bin/ssl_esock ]; then
cd /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/obj/
make
fi
echo '5. initial ejabberd configuration'
cd /usr/pkg/jabber/ejabberd/src
./configure
echo '6. edit ejabberd Makefiles'
for M in Makefile mod_*/Makefile; do
if [ ! -f $M.orig ]; then
mv $M $M.orig
sed -e s%/usr/local%/usr/pkg%g < $M.orig > $M
fi
done
echo '7. compile ejabberd'
gmake
for A in mod_irc mod_muc mod_pubsub; do
(cd $A; gmake)
done
echo ''
echo 'now edit ejabberd.cfg'
echo ''
echo 'to start ejabberd: erl -sname ejabberd -s ejabberd'
+66
View File
@@ -0,0 +1,66 @@
% jabber.dbc.mtview.ca.us
override_acls.
{acl, admin, {user, "mrose", "jabber.dbc.mtview.ca.us"}}.
{access, announce, [{allow, admin},
{deny, all}]}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{access, configure, [{allow, admin},
{deny, all}]}.
{access, disco_admin, [{allow, admin},
{deny, all}]}.
{access, muc_admin, [{allow, admin},
{deny, all}]}.
{access, register, [{deny, all}]}.
{access, s2s_shaper, [{fast, all}]}.
{auth_method, internal}.
{host, "jabber.dbc.mtview.ca.us"}.
{outgoing_s2s_port, 5269}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{welcome_message, none}.
{listen, [{5222, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper}]},
{5223, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper},
{ssl, [{certfile, "/etc/openssl/certs/ejabberd.pem"}]}]},
{5269, ejabberd_s2s_in,
[{shaper, s2s_shaper}]}]}.
{modules, [
{mod_register, []},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]},
{mod_private, []},
% {mod_irc, []},
{mod_muc, []},
{mod_pubsub, []},
{mod_time, []},
{mod_last, []},
{mod_version, []}
]}.
% Local Variables:
% mode: erlang
% End:
@@ -0,0 +1,77 @@
<!-- aim-transport.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/aim-transport-error.log</file>
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<format>%d %h %s</format>
<file>/var/log/jabber/aim-transport-record.log</file>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file> <!-- This file is part of jabberd-1.4.x. -->
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id='aim.SERVER.COM'>
<!-- aim-transport configuration. -->
<aimtrans xmlns='jabber:config:aimtrans'>
<vCard>
<FN>AIM/ICQ Transport</FN>
<DESC>This is the AIM/ICQ Transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://aim-transport.jabberstudio.org/</URL>
</vCard>
<charset>cp1252</charset>
</aimtrans>
<!-- aim-transport module. -->
<load>
<aim_transport>/usr/local/lib/jabber/aim-transport.so</aim_transport>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="icq-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5233</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/aim-transport.pid</pidfile>
</jabber>
+136
View File
@@ -0,0 +1,136 @@
<!-- ile.xml -->
<config>
<jabber>
<server>127.0.0.1</server>
<port>5238</port>
<secret>SECRET</secret>
<service>ile.SERVER.COM</service>
<connectsleep>7</connectsleep> <!-- seconds to wait if we get disconnected -->
<language>en</language>
<vCard>
<FN>I Love Email</FN>
<DESC>With this service you can receive email notifications.
Security warning: Be careful when using this. Your password will travel in clear from your client to your jabber server if you don't use SSL and it will probably travel in clear from the jabber server to your email server. Use with care. This shouldn't be an issue in your Intranet, but it is if you use an ILE installed in a foreign jabber server.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://ile.jabberstudio.org/</URL>
</vCard>
</jabber>
<debug>
<file>/var/log/jabber/ile.log</file>
<level>1</level> <!-- man Net::Jabber::Debug -->
</debug>
<mail>
<checkinterval>10</checkinterval> <!-- in minutes -->
<timeout>20</timeout> <!-- timeout for IMAP/POP connection, in seconds -->
</mail>
<files>
<users>/var/spool/jabber/ile.SERVER.COM/users.db</users>
<passwords>/var/spool/jabber/ile.SERVER.COM/passwords.db</passwords>
<hosts>/var/spool/jabber/ile.SERVER.COM/hosts.db</hosts>
<types>/var/spool/jabber/ile.SERVER.COM/types.db</types>
<notifyxa>/var/spool/jabber/ile.SERVER.COM/notifyxa.db</notifyxa>
<notifydnd>/var/spool/jabber/ile.SERVER.COM/notifydnd.db</notifydnd>
<urls>/var/spool/jabber/ile.SERVER.COM/urls.db</urls>
</files>
<form>
<en>
<instructions>Please fill in the fields,according to your email account settings and notification preferences</instructions>
<title>ILE: Email notification service</title>
<email_options>Email account settings</email_options>
<user>Username</user>
<pass>Password</pass>
<host>Hostname</host>
<type>Type</type>
<newmail>You have received NUM email messages since last time I checked, which was CHECKINTERVAL minutes ago.</newmail>
<errorcheck>There was an error while trying to check mail for ACCOUNT.</errorcheck>
<notify_options>Notification Options</notify_options>
<notifyxa>Notify even when Xtended Away (XA)</notifyxa>
<notifydnd>Notify even when Do Not Disturb (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Login to ACCOUNT</webmail_login>
<iledesc>ILE: an email notifier component: http://ile.jabberstudio.org</iledesc>
</en>
<es>
<instructions>Por favor, rellene los campos del formulario.</instructions>
<title>ILE: Servicio de notificación de correo</title>
<email_options>Configuración de la cuenta de correo</email_options>
<user>Usuario</user>
<pass>Clave</pass>
<host>Host</host>
<type>Tipo</type>
<newmail>Ha recibido NUM email(s) desde la última comprobación que fue hace CHECKINTERVAL minutos</newmail>
<errorcheck>Ha habido un error en la comprobación del correo para la cuenta ACCOUNT.</errorcheck>
<notify_options>Opciones de notificación</notify_options>
<notifyxa>Notificar incluso si muy ausente (XA)</notifyxa>
<notifydnd>Notificar incluso si no molestar (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Leer correo de ACCOUNT</webmail_login>
<iledesc>ILE: un notificador de nuevo email - http://ile.jabberstudio.org</iledesc>
</es>
<ca>
<instructions>Ompli els camps del formulari.</instructions>
<title>ILE: Servei de notificació de nou email</title>
<email_options>Dades del compte de mail</email_options>
<user>Usuari</user>
<pass>Clau</pass>
<host>Host</host>
<type>Tipus</type>
<newmail>Ha rebut NUM email(s) des de la última comprobació que va ser fa CHECKINTERVAL minuts.</newmail>
<errorcheck>S'ha produit un error en la comprobació del correu per al compte ACCOUNT.</errorcheck>
<notify_options>Opcions de notificació</notify_options>
<notifyxa>Notificar si molt absent (XA)</notifyxa>
<notifydnd>Notificar si no molestar (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Llegir correu de ACCOUNT</webmail_login>
<iledesc>ILE: un notificador de nou email - http://ile.jabberstudio.org</iledesc>
</ca>
<ro>
<!-- Contributed by Adrian Rappa -->
<instructions>Va rog completati urmatoarele campuri</instructions>
<title>I Love Email: new email notification service</title>
<email_options>Email account settings</email_options>
<user>Nume utilizator</user>
<pass>Parola</pass>
<host>Nume gazda</host>
<type>Tip</type>
<newmail>Ati primit NUM mesaj(e) de la ultima verificare, care a fost acum CHECKINTERVAL minute.</newmail>
<errorcheck>A fost eroare in timp ce incercam sa verific posta pentru ACCOUNT.</errorcheck>
<notify_options>Notification Options</notify_options>
<notifyxa>Notify even when Xtended Away (XA)</notifyxa>
<notifydnd>Notify even when Do Not Disturb (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Login to ACCOUNT</webmail_login>
<iledesc>ILE: an email notifier component: http://ile.jabberstudio.org</iledesc>
</ro>
<nl>
<!-- Contributed by Sander Devrieze -->
<instructions>Vul volgende velden in.</instructions>
<title>ILE: Dienst voor e-mailnotificaties</title>
<email_options>Instellingen van e-mailaccount</email_options>
<user>Gebruikersnaam</user>
<pass>Wachtwoord</pass>
<host>Inkomende mailserver</host>
<type>Type verbinding</type>
<newmail>U hebt NUM berichten ontvangen sinds CHECKINTERVAL minuten geleden.</newmail>
<errorcheck>Fout tijdens controle op nieuwe e-mails bij ACCOUNT. ILE zal deze account niet meer opnieuw controleren tot u uw registratiegegevens wijzigt of opnieuw aanmeldt.</errorcheck>
<notify_options>Notificatie-instellingen</notify_options>
<notifyxa>Notificeer ook in de status Niet Beschikbaar (XA)</notifyxa>
<notifydnd>Notificeer ook in de status Niet Storen (DND)</notifydnd>
<webmail_url>URL van webmail</webmail_url>
<webmail_login>Aanmelden op ACCOUNT</webmail_login>
<iledesc>ILE: een dienst om e-mailnotificaties te ontvangen: http://ile.jabberstudio.org</iledesc>
</nl>
</form>
</config>
@@ -0,0 +1,149 @@
<jggtrans>
<service jid="gg.SERVER.COM"/>
<!-- This connects the jabber-gg-transport process to ejabberd. -->
<connect id="gglinker">
<ip>127.0.0.1</ip>
<port>5237</port>
<secret>SECRET</secret>
</connect>
<register>
<!-- This tag contains the message displayed to users at registration time.
You can use <p/> and/or <br/> to break lines. Multiple spaces and newlines
are converted to just one, so formatting of config file doesn't really matter. -->
<instructions>
Fill in your GG number (after "username")
and password to register on the transport.
<p/>To change your information in the GaduGadu directory you need to fill in the other fields.
<p/>To remove registration you need to leave the form blank.
</instructions>
</register>
<search>
<!-- This tag contains the message displayed to users at search time. -->
<instructions>
To search people:<br/>
First fill in surname or family name, nickname, city, birthyear or range of birthyears (eg. 1950-1960)
and gender (you may fill in more fields at once).<br/>
or<br/>
Fill in phone number<br/>
or<br/>
Fill in the GG number of the person you are searching.
</instructions>
</search>
<gateway>
<!-- This is message, that may be displayed to user when adding gg contact. -->
<desc>Please fill in the GaduGadu number of the person you want to add.</desc>
<!-- And this is the prompt for GG number. -->
<prompt>GG Nummer</prompt>
</gateway>
<vCard>
<FN>Gadu-Gadu Transport</FN>
<DESC>This is the Gadu-Gadu Transport.</DESC>
<EMAIL>EMAIL@ADDRESS.COM</EMAIL>
<URL>http://www.jabberstudio.org/projects/jabber-gg-transport/</URL>
</vCard>
<!-- Default user locale (language).
Empty means system locale setting,
no (or commented-out) <default_locale> tag means no translations. -->
<!-- <default_locale>pl_PL</default_locale> -->
<!-- Logger configuration.
You may configure one logger of type "syslog" and/or one of type "file".
You may also not configure logging at all. -->
<log type="syslog" facility="local0"/>
<log type="file">/var/log/jabber/jabber-gg-transport.log</log>
<!-- Uncomment this, if you want proxy to be used for Gadu-Gadu connection. -->
<!--
<proxy>
<ip>127.0.0.1</ip>
<port>8080</port>
</proxy>
-->
<!-- You can change these values according to your needs. -->
<conn_timeout>60</conn_timeout>
<ping_interval>10</ping_interval>
<!-- Gadu-Gadu server doesn't seem to answer pings anymore :-(
So let's give it 10 year :-) -->
<pong_timeout>315360000</pong_timeout>
<!-- This time after disconnection from Gadu-Gadu server the transport
will try to connect again. -->
<reconnect>300</reconnect>
<!-- How long to wait before restart, after jabber server connection is broken
negative value means, that jggtrans should terminate. -->
<restart_timeout>60</restart_timeout>
<!-- Delay between the unavailable presence is received from user and loggin out
from Gadu-Gadu - for nice <presence type="invisible"/> support. -->
<disconnect_delay>5</disconnect_delay>
<!-- list of Gadu-Gadu servers to use.
<hub/> means "use GG hub to find server"
<server/> tag should contain server address and may contain "port"
attribute with port number. When TLS is available (supported by libgadu)
it will be used unless "tls" attribute is set to "no". Please notice,
that not all servers will accept TLS connections.
Servers (including hub) are tried in order as they appear in <servers/>
element.
A reasonable default server list is hardcoded in jggtrans.
-->
<!--
<servers>
<hub/>
<server port="443">217.17.41.90</server>
<server tls="no">217.17.41.85</server>
<server tls="no">217.17.41.88</server>
</servers>
-->
<!-- Spool directory. This is the place, where user info will be stored. -->
<!-- Be careful about permissions - users' Gadu-Gadu passwords are stored there. -->
<spool>/var/spool/jabber/gg.SERVER.COM/</spool>
<!-- Where to store pid file. This tag is optional. -->
<pidfile>/var/run/jabber/jabber-gg-transport.pid</pidfile>
<!-- jid allowed to do some administrative task (eg. discovering online users).
May be used multiple times. -->
<admin>GG_TRANSPORT_ADMIN@SERVER.COM</admin>
<!-- ACL gives detailed access control to the transport. -->
<acl>
<!-- Example entries: -->
<allow who="admin@SERVER.COM" what="iq/query?xmlns=http://jabber.org/protocol/stats"/>
<!-- will allow statistics gathering to admin@SERVER.COM -->
<deny who="*" what="iq/query?xmlns=http://jabber.org/protocol/stats"/>
<!-- will deny statistics gathering for anybody else -->
<!-- <allow who="*@SERVER.COM"/> -->
<!-- will allow anything else to users from "SERVER.COM" -->
<!-- <deny what="iq/query?xmlns=jabber:x:register"/> -->
<!-- will deny registration for all other users -->
<!-- <allow what="presence"/> -->
<!-- allow presence from anybody -->
<!-- <allow what="iq"/> -->
<!-- allow iq from anybody -->
<!-- <allow what="message"/> -->
<!-- allow message from anybody -->
<!-- <deny/> -->
<!-- will deny anything else -->
</acl>
</jggtrans>
+128
View File
@@ -0,0 +1,128 @@
<!-- jit.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<file>/var/log/jabber/jit-error</file> <!-- WPJabber logs with date. -->
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<file>/var/log/jabber/jit-record</file> <!-- WPJabber logs with date. -->
</log>
<!--
ejabberd do not provide XDB services.
xdb_file-jit.so (the renamed xdb_file.so from WPJabber) is
loaded in to handle all XDB requests.
Read also the documentation in xdb_file/README from the JIT package.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/xdb_file.so</xdb_file> <!-- The xdb_file.so from WPJabber/JIT. -->
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="icq.SERVER.COM">
<!--
Replace SERVER.COM with the same as above to enable sms.
-->
<host>sms.icq.SERVER.COM</host>
<!-- JIT configuration. -->
<icqtrans xmlns="jabber:config:icqtrans">
<sms>
<host>sms.icq.SERVER.COM</host>
<!-- Status of virtual "sms-contacts". -->
<show>away</show>
<status/>
</sms>
<instructions>Fill in your UIN and password.</instructions>
<search>Search ICQ users.</search>
<vCard>
<FN>ICQ Transport (JIT)</FN>
<DESC>This is the Jabber ICQ Transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://jit.jabberstudio.org/</URL>
</vCard>
<!-- Hashtable for users. -->
<prime>3907</prime>
<!-- Send messages from ICQ as chat to Jabber clients. -->
<chat/>
<!-- Enable this for ICQ web presence. -->
<web/>
<!--
If you don't want jabber:x:data forms
in reg and search uncomment this tag
(Not recomended).
-->
<no_xdata/>
<!--
This tag is necessary when using ejabberd.
In this way JIT will have its own contact list.
-->
<own_roster/>
<!--
When present, this tag will tell JIT not to try to
get the user's roster (which will take a bit of time
to fail in scenarios described above).
-->
<no_jabber_roster/>
<!-- File with stats. -->
<user_count_file>/var/spool/jabber/jit-count</user_count_file>
<!--
Interval beetween checking sessions: ping, messages, acks.
-->
<session_check>5</session_check>
<!-- Reconnect retries. -->
<reconnects>5</reconnects>
<!--
Time in sec when session can be inactive, 0=disabled.
-->
<session_timeout>18000</session_timeout>
<charset>windows-1252</charset>
<server>
<host port="5190">login.icq.com</host>
</server>
</icqtrans>
<!-- JIT module. -->
<load>
<icqtrans>/usr/local/lib/jabber/jit.so</icqtrans>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="icq-linker">
<host>SERVER.COM</host>
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5234</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/jit.pid</pidfile>
</jabber>
@@ -0,0 +1,118 @@
<!-- msn-transport.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/msn-transport-error.log</file>
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<format>%d %h %s</format>
<file>/var/log/jabber/msn-transport-record.log</file>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file>
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="msn.SERVER.COM">
<!-- msn-transport configuration. -->
<msntrans xmlns="jabber:config:msntrans">
<instructions>Fill in your MSN account and password (eg: user1@hotmail.com). A nickname is optional.</instructions>
<vCard>
<FN>MSN Transport</FN>
<DESC>This is the MSN Transport.</DESC>
<EMAIL>EMAIL@ADDRESS.COM</EMAIL>
<URL>http://msn-transport.jabberstudio.org/</URL>
</vCard>
<!--
Conference support allows you to create groupchat rooms on the
msn-transport and invite MSN users to join.
-->
<conference id="conference.msn.SERVER.COM">
<!--
This will make MSN transport invite you to a special groupchat
room when more then one user joins a normal one-on-one session.
Joining this room will make MSN transport "switch" the session
into groupchat mode. If you ignore it, MSN transport will
continue to send the messages as one-on-one chats.
-->
<invite>More than one user entered this chat session. Enter this room to switch to groupchat modus.</invite>
<notice>
<join> is available</join>
<leave> has leaved the room</leave>
</notice>
</conference>
<!-- Enable Hotmail inbox notification. -->
<headlines/>
<!--
Enable fancy friendly names
If the user enters a nickname upon registration, and the user has
a status message, their MSN friendly name will be "nickname - status message".
If the user does not enter a nickname on registration, but they do have
a status message, their friendly name will just be their status message.
If the user did enter a nickname on registration, but they have a blank status message,
then their friendly name will just be the registered nickname.
If the user did not enter a nickname on registration, and they have a blank status message,
their nickname will just be the username portion of their JID.
If the above chosen friendly name is too long, then it will be truncated and "..." placed
at the end. MSN only supports friendly names of 128 characters, so this is unavoidable.
If this is disabled, then the registered nick is always sent as the MSN friendly name,
or if that is blank, the username portion of their JID is sent instead.
-->
<fancy_friendly/>
</msntrans>
<!-- msn-transport module. -->
<load>
<msntrans>/usr/local/lib/jabber/msn-transport.so</msntrans>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="msn-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5235</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/msn-transport.pid</pidfile>
</jabber>
@@ -0,0 +1,86 @@
<!-- yahoo-transport-2.xml -->
<jabber>
<!--
You need to add the elogger entry here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/yahoo-transport-2-error.log</file>
<stderr/>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file>
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="yahoo.SERVER.COM">
<!-- yahoo-transport-2 configuration. -->
<config xmlns="jabber:config:yahoo">
<vCard>
<NAME>Yahoo! Transport</NAME>
<FN>vCard not implemented in current version</FN>
<DESC>This is the Yahoo! transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://yahoo-transport-2.jabberstudio.org/</URL>
</vCard>
<instructions>Fill in your YAHOO! Messenger username and password to register on this transport.</instructions>
<server>scs.msg.yahoo.com</server>
<port>5050</port>
<!--
The character map. This provides character set translation from UTF-8
to the indicated character map. See the man page for 'iconv' for available
character maps on your platform. CP1252 is the standard Windows character
set.
-->
<charmap>CP1252</charmap>
<!--
When this element exists, the transport will send new mail notifications as
well as a count of unread messages when the user initially logs in.
-->
<newmail/>
</config>
<!-- yahoo-transport-2 module. -->
<load>
<yahoo_transport>/usr/local/lib/jabber/yahoo-transport-2.so</yahoo_transport>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="yahoo-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5236</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/yahoo-transport-2.pid</pidfile>
</jabber>
+45
View File
@@ -0,0 +1,45 @@
#!/bin/sh
#########################################################
#
# aim-transport -- script to start aim-transport.
#
#########################################################
DAEMON=/usr/local/sbin/jabberd-aim-transport
CONF=/etc/jabber/aim-transport.xml
NAME=jabberd-aim-transport
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+43
View File
@@ -0,0 +1,43 @@
#!/bin/sh
#########################################################
#
# ile -- script to start ILE.
#
#########################################################
DAEMON=/usr/local/sbin/ile.pl
NAME=ile.pl
CONF=/etc/jabber/ile.xml
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
echo "Not implemented yet. Starting in normal mode"
$0 start
;;
start)
test -f $DAEMON || exit 0
echo "Starting $NAME."
$DAEMON $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|status|restart}"
exit 1
esac
@@ -0,0 +1,47 @@
#!/bin/sh
#########################################################
#
# jabber-gg-transport -- script to start jabber-gg-transport.
#
#########################################################
DAEMON=/usr/local/sbin/jggtrans
CONF=/etc/jabber/jabber-gg-transport.xml
NAME=jggtrans
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
rm /var/run/jabber/jabber-gg-transport.pid
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+45
View File
@@ -0,0 +1,45 @@
#!/bin/sh
#########################################################
#
# jit -- script to start JIT.
#
#########################################################
DAEMON=/usr/local/sbin/wpjabber-jit
CONF=/etc/jabber/jit.xml
NAME=wpjabber-jit
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+50
View File
@@ -0,0 +1,50 @@
#!/bin/sh
#########################################################
#
# msn-transport -- script to start MSN Transport.
#
#########################################################
DAEMON=/usr/local/sbin/jabberd-msn-transport
CONF=/etc/jabber/msn-transport.xml
NAME=jabberd-msn-transport
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
strace)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in strace mode."
strace -o /opt/ejabberd/var/log/jabber/strace.log $DAEMON -H $HOME -c $CONF &
;;
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+45
View File
@@ -0,0 +1,45 @@
#!/bin/sh
##############################################################
#
# yahoo-transport-2 -- script to start Yahoo-transport-2.
#
#############################################################
DAEMON=/usr/local/sbin/jabberd-yahoo-transport-2
CONF=/etc/jabber/yahoo-transport-2.xml
NAME=jabberd-yahoo-transport-2
HOME=/etc/jabber/
USER=ejabberd
#############################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+1
View File
@@ -0,0 +1 @@
*.beam
+27 -321
View File
@@ -1,150 +1,55 @@
# $Id$
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
EXPAT_CFLAGS = @EXPAT_CFLAGS@
ERLANG_CFLAGS= @ERLANG_CFLAGS@
EXPAT_LIBS = @EXPAT_LIBS@
ERLANG_LIBS = @ERLANG_LIBS@
ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj
INSTALLUSER=@INSTALLUSER@
# if no user was enabled, don't set privileges or ownership
ifeq ($(INSTALLUSER),)
O_USER=
G_USER=
CHOWN_COMMAND=echo
CHOWN_OUTPUT=/dev/null
INIT_USER=root
else
O_USER=-o $(INSTALLUSER)
G_USER=-g $(INSTALLUSER)
CHOWN_COMMAND=chown
CHOWN_OUTPUT=&1
INIT_USER=$(INSTALLUSER)
endif
EFLAGS += @ERLANG_SSLVER@ -pa .
# make debug=true to compile Erlang module with debug informations.
ifdef debug
EFLAGS+=+debug_info +export_all
endif
DEBUGTOOLS = p1_prof.erl etop_tr.erl
ifdef debugtools
SOURCES+=$(DEBUGTOOLS)
endif
ifeq (@hipe@, true)
EFLAGS+=+native
ERLC_FLAGS+=+debug_info
endif
ifeq (@roster_gateway_workaround@, true)
EFLAGS+=-DROSTER_GATEWAY_WORKAROUND
endif
ifeq (@full_xml@, true)
EFLAGS+=-DFULL_XML_SUPPORT
endif
ifeq (@transient_supervisors@, false)
EFLAGS+=-DNO_TRANSIENT_SUPERVISORS
endif
ifeq (@md2@, true)
EFLAGS+=-DHAVE_MD2
ERLANG_CFLAGS += -DHAVE_MD2
endif
INSTALL_EPAM=
ifeq (@pam@, pam)
INSTALL_EPAM=install -m 750 $(O_USER) epam $(PBINDIR)
ERLC_FLAGS+=-DROSTER_GATEWAY_WORKAROUND
endif
prefix = @prefix@
exec_prefix = @exec_prefix@
SUBDIRS = stun @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ @tls@ @odbc@ @ejabberd_zlib@
ERLSHLIBS =
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
SOURCES_ALL = $(wildcard *.erl)
SOURCES_MISC = $(ERLBEHAVS) $(DEBUGTOOLS)
SOURCES += $(filter-out $(SOURCES_MISC),$(SOURCES_ALL))
ERLBEHAVBEAMS = $(ERLBEHAVS:.erl=.beam)
SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @eldap@ @web@ stringprep @tls@ @odbc@
ERLSHLIBS = expat_erl.so
SOURCES = $(wildcard *.erl)
BEAMS = $(SOURCES:.erl=.beam)
DESTDIR =
# /etc/ejabberd/
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd
# /sbin/
SBINDIR = $(DESTDIR)@sbindir@
# /lib/ejabberd/
EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd
# /share/doc/ejabberd
PACKAGE_TARNAME = @PACKAGE_TARNAME@
datarootdir = @datarootdir@
DOCDIR = $(DESTDIR)@docdir@
# /usr/lib/ejabberd/ebin/
EJABBERDDIR = $(DESTDIR)/var/lib/ejabberd
BEAMDIR = $(EJABBERDDIR)/ebin
# /usr/lib/ejabberd/include/
INCLUDEDIR = $(EJABBERDDIR)/include
# /usr/lib/ejabberd/priv/
PRIVDIR = $(EJABBERDDIR)/priv
# /usr/lib/ejabberd/priv/bin
PBINDIR = $(PRIVDIR)/bin
# /usr/lib/ejabberd/priv/lib
SODIR = $(PRIVDIR)/lib
# /usr/lib/ejabberd/priv/msgs
MSGSDIR = $(PRIVDIR)/msgs
LOGDIR = $(DESTDIR)/var/log/ejabberd
ETCDIR = $(DESTDIR)/etc/ejabberd
# /var/lib/ejabberd/
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
# /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
# /var/log/ejabberd/
LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
endif
ifeq ($(shell uname),SunOs)
DYNAMIC_LIB_CFLAGS = -KPIC -G -z text
endif
ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj
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 $(EFLAGS) $<
@ERLC@ -W $(ERLC_FLAGS) $<
all-recursive install-recursive uninstall-recursive \
clean-recursive distclean-recursive devdoc-recursive \
clean-recursive distclean-recursive \
mostlyclean-recursive maintainer-clean-recursive:
@subdirs="$(SUBDIRS)"; for subdir in $$subdirs; do \
target=`echo $@|sed 's,-recursive,,'`; \
@@ -155,140 +60,31 @@ mostlyclean-recursive maintainer-clean-recursive:
%.hrl: %.asn1
@ERLC@ $(ASN_FLAGS) $<
@ERLC@ -W $(EFLAGS) $*.erl
$(ERLSHLIBS): %.so: %.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) \
$(subst ../,,$(subst .so,.c,$@)) \
$(ERLANG_LIBS) \
$(ERLANG_CFLAGS) \
-o $@ \
$(DYNAMIC_LIB_CFLAGS)
translations:
../tools/extract_translations/prepare-translation.sh -updateall
gcc -Wall $(CFLAGS) $(LDFLAGS) $(LIBS) \
$(subst ../,,$(subst .so,.c,$@)) \
$(EXPAT_LIBS) $(EXPAT_CFLAGS) \
$(ERLANG_LIBS) $(ERLANG_CFLAGS) \
-o $@ -fpic -shared
install: all
#
# Configuration files
install -d -m 750 $(G_USER) $(ETCDIR)
[ -f $(ETCDIR)/ejabberd.cfg ] \
&& install -b -m 640 $(G_USER) ejabberd.cfg.example $(ETCDIR)/ejabberd.cfg-new \
|| install -b -m 640 $(G_USER) ejabberd.cfg.example $(ETCDIR)/ejabberd.cfg
sed -e "s*@rootdir@*@prefix@*" \
-e "s*@installuser@*@INSTALLUSER@*" \
-e "s*@LIBDIR@*@libdir@*" \
-e "s*@SYSCONFDIR@*@sysconfdir@*" \
-e "s*@LOCALSTATEDIR@*@localstatedir@*" \
-e "s*@DOCDIR@*@docdir@*" \
-e "s*@erl@*@ERL@*" ejabberdctl.template \
> ejabberdctl.example
[ -f $(ETCDIR)/ejabberdctl.cfg ] \
&& install -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg-new \
|| install -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg
install -b -m 644 $(G_USER) inetrc $(ETCDIR)/inetrc
#
# Administration script
[ -d $(SBINDIR) ] || install -d -m 755 $(SBINDIR)
install -m 550 $(G_USER) ejabberdctl.example $(SBINDIR)/ejabberdctl
#
# Init script
sed -e "s*@ctlscriptpath@*$(SBINDIR)*" \
-e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \
> ejabberd.init
#
# Binary Erlang files
install -d $(BEAMDIR)
install -m 644 *.app $(BEAMDIR)
install -m 644 *.beam $(BEAMDIR)
rm -f $(BEAMDIR)/configure.beam
#
# ejabberd header files
install -d $(INCLUDEDIR)
install -m 644 *.hrl $(INCLUDEDIR)
install -d $(INCLUDEDIR)/eldap/
install -m 644 eldap/*.hrl $(INCLUDEDIR)/eldap/
install -d $(INCLUDEDIR)/mod_muc/
install -m 644 mod_muc/*.hrl $(INCLUDEDIR)/mod_muc/
install -d $(INCLUDEDIR)/mod_proxy65/
install -m 644 mod_proxy65/*.hrl $(INCLUDEDIR)/mod_proxy65/
install -d $(INCLUDEDIR)/mod_pubsub/
install -m 644 mod_pubsub/*.hrl $(INCLUDEDIR)/mod_pubsub/
install -d $(INCLUDEDIR)/web/
install -m 644 web/*.hrl $(INCLUDEDIR)/web/
#
# Binary C programs
install -d $(PBINDIR)
install -m 750 $(O_USER) ../tools/captcha.sh $(PBINDIR)
$(INSTALL_EPAM)
#
# Binary system libraries
install -m 644 *.app $(BEAMDIR)
install -d $(SODIR)
install -m 644 *.so $(SODIR)
#
# Translated strings
install -d $(MSGSDIR)
install -m 644 msgs/*.msg $(MSGSDIR)
#
# Spool directory
install -d -m 750 $(O_USER) $(SPOOLDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(SPOOLDIR)
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
#
# ejabberdctl lock directory
install -d -m 750 $(O_USER) $(CTLLOCKDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(CTLLOCKDIR)
#
# Log directory
install -d -m 750 $(O_USER) $(LOGDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(LOGDIR)
#
# Documentation
install -d $(DOCDIR)
[ -f ../doc/guide.html ] \
&& install -m 644 ../doc/dev.html $(DOCDIR) \
&& install -m 644 ../doc/guide.html $(DOCDIR) \
&& install -m 644 ../doc/*.png $(DOCDIR) \
|| echo "No ../doc/guide.html was built"
install -m 644 ../doc/*.txt $(DOCDIR)
[ -f ../doc/guide.pdf ] \
&& install -m 644 ../doc/guide.pdf $(DOCDIR) \
|| echo "No ../doc/guide.pdf was built"
install -m 644 ../COPYING $(DOCDIR)
install -d $(ETCDIR)
install -b -m 644 ejabberd.cfg.example $(ETCDIR)/ejabberd.cfg
install -d $(LOGDIR)
uninstall: uninstall-binary
uninstall-binary:
rm -f $(SBINDIR)/ejabberdctl
rm -fr $(DOCDIR)
rm -f $(BEAMDIR)/*.beam
rm -f $(BEAMDIR)/*.app
rm -fr $(BEAMDIR)
rm -f $(INCLUDEDIR)/*.hrl
rm -fr $(INCLUDEDIR)
rm -fr $(PBINDIR)
rm -f $(SODIR)/*.so
rm -fr $(SODIR)
rm -f $(MSGSDIR)/*.msgs
rm -fr $(MSGSDIR)
rm -fr $(PRIVDIR)
rm -fr $(EJABBERDDIR)
uninstall-all: uninstall-binary
rm -rf $(ETCDIR)
rm -rf $(EJABBERDDIR)
rm -rf $(SPOOLDIR)
rm -rf $(CTLLOCKDIR)
rm -rf $(LOGDIR)
clean: clean-recursive clean-local clean-devdoc
clean: clean-recursive clean-local
clean-local:
rm -f *.beam $(ERLSHLIBS) epam ejabberdctl.example
rm -f XmppAddr.asn1db XmppAddr.erl XmppAddr.hrl
rm -f *.beam $(ERLSHLIBS)
distclean: distclean-recursive clean-local
rm -f config.status
@@ -299,93 +95,3 @@ TAGS:
etags *.erl
Makefile: Makefile.in
dialyzer: $(BEAMS)
@dialyzer -c .
## Devdoc definitions
SRCDIR=.
DDTDIR=.
DEVDOCDIR=../doc/devdoc
DEVDOC_ERLS = $(wildcard ../doc/devdoc/*.erl)
DEVDOC_BEAMS = $(DEVDOC_ERLS:.erl=.beam)
APPNAME = ejabberd
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ./ejabberd.app)
.PHONY = all
HTMLS = $(SOURCES:%.erl=../doc/devdoc/%.html)
ERLHTMLS = $(SOURCES:%.erl=../doc/devdoc/%.erl.html)
SVGS = $(SOURCES:%.erl=../doc/devdoc/%.svg)
EDOCINDEX = $(DEVDOCDIR)/index.html
## Devdoc rules
devdoc: compile-devdoc devdoc-root devdoc-recursive
$(devdoc-customize)
$(devdoc-move)
devdoc-root: $(EDOCINDEX) $(HTMLS) $(ERLHTMLS) $(SVGS)
define devdoc-customize
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/<span class="attribute" >module<\/span>(\([A-Za-z0-9_]*\))/<span class="attribute" >module<\/span>(<a href="\1.html">\1<\/a>)/g;' {} \;
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/arity="\([0-9]*\)" >\([A-Za-z0-9_]*\)</><a class="function" id="\2-\1" href="EDOCFILENAME#\2-\1">\2<\/a></g;' {} \;
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/class="export" >\([A-Za-z0-9_]*\)\/\([0-9]*\)</class="export" ><a href="#\1-\2">\1\/\2<\/a></g;' {} \;
for fn in *.erl.html; do \
sed -i 's/EDOCFILENAME/'$${fn%.erl.html}.html'/g;' $${fn} ; \
sed = $${fn} | sed 'N;s/\n/ /;s/^\([0-9_]*\)/<a href="#\1" name="\1" class="l">\1<\/a>/' >$${fn}.tmp ; \
mv $${fn}.tmp $${fn} ; \
sed -i 's/<a href="#1" name="1" class="l">1<\/a> <html><link rel="stylesheet" type="text\/css"href="escobar.css"><\/link><body><pre><span class="comment" >/<html><link rel="stylesheet" type="text\/css" href="escobar.css"><\/link><body><pre><span class="comment" ><a href="#1" name="1" class="l">1<\/a> /g;' $${fn} ; \
done
-mv *.erl.html $(DEVDOCDIR)
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/<a href="overview-summary.html" target="overviewFrame">/<a href="index.html" target="_parent">/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/align=\"right\" border=\"0\" alt=\"erlang logo\"/alt=\"erlang logo\"><\/a><a href=\"http:\/\/www.ejabberd.im\/\"><img src=\"ejabberd-im.png\" alt=\"ejabberd Community\"><\/a><a href=\"http:\/\/www.process-one.net\/en\/ejabberd\/\"><img src=\"ejabberd-p1.png\" alt=\"ejabberd home\"><\/a><a href=\"http:\/\/www.process-one.net\/\"><img src=\"process-one.png\" alt=\"ProcessOne\"/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/^<h1>Module \([A-Za-z0-9_]*\)<\/h1>/<h1>Module \1 [<a href="\1.erl.html">erl<\/a> <a href="\1.svg">svg<\/a>]<\/h1>/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/class="function"><a name="\([A-Za-z0-9_]*\)-\([0-9_]*\)">/class="function"><a name="\1-\2" href="ESCOFILENAME#\1-\2">/g;' {} \;
-for fn in *.html; do sed -i 's/ESCOFILENAME/'$${fn%.html}.erl.html'/g;' $${fn} ; done
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="EXP\([A-Za-z0-9_]*\).html#\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="PRI\([A-Za-z0-9_]*\).html#\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="APP\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="EXM\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.process-one.net\/docs\/exmpp\/devdoc\/trunk\/\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="OTP\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.erlang.org\/doc\/man\/\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="OTP\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.erlang.org\/doc\/man\/erlang.html#\1-\2"/g;' {} \;
endef
define devdoc-move
-rm *.dot
-mv *.html $(DEVDOCDIR)
-mv *.svg $(DEVDOCDIR)
endef
compile-devdoc: $(DEVDOC_BEAMS)
[ ! -f funrelg.beam ] || mv funrelg.beam $(DEVDOCDIR)
[ ! -f escobar_hilite.beam ] || mv escobar_hilite.beam $(DEVDOCDIR)
[ ! -f escobar_run.beam ] || mv escobar_run.beam $(DEVDOCDIR)
$(EDOCINDEX):
@ERL@ -noshell -run edoc_run application "'$(APPNAME)'" '"$(SRCDIR)"' \
'[{dir,"$(DDTDIR)"},{packages,false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"overview.edoc"}]' -s init stop
sed -i 's/<title>The ejabberd application<\/title>/<title>ejabberd devdoc<\/title><link rel="shortcut icon" href="favicon.ico" type="image\/x-icon"\/>/g;' $(DDTDIR)/index.html
mv edoc-info $(DEVDOCDIR)
mv *.png $(DEVDOCDIR)
cp *.html $(DEVDOCDIR)
@ERL@ -noshell -pa $(DEVDOCDIR) -run escobar_run dir $(SRCDIR) $(SRCDIR) -s init stop
@ERL@ -noshell -pa $(DEVDOCDIR) -run funrelg dir $(SRCDIR) $(SRCDIR) -s init stop
$(devdoc-customize)
$(devdoc-move)
$(DEVDOCDIR)/%.erl.html: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run escobar_run file $< $(SRCDIR) -s init stop
$(DEVDOCDIR)/%.html: %.erl
@ERL@ -noshell -run edoc_run file $< \
'[{dir,"$(DDTDIR)"},{packages,false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"overview.edoc"}]' -s init stop
$(DEVDOCDIR)/%.svg: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run funrelg file $< $(SRCDIR) -s init stop
clean-devdoc:
rm -f $(DEVDOCDIR)/edoc-info
rm -f $(DEVDOCDIR)/erlang.png
rm -f $(DEVDOCDIR)/*.beam
rm -f $(DEVDOCDIR)/*.dot
rm -f $(DEVDOCDIR)/*.html
rm -f $(DEVDOCDIR)/*.svg
+18 -37
View File
@@ -52,98 +52,78 @@ release : build release_clean
mkdir $(SRC_DIR)\eldap
copy eldap\eldap.* $(SRC_DIR)\eldap
copy eldap\ELDAPv3.asn $(SRC_DIR)\eldap
mkdir $(SRC_DIR)\mod_irc
copy mod_irc\*.erl $(SRC_DIR)\mod_irc
copy mod_irc\*.c $(SRC_DIR)\mod_irc
mkdir $(SRC_DIR)\mod_muc
copy mod_muc\*.erl $(SRC_DIR)\mod_muc
mkdir $(SRC_DIR)\mod_pubsub
copy mod_pubsub\*.erl $(SRC_DIR)\mod_pubsub
mkdir $(SRC_DIR)\mod_proxy65
copy mod_proxy65\*.erl $(SRC_DIR)\mod_proxy65
copy mod_proxy65\*.hrl $(SRC_DIR)\mod_proxy65
mkdir $(SRC_DIR)\stringprep
copy stringprep\*.erl $(SRC_DIR)\stringprep
copy stringprep\*.c $(SRC_DIR)\stringprep
copy stringprep\*.tcl $(SRC_DIR)\stringprep
mkdir $(SRC_DIR)\stun
copy stun\*.erl $(SRC_DIR)\stun
copy stun\*.hrl $(SRC_DIR)\stun
mkdir $(SRC_DIR)\tls
copy tls\*.erl $(SRC_DIR)\tls
copy tls\*.c $(SRC_DIR)\tls
mkdir $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.erl $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.c $(SRC_DIR)\ejabberd_zlib
mkdir $(SRC_DIR)\web
copy web\*.erl $(SRC_DIR)\web
mkdir $(SRC_DIR)\odbc
copy odbc\*.erl $(SRC_DIR)\odbc
copy odbc\*.sql $(EREL)
mkdir $(DOC_DIR)
copy ..\doc\*.txt $(DOC_DIR)
copy ..\doc\*.html $(DOC_DIR)
copy ..\doc\*.png $(DOC_DIR)
SOURCE =
OBJECT =
DLL =
SOURCE = expat_erl.c
OBJECT = expat_erl.o
DLL = expat_erl.dll
build : $(DLL) compile-beam all-recursive
all-recursive :
cd eldap
nmake -nologo -f Makefile.win32
cd ..\mod_irc
nmake -nologo -f Makefile.win32
cd ..\mod_muc
nmake -nologo -f Makefile.win32
cd ..\mod_pubsub
nmake -nologo -f Makefile.win32
cd ..\mod_proxy65
nmake -nologo -f Makefile.win32
cd ..\stringprep
nmake -nologo -f Makefile.win32
cd ..\stun
nmake -nologo -f Makefile.win32
cd ..\tls
nmake -nologo -f Makefile.win32
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32
cd ..\web
nmake -nologo -f Makefile.win32
cd ..\odbc
nmake -nologo -f Makefile.win32
cd ..
compile-beam : XmppAddr.hrl
erl -s make all report -noinput -s erlang halt
XmppAddr.hrl : XmppAddr.asn1
erlc -bber_bin +der +compact_bit_string +optimize +noobj XmppAddr.asn1
compile-beam :
erlc *.erl
CLEAN : clean-recursive clean-local
clean-local :
-@erase $(OBJECT)
-@erase $(DLL)
-@erase expat_erl.exp
-@erase expat_erl.lib
-@erase *.beam
-@erase XmppAddr.asn1db
-@erase XmppAddr.erl
-@erase XmppAddr.hrl
clean-recursive :
cd eldap
nmake -nologo -f Makefile.win32 clean
cd ..\mod_irc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_muc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_pubsub
nmake -nologo -f Makefile.win32 clean
cd ..\mod_proxy65
nmake -nologo -f Makefile.win32 clean
cd ..\stringprep
nmake -nologo -f Makefile.win32 clean
cd ..\stun
nmake -nologo -f Makefile.win32 clean
cd ..\tls
nmake -nologo -f Makefile.win32 clean
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32 clean
cd ..\web
nmake -nologo -f Makefile.win32 clean
cd ..\odbc
@@ -155,13 +135,14 @@ distclean : release_clean clean
-@erase Makefile.inc
CC=cl.exe
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include"
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT $(EXPAT_FLAG) -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(EXPAT_DIR)\source\lib"
LD=link.exe
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(EXPAT_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
$(DLL) : $(OBJECT)
$(LD) $(LD_FLAGS) -out:$(DLL) $(OBJECT)
$(OBJECT) : $(SOURCE)
$(CC) $(CC_FLAGS) -c -Fo$(OBJECT) $(SOURCE)
$(CC) $(CC_FLAGS) -c -Fo$(OBJECT) $(SOURCE)
-235
View File
@@ -1,235 +0,0 @@
AC_DEFUN([AM_WITH_ZLIB],
[ AC_ARG_WITH(zlib,
[AC_HELP_STRING([--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
ZLIB_CFLAGS="-I$with_zlib/include"
ZLIB_LIBS="-L$with_zlib/lib"
fi
AC_CHECK_LIB(z, gzgets,
[ ZLIB_LIBS="$ZLIB_LIBS -lz"
zlib_found=yes ],
[ 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])
fi
zlib_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $ZLIB_CFLAGS"
zlib_save_CPPFLAGS="$CFLAGS"
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])
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
PAM_CFLAGS=
PAM_LIBS=
if test x"$with_pam" != x; then
PAM_CFLAGS="-I$with_pam/include"
PAM_LIBS="-L$with_pam/lib"
fi
AC_CHECK_LIB(pam, pam_start,
[ PAM_LIBS="$PAM_LIBS -lpam"
pam_found=yes ],
[ 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])
fi
pam_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PAM_CFLAGS"
pam_save_CPPFLAGS="$CPPFLAGS"
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])
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])])
AC_PATH_TOOL(ERLC, erlc, , $with_erlang:$with_erlang/bin:$PATH)
AC_PATH_TOOL(ERL, erl, , $with_erlang:$with_erlang/bin:$PATH)
if test "z$ERLC" = "z" || test "z$ERL" = "z"; then
AC_MSG_ERROR([erlang not found])
fi
cat >>conftest.erl <<_EOF
-module(conftest).
-author('alexey@sevcom.net').
-export([[start/0]]).
start() ->
EIDirS = code:lib_dir("erl_interface") ++ "\n",
EILibS = libpath("erl_interface") ++ "\n",
EXMPPDir = code:lib_dir("exmpp"),
case EXMPPDir of
{error, bad_name} -> exit("exmpp not found");
_ -> ok
end,
EXMPPDirS = EXMPPDir ++ "\n",
RootDirS = code:root_dir() ++ "\n",
file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ ssldef() ++ EXMPPDirS ++ RootDirS)),
halt().
ssldef() ->
OTP = (catch erlang:system_info(otp_release)),
if
OTP >= "R14" -> "-DSSL40\n";
OTP >= "R12" -> "-DSSL39\n";
true -> "\n"
end.
%% return physical architecture based on OS/Processor
archname() ->
ArchStr = erlang:system_info(system_architecture),
case os:type() of
{win32, _} -> "windows";
{unix,UnixName} ->
Specs = string:tokens(ArchStr,"-"),
Cpu = case lists:nth(2,Specs) of
"pc" -> "x86";
_ -> hd(Specs)
end,
atom_to_list(UnixName) ++ "-" ++ Cpu;
_ -> "generic"
end.
%% Return arch-based library path or a default value if this directory
%% does not exist
libpath(App) ->
PrivDir = code:priv_dir(App),
ArchDir = archname(),
LibArchDir = filename:join([[PrivDir,"lib",ArchDir]]),
case file:list_dir(LibArchDir) of
%% Arch lib dir exists: We use it
{ok, _List} -> LibArchDir;
%% Arch lib dir does not exist: Return the default value
%% ({error, enoent}):
_Error -> code:lib_dir("erl_interface") ++ "/lib"
end.
_EOF
if ! $ERLC conftest.erl; then
AC_MSG_ERROR([could not compile sample program])
fi
if ! $ERL -s conftest -noshell; then
AC_MSG_ERROR([could not run sample program])
fi
if ! test -f conftest.out; then
AC_MSG_ERROR([erlang program was not properly executed, (conftest.out was not produced)])
fi
# First line
ERLANG_EI_DIR=`cat conftest.out | head -n 1`
# Second line
ERLANG_EI_LIB=`cat conftest.out | head -n 2 | tail -n 1`
# Third line
ERLANG_SSLVER=`cat conftest.out | head -n 3 | tail -n 1`
# Fourth line
ERLANG_EXMPP=`cat conftest.out | head -n 4 | tail -n 1`
# End line
ERLANG_DIR=`cat conftest.out | tail -n 1`
ERLANG_CFLAGS="-I$ERLANG_EI_DIR/include -I$ERLANG_DIR/usr/include"
ERLANG_LIBS="-L$ERLANG_EI_LIB -lerl_interface -lei"
AC_SUBST(ERLANG_CFLAGS)
AC_SUBST(ERLANG_LIBS)
AC_SUBST(ERLANG_SSLVER)
AC_SUBST(ERLANG_EXMPP)
AC_SUBST(ERLC)
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)])],
[mr_enable_$1="$enableval"],
[mr_enable_$1=$2])
if test "$mr_enable_$1" = "yes"; then
$1=$1
make_$1=$1/Makefile
fi
AC_MSG_RESULT($mr_enable_$1)
AC_SUBST($1)
AC_SUBST(make_$1)
])
dnl <openssl>
AC_DEFUN([AM_WITH_OPENSSL],
[ AC_ARG_WITH(openssl,
[AC_HELP_STRING([--with-openssl=PREFIX], [prefix where OPENSSL is installed])])
unset SSL_LIBS;
unset SSL_CFLAGS;
have_openssl=no
if test x"$tls" != x; then
for ssl_prefix in $withval /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr; do
printf "looking for openssl in $ssl_prefix...\n"
SSL_CFLAGS="-I$ssl_prefix/include"
SSL_LIBS="-L$ssl_prefix/lib -lcrypto"
AC_CHECK_LIB(ssl, SSL_new, [ have_openssl=yes ], [ have_openssl=no ], [ $SSL_LIBS $SSL_CFLAGS ])
if test x"$have_openssl" = xyes; then
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="-I$ssl_prefix/include $CPPFLAGS"
AC_CHECK_HEADERS(openssl/ssl.h, have_openssl_h=yes)
CPPFLAGS=$save_CPPFLAGS
if test x"$have_openssl_h" = xyes; then
have_openssl=yes
printf "openssl found in $ssl_prefix\n";
SSL_LIBS="-L$ssl_prefix/lib -lssl -lcrypto"
CPPFLAGS="-I$ssl_prefix/include $CPPFLAGS"
SSL_CFLAGS="-DHAVE_SSL"
break
fi
else
# Clear this from the autoconf cache, so in the next pass of
# this loop with different -L arguments, it will test again.
unset ac_cv_lib_ssl_SSL_new
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])
fi
AC_SUBST(SSL_LIBS)
AC_SUBST(SSL_CFLAGS)
fi
])
dnl <openssl/>
+28 -170
View File
@@ -1,76 +1,27 @@
%%%----------------------------------------------------------------------
%%% File : acl.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : ACL support
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(acl).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/0,
to_record/3,
add/3,
add_list/3,
match_rule/3,
for_host/1,
% for debugging only
match_acl/3]).
-include("ejabberd.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
%% @type aclspec() = all | JID_Exact | JID_Regexp | JID_Glob | Shared_Group
%% JID_Exact = {user, U} | {user, U, S} | {server, S} | {resource, R}
%% U = string()
%% S = string()
%% R = string()
%% JID_Regexp = {user_regexp, UR} | {user_regexp, UR, S} | {server_regexp, SR} | {resource_regexp, RR} | {node_regexp, UR, SR}
%% UR = string()
%% SR = string()
%% RR = string()
%% JID_Glob = {user_glob, UG} | {user_glob, UG, S} | {server_glob, SG} | {resource_glob, RG} | {node_glob, UG, SG}
%% UG = string()
%% SG = string()
%% RG = string()
%% Shared_Group = {shared_group, G} | {shared_group, G, H}
%% G = string()
%% H = string().
%% @type acl() = {acl, ACLName, ACLSpec}
%% ACLName = atom()
%% ACLSpec = aclspec().
%% Record in its Ejabberd-configuration-file variant.
%% @type storedacl() = {acl, {ACLName, Host}, ACLSpec}
%% ACLName = atom()
%% Host = global | string()
%% ACLSpec = aclspec().
%% Record in its Mnesia-table-record variant.
-record(acl, {aclname, aclspec}).
%% @spec () -> ok
start() ->
mnesia:create_table(acl,
[{disc_copies, [node()]},
@@ -79,32 +30,16 @@ start() ->
mnesia:add_table_copy(acl, node(), ram_copies),
ok.
%% @spec (Host, ACLName, ACLSpec) -> storedacl()
%% Host = global | string()
%% ACLName = atom()
%% ACLSpec = aclspec()
to_record(Host, ACLName, ACLSpec) ->
#acl{aclname = {ACLName, Host}, aclspec = normalize_spec(ACLSpec)}.
%% @spec (Host, ACLName, ACLSpec) -> {atomic, ok} | {aborted, Reason}
%% Host = global | string()
%% ACLName = atom()
%% ACLSpec = all | none | aclspec()
%% Reason = term()
#acl{aclname = {ACLName, Host}, aclspec = ACLSpec}.
add(Host, ACLName, ACLSpec) ->
F = fun() ->
mnesia:write(#acl{aclname = {ACLName, Host},
aclspec = normalize_spec(ACLSpec)})
aclspec = ACLSpec})
end,
mnesia:transaction(F).
%% @spec (Host, ACLs, Clear) -> ok | false
%% Host = global | string()
%% ACLs = [acl()]
%% Clear = bool()
add_list(Host, ACLs, Clear) ->
F = fun() ->
if
@@ -123,7 +58,7 @@ add_list(Host, ACLs, Clear) ->
aclspec = ACLSpec} ->
mnesia:write(
#acl{aclname = {ACLName, Host},
aclspec = normalize_spec(ACLSpec)})
aclspec = ACLSpec})
end
end, ACLs)
end,
@@ -134,33 +69,7 @@ add_list(Host, ACLs, Clear) ->
false
end.
%% @spec (String) -> Prepd_String
%% String = string()
%% Prepd_String = string()
normalize(String) ->
exmpp_stringprep:nodeprep(String).
%% @spec (ACLSpec) -> Normalized_ACLSpec
%% ACLSpec = all | none | aclspec()
%% Normalized_ACLSpec = aclspec()
normalize_spec({A, B}) ->
{A, normalize(B)};
normalize_spec({A, B, C}) ->
{A, normalize(B), normalize(C)};
normalize_spec(all) ->
all;
normalize_spec(none) ->
none.
%% @spec (Host, Rule, JID) -> Access
%% Host = global | string()
%% Rule = all | none | atom()
%% JID = exmpp_jid:jid()
%% Access = allow | deny | atom()
match_rule(global, Rule, JID) ->
case Rule of
@@ -206,37 +115,23 @@ match_rule(Host, Rule, JID) ->
end
end.
%% @spec (ACLs, JID, Host) -> Access
%% ACLs = [{Access, ACLName}]
%% Access = deny | atom()
%% ACLName = atom()
%% JID = exmpp_jid:jid()
%% Host = string()
match_acls([], _, _Host) ->
match_acls([], _, Host) ->
deny;
match_acls([{Access, ACLName} | ACLs], JID, Host) ->
case match_acl(ACLName, JID, Host) of
match_acls([{Access, ACL} | ACLs], JID, Host) ->
case match_acl(ACL, JID, Host) of
true ->
Access;
_ ->
match_acls(ACLs, JID, Host)
end.
%% @spec (ACLName, JID, Host) -> bool()
%% ACLName = all | none | atom()
%% JID = exmpp_jid:jid()
%% Host = string()
match_acl(ACLName, JID, Host) ->
case ACLName of
match_acl(ACL, JID, Host) ->
case ACL of
all -> true;
none -> false;
_ ->
User = exmpp_jid:prep_node_as_list(JID),
Server = exmpp_jid:prep_domain_as_list(JID),
Resource = exmpp_jid:prep_resource_as_list(JID),
lists:any(fun(#acl{aclname=Name, aclspec = Spec}) ->
{User, Server, Resource} = jlib:jid_tolower(JID),
lists:any(fun(#acl{aclspec = Spec}) ->
case Spec of
all ->
true;
@@ -245,40 +140,28 @@ match_acl(ACLName, JID, Host) ->
andalso
((Host == Server) orelse
((Host == global) andalso
?IS_MY_HOST(Server)));
lists:member(Server, ?MYHOSTS)));
{user, U, S} ->
(U == User) andalso (S == Server);
{server, S} ->
S == Server;
{resource, R} ->
R == Resource;
{user_regexp, UR} when is_tuple(Name),
element(2, Name) =:= global ->
?IS_MY_HOST(Server)
andalso is_regexp_match(User, UR);
{user_regexp, UR} ->
((Host == Server) orelse
((Host == global) andalso
?IS_MY_HOST(Server)))
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);
{server_regexp, SR} ->
is_regexp_match(Server, SR);
{resource_regexp, RR} ->
is_regexp_match(Resource, RR);
{node_regexp, UR, SR} ->
is_regexp_match(Server, SR) andalso
is_regexp_match(User, UR);
{user_glob, UR} ->
((Host == Server) orelse
((Host == global) andalso
?IS_MY_HOST(Server)))
lists:member(Server, ?MYHOSTS)))
andalso
is_glob_match(User, UR);
{user_glob, UR, S} ->
@@ -286,54 +169,29 @@ match_acl(ACLName, JID, Host) ->
is_glob_match(User, UR);
{server_glob, SR} ->
is_glob_match(Server, SR);
{resource_glob, RR} ->
is_glob_match(Resource, RR);
{node_glob, UR, SR} ->
is_glob_match(Server, SR) andalso
is_glob_match(User, UR);
WrongSpec ->
?ERROR_MSG(
"Wrong ACL expression: ~p~n"
"Check your config file and reload it with the override_acls option enabled",
[WrongSpec]),
false
is_glob_match(User, UR)
end
end,
ets:lookup(acl, {ACLName, global}) ++
ets:lookup(acl, {ACLName, Host}))
ets:lookup(acl, {ACL, global}) ++
ets:lookup(acl, {ACL, Host}))
end.
%% @spec (String, RegExp) -> bool()
%% String = string() | undefined
%% RegExp = string()
is_regexp_match(undefined, _RegExp) ->
false;
is_regexp_match(String, RegExp) ->
try re:run(String, RegExp, [{capture, none}]) of
case regexp:first_match(String, RegExp) of
nomatch ->
false;
match ->
true
catch
_:ErrDesc ->
{match, _, _} ->
true;
{error, ErrDesc} ->
?ERROR_MSG(
"Wrong regexp ~p in ACL:~n~p",
[RegExp, ErrDesc]),
"Wrong regexp ~p in ACL: ~p",
[RegExp, lists:flatten(regexp:format_error(ErrDesc))]),
false
end.
%% @spec (String, Glob) -> bool()
%% String = string() | undefined
%% Glob = string()
is_glob_match(String, Glob) ->
is_regexp_match(String, xmerl_regexp:sh_to_awk(Glob)).
is_regexp_match(String, regexp:sh_to_awk(Glob)).
for_host(Host) ->
mnesia:select(acl,
ets:fun2ms(fun (#acl{aclname = {_ACLName, H}})
when H =:= Host ->
object()
end)).
+263
View File
@@ -0,0 +1,263 @@
AC_DEFUN(AM_WITH_EXPAT,
[ AC_ARG_WITH(expat,
[ --with-expat=PREFIX prefix where EXPAT is installed])
EXPAT_CFLAGS=
EXPAT_LIBS=
if test x"$with_expat" != x; then
EXPAT_CFLAGS="-I$with_expat/include"
EXPAT_LIBS="-L$with_expat/lib"
fi
AC_CHECK_LIB(expat, XML_ParserCreate,
[ EXPAT_LIBS="$EXPAT_LIBS -lexpat"
expat_found=yes ],
[ expat_found=no ],
"$EXPAT_LIBS")
if test $expat_found = no; then
AC_MSG_ERROR([Could not find the Expat library])
fi
expat_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $EXPAT_CFLAGS"
AC_CHECK_HEADERS(expat.h, , expat_found=no)
if test $expat_found = no; then
AC_MSG_ERROR([Could not find expat.h])
fi
CFLAGS="$expat_save_CFLAGS"
AC_SUBST(EXPAT_CFLAGS)
AC_SUBST(EXPAT_LIBS)
])
AC_DEFUN(AM_WITH_ERLANG,
[ AC_ARG_WITH(erlang,
[ --with-erlang=PREFIX path to erlc and erl ])
AC_PATH_TOOL(ERLC, erlc, , $PATH:$with_erlang:$with_erlang/bin)
AC_PATH_TOOL(ERL, erl, , $PATH:$with_erlang:$with_erlang/bin)
if test "z$ERLC" == "z" || test "z$ERL" == "z"; then
AC_MSG_ERROR([erlang not found])
fi
cat >>conftest.erl <<_EOF
-module(conftest).
-author('alexey@sevcom.net').
-export([[start/0]]).
start() ->
EIDirS = code:lib_dir("erl_interface") ++ "\n",
EILibS = libpath("erl_interface") ++ "\n",
RootDirS = code:root_dir() ++ "\n",
file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ RootDirS)),
halt().
%% return physical architecture based on OS/Processor
archname() ->
ArchStr = erlang:system_info(system_architecture),
case os:type() of
{win32, _} -> "windows";
{unix,UnixName} ->
Specs = string:tokens(ArchStr,"-"),
Cpu = case lists:nth(2,Specs) of
"pc" -> "x86";
_ -> hd(Specs)
end,
atom_to_list(UnixName) ++ "-" ++ Cpu;
_ -> "generic"
end.
%% Return arch-based library path or a default value if this directory
%% does not exist
libpath(App) ->
PrivDir = code:priv_dir(App),
ArchDir = archname(),
LibArchDir = filename:join([[PrivDir,"lib",ArchDir]]),
case file:list_dir(LibArchDir) of
%% Arch lib dir exists: We use it
{ok, _List} -> LibArchDir;
%% Arch lib dir does not exist: Return the default value
%% ({error, enoent}):
_Error -> code:lib_dir("erl_interface") ++ "/lib"
end.
_EOF
if ! $ERLC conftest.erl; then
AC_MSG_ERROR([could not compile sample program])
fi
if ! $ERL -s conftest -noshell; then
AC_MSG_ERROR([could not run sample program])
fi
if ! test -f conftest.out; then
AC_MSG_ERROR([erlang program was not properly executed, (conftest.out was not produced)])
fi
# First line
ERLANG_EI_DIR=`cat conftest.out | head -n 1`
# Second line
ERLANG_EI_LIB=`cat conftest.out | head -n 2 | tail -n 1`
# Third line
ERLANG_DIR=`cat conftest.out | tail -n 1`
ERLANG_CFLAGS="-I$ERLANG_EI_DIR/include -I$ERLANG_DIR/usr/include"
ERLANG_LIBS="-L$ERLANG_EI_LIB -lerl_interface -lei"
AC_SUBST(ERLANG_CFLAGS)
AC_SUBST(ERLANG_LIBS)
AC_SUBST(ERLC)
AC_SUBST(ERL)
])
AC_DEFUN(AC_MOD_ENABLE,
[
$1=
make_$1=
AC_MSG_CHECKING([whether build $1])
AC_ARG_ENABLE($1,
[ --enable-$1 enable $1 (default: $2)],
[mr_enable_$1="$enableval"],
[mr_enable_$1=$2])
if test "$mr_enable_$1" = "yes"; then
$1=$1
make_$1=$1/Makefile
fi
AC_MSG_RESULT($mr_enable_$1)
AC_SUBST($1)
AC_SUBST(make_$1)
])
dnl From Bruno Haible.
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],
[ --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
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
done
])
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
am_cv_func_iconv="no, consider installing GNU libiconv"
am_cv_lib_iconv=no
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_func_iconv=yes)
if test "$am_cv_func_iconv" != yes; then
am_save_LIBS="$LIBS"
LIBS="$LIBS -liconv"
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_lib_iconv=yes
am_cv_func_iconv=yes)
LIBS="$am_save_LIBS"
fi
dnl trying /usr/local
if test "$am_cv_func_iconv" != yes; then
am_save_LIBS="$LIBS"
am_save_CFLAGS="$CFLAGS"
am_save_LDFLAGS="$LDFLAGS"
LIBS="$LIBS -liconv"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CFLAGS="$CFLAGS -I/usr/local/include"
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_lib_iconv=yes
am_cv_func_iconv=yes
CPPFLAGS="$CPPFLAGS -I/usr/local/include",
LDFLAGS="$am_save_LDFLAGS"
CFLAGS="$am_save_CFLAGS")
LIBS="$am_save_LIBS"
fi
])
if test "$am_cv_func_iconv" = yes; then
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
AC_MSG_CHECKING([for iconv declaration])
AC_CACHE_VAL(am_cv_proto_iconv, [
AC_TRY_COMPILE([
#include <stdlib.h>
#include <iconv.h>
extern
#ifdef __cplusplus
"C"
#endif
#if defined(__STDC__) || defined(__cplusplus)
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
#else
size_t iconv();
#endif
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
AC_MSG_RESULT([$]{ac_t:-
}[$]am_cv_proto_iconv)
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
[Define as const if the declaration of iconv() needs const.])
fi
LIBICONV=
if test "$am_cv_lib_iconv" = yes; then
LIBICONV="-liconv"
fi
AC_SUBST(LIBICONV)
])
dnl <openssl>
AC_DEFUN(AM_WITH_OPENSSL,
[ AC_ARG_WITH(openssl,
[ --with-openssl=PREFIX prefix where OPENSSL is installed ])
unset SSL_LIBS;
unset SSL_CFLAGS;
have_openssl=no
if test x"$tls" != x; then
for ssl_prefix in $withval /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr; do
printf "looking for openssl in $ssl_prefix...\n"
SSL_CFLAGS="-I$ssl_prefix/include/openssl"
SSL_LIBS="-L$ssl_prefix/lib -lcrypto"
AC_CHECK_LIB(ssl, SSL_new, [ have_openssl=yes ], [ have_openssl=no ], [ $SSL_LIBS $SSL_CFLAGS ])
if test x"$have_openssl" = xyes; then
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="-I$ssl_prefix/lib $CPPFLAGS"
AC_CHECK_HEADERS(openssl/ssl.h, have_openssl_h=yes)
CPPFLAGS=$save_CPPFLAGS
if test x"$have_openssl_h" = xyes; then
have_openssl=yes
printf "openssl found in $ssl_prefix\n";
SSL_LIBS="-L$ssl_prefix/lib -lssl -lcrypto"
CPPFLAGS="-I$ssl_prefix/lib $CPPFLAGS"
SSL_CFLAGS="-DHAVE_SSL"
break
fi
fi
done
if test x${have_openssl} != xyes; then
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)
fi
])
dnl <openssl/>
-132
View File
@@ -1,132 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : adhoc.erl
%%% Author : Magnus Henoch <henoch@dtek.chalmers.se>
%%% Purpose : Provide helper functions for ad-hoc commands (XEP-0050)
%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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(adhoc).
-author('henoch@dtek.chalmers.se').
-export([parse_request/1,
produce_response/2,
produce_response/1]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl").
-include("adhoc.hrl").
%% Parse an ad-hoc request. Return either an adhoc_request record or
%% an {error, ErrorType} tuple.
parse_request(#iq{type = Type, ns = NS, payload = SubEl, lang = Lang}) ->
try
case {Type, NS} of
{set, ?NS_ADHOC} ->
?DEBUG("entering parse_request...", []),
Node = exmpp_xml:get_attribute_as_list(SubEl, <<"node">>, ""),
SessionID = exmpp_xml:get_attribute_as_list(SubEl, <<"sessionid">>, ""),
Action = exmpp_xml:get_attribute_as_list(SubEl, <<"action">>, ""),
XData = find_xdata_el(SubEl),
AllEls = exmpp_xml:get_child_elements(SubEl),
Others = case XData of
false ->
AllEls;
_ ->
lists:delete(XData, AllEls)
end,
#adhoc_request{lang = Lang,
node = Node,
sessionid = SessionID,
action = Action,
xdata = XData,
others = Others};
_ ->
{error, 'bad-request'}
end
catch
_ ->
{error, 'bad-request'}
end.
%% Borrowed from mod_vcard.erl
find_xdata_el(#xmlel{children = SubEls}) ->
find_xdata_el1(SubEls).
find_xdata_el1([]) ->
false;
find_xdata_el1([#xmlel{ns = ?NS_DATA_FORMS} = El | _Els]) ->
El;
find_xdata_el1([_ | Els]) ->
find_xdata_el1(Els).
%% Produce a <command/> node to use as response from an adhoc_response
%% record, filling in values for language, node and session id from
%% the request.
produce_response(#adhoc_request{lang = Lang,
node = Node,
sessionid = SessionID},
Response) ->
produce_response(Response#adhoc_response{lang = Lang,
node = Node,
sessionid = SessionID}).
%% Produce a <command/> node to use as response from an adhoc_response
%% record.
produce_response(#adhoc_response{lang = _Lang,
node = Node,
sessionid = ProvidedSessionID,
status = Status,
defaultaction = DefaultAction,
actions = Actions,
notes = Notes,
elements = Elements}) ->
SessionID = if is_list(ProvidedSessionID), ProvidedSessionID /= "" ->
ProvidedSessionID;
true ->
jlib:now_to_utc_string(now())
end,
case Actions of
[] ->
ActionsEls = [];
_ ->
case DefaultAction of
"" ->
ActionsElAttrs = [];
_ ->
ActionsElAttrs = [?XMLATTR(<<"execute">>, DefaultAction)]
end,
ActionsEls = [#xmlel{ns = ?NS_ADHOC, name = 'actions', attrs =
ActionsElAttrs, children =
[#xmlel{ns = ?NS_ADHOC, name = Action} || Action <- Actions]}]
end,
NotesEls = lists:map(fun({Type, Text}) ->
#xmlel{ns = ?NS_ADHOC, name = 'note', attrs =
[?XMLATTR(<<"type">>, Type)],
children = [#xmlcdata{cdata = list_to_binary(Text)}]}
end, Notes),
#xmlel{ns = ?NS_ADHOC, name = 'command', attrs =
[?XMLATTR(<<"sessionid">>, SessionID),
?XMLATTR(<<"node">>, Node),
?XMLATTR(<<"status">>, Status)], children =
ActionsEls ++ NotesEls ++ Elements}.
-36
View File
@@ -1,36 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%%----------------------------------------------------------------------
-record(adhoc_request, {lang,
node,
sessionid,
action,
xdata,
others}).
-record(adhoc_response, {lang,
node,
sessionid,
status,
defaultaction = "",
actions = [],
notes = [],
elements = []}).
-604
View File
@@ -1,604 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : cache_tab.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description : Caching key-value table
%%%
%%% Created : 29 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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(cache_tab).
-define(GEN_SERVER, gen_server).
-behaviour(?GEN_SERVER).
%% API
-export([start_link/4, new/2, delete/1, delete/3, lookup/3,
insert/4, info/2, tab2list/1, setopts/2,
dirty_lookup/3, dirty_insert/4, dirty_delete/3,
all/0, test/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-record(state, {tab = treap:empty(),
name,
size = 0,
owner,
max_size,
life_time,
warn,
hits = 0,
miss = 0,
procs_num,
cache_missed,
lru,
shrink_size}).
-define(PROCNAME, ?MODULE).
-define(CALL_TIMEOUT, 60000).
%% Defaults
-define(MAX_SIZE, 1000).
-define(WARN, true).
-define(CACHE_MISSED, true).
-define(LRU, true).
-define(LIFETIME, 600). %% 10 minutes
%%====================================================================
%% API
%%====================================================================
start_link(Proc, Tab, Opts, Owner) ->
?GEN_SERVER:start_link({local, Proc}, ?MODULE,
[Tab, Opts, get_proc_num(), Owner], []).
new(Tab, Opts) ->
Res = lists:flatmap(
fun(Proc) ->
Spec = {{Tab, Proc},
{?MODULE, start_link,
[Proc, Tab, Opts, self()]},
permanent,
brutal_kill,
worker,
[?MODULE]},
case supervisor:start_child(cache_tab_sup, Spec) of
{ok, _Pid} ->
[ok];
R ->
[R]
end
end, get_all_procs(Tab)),
case lists:filter(fun(ok) -> false; (_) -> true end, Res) of
[] ->
ok;
Err ->
{error, Err}
end.
delete(Tab) ->
lists:foreach(
fun(Proc) ->
supervisor:terminate_child(cache_tab_sup, {Tab, Proc}),
supervisor:delete_child(cache_tab_sup, {Tab, Proc})
end, get_all_procs(Tab)).
delete(Tab, Key, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {delete, Key, F}, ?CALL_TIMEOUT).
dirty_delete(Tab, Key, F) ->
F(),
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {cache_delete, Key}, ?CALL_TIMEOUT).
lookup(Tab, Key, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {lookup, Key, F}, ?CALL_TIMEOUT).
dirty_lookup(Tab, Key, F) ->
Proc = get_proc_by_hash(Tab, Key),
case ?GEN_SERVER:call(Proc, {cache_lookup, Key}, ?CALL_TIMEOUT) of
{ok, '$cached_mismatch'} ->
error;
{ok, Val} ->
{ok, Val};
_ ->
{Result, NewVal} = case F() of
{ok, Val} ->
{{ok, Val}, Val};
_ ->
{error, '$cached_mismatch'}
end,
?GEN_SERVER:call(
Proc, {cache_insert, Key, NewVal}, ?CALL_TIMEOUT),
Result
end.
insert(Tab, Key, Val, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {insert, Key, Val, F}, ?CALL_TIMEOUT).
dirty_insert(Tab, Key, Val, F) ->
F(),
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {cache_insert, Key, Val}, ?CALL_TIMEOUT).
info(Tab, Info) ->
case lists:map(
fun(Proc) ->
?GEN_SERVER:call(Proc, {info, Info}, ?CALL_TIMEOUT)
end, get_all_procs(Tab)) of
Res when Info == size ->
{ok, lists:sum(Res)};
Res when Info == all ->
{ok, Res};
Res when Info == ratio ->
{H, M} = lists:foldl(
fun({Hits, Miss}, {HitsAcc, MissAcc}) ->
{HitsAcc + Hits, MissAcc + Miss}
end, {0, 0}, Res),
{ok, [{hits, H}, {miss, M}]};
_ ->
{error, badarg}
end.
setopts(Tab, Opts) ->
lists:foreach(
fun(Proc) ->
?GEN_SERVER:call(Proc, {setopts, Opts}, ?CALL_TIMEOUT)
end, get_all_procs(Tab)).
tab2list(Tab) ->
lists:flatmap(
fun(Proc) ->
?GEN_SERVER:call(Proc, tab2list, ?CALL_TIMEOUT)
end, get_all_procs(Tab)).
all() ->
lists:usort(
[Tab || {{Tab, _}, _, _, _} <- supervisor:which_children(cache_tab_sup)]).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([Tab, Opts, N, Pid]) ->
State = #state{procs_num = N,
owner = Pid,
name = Tab},
{ok, do_setopts(State, Opts)}.
handle_call({lookup, Key, F}, _From, #state{tab = T} = State) ->
CleanPrio = clean_priority(State#state.life_time),
case treap:lookup(Key, T) of
{ok, Prio, Val} when (State#state.lru == true) or (Prio =< CleanPrio) ->
Hits = State#state.hits,
NewState = treap_update(Key, Val, State#state{hits = Hits + 1}),
case Val of
'$cached_mismatch' ->
{reply, error, NewState};
_ ->
{reply, {ok, Val}, NewState}
end;
_ ->
case catch F() of
{ok, Val} ->
Miss = State#state.miss,
NewState = treap_insert(Key, Val, State),
{reply, {ok, Val}, NewState#state{miss = Miss + 1}};
{'EXIT', Reason} ->
print_error(lookup, [Key], Reason, State),
{reply, error, State};
_ ->
Miss = State#state.miss,
NewState = State#state{miss = Miss + 1},
if State#state.cache_missed ->
{reply, error,
treap_insert(Key, '$cached_mismatch', NewState)};
true ->
{reply, error, NewState}
end
end
end;
handle_call({cache_lookup, Key}, _From, #state{tab = T} = State) ->
CleanPrio = clean_priority(State#state.life_time),
case treap:lookup(Key, T) of
{ok, Prio, Val} when (State#state.lru == true) or (Prio =< CleanPrio) ->
Hits = State#state.hits,
NewState = treap_update(Key, Val, State#state{hits = Hits + 1}),
{reply, {ok, Val}, NewState};
_ ->
Miss = State#state.miss,
NewState = State#state{miss = Miss + 1},
{reply, error, NewState}
end;
handle_call({insert, Key, Val, F}, _From, #state{tab = T} = State) ->
case treap:lookup(Key, T) of
{ok, _Prio, Val} ->
{reply, ok, treap_update(Key, Val, State)};
_ ->
case catch F() of
{'EXIT', Reason} ->
print_error(insert, [Key, Val], Reason, State),
{reply, ok, State};
_ ->
{reply, ok, treap_insert(Key, Val, State)}
end
end;
handle_call({cache_insert, _, '$cached_mismatch'}, _From,
#state{cache_missed = false} = State) ->
{reply, ok, State};
handle_call({cache_insert, Key, Val}, _From, State) ->
{reply, ok, treap_insert(Key, Val, State)};
handle_call({delete, Key, F}, _From, State) ->
NewState = treap_delete(Key, State),
case catch F() of
{'EXIT', Reason} ->
print_error(delete, [Key], Reason, State);
_ ->
ok
end,
{reply, ok, NewState};
handle_call({cache_delete, Key}, _From, State) ->
NewState = treap_delete(Key, State),
{reply, ok, NewState};
handle_call({info, Info}, _From, State) ->
Res = case Info of
size ->
State#state.size;
ratio ->
{State#state.hits, State#state.miss};
all ->
[{max_size, State#state.max_size},
{life_time, State#state.life_time},
{shrink_size, State#state.shrink_size},
{size, State#state.size},
{owner, State#state.owner},
{hits, State#state.hits},
{miss, State#state.miss},
{cache_missed, State#state.cache_missed},
{lru, State#state.lru},
{warn, State#state.warn}];
_ ->
badarg
end,
{reply, Res, State};
handle_call(tab2list, _From, #state{tab = T} = State) ->
Res = treap:fold(
fun({Key, _, Val}, Acc) ->
[{Key, Val}|Acc]
end, [], T),
{reply, Res, State};
handle_call({setopts, Opts}, _From, State) ->
{reply, ok, do_setopts(State, Opts)};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
do_setopts(#state{procs_num = N} = State, Opts) ->
MaxSize = case {proplists:get_value(max_size, Opts),
State#state.max_size} of
{MS, _} when is_integer(MS), MS > 0 ->
round(MS/N);
{unlimited, _} ->
unlimited;
{_, undefined} ->
round(?MAX_SIZE/N);
{_, MS} ->
MS
end,
LifeTime = case {proplists:get_value(life_time, Opts),
State#state.life_time} of
{LT, _} when is_integer(LT), LT > 0 ->
LT*1000*1000;
{unlimited, _} ->
unlimited;
{_, undefined} ->
?LIFETIME*1000*1000;
{_, LT} ->
LT
end,
ShrinkSize = case {proplists:get_value(shrink_size, Opts),
State#state.shrink_size} of
{SS, _} when is_integer(SS), SS > 0 ->
round(SS/N);
_ when is_integer(MaxSize) ->
round(MaxSize/2);
_ ->
unlimited
end,
Warn = case {proplists:get_value(warn, Opts),
State#state.warn} of
{true, _} ->
true;
{false, _} ->
false;
{_, undefined} ->
?WARN;
{_, W} ->
W
end,
CacheMissed = case proplists:get_value(
cache_missed, Opts, State#state.cache_missed) of
false ->
false;
true ->
true;
_ ->
?CACHE_MISSED
end,
LRU = case proplists:get_value(
lru, Opts, State#state.lru) of
false ->
false;
true ->
true;
_ ->
?LRU
end,
State#state{max_size = MaxSize,
warn = Warn,
life_time = LifeTime,
cache_missed = CacheMissed,
lru = LRU,
shrink_size = ShrinkSize}.
get_proc_num() ->
erlang:system_info(logical_processors).
get_proc_by_hash(Tab, Term) ->
N = erlang:phash2(Term, get_proc_num()) + 1,
get_proc(Tab, N).
get_proc(Tab, N) ->
list_to_atom(atom_to_list(?PROCNAME) ++ "_" ++
atom_to_list(Tab) ++ "_" ++ integer_to_list(N)).
get_all_procs(Tab) ->
[get_proc(Tab, N) || N <- lists:seq(1, get_proc_num())].
now_priority() ->
{MSec, Sec, USec} = now(),
-((MSec*1000000 + Sec)*1000000 + USec).
clean_priority(LifeTime) ->
if is_integer(LifeTime) ->
now_priority() + LifeTime;
true ->
unlimited
end.
treap_update(Key, Val, #state{tab = T, lru = LRU} = State) ->
if LRU ->
Priority = now_priority(),
NewT = treap:insert(Key, Priority, Val, T),
State#state{tab = NewT};
true ->
State
end.
treap_insert(Key, Val, State) ->
State1 = clean_treap(State),
#state{size = Size} = State2 = shrink_treap(State1),
T = State2#state.tab,
case treap:lookup(Key, T) of
{ok, _, Val} ->
treap_update(Key, Val, State2);
{ok, _, _} ->
NewT = treap:insert(Key, now_priority(), Val, T),
State2#state{tab = NewT};
_ ->
NewT = treap:insert(Key, now_priority(), Val, T),
State2#state{tab = NewT, size = Size+1}
end.
treap_delete(Key, #state{tab = T, size = Size} = State) ->
case treap:lookup(Key, T) of
{ok, _, _} ->
NewT = treap:delete(Key, T),
clean_treap(State#state{tab = NewT, size = Size-1});
_ ->
State
end.
clean_treap(#state{tab = T, size = Size, life_time = LifeTime} = State) ->
if is_integer(LifeTime) ->
Priority = now_priority(),
{Cleaned, NewT} = clean_treap(T, Priority + LifeTime, 0),
State#state{size = Size - Cleaned, tab = NewT};
true ->
State
end.
clean_treap(Treap, CleanPriority, N) ->
case treap:is_empty(Treap) of
true ->
{N, Treap};
false ->
{_Key, Priority, _Value} = treap:get_root(Treap),
if Priority > CleanPriority ->
clean_treap(treap:delete_root(Treap), CleanPriority, N+1);
true ->
{N, Treap}
end
end.
shrink_treap(#state{tab = T,
max_size = MaxSize,
shrink_size = ShrinkSize,
warn = Warn,
size = Size} = State) when Size >= MaxSize ->
if Warn ->
?WARNING_MSG("shrinking table:~n"
"** Table: ~p~n"
"** Processes Number: ~p~n"
"** Max Size: ~p items~n"
"** Shrink Size: ~p items~n"
"** Life Time: ~p microseconds~n"
"** Hits/Miss: ~p/~p~n"
"** Owner: ~p~n"
"** Cache Missed: ~p~n"
"** Instruction: you have to tune cacheing options"
" if this message repeats too frequently",
[State#state.name, State#state.procs_num,
MaxSize, ShrinkSize, State#state.life_time,
State#state.hits, State#state.miss,
State#state.owner, State#state.cache_missed]);
true ->
ok
end,
{Shrinked, NewT} = shrink_treap(T, ShrinkSize, 0),
State#state{tab = NewT, size = Size - Shrinked};
shrink_treap(State) ->
State.
shrink_treap(T, ShrinkSize, ShrinkSize) ->
{ShrinkSize, T};
shrink_treap(T, ShrinkSize, N) ->
case treap:is_empty(T) of
true ->
{N, T};
false ->
shrink_treap(treap:delete_root(T), ShrinkSize, N+1)
end.
print_error(Operation, Args, Reason, State) ->
?ERROR_MSG("callback failed:~n"
"** Tab: ~p~n"
"** Owner: ~p~n"
"** Operation: ~p~n"
"** Args: ~p~n"
"** Reason: ~p",
[State#state.name, State#state.owner,
Operation, Args, Reason]).
%%--------------------------------------------------------------------
%%% Tests
%%--------------------------------------------------------------------
-define(lookup, dirty_lookup).
-define(delete, dirty_delete).
-define(insert, dirty_insert).
%%-define(lookup, lookup).
%%-define(delete, delete).
%%-define(insert, insert).
test() ->
LifeTime = 2,
ok = new(test_tbl, [{life_time, LifeTime}, {max_size, unlimited}]),
check([]),
ok = ?insert(test_tbl, "key", "value", fun() -> ok end),
check([{"key", "value"}]),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", "value"}]),
io:format("** waiting for ~p seconds to check if LRU works fine...~n",
[LifeTime+1]),
timer:sleep(timer:seconds(LifeTime+1)),
ok = ?insert(test_tbl, "key1", "value1", fun() -> ok end),
check([{"key1", "value1"}]),
ok = ?delete(test_tbl, "key1", fun() -> ok end),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> {ok, "value"} end),
check([{"key", "value"}]),
ok = ?delete(test_tbl, "key", fun() -> ok end),
check([]),
%% io:format("** testing buggy callbacks...~n"),
%% delete(test_tbl, "key", fun() -> erlang:error(badarg) end),
%% insert(test_tbl, "key", "val", fun() -> erlang:error(badarg) end),
%% lookup(test_tbl, "key", fun() -> erlang:error(badarg) end),
check([]),
delete(test_tbl),
test1().
test1() ->
MaxSize = 10,
ok = new(test_tbl, [{max_size, MaxSize}, {shrink_size, 1}, {warn, false}]),
lists:foreach(
fun(N) ->
ok = ?insert(test_tbl, N, N, fun() -> ok end)
end, lists:seq(1, MaxSize*get_proc_num())),
{ok, MaxSize} = info(test_tbl, size),
delete(test_tbl),
test2().
test2() ->
LifeTime = 2,
ok = new(test_tbl, [{life_time, LifeTime},
{max_size, unlimited},
{lru, false}]),
check([]),
ok = ?insert(test_tbl, "key", "value", fun() -> ok end),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", "value"}]),
io:format("** waiting for ~p seconds to check if non-LRU works fine...~n",
[LifeTime+1]),
timer:sleep(timer:seconds(LifeTime+1)),
error = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", '$cached_mismatch'}]),
ok = ?insert(test_tbl, "key", "value1", fun() -> ok end),
check([{"key", "value1"}]),
delete(test_tbl),
io:format("** testing speed, this may take a while...~n"),
test3(1000),
test3(10000),
test3(100000),
test3(1000000).
test3(Iter) ->
ok = new(test_tbl, [{max_size, unlimited}, {life_time, unlimited}]),
L = lists:seq(1, Iter),
T1 = now(),
lists:foreach(
fun(N) ->
ok = ?insert(test_tbl, N, N, fun() -> ok end)
end, L),
io:format("** average insert (size = ~p): ~p usec~n",
[Iter, round(timer:now_diff(now(), T1)/Iter)]),
T2 = now(),
lists:foreach(
fun(N) ->
{ok, N} = ?lookup(test_tbl, N, fun() -> ok end)
end, L),
io:format("** average lookup (size = ~p): ~p usec~n",
[Iter, round(timer:now_diff(now(), T2)/Iter)]),
{ok, Iter} = info(test_tbl, size),
delete(test_tbl).
check(List) ->
Size = length(List),
{ok, Size} = info(test_tbl, size),
List = tab2list(test_tbl).
-53
View File
@@ -1,53 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : cache_tab_sup.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description : Cache tables supervisor
%%%
%%% Created : 30 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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(cache_tab_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
%% Supervisor callbacks
-export([init/1]).
-define(SERVER, ?MODULE).
%%====================================================================
%% API functions
%%====================================================================
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
%%====================================================================
%% Supervisor callbacks
%%====================================================================
init([]) ->
{ok, {{one_for_one,10,1}, []}}.
%%====================================================================
%% Internal functions
%%====================================================================
-1533
View File
File diff suppressed because it is too large Load Diff
-1693
View File
File diff suppressed because it is too large Load Diff
Vendored Executable
+5443
View File
File diff suppressed because it is too large Load Diff
+13 -134
View File
@@ -2,59 +2,36 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.53)
AC_INIT(ejabberd, m4_esyscmd([grep -o -E "\{vsn,.\".*\"\}" ejabberd.app | cut -d \" -f 2 | tr -d '\n']), [ejabberd@process-one.net], [ejabberd])
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -Wall"
fi
#locating erlang
AM_WITH_ERLANG
#locating iconv
AM_ICONV
#locating libexpat
AM_WITH_EXPAT
# 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(/)
# Checks for library functions.
AC_FUNC_MALLOC
AC_HEADER_STDC
AC_MOD_ENABLE(mod_muc, yes)
AC_MOD_ENABLE(mod_proxy65, yes)
AC_MOD_ENABLE(mod_pubsub, yes)
AC_MOD_ENABLE(mod_irc, yes)
AC_MOD_ENABLE(mod_muc, 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_ARG_ENABLE(hipe,
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
[case "${enableval}" in
yes) hipe=true ;;
no) hipe=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-hipe) ;;
esac],[hipe=false])
AC_SUBST(hipe)
AC_MOD_ENABLE(tls, yes)
AC_MOD_ENABLE(odbc, no)
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],
[case "${enableval}" in
yes) roster_gateway_workaround=true ;;
no) roster_gateway_workaround=false ;;
@@ -62,113 +39,15 @@ AC_ARG_ENABLE(roster_gateway_workaround,
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)])],
[case "${enableval}" in
yes) db_type=mssql ;;
no) db_type=generic ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
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)])],
[case "${enableval}" in
yes) transient_supervisors=true ;;
no) transient_supervisors=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-transient_supervisors) ;;
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)])],
[case "${enableval}" in
yes) full_xml=true ;;
no) full_xml=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-full-xml) ;;
esac],[full_xml=false])
AC_SUBST(full_xml)
AC_CONFIG_FILES([Makefile
$make_mod_irc
$make_mod_muc
$make_mod_pubsub
$make_mod_proxy65
$make_eldap
$make_pam
$make_web
stun/Makefile
stringprep/Makefile
$make_tls
$make_odbc
$make_ejabberd_zlib])
$make_odbc])
#openssl
AM_WITH_OPENSSL
# If ssl is kerberized it need krb5.h
# On RedHat and OpenBSD, krb5.h is in an unsual place:
KRB5_INCLUDE="`krb5-config --cflags 2>/dev/null`"
if test -n "$KRB5_INCLUDE" ; then
CPPFLAGS="$CPPFLAGS $KRB5_INCLUDE"
else
# For RedHat For BSD
for D in /usr/kerberos/include /usr/include/kerberos /usr/include/kerberosV
do
if test -d $D ; then
CPPFLAGS="$CPPFLAGS -I$D"
fi
done
fi
AC_CHECK_HEADER(krb5.h,,)
ENABLEUSER=""
AC_ARG_ENABLE(user,
[AS_HELP_STRING([--enable-user[[[[=USER]]]]], [allow this system user to start ejabberd (default: no)])],
[case "${enableval}" in
yes) ENABLEUSER=`whoami` ;;
no) ENABLEUSER="" ;;
*) ENABLEUSER=$enableval
esac],
[])
if test "$ENABLEUSER" != ""; then
echo "allow this system user to start ejabberd: $ENABLEUSER"
AC_SUBST([INSTALLUSER], [$ENABLEUSER])
fi
AC_CHECK_HEADER(openssl/md2.h, md2=true, md2=false)
AC_SUBST(md2)
AC_CANONICAL_SYSTEM
#AC_DEFINE_UNQUOTED(CPU_VENDOR_OS, "$target")
#AC_SUBST(target_os)
case "$target_os" in
*darwin10*)
echo "Target OS is 'Darwin10'"
AC_LANG(Erlang)
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([],[dnl
halt(case erlang:system_info(wordsize) of
8 -> 0; 4 -> 1 end)])],
[AC_MSG_NOTICE(found 64-bit Erlang)
CBIT=-m64],
[AC_MSG_NOTICE(found 32-bit Erlang)
CBIT=-m32])
;;
*)
echo "Target OS is '$target_os'"
CBIT=""
;;
esac
CFLAGS="$CFLAGS $CBIT"
LD_SHARED="$LD_SHARED $CBIT"
echo "CBIT is set to '$CBIT'"
AC_OUTPUT
echo
echo "********************** WARNING ! ************************"
echo "* ejabberd master is NOT ready for real usage yet, *"
echo "* because it is still in heavy development. *"
echo "* Don't use ejabberd master, it is still alpha code! *"
echo "* Please use ejabberd 2.1.x branch instead. *"
echo "*********************************************************"
echo
+27 -40
View File
@@ -1,31 +1,14 @@
%%%----------------------------------------------------------------------
%%% File : configure.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose :
%%% Created : 27 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
%%% Created : 27 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(configure).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/0]).
@@ -42,34 +25,38 @@ start() ->
end,
case Static of
true ->
ZlibDir = "ZLIB_DIR = c:\\sdk\\GnuWin32\n",
ZlibLib = "ZLIB_LIB = $(ZLIB_DIR)\\lib\\zlib.lib\n";
ExpatLib = "EXPAT_LIB = $(EXPAT_DIR)\\StaticLibs\\libexpatMT.lib\n",
ExpatFlag = "EXPAT_FLAG = -DXML_STATIC\n",
IconvDir = "ICONV_DIR = c:\\progra~1\\libiconv-1.9.1-static\n",
IconvLib = "ICONV_LIB = $(ICONV_DIR)\\lib\\iconv.lib\n";
false ->
ZlibDir = "ZLIB_DIR = c:\\sdk\\GnuWin32\n",
ZlibLib = "ZLIB_LIB = $(ZLIB_DIR)\\lib\\zlib.lib\n"
ExpatLib = "EXPAT_LIB = $(EXPAT_DIR)\\Libs\\libexpat.lib\n",
ExpatFlag = "",
IconvDir = "ICONV_DIR = c:\\progra~1\\libiconv-1.9.1\n",
IconvLib = "ICONV_LIB = $(ICONV_DIR)\\lib\\iconv.lib\n"
end,
EVersion = "ERLANG_VERSION = " ++ erlang:system_info(version) ++ "\n",
EIDirS = "EI_DIR = " ++ code:lib_dir(erl_interface) ++ "\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",
OpenSSLDir = "OPENSSL_DIR = c:\\sdk\\OpenSSL\n",
DBType = "DBTYPE = generic\n", %% 'generic' or 'mssql'
ExpatDir = "EXPAT_DIR = c:\\progra~1\\expat-1.95.7\n",
OpenSSLDir = "OPENSSL_DIR = c:\\progra~1\\OpenSSL\n",
SSLDir = "SSLDIR = " ++ code:lib_dir(ssl) ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir(stdlib) ++ "\n",
SSLDir = "SSLDIR = " ++ code:lib_dir("ssl") ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir("stdlib") ++ "\n",
file:write_file("Makefile.inc",
list_to_binary(EVersion ++
EIDirS ++
list_to_binary(EIDirS ++
RootDirS ++
Version ++
SSLDir ++
StdLibDir ++
OpenSSLDir ++
DBType ++
ZlibDir ++
ZlibLib)),
ExpatDir ++
ExpatLib ++
ExpatFlag ++
IconvDir ++
IconvLib)),
halt().
+68 -210
View File
@@ -1,245 +1,119 @@
%%%----------------------------------------------------------------------
%%% File : cyrsasl.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Cyrus SASL-like library
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(cyrsasl).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/0,
register_mechanism/3,
listmech/1,
server_new/8,
server_new/6,
server_start/3,
server_step/2]).
-include("cyrsasl.hrl").
-include("ejabberd.hrl").
%% @type saslmechanism() = {sasl_mechanism, Mechanism, Module, Require_Plain}
%% Mechanism = string()
%% Module = atom()
%% Require_Plain = bool().
%% Registry entry of a supported SASL mechanism.
-record(sasl_mechanism, {mechanism, module, require_plain_password}).
%% @type saslstate() = {sasl_state, Service, Myname, Realm, GetPassword, CheckPassword, CheckPasswordDigest, Mech_Mod, Mech_State}
%% Service = string()
%% Myname = string()
%% Realm = string()
%% GetPassword = function()
%% CheckPassword = function()
%% CheckPasswordDigest = any()
%% Mech_Mod = atom()
%% Mech_State = term().
%% State of this process.
-record(sasl_state, {service, myname,
mech_mod, mech_state, params}).
-record(sasl_state, {service, myname, realm,
get_password, check_password,
mech_mod, mech_state}).
-export([behaviour_info/1]).
%% @hidden
behaviour_info(callbacks) ->
[{mech_new, 1}, {mech_step, 2}];
behaviour_info(_Other) ->
[{mech_new, 2},
{mech_step, 2}];
behaviour_info(Other) ->
undefined.
%% @spec () -> ok
start() ->
ets:new(sasl_mechanism, [named_table,
public,
{keypos, #sasl_mechanism.mechanism}]),
cyrsasl_plain:start([]),
cyrsasl_digest:start([]),
cyrsasl_anonymous:start([]),
maybe_try_start_gssapi(),
ok.
maybe_try_start_gssapi() ->
case os:getenv("KRB5_KTNAME") of
false ->
ok;
_String ->
try_start_gssapi()
end.
try_start_gssapi() ->
case code:load_file(esasl) of
{module, _Module} ->
cyrsasl_gssapi:start([]);
{error, What} ->
?ERROR_MSG("Support for GSSAPI not started because esasl.beam was not found: ~p", [What])
end.
%% @spec (Mechanism, Module, Require_Plain) -> true
%% Mechanism = string()
%% Module = atom()
%% Require_Plain = bool()
register_mechanism(Mechanism, Module, RequirePlainPassword) ->
ets:insert(sasl_mechanism,
#sasl_mechanism{mechanism = Mechanism,
module = Module,
require_plain_password = RequirePlainPassword}).
% TODO use callbacks
%-include("ejabberd.hrl").
%-include("jlib.hrl").
%check_authzid(_State, Props) ->
% AuthzId = xml:get_attr_s(authzid, Props),
% case jlib:string_to_jid(AuthzId) of
% error ->
% {error, "invalid-authzid"};
% JID ->
% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
% {U, S, R} = jlib:short_prepd_jid(JID),
% case R of
% "" ->
% {error, "invalid-authzid"};
% _ ->
% case {LUser, ?MYNAME} of
% {U, S} ->
% ok;
% _ ->
% {error, "invalid-authzid"}
% end
% end
% end.
%% @spec (State, Props) -> ok | {error, 'not-authorized'}
%% State = saslstate()
%% Props = [{Key, Value}]
%% Key = atom()
%% Value = string()
check_credentials(_State, Props) ->
case proplists:get_value(username, Props) of
undefined ->
{error, 'not-authorized'};
User ->
case exmpp_stringprep:is_node(User) of
false -> {error, 'not-authorized'};
true -> ok
% TODO: use callbacks
-include("ejabberd.hrl").
-include("jlib.hrl").
check_authzid(State, Props) ->
AuthzId = xml:get_attr_s(authzid, Props),
case jlib:string_to_jid(AuthzId) of
error ->
{error, "invalid-authzid"};
JID ->
LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
{U, S, R} = jlib:jid_tolower(JID),
case R of
"" ->
{error, "invalid-authzid"};
_ ->
case {LUser, ?MYNAME} of
{U, S} ->
ok;
_ ->
{error, "invalid-authzid"}
end
end
end.
%% @spec (Host) -> [Mechanism]
%% Host = string()
%% Mechanism = string()
check_credentials(State, Props) ->
User = xml:get_attr_s(username, Props),
case jlib:nodeprep(User) of
error ->
{error, "not-authorized"};
"" ->
{error, "not-authorized"};
LUser ->
ok
end.
listmech(Host) ->
RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
ets:select(sasl_mechanism,
[{#sasl_mechanism{mechanism = '$1',
require_plain_password = '$2',
_ = '_'},
if
RequirePlainPassword ->
[{'==', '$2', false}];
true ->
[]
end,
['$1']}]).
Mechs = ets:select(sasl_mechanism,
[{#sasl_mechanism{mechanism = '$1',
require_plain_password = '$2',
_ = '_'},
if
RequirePlainPassword ->
[{'==', '$2', false}];
true ->
[]
end,
['$1']}]),
filter_anonymous(Host, Mechs).
%% @spec (Service, ServerFQDN, UserRealm, SecFlags, GetPassword, CheckPassword, CheckPasswordDigest, Socket) -> saslstate()
%% Service = string()
%% ServerFQDN = string()
%% UserRealm = string()
%% SecFlags = [term()]
%% GetPassword = function()
%% CheckPassword = function()
server_new(Service, ServerFQDN, UserRealm, _SecFlags,
GetPassword, CheckPassword, CheckPasswordDigest, Socket) ->
Params = #sasl_params{
host = ServerFQDN,
realm = UserRealm,
get_password = GetPassword,
check_password = CheckPassword,
check_password_digest= CheckPasswordDigest,
socket = Socket
},
server_new(Service, ServerFQDN, UserRealm, SecFlags,
GetPassword, CheckPassword) ->
#sasl_state{service = Service,
myname = ServerFQDN,
params = Params}.
%% @spec (State, Mech, ClientIn) -> Ok | Continue | Error
%% State = saslstate()
%% Mech = string()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = [{Key, Value}]
%% Key = atom()
%% Value = string()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Reason = term()
%% Username = string()
realm = UserRealm,
get_password = GetPassword,
check_password = CheckPassword}.
server_start(State, Mech, ClientIn) ->
case lists:member(Mech, listmech(State#sasl_state.myname)) of
true ->
case ets:lookup(sasl_mechanism, Mech) of
[#sasl_mechanism{module = Module}] ->
{ok, MechState} =
Module:mech_new(State#sasl_state.params),
server_step(State#sasl_state{mech_mod = Module,
mech_state = MechState},
ClientIn);
_ ->
{error, 'invalid-mechanism'}
end;
false ->
{error, 'invalid-mechanism'}
case ets:lookup(sasl_mechanism, Mech) of
[#sasl_mechanism{module = Module}] ->
{ok, MechState} = Module:mech_new(State#sasl_state.get_password,
State#sasl_state.check_password),
server_step(State#sasl_state{mech_mod = Module,
mech_state = MechState},
ClientIn);
_ ->
{error, "no-mechanism"}
end.
%% @spec (State, ClientIn) -> Ok | Continue | Error
%% State = saslstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = [{Key, Value}]
%% Key = atom()
%% Value = string()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Reason = term()
%% Username = string()
server_step(State, ClientIn) ->
Module = State#sasl_state.mech_mod,
MechState = State#sasl_state.mech_state,
@@ -254,23 +128,7 @@ server_step(State, ClientIn) ->
{continue, ServerOut, NewMechState} ->
{continue, ServerOut,
State#sasl_state{mech_state = NewMechState}};
{error, Error, Username} ->
{error, Error, Username};
{error, Error} ->
{error, Error}
end.
%% @spec (Host, Mechs) -> [Filtered_Mechs]
%% Host = string()
%% Mechs = [Mech]
%% Mech = string()
%% Filtered_Mechs = [Mech]
%%
%% @doc Remove the anonymous mechanism from the list if not enabled for
%% the given host.
filter_anonymous(Host, Mechs) ->
case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of
true -> Mechs;
false -> Mechs -- ["ANONYMOUS"]
end.
-15
View File
@@ -1,15 +0,0 @@
%% @type saslparams() = {sasl_params, Host, Realm, GetPassword, CheckPassword, CheckPasswordDigest}
%% Host = string()
%% Realm = string()
%% GetPassword = function()
%% CheckPassword = function()
%% CheckPasswordDigest = any().
%% Parameters for SASL.
-record(sasl_params, {
host,
realm,
get_password,
check_password,
check_password_digest,
socket}).
-76
View File
@@ -1,76 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : cyrsasl_anonymous.erl
%%% Author : Magnus Henoch <henoch@dtek.chalmers.se>
%%% Purpose : ANONYMOUS SASL mechanism
%%% See http://www.ietf.org/internet-drafts/draft-ietf-sasl-anon-05.txt
%%% Created : 23 Aug 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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(cyrsasl_anonymous).
-export([start/1, stop/0, mech_new/1, mech_step/2]).
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
%% @type mechstate() = {state, Server}
%% Server = string().
-record(state, {server}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) ->
cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false),
ok.
%% @spec () -> ok
stop() ->
ok.
mech_new(#sasl_params{host=Host}) ->
{ok, #state{server = Host}}.
%% @spec (State, ClientIn) -> Ok | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {auth_module, AuthModule}
%% Username = string()
%% AuthModule = ejabberd_auth_anonymous
%% Error = {error, 'not-authorized'}
mech_step(State, _ClientIn) ->
%% We generate a random username:
User = lists:concat([randoms:get_string() | tuple_to_list(now())]),
Server = State#state.server,
%% 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}]}
end.
+38 -237
View File
@@ -3,85 +3,32 @@
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : DIGEST-MD5 SASL mechanism
%%% Created : 11 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(cyrsasl_digest).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/1,
stop/0,
mech_new/1,
mech_new/2,
mech_step/2]).
-include("ejabberd.hrl").
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
%% @type mechstate() = {state, Step, Nonce, Username, AuthzId, GetPassword, CheckPassword, AuthModule, Host}
%% Step = 1 | 3 | 5
%% Nonce = string()
%% Username = string()
%% AuthzId = string()
%% GetPassword = function()
%% AuthModule = atom()
%% Host = string().
-record(state, {step, nonce, username, authzid, get_password, check_password, auth_module,
host}).
%% @spec (Opts) -> true
%% Opts = term()
-record(state, {step, nonce, username, authzid, get_password}).
start(_Opts) ->
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
%% @spec () -> ok
stop() ->
ok.
mech_new(#sasl_params{host=Host, get_password=GetPassword,
check_password_digest=CheckPasswordDigest}) ->
mech_new(GetPassword, _CheckPassword) ->
{ok, #state{step = 1,
nonce = randoms:get_string(),
host = Host,
get_password = GetPassword,
check_password = CheckPasswordDigest}}.
%% @spec (State, ClientIn) -> Ok | Continue | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
%% Username = string()
%% AuthzId = string()
%% AuthModule = atom()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = mechstate()
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
get_password = GetPassword}}.
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
{continue,
@@ -91,63 +38,43 @@ mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
case parse(ClientIn) of
bad ->
{error, 'bad-protocol'};
{error, "bad-protocol"};
KeyVals ->
DigestURI = proplists:get_value("digest-uri", KeyVals, ""),
UserName = proplists:get_value("username", KeyVals, ""),
case is_digesturi_valid(DigestURI, State#state.host) of
UserName = xml:get_attr_s("username", KeyVals),
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 = proplists:get_value("authzid", KeyVals, ""),
case (State#state.get_password)(UserName) of
{false, _} ->
{error, 'not-authorized', UserName};
{Passwd, AuthModule} ->
case (State#state.check_password)(UserName, "",
proplists:get_value("response", KeyVals, ""),
fun(PW) -> response(KeyVals, UserName, PW, Nonce, AuthzId,
"AUTHENTICATE") end) of
{true, _} ->
RspAuth = response(KeyVals,
UserName, Passwd,
Nonce, AuthzId, ""),
{continue,
"rspauth=" ++ RspAuth,
State#state{step = 5,
auth_module = AuthModule,
username = UserName,
authzid = AuthzId}};
false ->
{error, 'not-authorized', UserName};
{false, _} ->
{error, 'not-authorized', UserName}
end
{error, "not-authorized"};
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"}
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]),
{error, 'bad-protocol'}.
io:format("SASL DIGEST: A ~p B ~p", [A,B]),
{error, "bad-protocol"}.
%% @spec (S) -> [{Key, Value}] | bad
%% S = string()
%% Key = string()
%% Value = string()
parse(S) ->
parse1(S, "", []).
%% @hidden
parse1([$= | Cs], S, Ts) ->
parse2(Cs, lists:reverse(S), "", Ts);
parse1([$, | Cs], [], Ts) ->
@@ -161,28 +88,20 @@ parse1([], [], T) ->
parse1([], _S, _T) ->
bad.
%% @hidden
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.
%% @hidden
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([], _, _, _) ->
bad.
%% @hidden
parse4([$, | Cs], Key, Val, Ts) ->
parse1(Cs, "", [{Key, lists:reverse(Val)} | Ts]);
parse4([$\s | Cs], Key, Val, Ts) ->
@@ -193,46 +112,18 @@ parse4([], Key, Val, Ts) ->
parse1([], "", [{Key, lists:reverse(Val)} | Ts]).
%% @spec (DigestURICase, JabberHost) -> bool()
%% DigestURICase = string()
%% JabberHost = string()
%%
%% @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 = exmpp_stringprep:to_lower(DigestURICase),
case catch string:tokens(DigestURI, "/") of
["xmpp", Host] when Host == JabberHost ->
true;
["xmpp", _Host, ServName] when ServName == JabberHost ->
true;
_ ->
false
end.
%% @hidden
digit_to_xchar(D) when (D >= 0) and (D < 10) ->
D + 48;
digit_to_xchar(D) ->
D + 87.
%% @hidden
hex(S) ->
hex(S, []).
%% @hidden
hex([], Res) ->
lists:reverse(Res);
hex([N | Ns], Res) ->
@@ -240,35 +131,20 @@ hex([N | Ns], Res) ->
digit_to_xchar(N div 16) | Res]).
%% @spec (KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) -> string()
%% KeyVals = [{Key, Value}]
%% Key = string()
%% Value = string()
%% User = string()
%% Passwd = string()
%% Nonce = string()
%% AuthzId = nil() | string()
%% A2Prefix = string()
response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
Realm = proplists:get_value("realm", KeyVals, ""),
CNonce = proplists:get_value("cnonce", KeyVals, ""),
DigestURI = proplists:get_value("digest-uri", KeyVals, ""),
NC = proplists:get_value("nc", KeyVals, ""),
QOP = proplists:get_value("qop", KeyVals, ""),
%% handle non-fully latin-1 strings as specified
%% on RFC 2831 Section 2.1.2.1 (EJAB-476)
SUser = sanitize(User),
SPasswd = sanitize(Passwd),
SRealm = sanitize(Realm),
Realm = xml:get_attr_s("realm", KeyVals),
CNonce = xml:get_attr_s("cnonce", KeyVals),
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
NC = xml:get_attr_s("nc", KeyVals),
QOP = xml:get_attr_s("qop", KeyVals),
A1 = case AuthzId of
"" ->
binary_to_list(
crypto:md5(SUser ++ ":" ++ SRealm ++ ":" ++ SPasswd)) ++
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
":" ++ Nonce ++ ":" ++ CNonce;
_ ->
binary_to_list(
crypto:md5(SUser ++ ":" ++ SRealm ++ ":" ++ SPasswd)) ++
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
":" ++ Nonce ++ ":" ++ CNonce ++ ":" ++ AuthzId
end,
A2 = case QOP of
@@ -284,79 +160,4 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
hex(binary_to_list(crypto:md5(T))).
sanitize(V) ->
L = from_utf8(V),
case lists:all(fun is_latin1/1, L) of
true -> L;
false -> V
end.
%%%% copied from xmerl_ucs:from_utf8/1 and xmerl_ucs:is_latin1/1 , to not
%%%% require xmerl as a dependency only for this.
from_utf8(Bin) when is_binary(Bin) -> from_utf8(binary_to_list(Bin));
from_utf8(List) ->
case expand_utf8(List) of
{Result,0} -> Result;
{_Res,_NumBadChar} ->
exit({ucs,{bad_utf8_character_code}})
end.
%% expand_utf8([Byte]) -> {[UnicodeChar],NumberOfBadBytes}
%% Expand UTF8 byte sequences to ISO 10646/Unicode
%% charactes. Any illegal bytes are removed and the number of
%% bad bytes are returned.
%%
%% Reference:
%% RFC 3629: "UTF-8, a transformation format of ISO 10646".
expand_utf8(Str) ->
expand_utf8_1(Str, [], 0).
expand_utf8_1([C|Cs], Acc, Bad) when C < 16#80 ->
%% Plain Ascii character.
expand_utf8_1(Cs, [C|Acc], Bad);
expand_utf8_1([C1,C2|Cs], Acc, Bad) when C1 band 16#E0 =:= 16#C0,
C2 band 16#C0 =:= 16#80 ->
case ((C1 band 16#1F) bsl 6) bor (C2 band 16#3F) of
C when 16#80 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([C1,C2,C3|Cs], Acc, Bad) when C1 band 16#F0 =:= 16#E0,
C2 band 16#C0 =:= 16#80,
C3 band 16#C0 =:= 16#80 ->
case ((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor
(C3 band 16#3F) of
C when 16#800 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([C1,C2,C3,C4|Cs], Acc, Bad) when C1 band 16#F8 =:= 16#F0,
C2 band 16#C0 =:= 16#80,
C3 band 16#C0 =:= 16#80,
C4 band 16#C0 =:= 16#80 ->
case ((((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor
(C3 band 16#3F)) bsl 6) bor (C4 band 16#3F) of
C when 16#10000 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([_|Cs], Acc, Bad) ->
%% Ignore bad character.
expand_utf8_1(Cs, Acc, Bad+1);
expand_utf8_1([], Acc, Bad) -> {lists:reverse(Acc),Bad}.
%%% Test for legitimate Latin-1 code
is_latin1(Ch) when is_integer(Ch), Ch >= 0, Ch =< 255 -> true;
is_latin1(_) -> false.
-164
View File
@@ -1,164 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : cyrsasl_gssapi.erl
%%% Author : Mikael Magnusson <mikma@users.sourceforge.net>
%%% Purpose : GSSAPI SASL mechanism
%%% Created : 1 June 2007 by Mikael Magnusson <mikma@users.sourceforge.net>
%%%----------------------------------------------------------------------
%%%
%%% Copyright (C) 2007-2009 Mikael Magnusson <mikma@users.sourceforge.net>
%%%
%%% Permission is hereby granted, free of charge, to any person
%%% obtaining a copy of this software and associated documentation
%%% files (the "Software"), to deal in the Software without
%%% restriction, including without limitation the rights to use, copy,
%%% modify, merge, publish, distribute, sublicense, and/or sell copies
%%% of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be
%%% included in all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
%%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
%%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
%%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%
%%%
%%% configuration options:
%%% {sasl_realm, "<Kerberos realm>"}.
%%%
%%% environment variables:
%%% KRB5_KTNAME
%%%
-module(cyrsasl_gssapi).
-author('mikma@users.sourceforge.net').
-export([start/1,
stop/0,
mech_new/1,
mech_step/2]).
-include("ejabberd.hrl").
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
-define(SERVER, ?MODULE).
-define(SERVICE, "xmpp").
-record(state, {sasl,
needsmore=true,
step=0,
host,
realm,
authid,
authzid,
authrealm,
error}).
start(_Opts) ->
ChildSpec =
{?SERVER,
{esasl, start_link, [{local, ?SERVER}]},
transient,
1000,
worker,
[esasl]},
case supervisor:start_child(ejabberd_sup, ChildSpec) of
{ok, _Pid} ->
cyrsasl:register_mechanism("GSSAPI", ?MODULE, false);
{error, Error} = E ->
?ERROR_MSG("esasl failed: ~p", [Error]),
E
end.
stop() ->
catch esasl:stop(?SERVER),
supervisor:terminate_child(ejabberd_sup, ?SERVER),
supervisor:delete_child(ejabberd_sup, ?SERVER).
mech_new(#sasl_params{host=Host, realm=Realm, socket=Socket}) ->
case ejabberd_socket:gethostname(Socket) of
{ok, FQDN} ->
?DEBUG("mech_new ~p ~p ~p~n", [Host, Realm, FQDN]),
case esasl:server_start(?SERVER, "GSSAPI", ?SERVICE, FQDN) of
{ok, Sasl} ->
{ok, #state{sasl=Sasl,host=Host,realm=Realm}};
{error, {gsasl_error, Error}} ->
{ok, Str} = esasl:str_error(?SERVER, Error),
?DEBUG("esasl error: ~p", [Str]),
{ok, #state{needsmore=error,error="internal-server-error"}};
{error, Error} ->
?DEBUG("esasl error: ~p", [Error]),
{ok, #state{needsmore=error,error="internal-server-error"}}
end;
{error, Error} ->
?DEBUG("gethostname error: ~p", [Error]),
{ok, #state{needsmore=error,error="internal-server-error"}}
end.
mech_step(State, ClientIn) when is_list(ClientIn) ->
catch do_step(State, ClientIn).
do_step(#state{needsmore=error,error=Error}=_State, _) ->
{error, Error};
do_step(#state{needsmore=false}=State, _) ->
check_user(State);
do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
?DEBUG("mech_step~n", []),
case esasl:step(Sasl, list_to_binary(ClientIn)) of
{ok, RspAuth} ->
?DEBUG("ok~n", []),
{ok, Display_name} = esasl:property_get(Sasl, gssapi_display_name),
{ok, Authzid} = esasl:property_get(Sasl, authzid),
{Authid, [$@ | Auth_realm]} =
lists:splitwith(fun(E)->E =/= $@ end, Display_name),
State1 = State#state{authid=Authid,
authzid=Authzid,
authrealm=Auth_realm},
handle_step_ok(State1, binary_to_list(RspAuth));
{needsmore, RspAuth} ->
?DEBUG("needsmore~n", []),
if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) ->
{error, "not-authorized"};
true ->
{continue, binary_to_list(RspAuth),
State#state{step=Step+1}}
end;
{error, _} ->
{error, "not-authorized"}
end.
handle_step_ok(State, []) ->
check_user(State);
handle_step_ok(#state{step=Step}=State, RspAuth) ->
?DEBUG("continue~n", []),
{continue, RspAuth, State#state{needsmore=false,step=Step+1}}.
check_user(#state{authid=Authid,authzid=Authzid,
authrealm=Auth_realm,host=Host,realm=Realm}) ->
if Realm =/= Auth_realm ->
?DEBUG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
throw({error, "not-authorized"});
true ->
ok
end,
case ejabberd_auth:is_user_exists(Authid, Host) of
false ->
?DEBUG("bad user ~p~n",[Authid]),
throw({error, "not-authorized"});
true ->
ok
end,
?DEBUG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]),
{ok, [{username, Authid}, {authzid, Authzid}]}.
+13 -84
View File
@@ -1,112 +1,48 @@
%%%----------------------------------------------------------------------
%%% File : cyrsasl_plain.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : PLAIN SASL mechanism
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(cyrsasl_plain).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/1, stop/0, mech_new/1, mech_step/2, parse/1]).
-include("cyrsasl.hrl").
-export([start/1, stop/0, mech_new/2, mech_step/2, parse/1]).
-behaviour(cyrsasl).
%% @type mechstate() = {state, CheckPassword}
%% CheckPassword = function().
-record(state, {check_password}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) ->
cyrsasl:register_mechanism("PLAIN", ?MODULE, false),
ok.
%% @spec () -> ok
stop() ->
ok.
mech_new(#sasl_params{check_password = CheckPassword}) ->
mech_new(_GetPassword, CheckPassword) ->
{ok, #state{check_password = CheckPassword}}.
%% @spec (State, ClientIn) -> Ok | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
%% Username = string()
%% AuthzId = string()
%% AuthModule = atom()
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
mech_step(State, ClientIn) ->
case prepare(ClientIn) of
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}]};
{false, ReasonAuthFail} when is_list(ReasonAuthFail) ->
{error, ReasonAuthFail, User};
true ->
{ok, [{username, User}, {authzid, AuthzId}]};
_ ->
{error, 'not-authorized', User}
{error, "bad-auth"}
end;
_ ->
{error, 'bad-protocol'}
{error, "bad-protocol"}
end.
prepare(ClientIn) ->
case parse(ClientIn) of
[[], UserMaybeDomain, Password] ->
case parse_domain(UserMaybeDomain) of
%% <NUL>login@domain<NUL>pwd
[User, _Domain] ->
[UserMaybeDomain, User, Password];
%% <NUL>login<NUL>pwd
[User] ->
["", User, Password]
end;
%% login@domain<NUL>login<NUL>pwd
[AuthzId, User, Password] ->
[AuthzId, User, Password];
_ ->
error
end.
%% @hidden
parse(S) ->
parse1(S, "", []).
%% @hidden
parse1([0 | Cs], S, T) ->
parse1(Cs, "", [lists:reverse(S) | T]);
parse1([C | Cs], S, T) ->
@@ -117,12 +53,5 @@ parse1([], S, T) ->
lists:reverse([lists:reverse(S) | T]).
parse_domain(S) ->
parse_domain1(S, "", []).
parse_domain1([$@ | Cs], S, T) ->
parse_domain1(Cs, "", [lists:reverse(S) | T]);
parse_domain1([C | Cs], S, T) ->
parse_domain1(Cs, [C | S], T);
parse_domain1([], S, T) ->
lists:reverse([lists:reverse(S) | T]).
-268
View File
@@ -1,268 +0,0 @@
%% Copyright (c) 2007
%% Mats Cronqvist <mats.cronqvist@ericsson.com>
%% Chris Newcombe <chris.newcombe@gmail.com>
%% Jacob Vorreuter <jacob.vorreuter@gmail.com>
%%
%% Permission is hereby granted, free of charge, to any person
%% obtaining a copy of this software and associated documentation
%% files (the "Software"), to deal in the Software without
%% restriction, including without limitation the rights to use,
%% copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the
%% Software is furnished to do so, subject to the following
%% conditions:
%%
%% The above copyright notice and this permission notice shall be
%% included in all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
%% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
%% OTHER DEALINGS IN THE SOFTWARE.
%%%-------------------------------------------------------------------
%%% File : dynamic_compile.erl
%%% Description :
%%% Authors : Mats Cronqvist <mats.cronqvist@ericsson.com>
%%% Chris Newcombe <chris.newcombe@gmail.com>
%%% Jacob Vorreuter <jacob.vorreuter@gmail.com>
%%% TODO :
%%% - add support for limit include-file depth (and prevent circular references)
%%% prevent circular macro expansion set FILE correctly when -module() is found
%%% -include_lib support $ENVVAR in include filenames
%%% substitute-stringize (??MACRO)
%%% -undef/-ifdef/-ifndef/-else/-endif
%%% -file(File, Line)
%%%-------------------------------------------------------------------
-module(dynamic_compile).
%% API
-export([from_string/1, from_string/2]).
-import(lists, [reverse/1, keyreplace/4]).
%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function:
%% Description:
%% Returns a binary that can be used with
%% code:load_binary(Module, ModuleFilenameForInternalRecords, Binary).
%%--------------------------------------------------------------------
from_string(CodeStr) ->
from_string(CodeStr, []).
% takes Options as for compile:forms/2
from_string(CodeStr, CompileFormsOptions) ->
%% Initialise the macro dictionary with the default predefined macros,
%% (adapted from epp.erl:predef_macros/1
Filename = "compiled_from_string",
%%Machine = list_to_atom(erlang:system_info(machine)),
Ms0 = dict:new(),
% Ms1 = dict:store('FILE', {[], "compiled_from_string"}, Ms0),
% Ms2 = dict:store('LINE', {[], 1}, Ms1), % actually we might add special code for this
% Ms3 = dict:store('MODULE', {[], undefined}, Ms2),
% Ms4 = dict:store('MODULE_STRING', {[], undefined}, Ms3),
% Ms5 = dict:store('MACHINE', {[], Machine}, Ms4),
% InitMD = dict:store(Machine, {[], true}, Ms5),
InitMD = Ms0,
%% From the docs for compile:forms:
%% When encountering an -include or -include_dir directive, the compiler searches for header files in the following directories:
%% 1. ".", the current working directory of the file server;
%% 2. the base name of the compiled file;
%% 3. the directories specified using the i option. The directory specified last is searched first.
%% In this case, #2 is meaningless.
IncludeSearchPath = ["." | reverse([Dir || {i, Dir} <- CompileFormsOptions])],
{RevForms, _OutMacroDict} = scan_and_parse(CodeStr, Filename, 1, [], InitMD, IncludeSearchPath),
Forms = reverse(RevForms),
%% note: 'binary' is forced as an implicit option, whether it is provided or not.
case compile:forms(Forms, CompileFormsOptions) of
{ok, ModuleName, CompiledCodeBinary} when is_binary(CompiledCodeBinary) ->
{ModuleName, CompiledCodeBinary};
{ok, ModuleName, CompiledCodeBinary, []} when is_binary(CompiledCodeBinary) -> % empty warnings list
{ModuleName, CompiledCodeBinary};
{ok, _ModuleName, _CompiledCodeBinary, Warnings} ->
throw({?MODULE, warnings, Warnings});
Other ->
throw({?MODULE, compile_forms, Other})
end.
%%====================================================================
%% Internal functions
%%====================================================================
%%% Code from Mats Cronqvist
%%% See http://www.erlang.org/pipermail/erlang-questions/2007-March/025507.html
%%%## 'scan_and_parse'
%%%
%%% basically we call the OTP scanner and parser (erl_scan and
%%% erl_parse) line-by-line, but check each scanned line for (or
%%% definitions of) macros before parsing.
%% returns {ReverseForms, FinalMacroDict}
scan_and_parse([], _CurrFilename, _CurrLine, RevForms, MacroDict, _IncludeSearchPath) ->
{RevForms, MacroDict};
scan_and_parse(RemainingText, CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath) ->
case scanner(RemainingText, CurrLine, MacroDict) of
{tokens, NLine, NRemainingText, Toks} ->
{ok, Form} = erl_parse:parse_form(Toks),
scan_and_parse(NRemainingText, CurrFilename, NLine, [Form | RevForms], MacroDict, IncludeSearchPath);
{macro, NLine, NRemainingText, NMacroDict} ->
scan_and_parse(NRemainingText, CurrFilename, NLine, RevForms,NMacroDict, IncludeSearchPath);
{include, NLine, NRemainingText, IncludeFilename} ->
IncludeFileRemainingTextents = read_include_file(IncludeFilename, IncludeSearchPath),
%%io:format("include file ~p contents: ~n~p~nRemainingText = ~p~n", [IncludeFilename,IncludeFileRemainingTextents, RemainingText]),
%% Modify the FILE macro to reflect the filename
%%IncludeMacroDict = dict:store('FILE', {[],IncludeFilename}, MacroDict),
IncludeMacroDict = MacroDict,
%% Process the header file (inc. any nested header files)
{RevIncludeForms, IncludedMacroDict} = scan_and_parse(IncludeFileRemainingTextents, IncludeFilename, 1, [], IncludeMacroDict, IncludeSearchPath),
%io:format("include file results = ~p~n", [R]),
%% Restore the FILE macro in the NEW MacroDict (so we keep any macros defined in the header file)
%%NMacroDict = dict:store('FILE', {[],CurrFilename}, IncludedMacroDict),
NMacroDict = IncludedMacroDict,
%% Continue with the original file
scan_and_parse(NRemainingText, CurrFilename, NLine, RevIncludeForms ++ RevForms, NMacroDict, IncludeSearchPath);
done ->
scan_and_parse([], CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath)
end.
scanner(Text, Line, MacroDict) ->
case erl_scan:tokens([],Text,Line) of
{done, {ok,Toks,NLine}, LeftOverChars} ->
case pre_proc(Toks, MacroDict) of
{tokens, NToks} -> {tokens, NLine, LeftOverChars, NToks};
{macro, NMacroDict} -> {macro, NLine, LeftOverChars, NMacroDict};
{include, Filename} -> {include, NLine, LeftOverChars, Filename}
end;
{more, _Continuation} ->
%% This is supposed to mean "term is not yet complete" (i.e. a '.' has
%% not been reached yet).
%% However, for some bizarre reason we also get this if there is a comment after the final '.' in a file.
%% So we check to see if Text only consists of comments.
case is_only_comments(Text) of
true ->
done;
false ->
throw({incomplete_term, Text, Line})
end
end.
is_only_comments(Text) -> is_only_comments(Text, not_in_comment).
is_only_comments([], _) -> true;
is_only_comments([$ |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
is_only_comments([$\t |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
is_only_comments([$\n |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
is_only_comments([$% |T], not_in_comment) -> is_only_comments(T, in_comment); % found start of a comment
is_only_comments(_, not_in_comment) -> false;
% found any significant char NOT in a comment
is_only_comments([$\n |T], in_comment) -> is_only_comments(T, not_in_comment); % found end of a comment
is_only_comments([_ |T], in_comment) -> is_only_comments(T, in_comment). % skipping over in-comment chars
%%%## 'pre-proc'
%%%
%%% have to implement a subset of the pre-processor, since epp insists
%%% on running on a file.
%%% only handles 2 cases;
%% -define(MACRO, something).
%% -define(MACRO(VAR1,VARN),{stuff,VAR1,more,stuff,VARN,extra,stuff}).
pre_proc([{'-',_},{atom,_,define},{'(',_},{_,_,Name}|DefToks],MacroDict) ->
false = dict:is_key(Name, MacroDict),
case DefToks of
[{',',_} | Macro] ->
{macro, dict:store(Name, {[], macro_body_def(Macro, [])}, MacroDict)};
[{'(',_} | Macro] ->
{macro, dict:store(Name, macro_params_body_def(Macro, []), MacroDict)}
end;
pre_proc([{'-',_}, {atom,_,include}, {'(',_}, {string,_,Filename}, {')',_}, {dot,_}], _MacroDict) ->
{include, Filename};
pre_proc(Toks,MacroDict) ->
{tokens, subst_macros(Toks, MacroDict)}.
macro_params_body_def([{')',_},{',',_} | Toks], RevParams) ->
{reverse(RevParams), macro_body_def(Toks, [])};
macro_params_body_def([{var,_,Param} | Toks], RevParams) ->
macro_params_body_def(Toks, [Param | RevParams]);
macro_params_body_def([{',',_}, {var,_,Param} | Toks], RevParams) ->
macro_params_body_def(Toks, [Param | RevParams]).
macro_body_def([{')',_}, {dot,_}], RevMacroBodyToks) ->
reverse(RevMacroBodyToks);
macro_body_def([Tok|Toks], RevMacroBodyToks) ->
macro_body_def(Toks, [Tok | RevMacroBodyToks]).
subst_macros(Toks, MacroDict) ->
reverse(subst_macros_rev(Toks, MacroDict, [])).
%% returns a reversed list of tokes
subst_macros_rev([{'?',_}, {_,LineNum,'LINE'} | Toks], MacroDict, RevOutToks) ->
%% special-case for ?LINE, to avoid creating a new MacroDict for every line in the source file
subst_macros_rev(Toks, MacroDict, [{integer,LineNum,LineNum}] ++ RevOutToks);
subst_macros_rev([{'?',_}, {_,_,Name}, {'(',_} = Paren | Toks], MacroDict, RevOutToks) ->
case dict:fetch(Name, MacroDict) of
{[], MacroValue} ->
%% This macro does not have any vars, so ignore the fact that the invocation is followed by "(...stuff"
%% Recursively expand any macro calls inside this macro's value
%% TODO: avoid infinite expansion due to circular references (even indirect ones)
RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
subst_macros_rev([Paren|Toks], MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
ParamsAndBody ->
%% This macro does have vars.
%% Collect all of the passe arguments, in an ordered list
{NToks, Arguments} = subst_macros_get_args(Toks, []),
%% Expand the varibles
ExpandedParamsToks = subst_macros_subst_args_for_vars(ParamsAndBody, Arguments),
%% Recursively expand any macro calls inside this macro's value
%% TODO: avoid infinite expansion due to circular references (even indirect ones)
RevExpandedOtherMacrosToks = subst_macros_rev(ExpandedParamsToks, MacroDict, []),
subst_macros_rev(NToks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks)
end;
subst_macros_rev([{'?',_}, {_,_,Name} | Toks], MacroDict, RevOutToks) ->
%% This macro invocation does not have arguments.
%% Therefore the definition should not have parameters
{[], MacroValue} = dict:fetch(Name, MacroDict),
%% Recursively expand any macro calls inside this macro's value
%% TODO: avoid infinite expansion due to circular references (even indirect ones)
RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
subst_macros_rev(Toks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
subst_macros_rev([Tok|Toks], MacroDict, RevOutToks) ->
subst_macros_rev(Toks, MacroDict, [Tok|RevOutToks]);
subst_macros_rev([], _MacroDict, RevOutToks) -> RevOutToks.
subst_macros_get_args([{')',_} | Toks], RevArgs) ->
{Toks, reverse(RevArgs)};
subst_macros_get_args([{',',_}, {var,_,ArgName} | Toks], RevArgs) ->
subst_macros_get_args(Toks, [ArgName| RevArgs]);
subst_macros_get_args([{var,_,ArgName} | Toks], RevArgs) ->
subst_macros_get_args(Toks, [ArgName | RevArgs]).
subst_macros_subst_args_for_vars({[], BodyToks}, []) ->
BodyToks;
subst_macros_subst_args_for_vars({[Param | Params], BodyToks}, [Arg|Args]) ->
NBodyToks = keyreplace(Param, 3, BodyToks, {var,1,Arg}),
subst_macros_subst_args_for_vars({Params, NBodyToks}, Args).
read_include_file(Filename, IncludeSearchPath) ->
case file:path_open(IncludeSearchPath, Filename, [read, raw, binary]) of
{ok, IoDevice, FullName} ->
{ok, Data} = file:read(IoDevice, filelib:file_size(FullName)),
file:close(IoDevice),
binary_to_list(Data);
{error, Reason} ->
throw({failed_to_read_include_file, Reason, Filename, IncludeSearchPath})
end.
+12 -80
View File
@@ -1,125 +1,56 @@
% $Id$
{application, ejabberd,
[{description, "ejabberd"},
{vsn, "3.0.0-alpha-x"},
{vsn, "1.0.0"},
{modules, [acl,
adhoc,
configure,
cyrsasl_anonymous,
cyrsasl,
cyrsasl_digest,
cyrsasl_plain,
ejabberd_admin,
ejabberd_app,
ejabberd_auth_anonymous,
ejabberd_auth,
ejabberd_auth_external,
ejabberd_auth_ldap,
ejabberd_auth_pam,
ejabberd_auth_storage,
ejabberd,
ejabberd_app,
ejabberd_auth,
ejabberd_c2s,
ejabberd_c2s_config,
ejabberd_config,
ejabberd_ctl,
ejabberd_frontend_socket,
ejabberd_hooks,
ejabberd_http,
ejabberd_http_bind,
ejabberd_http_poll,
ejabberd_listener,
ejabberd_local,
ejabberd_logger_h,
ejabberd_loglevel,
ejabberd_node_groups,
ejabberd_rdbms,
ejabberd_receiver,
ejabberd_local,
ejabberd_router,
ejabberd_router_multicast,
ejabberd_s2s,
ejabberd_s2s_in,
ejabberd_s2s_out,
ejabberd_service,
ejabberd_sm,
ejabberd_socket,
ejabberd_sup,
ejabberd_system_monitor,
ejabberd_tmp_sup,
ejabberd_update,
ejabberd_web_admin,
ejabberd_web,
ejabberd_zlib,
ejd2odbc,
eldap,
eldap_filter,
eldap_pool,
eldap_utils,
'ELDAPv3',
extauth,
gen_iq_handler,
gen_mod,
gen_pubsub_node,
gen_pubsub_nodetree,
idna,
jd2ejd,
jlib,
mod_adhoc,
mod_announce,
mod_caps,
mod_configure2,
mod_configure,
mod_disco,
mod_echo,
mod_http_bind,
mod_http_fileserver,
mod_last,
mod_muc,
mod_muc_log,
mod_muc_room,
mod_offline,
mod_privacy,
mod_private,
mod_proxy65,
mod_proxy65_lib,
mod_proxy65_service,
mod_proxy65_sm,
mod_proxy65_stream,
mod_pubsub,
mod_register,
mod_roster,
mod_service_log,
mod_shared_roster,
mod_stats,
mod_time,
mod_vcard,
mod_vcard_ldap,
mod_version,
node_buddy,
node_club,
node_default,
node_dispatch,
node_pep,
node_private,
node_public,
nodetree_default,
nodetree_virtual,
p1_fsm,
p1_mnesia,
p1_prof,
randoms,
sha,
shaper,
stringprep,
stringprep_sup,
tls,
translate,
xml,
'XmppAddr'
xml_stream
]},
{registered, [ejabberd,
ejabberd_sup,
ejabberd_auth,
ejabberd_router,
ejabberd_router_multicast,
ejabberd_sm,
ejabberd_s2s,
ejabberd_local,
@@ -132,6 +63,7 @@
ejabberd_mod_roster,
ejabberd_mod_echo,
ejabberd_mod_pubsub,
ejabberd_mod_irc,
ejabberd_mod_muc,
ejabberd_offline,
random_generator
@@ -141,7 +73,7 @@
{mod, {ejabberd_app, []}}]}.
%% Local Variables:
%% mode: erlang
%% End:
%% vim: set filetype=erlang tabstop=8:
% Local Variables:
% mode: erlang
% End:
+122 -593
View File
@@ -1,637 +1,166 @@
%%%
%%% ejabberd configuration file
%%%
%%%'
% $Id$
%%% The parameters used in this configuration file are explained in more detail
%%% in the ejabberd Installation and Operation Guide.
%%% Please consult the Guide in case of doubts, it is included with
%%% your copy of ejabberd, and is also available online at
%%% http://www.process-one.net/en/ejabberd/docs/
%override_acls.
%%% This configuration file contains Erlang terms.
%%% In case you want to understand the syntax, here are the concepts:
%%%
%%% - The character to comment a line is %
%%%
%%% - Each term ends in a dot, for example:
%%% override_global.
%%%
%%% - A tuple has a fixed definition, its elements are
%%% enclosed in {}, and separated with commas:
%%% {loglevel, 4}.
%%%
%%% - A list can have as many elements as you want,
%%% and is enclosed in [], for example:
%%% [http_poll, web_admin, tls]
%%%
%%% - A keyword of ejabberd is a word in lowercase.
%%% Strings are enclosed in "" and can contain spaces, dots, ...
%%% {language, "en"}.
%%% {ldap_rootdn, "dc=example,dc=com"}.
%%%
%%% - This term includes a tuple, a keyword, a list, and two strings:
%%% {hosts, ["jabber.example.net", "im.example.com"]}.
%%%
% Users that have admin access. Add line like one of the following after you
% will be successfully registered on server to get admin access:
%{acl, admin, {user, "aleksey"}}.
%{acl, admin, {user, "ermine"}}.
%%%. =======================
%%%' OVERRIDE STORED OPTIONS
% Blocked users:
%{acl, blocked, {user, "test"}}.
%%
%% Override the old values stored in the database.
%%
%%
%% Override global options (shared by all ejabberd nodes in a cluster).
%%
%%override_global.
%%
%% Override local options (specific for this particular ejabberd node).
%%
%%override_local.
%%
%% Remove the Access Control Lists before new ones are added.
%%
%%override_acls.
%%%. =========
%%%' DEBUGGING
%%
%% loglevel: Verbosity of log files generated by ejabberd.
%% 0: No ejabberd log at all (not recommended)
%% 1: Critical
%% 2: Error
%% 3: Warning
%% 4: Info
%% 5: Debug
%%
{loglevel, 4}.
%%
%% watchdog_admins: Only useful for developers: if an ejabberd process
%% consumes a lot of memory, send live notifications to these XMPP
%% accounts.
%%
%%{watchdog_admins, ["bob@example.com"]}.
%%%. =====================
%%%' CLUSTER CONFIGURATION
%% clusterid: the integer id of the cluster of nodes this node will
%% belong to.
{clusterid, 1}.
%%%. ================
%%%' SERVED HOSTNAMES
%%
%% hosts: Domains served by ejabberd.
%% You can define one or several, for example:
%% {hosts, ["localhost", "example.net", "example.com", "example.org"]}.
%%
%% Additional hosts will be discovered from the 'hosts' database table
%% configured for the first host.
{hosts, ["localhost"]}.
%%
%% route_subdomains: Delegate subdomains to other XMPP servers.
%% For example, if this ejabberd serves example.org and you want
%% to allow communication with an XMPP server called im.example.org.
%%
%%{route_subdomains, s2s}.
%%%. ===============
%%%' LISTENING PORTS
%%
%% listen: The ports ejabberd will listen on, which service each is handled
%% by and what options to start it with.
%%
{listen,
[
{5222, ejabberd_c2s, [
%%
%% If TLS is compiled in and you installed a SSL
%% certificate, specify the full path to the
%% file and uncomment this line:
%%
%%{certfile, "/path/to/ssl.pem"}, starttls,
{access, c2s},
{shaper, c2s_shaper},
{max_stanza_size, 65536}
]},
%%
%% To enable the old SSL connection method on port 5223:
%%
%%{5223, ejabberd_c2s, [
%% {access, c2s},
%% {shaper, c2s_shaper},
%% {certfile, "/path/to/ssl.pem"}, tls,
%% {max_stanza_size, 65536}
%% ]},
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
%%
%% ejabberd_service: Interact with external components (transports, ...)
%%
%%{8888, ejabberd_service, [
%% {access, all},
%% {shaper_rule, fast},
%% {ip, {127, 0, 0, 1}},
%% {hosts, ["icq.example.org", "sms.example.org"],
%% [{password, "secret"}]
%% }
%% ]},
%%
%% ejabberd_stun: Handles STUN Binding requests
%%
%%{{3478, udp}, ejabberd_stun, []},
{5280, ejabberd_http, [
%%{request_handlers,
%% [
%% {["pub", "archive"], mod_http_fileserver}
%% ]},
captcha,
http_bind,
http_poll,
%%register,
web_admin
]}
]}.
%%
%% s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections.
%% Allowed values are: false optional required required_trusted
%% You must specify a certificate file.
%%
%%{s2s_use_starttls, optional}.
%%
%% s2s_certfile: Specify a certificate file.
%%
%%{s2s_certfile, "/path/to/ssl.pem"}.
%%
%% domain_certfile: Specify a different certificate for each served hostname.
%%
%%{domain_certfile, "example.org", "/path/to/example_org.pem"}.
%%{domain_certfile, "example.com", "/path/to/example_com.pem"}.
%%
%% S2S whitelist or blacklist
%%
%% Default s2s policy for undefined hosts.
%%
%%{s2s_default_policy, allow}.
%%
%% Allow or deny communication with specific servers.
%%
%%{{s2s_host, "goodhost.org"}, allow}.
%%{{s2s_host, "badhost.org"}, deny}.
%%
%% Outgoing S2S options
%%
%% Preferred address families (which to try first) and connect timeout
%% in milliseconds.
%%
%%{outgoing_s2s_options, [ipv4, ipv6], 10000}.
%%%. ==============
%%%' AUTHENTICATION
%%
%% auth_method: Method used to authenticate the users.
%% The default method is the internal Mnesia database storage.
%% If you want to use a different method,
%% comment those lines and enable the desired lines later.
%%
{auth_method, storage}.
{auth_storage, mnesia}.
%%
%% Authentication using ODBC
%% Remember to setup a database in the next section.
%%
%%{auth_method, storage}.
%%{auth_storage, odbc}.
%%
%% Authentication using external script
%% Make sure the script is executable by ejabberd.
%%
%%{auth_method, external}.
%%{extauth_program, "/path/to/authentication/script"}.
%%
%% Authentication using PAM
%%
%%{auth_method, pam}.
%%{pam_service, "pamservicename"}.
%%
%% Authentication using LDAP
%%
%%{auth_method, ldap}.
%%
%% List of LDAP servers:
%%{ldap_servers, ["localhost"]}.
%%
%% Encryption of connection to LDAP servers:
%%{ldap_encrypt, none}.
%%{ldap_encrypt, tls}.
%%
%% Port to connect to on LDAP servers:
%%{ldap_port, 389}.
%%{ldap_port, 636}.
%%
%% LDAP manager:
%%{ldap_rootdn, "dc=example,dc=com"}.
%%
%% Password of LDAP manager:
%%{ldap_password, "******"}.
%%
%% Search base of LDAP directory:
%%{ldap_base, "dc=example,dc=com"}.
%%
%% LDAP attribute that holds user ID:
%%{ldap_uids, [{"mail", "%u@mail.example.org"}]}.
%%
%% LDAP filter:
%%{ldap_filter, "(objectClass=shadowAccount)"}.
%%
%% Anonymous login support:
%% auth_method: anonymous
%% anonymous_protocol: sasl_anon | login_anon | both
%% allow_multiple_connections: true | false
%%
%%{host_config, "public.example.org", [{auth_method, anonymous},
%% {allow_multiple_connections, false},
%% {anonymous_protocol, sasl_anon}]}.
%%
%% To use both anonymous and internal authentication:
%%
%%{host_config, "public.example.org", [{auth_method, [internal, anonymous]}]}.
%%%. ==============
%%%' DATABASE SETUP
%% ejabberd by default uses the internal Mnesia database,
%% so you do not necessarily need this section.
%% This section provides configuration examples in case
%% you want to use other database backends.
%% Please consult the ejabberd Guide for details on database creation.
%% Template host ODBC configuration.
%% The host specified here will be used by default for all discovered vhosts.
%% The actual ODBC server configuration must be provided in a host_config directive.
{odbc_server, {host, "localhost"}}.
{host_config, "localhost",
[
%%
%% MySQL server:
%%
%%{odbc_server, {mysql, "server", "database", "username", "password"}}
%%
%% If you want to specify the port:
%%{odbc_server, {mysql, "server", 1234, "database", "username", "password"}}
%%
%% PostgreSQL server:
%%
%%{odbc_server, {pgsql, "server", "database", "username", "password"}}
%%
%% If you want to specify the port:
%%{odbc_server, {pgsql, "server", 1234, "database", "username", "password"}}
%%
]
}.
%% If you use PostgreSQL, have a large database, and need a
%% faster but inexact replacement for "select count(*) from users"
%%
%%{pgsql_users_number_estimate, true}.
%%
%% ODBC compatible or MSSQL server:
%%
%%{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
%%
%% Number of connections to open to the database for each virtual host
%%
%%{odbc_pool_size, 10}.
%%
%% Interval to make a dummy SQL request to keep the connections to the
%% database alive. Specify in seconds: for example 28800 means 8 hours
%%
%%{odbc_keepalive_interval, undefined}.
%%%. ===============
%%%' TRAFFIC SHAPERS
%%
%% The "normal" shaper limits traffic speed to 1000 B/s
%%
{shaper, normal, {maxrate, 1000}}.
%%
%% The "fast" shaper limits traffic speed to 50000 B/s
%%
{shaper, fast, {maxrate, 50000}}.
%%
%% This option specifies the maximum number of elements in the queue
%% of the FSM. Refer to the documentation for details.
%%
{max_fsm_queue, 1000}.
%%%. ====================
%%%' ACCESS CONTROL LISTS
%%
%% The 'admin' ACL grants administrative privileges to XMPP accounts.
%% You can put here as many accounts as you want.
%%
%%{acl, admin, {user, "aleksey", "localhost"}}.
%%{acl, admin, {user, "ermine", "example.org"}}.
%%
%% Blocked users
%%
%%{acl, blocked, {user, "baduser", "example.org"}}.
%%{acl, blocked, {user, "test"}}.
%%
%% Local users: don't modify this line.
%%
% Local users:
{acl, local, {user_regexp, ""}}.
%%
%% More examples of ACLs
%%
%%{acl, jabberorg, {server, "jabber.org"}}.
%%{acl, aleksey, {user, "aleksey", "jabber.ru"}}.
%%{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"}}
%% ]
%%}.
% Another examples of ACLs:
%{acl, jabberorg, {server, "jabber.org"}}.
%{acl, aleksey, {user, "aleksey", "jabber.ru"}}.
%{acl, test, {user_regexp, "^test"}}.
%{acl, test, {user_glob, "test*"}}.
%%%. ============
%%%' ACCESS RULES
% Only admins can use configuration interface:
{access, configure, [{allow, admin}]}.
%% Maximum number of simultaneous sessions allowed for a single user:
{access, max_user_sessions, [{10, all}]}.
% Every username can be registered via in-band registration:
% You could replace {allow, all} with {deny, all} to prevent user from using
% in-band registration
{access, register, [{allow, all}]}.
%% Maximum number of offline messages that users can have:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
% After successful registration user will get message with following subject
% and body:
{welcome_message,
{"Welcome!",
"Welcome to Jabber Service. "
"For information about Jabber visit http://jabber.org"}}.
% Replace them with 'none' if you don't want to send such message:
%{welcome_message, none}.
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
% List of people who will get notifications about registered users
%{registration_watchers, ["admin1@localhost",
% "admin2@localhost"]}.
%% Only non-blocked users can use c2s connections:
% Only admins can send announcement messages:
{access, announce, [{allow, admin}]}.
% Only non-blocked users can use c2s connections:
{access, c2s, [{deny, blocked},
{allow, all}]}.
%% For C2S connections, all users except admins use the "normal" shaper
% Set shaper with name "normal" to limit traffic speed to 1000B/s
{shaper, normal, {maxrate, 1000}}.
% Set shaper with name "fast" to limit traffic speed to 50000B/s
{shaper, fast, {maxrate, 50000}}.
% For all users except admins used "normal" shaper
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
%% All S2S connections use the "fast" shaper
% For all S2S connections used "fast" shaper
{access, s2s_shaper, [{fast, all}]}.
%% Only admins can send announcement messages:
{access, announce, [{allow, admin}]}.
%% Only admins can use the configuration interface:
{access, configure, [{allow, admin}]}.
%% Admins of this server are also admins of the MUC service:
% Admins of this server are also admins of MUC service:
{access, muc_admin, [{allow, admin}]}.
%% Only accounts of the local ejabberd server can create rooms:
{access, muc_create, [{allow, local}]}.
%% All users are allowed to use the MUC service:
% All users are allowed to use MUC service:
{access, muc, [{allow, all}]}.
%% Only accounts on the local ejabberd server can create Pubsub nodes:
{access, pubsub_createnode, [{allow, local}]}.
%% In-band registration allows registration of any possible username.
%% To disable in-band registration, replace 'allow' with 'deny'.
{access, register, [{allow, all}]}.
%% By default the frequency of account registrations from the same IP
%% is limited to 1 account every 10 minutes. To disable, specify: 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}]}
%% ]
%%}.
% This rule allows access only for local users:
{access, local, [{allow, local}]}.
%%%. =======
%%%' CAPTCHA
% Authentification method. If you want to use internal user base, then use
% this line:
{auth_method, internal}.
%%
%% Full path to a script that generates the image.
%%
%%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
% For LDAP authentification use these lines instead of above one:
%{auth_method, ldap}.
%{ldap_servers, ["localhost"]}. % List of LDAP servers
%{ldap_uidattr, "uid"}. % LDAP attribute that holds user ID
%{ldap_base, "dc=example,dc=com"}. % Search base of LDAP directory
%{ldap_rootdn, "dc=example,dc=com"}. % LDAP manager
%{ldap_password, "******"}. % Password to LDAP manager
%% Host for the URL and port where ejabberd listens for CAPTCHA requests.
%%
%%{captcha_host, "example.org:5280"}.
% For authentification via external script use the following:
%{auth_method, external}.
%{extauth_program, "/path/to/authentification/script"}.
% For authentification via ODBC use the following:
%{auth_method, odbc}.
%{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
%%%. ================
%%%' DEFAULT LANGUAGE
% Host name:
{hosts, ["localhost"]}.
%%
%% language: Default language used for server messages.
%%
% Default language for server messages
{language, "en"}.
%%
%% Set a different default language in a virtual host.
%%
%%{host_config, "localhost",
%% [{language, "ru"}]
%%}.
% Listened ports:
{listen,
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper},
starttls, {certfile, "./ssl.pem"}]},
{5223, ejabberd_c2s, [{access, c2s},
tls, {certfile, "./ssl.pem"}]},
% Use these two lines instead if TLS support is not compiled
%{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
%{5223, ejabberd_c2s, [{access, c2s}, ssl, {certfile, "./ssl.pem"}]},
{5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]},
{5280, ejabberd_http, [http_poll, web_admin]},
{8888, ejabberd_service, [{access, all},
{hosts, ["icq.localhost", "sms.localhost"],
[{password, "secret"}]}]}
]}.
%%%. ================
%%%' INSTANCE MODULES
% Use STARTTLS+Dialback for S2S connections
{s2s_use_starttls, true}.
{s2s_certfile, "./ssl.pem"}.
%{domain_certfile, "example.org", "./example_org.pem"}.
%{domain_certfile, "example.com", "./example_com.pem"}.
%%
%% Modules to start for every virtual host.
%%
%% Note: One copy of each module will be started for each host.
%%
% If SRV lookup fails, then port 5269 is used to communicate with remote server
{outgoing_s2s_port, 5269}.
% Used modules:
{modules,
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
{mod_caps, []}, % 1 proc/host
{mod_configure,[]}, % requires mod_adhoc
{mod_disco, []},
%%{mod_echo, [{host, "echo.localhost"}]},
{mod_http_bind, []},
%%{mod_http_fileserver, [
%% {docroot, "/var/www"},
%% {accesslog, "/var/log/ejabberd/access.log"}
%% ]},
{mod_last, []},
{mod_muc, [ % 1 proc/host
{host, "conference.@HOST@"},
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
%%{mod_muc_log,[]},
%%{mod_multicast,[]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_ping, []},
%%{mod_pres_counter,[{count, 5}, {interval, 60}]},
{mod_privacy, []},
{mod_private, []},
%%{mod_proxy65,[]},
%%{mod_pubsub, [ % 1 proc/host
%% {access_createnode, pubsub_createnode},
%% {ignore_pep_from_offline, true}, % reduces resource comsumption, but XEP incompliant
%% %%{ignore_pep_from_offline, false}, % XEP compliant, but increases resource comsumption
%% {last_item_cache, false},
%% {plugins, ["flat", "pep"]} % pep requires mod_caps
%% ]},
{mod_register, [
%%
%% Protect In-Band account registrations with CAPTCHA.
%%
%%{captcha_protected, true},
%%
%% Set the minimum informational entropy for passwords.
%%
%%{password_strength, 32},
%%
%% After successful registration, the user receives
%% a message with this subject and body.
%%
{welcome_message, {"Welcome!",
"Hi.\nWelcome to this XMPP server."}},
%%
%% When a user registers, send a notification to
%% these XMPP accounts.
%%
%%{registration_watchers, ["admin1@example.org"]},
%%
%% Only clients in the server machine can register accounts
%%
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
%%
%% Local c2s or remote s2s users cannot register accounts
%%
%%{access_from, deny},
{access, register}
]},
%%{mod_register_web, [
%%
%% When a user registers, send a notification to
%% these XMPP accounts.
%%
%%{registration_watchers, ["admin1@example.org"]}
%% ]},
{mod_roster, []},
%%{mod_service_log,[]},
{mod_shared_roster,[]},
{mod_stats, []},
{mod_time, []},
{mod_vcard, []}, % 1 proc/host
{mod_version, []}
{mod_register, [{access, register}]},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},
{mod_configure2, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_announce, [{access, announce}]},
{mod_echo, [{host, "echo.localhost"}]},
{mod_private, []},
{mod_irc, []},
% Default options for mod_muc:
% host: "conference." ++ ?MYNAME
% access: all
% access_create: all
% access_admin: none (only room creator has owner privileges)
{mod_muc, [{access, muc},
{access_create, muc},
{access_admin, muc_admin}]},
{mod_pubsub, []},
{mod_time, []},
{mod_last, []},
{mod_version, []}
]}.
%%%.
%%%' STATIC MODULES
%%
%% Modules to start for the global virtual host ("localhost").
%%
%% The functionality of these modules will be enabled in all ejabberd
%% virtual hosts without consuming more resources.
%%
{static_modules,
[
]}.
%%%.
%%%' HOST SPECIFIC MODULES
%%
%% Enable modules with custom options in a specific virtual host
%%
%%{host_config, "localhost",
%% [{{add, modules},
%% [
%% {mod_echo, [{host, "mirror.localhost"}]}
%% ]
%% }
%% ]}.
%%%.
%%%'
%%% Local Variables:
%%% mode: erlang
%%% End:
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker:
% Local Variables:
% mode: erlang
% End:
+8 -84
View File
@@ -1,49 +1,24 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : ejabberd wrapper: start / stop
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(ejabberd).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/0, stop/0,
get_so_path/0,
get_bin_path/0,
get_pid_file/0,
is_my_host/1,
normalize_host/1
]).
-include("ejabberd.hrl").
get_so_path/0]).
start() ->
%%ejabberd_cover:start(),
application:start(ejabberd).
stop() ->
application:stop(ejabberd).
%%ejabberd_cover:stop().
get_so_path() ->
case os:getenv("EJABBERD_SO_PATH") of
@@ -57,54 +32,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.
is_my_host([$* | _]) ->
false;
is_my_host(Host) ->
case ejabberd_config:get_local_option({Host, host}) of
undefined ->
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
case ejabberd_config:get_local_option({WCHost, host}) of
undefined ->
false;
_ ->
true
end;
_ ->
true
end.
normalize_host(global) ->
global;
normalize_host(Host) ->
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
case ejabberd_config:get_local_option({WCHost, host}) of
undefined ->
Host;
_ ->
WCHost
end.
%% @spec () -> false | string()
get_pid_file() ->
case os:getenv("EJABBERD_PID_PATH") of
false ->
false;
"" ->
false;
Path ->
Path
end.
+27 -49
View File
@@ -1,63 +1,41 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% File : ejabberd.hrl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
%%% Created : 17 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
%% 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(VERSION, "1.0.0").
-define(IS_MY_HOST(Host), ejabberd:is_my_host(Host)).
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)). %% Deprecated
%-define(ejabberd_debug, true).
%-define(DBGFSM, true).
-ifdef(ejabberd_debug).
-define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
[self(),?MODULE,?LINE]++Args)).
-else.
-define(DEBUG(F,A),[]).
-endif.
-define(ERROR_MSG(Format, Args),
error_logger:error_msg("E(~p:~p:~p): "++Format++"~n",
[self(),?MODULE,?LINE]++Args)).
-define(INFO_MSG(Format, Args),
error_logger:info_msg("I(~p:~p:~p): "++Format++"~n",
[self(),?MODULE,?LINE]++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(EJABBERD_URI, "http://www.process-one.net/en/ejabberd/").
-define(S2STIMEOUT, 600000).
-define(PRIVACY_SUPPORT, true).
%%-define(DBGFSM, true).
%% ---------------------------------
%% 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)).
-define(INFO_MSG(Format, Args),
ejabberd_logger:info_msg(?MODULE,?LINE,Format, Args)).
-define(WARNING_MSG(Format, Args),
ejabberd_logger:warning_msg(?MODULE,?LINE,Format, Args)).
-define(ERROR_MSG(Format, Args),
ejabberd_logger:error_msg(?MODULE,?LINE,Format, Args)).
-define(CRITICAL_MSG(Format, Args),
ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
-46
View File
@@ -1,46 +0,0 @@
#! /bin/sh
set -o errexit
set -o nounset
DIR=@ctlscriptpath@
CTL="$DIR"/ejabberdctl
USER=@installuser@
test -x "$CTL" || {
echo "ERROR: ejabberd not found: $DIR"
exit 1
}
grep ^"$USER": /etc/passwd >/dev/null || {
echo "ERROR: System user not found: $USER"
exit 2
}
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
case "$1" in
start)
test -x "$CTL" || exit 0
echo "Starting ejabberd..."
su - $USER -c "$CTL start"
su - $USER -c "$CTL started"
echo "done."
;;
stop)
test -x "$CTL" || exit 0
echo "Stopping ejabberd..."
su - $USER -c "$CTL stop"
su - $USER -c "$CTL stopped"
echo "done."
;;
force-reload|restart)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload}"
exit 1
esac
exit 0
-603
View File
@@ -1,603 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : ejabberd_admin.erl
%%% Author : Mickael Remond <mremond@process-one.net>
%%% Purpose : Administrative functions and commands
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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_admin).
-author('mickael.remond@process-one.net').
-export([start/0, stop/0,
%% Server
status/0, reopen_log/0,
stop_kindly/2, send_service_message_all_mucs/2,
%% Erlang
update_list/0, update/1,
%% Accounts
register/3, unregister/2,
registered_users/1,
%% For debugging gen_storage
get_last_info/0,
get_last_info/2,
%% Migration jabberd1.4
import_file/1, import_dir/1,
%% Purge DB
delete_expired_messages/0, delete_old_messages/1,
%% Mnesia
set_master/1,
backup_mnesia/1, restore_mnesia/1,
dump_mnesia/1, dump_table/2, load_mnesia/1,
install_fallback_mnesia/1,
dump_to_textfile/1, dump_to_textfile/2,
mnesia_change_nodename/4,
restore/1 % Still used by some modules
]).
-include("ejabberd.hrl").
-include("ejabberd_commands.hrl").
start() ->
ejabberd_commands:register_commands(commands()).
stop() ->
ejabberd_commands:unregister_commands(commands()).
%%%
%%% ejabberd commands
%%%
commands() ->
[
%% The commands status, stop and restart are implemented also in ejabberd_ctl
%% They are defined here so that other interfaces can use them too
#ejabberd_commands{name = status, tags = [server],
desc = "Get status of the ejabberd server",
module = ?MODULE, function = status,
args = [], result = {res, restuple}},
#ejabberd_commands{name = stop, tags = [server],
desc = "Stop ejabberd gracefully",
module = init, function = stop,
args = [], result = {res, rescode}},
#ejabberd_commands{name = restart, tags = [server],
desc = "Restart ejabberd gracefully",
module = init, function = restart,
args = [], result = {res, rescode}},
#ejabberd_commands{name = reopen_log, tags = [logs, server],
desc = "Reopen the log files",
module = ?MODULE, function = reopen_log,
args = [], result = {res, rescode}},
#ejabberd_commands{name = stop_kindly, tags = [server],
desc = "Inform users and rooms, wait, and stop the server",
module = ?MODULE, function = stop_kindly,
args = [{delay, integer}, {announcement, string}],
result = {res, rescode}},
#ejabberd_commands{name = get_loglevel, tags = [logs, server],
desc = "Get the current loglevel",
module = ejabberd_loglevel, function = get,
args = [],
result = {leveltuple, {tuple, [{levelnumber, integer},
{levelatom, atom},
{leveldesc, string}
]}}},
#ejabberd_commands{name = update_list, tags = [server],
desc = "List modified modules that can be updated",
module = ?MODULE, function = update_list,
args = [],
result = {modules, {list, {module, string}}}},
#ejabberd_commands{name = update, tags = [server],
desc = "Update the given module, or use the keyword: all",
module = ?MODULE, function = update,
args = [{module, string}],
result = {res, restuple}},
#ejabberd_commands{name = register, tags = [accounts],
desc = "Register a user",
module = ?MODULE, function = register,
args = [{user, string}, {host, string}, {password, string}],
result = {res, restuple}},
#ejabberd_commands{name = unregister, tags = [accounts],
desc = "Unregister a user",
module = ?MODULE, function = unregister,
args = [{user, string}, {host, string}],
result = {res, restuple}},
#ejabberd_commands{name = registered_users, tags = [accounts],
desc = "List all registered users in HOST",
module = ?MODULE, function = registered_users,
args = [{host, string}],
result = {users, {list, {username, string}}}},
#ejabberd_commands{name = gli, tags = [accounts],
desc = "Get information about last access of an account",
module = ?MODULE, function = get_last_info,
args = [],
result = {lastinfo, {tuple, [{timestamp, integer},
{status, string}
]}}},
#ejabberd_commands{name = get_last_info, tags = [accounts],
desc = "Get information about last access of an account",
module = ?MODULE, function = get_last_info,
args = [{user, string}, {host, string}],
result = {lastinfo, {tuple, [{timestamp, integer},
{status, string}
]}}},
#ejabberd_commands{name = import_file, tags = [mnesia],
desc = "Import user data from jabberd14 spool file",
module = ?MODULE, function = import_file,
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = import_dir, tags = [mnesia],
desc = "Import users data from jabberd14 spool dir",
module = ?MODULE, function = import_dir,
args = [{file, string}],
result = {res, restuple}},
#ejabberd_commands{name = import_piefxis, tags = [mnesia],
desc = "Import users data from a PIEFXIS file (XEP-0227)",
module = ejabberd_piefxis, function = import_file,
args = [{file, string}], result = {res, rescode}},
#ejabberd_commands{name = export_piefxis, tags = [mnesia],
desc = "Export data of all users in the server to PIEFXIS files (XEP-0227)",
module = ejabberd_piefxis, function = export_server,
args = [{dir, string}], result = {res, rescode}},
#ejabberd_commands{name = export_piefxis_host, tags = [mnesia],
desc = "Export data of users in a host to PIEFXIS files (XEP-0227)",
module = ejabberd_piefxis, function = export_host,
args = [{dir, string}, {host, string}], result = {res, rescode}},
#ejabberd_commands{name = delete_expired_messages, tags = [purge],
desc = "Delete expired offline messages from database",
module = ?MODULE, function = delete_expired_messages,
args = [], result = {res, rescode}},
#ejabberd_commands{name = delete_old_messages, tags = [purge],
desc = "Delete offline messages older than DAYS",
module = ?MODULE, function = delete_old_messages,
args = [{days, integer}], result = {res, rescode}},
#ejabberd_commands{name = set_master, tags = [mnesia],
desc = "Set master node of the clustered Mnesia tables",
longdesc = "If you provide as nodename \"self\", this "
"node will be set as its own master.",
module = ?MODULE, function = set_master,
args = [{nodename, string}], result = {res, restuple}},
#ejabberd_commands{name = mnesia_change_nodename, tags = [mnesia],
desc = "Change the erlang node name in a backup file",
module = ?MODULE, function = mnesia_change_nodename,
args = [{oldnodename, string}, {newnodename, string},
{oldbackup, string}, {newbackup, string}],
result = {res, restuple}},
#ejabberd_commands{name = backup, tags = [mnesia],
desc = "Store the database to backup file",
module = ?MODULE, function = backup_mnesia,
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = restore, tags = [mnesia],
desc = "Restore the database from backup file",
module = ?MODULE, function = restore_mnesia,
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = dump, tags = [mnesia],
desc = "Dump the database to text file",
module = ?MODULE, function = dump_mnesia,
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = dump_table, tags = [mnesia],
desc = "Dump a table to text file",
module = ?MODULE, function = dump_table,
args = [{file, string}, {table, string}], result = {res, restuple}},
#ejabberd_commands{name = load, tags = [mnesia],
desc = "Restore the database from text file",
module = ?MODULE, function = load_mnesia,
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = install_fallback, tags = [mnesia],
desc = "Install the database from a fallback file",
module = ?MODULE, function = install_fallback_mnesia,
args = [{file, string}], result = {res, restuple}}
].
%%%
%%% Server management
%%%
status() ->
{InternalStatus, ProvidedStatus} = init:get_status(),
String1 = io_lib:format("The node ~p is ~p. Status: ~p",
[node(), InternalStatus, ProvidedStatus]),
{Is_running, String2} =
case lists:keysearch(ejabberd, 1, application:which_applications()) of
false ->
{ejabberd_not_running, "ejabberd is not running in that node."};
{value, {_, _, Version}} ->
{ok, io_lib:format("ejabberd ~s is running in that node", [Version])}
end,
{Is_running, String1 ++ String2}.
reopen_log() ->
ejabberd_hooks:run(reopen_log_hook, []),
%% TODO: Use the Reopen log API for logger_h ?
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,
ok.
%% 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.
%%%
%%% Stop Kindly
%%%
stop_kindly(DelaySeconds, AnnouncementText) ->
Subject = io_lib:format("Server stop in ~p seconds!", [DelaySeconds]),
WaitingDesc = io_lib:format("Waiting ~p seconds", [DelaySeconds]),
Steps = [{"Stopping ejabberd port listeners",
ejabberd_listener, stop_listeners, []},
{"Sending announcement to connected users",
mod_announce, send_announcement_to_all,
[?MYNAME, Subject, AnnouncementText]},
{"Sending service message to MUC rooms",
ejabberd_admin, send_service_message_all_mucs,
[Subject, AnnouncementText]},
{WaitingDesc, timer, sleep, [DelaySeconds * 1000]},
{"Stopping ejabberd", application, stop, [ejabberd]},
{"Stopping Mnesia", mnesia, stop, []},
{"Stopping Erlang node", init, stop, []}
],
NumberLast = length(Steps),
TimestampStart = calendar:datetime_to_gregorian_seconds({date(), time()}),
lists:foldl(
fun({Desc, Mod, Func, Args}, NumberThis) ->
SecondsDiff =
calendar:datetime_to_gregorian_seconds({date(), time()})
- TimestampStart,
io:format("[~p/~p ~ps] ~s... ",
[NumberThis, NumberLast, SecondsDiff, Desc]),
Result = apply(Mod, Func, Args),
io:format("~p~n", [Result]),
NumberThis+1
end,
1,
Steps),
ok.
send_service_message_all_mucs(Subject, AnnouncementText) ->
Message = io_lib:format("~s~n~s", [Subject, AnnouncementText]),
lists:foreach(
fun(ServerHost) ->
MUCHost = gen_mod:get_module_opt_host(
ServerHost, mod_muc, "conference.@HOST@"),
MUCHostB = list_to_binary(MUCHost),
mod_muc:broadcast_service_message(MUCHostB, Message)
end,
?MYHOSTS).
%%%
%%% ejabberd_update
%%%
update_list() ->
{ok, _Dir, UpdatedBeams, _Script, _LowLevelScript, _Check} =
ejabberd_update:update_info(),
[atom_to_list(Beam) || Beam <- UpdatedBeams].
update("all") ->
[update_module(ModStr) || ModStr <- update_list()];
update(ModStr) ->
update_module(ModStr).
update_module(ModuleNameString) ->
ModuleName = list_to_atom(ModuleNameString),
case ejabberd_update:update([ModuleName]) of
{ok, Res} -> {ok, io_lib:format("Updated: ~p", [Res])};
{error, Reason} -> {error, Reason}
end.
%%%
%%% Account management
%%%
register(User, Host, Password) ->
case ejabberd_auth:try_register(User, Host, Password) of
{atomic, ok} ->
{ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
{atomic, exists} ->
String = io_lib:format("User ~s@~s already registered at node ~p",
[User, Host, node()]),
{exists, String};
{error, Reason} ->
String = io_lib:format("Can't register user ~s@~s at node ~p: ~p",
[User, Host, node(), Reason]),
{cannot_register, String}
end.
unregister(User, Host) ->
ejabberd_auth:remove_user(User, Host),
{ok, ""}.
registered_users(Host) ->
Users = ejabberd_auth:get_vh_registered_users(Host),
SUsers = lists:sort(Users),
lists:map(fun({U, _S}) -> U end, SUsers).
get_last_info() -> get_last_info("badlop", "localhost").
get_last_info(User, Server) ->
case mod_last:get_last_info(User, Server) of
{ok, TimeStamp, Status} -> {TimeStamp, Status};
not_found -> {"never", ""}
end.
%%%
%%% Migration management
%%%
import_file(Path) ->
case jd2ejd:import_file(Path) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't import jabberd14 spool file ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_import_file, String}
end.
import_dir(Path) ->
case jd2ejd:import_dir(Path) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't import jabberd14 spool dir ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_import_dir, String}
end.
%%%
%%% Purge DB
%%%
delete_expired_messages() ->
mod_offline:remove_expired_messages(),
ok.
delete_old_messages(Days) ->
mod_offline:remove_old_messages(Days),
ok.
%%%
%%% Mnesia management
%%%
set_master("self") ->
set_master(node());
set_master(NodeString) when is_list(NodeString) ->
set_master(list_to_atom(NodeString));
set_master(Node) when is_atom(Node) ->
case mnesia:set_master_nodes([Node]) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't set master node ~p at node ~p:~n~p",
[Node, node(), Reason]),
{error, String}
end.
backup_mnesia(Path) ->
case mnesia:backup(Path) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't store backup in ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_backup, String}
end.
restore_mnesia(Path) ->
case ejabberd_admin:restore(Path) of
{atomic, _} ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't restore backup from ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_restore, String};
{aborted,{no_exists,Table}} ->
String = io_lib:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.",
[filename:absname(Path), node(), Table]),
{table_not_exists, String};
{aborted,enoent} ->
String = io_lib:format("Can't restore backup from ~p at node ~p: File not found.",
[filename:absname(Path), node()]),
{file_not_found, String}
end.
%% Mnesia database restore
%% This function is called from ejabberd_ctl, ejabberd_web_admin and
%% mod_configure/adhoc
restore(Path) ->
mnesia:restore(Path, [{keep_tables,keep_tables()},
{default_op, skip_tables}]).
%% This function return a list of tables that should be kept from a previous
%% version backup.
%% Obsolete tables or tables created by module who are no longer used are not
%% restored and are ignored.
keep_tables() ->
lists:flatten([acl, passwd, config, local_config, disco_publish,
keep_modules_tables()]).
%% Returns the list of modules tables in use, according to the list of actually
%% loaded modules
keep_modules_tables() ->
lists:map(fun(Module) -> module_tables(Module) end,
gen_mod:loaded_modules(?MYNAME)).
%% TODO: This mapping should probably be moved to a callback function in each
%% module.
%% Mapping between modules and their tables
module_tables(mod_announce) -> [motd, motd_users];
module_tables(mod_irc) -> [irc_custom];
module_tables(mod_last) -> [last_activity];
module_tables(mod_muc) -> [muc_room, muc_registered];
module_tables(mod_offline) -> [offline_msg];
module_tables(mod_privacy) -> [privacy];
module_tables(mod_private) -> [private_storage];
module_tables(mod_pubsub) -> [pubsub_node];
module_tables(mod_roster) -> [roster];
module_tables(mod_shared_roster) -> [sr_group, sr_user];
module_tables(mod_vcard) -> [vcard, vcard_search];
module_tables(_Other) -> [].
get_local_tables() ->
Tabs1 = lists:delete(schema, mnesia:system_info(local_tables)),
Tabs = lists:filter(
fun(T) ->
case mnesia:table_info(T, storage_type) of
disc_copies -> true;
disc_only_copies -> true;
_ -> false
end
end, Tabs1),
Tabs.
dump_mnesia(Path) ->
Tabs = get_local_tables(),
dump_tables(Path, Tabs).
dump_table(Path, STable) ->
Table = list_to_atom(STable),
dump_tables(Path, [Table]).
dump_tables(Path, Tables) ->
case dump_to_textfile(Path, Tables) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't store dump in ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_dump, String}
end.
dump_to_textfile(File) ->
Tabs = get_local_tables(),
dump_to_textfile(File, Tabs).
dump_to_textfile(File, Tabs) ->
dump_to_textfile(mnesia:system_info(is_running), Tabs, file:open(File, [write])).
dump_to_textfile(yes, Tabs, {ok, F}) ->
Defs = lists:map(
fun(T) -> {T, [{record_name, mnesia:table_info(T, record_name)},
{attributes, mnesia:table_info(T, attributes)}]}
end,
Tabs),
io:format(F, "~p.~n", [{tables, Defs}]),
lists:foreach(fun(T) -> dump_tab(F, T) end, Tabs),
file:close(F);
dump_to_textfile(_, _, {ok, F}) ->
file:close(F),
{error, mnesia_not_running};
dump_to_textfile(_, _, {error, Reason}) ->
{error, Reason}.
dump_tab(F, T) ->
W = mnesia:table_info(T, wild_pattern),
{atomic,All} = mnesia:transaction(
fun() -> mnesia:match_object(T, W, read) end),
lists:foreach(
fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All).
load_mnesia(Path) ->
case mnesia:load_textfile(Path) of
{atomic, ok} ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't load dump in ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_load, String}
end.
install_fallback_mnesia(Path) ->
case mnesia:install_fallback(Path) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't install fallback from ~p at node ~p: ~p",
[filename:absname(Path), node(), Reason]),
{cannot_fallback, String}
end.
mnesia_change_nodename(FromString, ToString, Source, Target) ->
From = list_to_atom(FromString),
To = list_to_atom(ToString),
Switch =
fun
(Node) when Node == From ->
io:format(" - Replacing nodename: '~p' with: '~p'~n", [From, To]),
To;
(Node) when Node == To ->
%% throw({error, already_exists});
io:format(" - Node: '~p' will not be modified (it is already '~p')~n", [Node, To]),
Node;
(Node) ->
io:format(" - Node: '~p' will not be modified (it is not '~p')~n", [Node, From]),
Node
end,
Convert =
fun
({schema, db_nodes, Nodes}, Acc) ->
io:format(" +++ db_nodes ~p~n", [Nodes]),
{[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
({schema, version, Version}, Acc) ->
io:format(" +++ version: ~p~n", [Version]),
{[{schema, version, Version}], Acc};
({schema, cookie, Cookie}, Acc) ->
io:format(" +++ cookie: ~p~n", [Cookie]),
{[{schema, cookie, Cookie}], Acc};
({schema, Tab, CreateList}, Acc) ->
io:format("~n * Checking table: '~p'~n", [Tab]),
Keys = [ram_copies, disc_copies, disc_only_copies],
OptSwitch =
fun({Key, Val}) ->
case lists:member(Key, Keys) of
true ->
io:format(" + Checking key: '~p'~n", [Key]),
{Key, lists:map(Switch, Val)};
false-> {Key, Val}
end
end,
Res = {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc},
Res;
(Other, Acc) ->
{[Other], Acc}
end,
mnesia:traverse_backup(Source, Target, Convert, switched).
+41 -186
View File
@@ -1,103 +1,47 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_app.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : ejabberd's application callback module
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(ejabberd_app).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(application).
-export([start_modules/0,start/2, get_log_path/0, 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),
write_pid_file(),
application:start(sasl),
application:start(exmpp),
randoms:start(),
db_init(),
sha:start(),
start(),
catch ssl:start(),
translate:start(),
acl:start(),
ejabberd_ctl:init(),
ejabberd_commands:init(),
ejabberd_admin:start(),
gen_mod:start(),
ejabberd_config:start(),
ejabberd_check:config(),
connect_nodes(),
%% Loading ASN.1 driver explicitly to avoid races in LDAP
catch asn1rt:load_driver(),
Sup = ejabberd_sup:start_link(),
ejabberd_rdbms:start(),
ejabberd_auth:start(),
cyrsasl:start(),
% Profiling
%ejabberd_debug:eprof_start(),
%ejabberd_debug:fprof_start(),
maybe_add_nameservers(),
print_start_debug_info(),
start_modules(),
ejabberd_cluster:announce(),
ejabberd_node_groups:start(),
ejabberd_listener:start_listeners(),
?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
%eprof:start(),
%eprof:profile([self()]),
%fprof:trace(start, "/tmp/fprof"),
start(),
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(),
ejabberd_admin:stop(),
broadcast_c2s_shutdown(),
timer:sleep(5000),
State.
%% All the processes were killed when this function is called
stop(_State) ->
?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]),
delete_pid_file(),
%%ejabberd_debug:stop(),
stop(_StartArgs) ->
ok.
%%%
%%% Internal functions
%%%
start() ->
spawn_link(?MODULE, init, []).
@@ -105,10 +49,33 @@ init() ->
register(ejabberd, self()),
%erlang:system_flag(fullsweep_after, 0),
%error_logger:logfile({open, ?LOG_PATH}),
LogPath = get_log_path(),
LogPath =
case application:get_env(log_path) of
{ok, Path} ->
Path;
undefined ->
case os:getenv("EJABBERD_LOG_PATH") of
false ->
?LOG_PATH;
Path ->
Path
end
end,
error_logger:add_report_handler(ejabberd_logger_h, LogPath),
erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
ok.
case erl_ddll:load_driver(ejabberd:get_so_path(), expat_erl) of
ok -> ok;
{error, already_loaded} -> ok
end,
Port = open_port({spawn, expat_erl}, [binary]),
loop(Port).
loop(Port) ->
receive
_ ->
loop(Port)
end.
db_init() ->
case mnesia:system_info(extra_db_nodes) of
@@ -117,20 +84,10 @@ db_init() ->
_ ->
ok
end,
application:start(mnesia, permanent),
mnesia:start(),
mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
%% Start all the modules in all the hosts
start_modules() ->
case ejabberd_config:get_local_option({static_modules, global}) of
undefined ->
ok;
StaticModules ->
lists:foreach(
fun({Module, Args}) ->
gen_mod:start_module(global, Module, Args)
end, StaticModules)
end,
load_modules() ->
lists:foreach(
fun(Host) ->
case ejabberd_config:get_local_option({modules, Host}) of
@@ -144,105 +101,3 @@ 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 ->
ok;
Nodes when is_list(Nodes) ->
lists:foreach(fun(Node) ->
net_kernel:connect_node(Node)
end, Nodes)
end.
%% @spec () -> string()
%% @doc Returns the full path to the ejabberd log file.
%% It first checks for application configuration parameter 'log_path'.
%% If not defined it checks the environment variable EJABBERD_LOG_PATH.
%% And if that one is neither defined, returns the default value:
%% "ejabberd.log" in current directory.
get_log_path() ->
case application:get_env(log_path) of
{ok, Path} ->
Path;
undefined ->
case os:getenv("EJABBERD_LOG_PATH") of
false ->
?LOG_PATH;
Path ->
Path
end
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).
broadcast_c2s_shutdown() ->
Children = supervisor:which_children(ejabberd_c2s_sup),
lists:foreach(
fun({_, C2SPid, _, _}) ->
C2SPid ! system_shutdown
end, Children).
%%%
%%% PID file
%%%
write_pid_file() ->
case ejabberd:get_pid_file() of
false ->
ok;
PidFilename ->
write_pid_file(os:getpid(), PidFilename)
end.
write_pid_file(Pid, PidFilename) ->
case file:open(PidFilename, [write]) of
{ok, Fd} ->
io:format(Fd, "~s~n", [Pid]),
file:close(Fd);
{error, Reason} ->
?ERROR_MSG("Cannot write PID file ~s~nReason: ~p", [PidFilename, Reason]),
throw({cannot_write_pid_file, PidFilename, Reason})
end.
delete_pid_file() ->
case ejabberd:get_pid_file() of
false ->
ok;
PidFilename ->
file:delete(PidFilename)
end.
print_start_debug_info() ->
?DEBUG("Inet DB RC:~n~p", [inet_db:get_rc()]),
?DEBUG("Mnesia database:~n~p", [mnesia:system_info(all)]),
?DEBUG("Mnesia tables:~n~p",
[ [{Table, mnesia:table_info(Table, all)} ||
Table <- lists:sort(mnesia:system_info(tables))] ]),
ok.
+46 -454
View File
@@ -1,504 +1,96 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Authentification
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
%% TODO: Use the functions in ejabberd auth to add and remove users.
-module(ejabberd_auth).
-author('alexey@process-one.net').
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
%% External exports
-export([start/0,
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,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
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,
remove_user/3,
plain_password_required/1,
entropy/1
plain_password_required/1
]).
-export([start/1
,start_module/2
,stop_module/2
,start_modules/2
,start_method/2
,stop_method/2
,start_methods/2
]).
-export([auth_modules/1]).
-include("ejabberd.hrl").
%% @type authmodule() = ejabberd_auth_anonymous | ejabberd_auth_external |
%% ejabberd_auth_ldap | ejabberd_auth_pam |
%% ejabberd_auth_storage | atom().
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec () -> term()
start() ->
?DEBUG("About to start auth modules. Hosts: ~p", [?MYHOSTS]),
lists:foreach(fun start/1, ?MYHOSTS).
lists:foreach(fun(Host) ->
(auth_module(Host)):start(Host)
end, ?MYHOSTS).
start(Host) ->
start_modules(Host, auth_modules(Host)).
plain_password_required(Server) ->
(auth_module(Server)):plain_password_required().
start_modules(Host, Modules) when is_list(Modules) ->
lists:foreach(fun (M) -> start_module(Host, M) end, Modules).
start_module(Host, Module) when is_atom(Module) ->
Module:start(Host).
stop_module(Host, Module) when is_atom(Module) ->
Module:stop(Host).
check_password(User, Server, Password) ->
(auth_module(Server)):check_password(User, Server, Password).
start_methods(Host, Methods) when is_list(Methods) ->
lists:foreach(fun (M) -> start_method(Host, M) end, Methods).
start_method(Host, Method) when is_atom(Method) ->
start_module(Host, module_name(Method)).
stop_method(Host, Method) when is_atom(Method) ->
stop_module(Host, module_name(Method)).
check_password(User, Server, Password, StreamID, Digest) ->
(auth_module(Server)):check_password(User, Server, Password, StreamID, Digest).
set_password(User, Server, Password) ->
(auth_module(Server)):set_password(User, Server, Password).
%% @spec (Server) -> bool()
%% Server = string()
plain_password_required(Server) when is_list(Server) ->
lists:any(
fun(M) ->
M:plain_password_required()
end, auth_modules(Server)).
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Check if the user and password can login in server.
check_password(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
case check_password_with_authmodule(User, Server, Password) of
{true, _AuthModule} -> true;
{false, _Reason} -> false
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
%% @doc Check if the user and password can login in server.
check_password(User, Server, Password, Digest, DigestGen)
when is_list(User), is_list(Server), is_list(Password),
is_list(Digest), is_function(DigestGen) ->
case check_password_with_authmodule(User, Server, Password,
Digest, DigestGen) of
{true, _AuthModule} -> true;
{false, _Reason} -> false
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% {true, AuthModule} | {false, Reason::string()}
%% where
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
%% | ejabberd_auth_ldap | ejabberd_auth_pam | ejabberd_auth_storage
%% @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.
check_password_with_authmodule(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
check_password_loop(auth_modules(Server), [User, Server, Password], "").
%% @spec (User, Server, Password, Digest, DigestGen) -> {true, AuthModule} | false
%% User = string()
%% Server = string()
%% Password = string() | undefined
%% Digest = string() | undefined
%% DigestGen = function()
%% AuthModule = authmodule()
%% @doc Check the password is valid and also return the authentication module that accepts it.
%% The password is 'undefined' if the client
%% authenticates using the digest method as defined in
%% XEP-0078: Non-SASL Authentication
check_password_with_authmodule(User, Server, Password, Digest, DigestGen)
when is_list(User), is_list(Server), (is_list(Password) orelse Password == 'undefined'),
is_function(DigestGen), (is_list(Digest) orelse Digest == 'undefined')->
check_password_loop(auth_modules(Server), [User, Server, Password,
Digest, DigestGen], "").
check_password_loop([], _Args, LastReason) ->
{false, LastReason};
check_password_loop([AuthModule | AuthModules], Args, PreviousReason) ->
case apply(AuthModule, check_password, Args) of
try_register(User, Server, Password) ->
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
true ->
{true, AuthModule};
{false, Reason} when Reason /= "" ->
check_password_loop(AuthModules, Args, Reason);
{false, ""} ->
check_password_loop(AuthModules, Args, PreviousReason);
(auth_module(Server)):try_register(User, Server, Password);
false ->
check_password_loop(AuthModules, Args, PreviousReason)
{error, not_allowed}
end.
%% @spec (User, Server, Password) -> ok | {error, ErrorType}
%% User = string()
%% Server = string()
%% Password = string()
%% 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)
when is_list(User), is_list(Server), is_list(Password) ->
lists:foldl(
fun(M, {error, _}) ->
M:set_password(User, Server, Password);
(_M, Res) ->
Res
end, {error, not_allowed}, auth_modules(Server)).
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string() | nil()
try_register(_User, _Server, "") ->
%% We do not allow empty password
{error, not_allowed};
try_register(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
case is_user_exists(User, Server) of
true ->
{atomic, exists};
false ->
case ?IS_MY_HOST(exmpp_stringprep:nameprep(Server)) of
true ->
Res = lists:foldl(
fun (_M, {atomic, ok} = Res) ->
Res;
(M, _) ->
M:try_register(User, Server, Password)
end, {error, not_allowed}, auth_modules(Server)),
trigger_register_hooks(Res, User, Server);
false ->
{error, not_allowed}
end
end.
trigger_register_hooks({atomic, ok} = Res, User, Server) ->
ejabberd_hooks:run(register_user, list_to_binary(Server),
[User, Server]),
Res;
trigger_register_hooks(Res, _User, _Server) ->
Res.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
dirty_get_registered_users() ->
lists:flatmap(
fun(M) ->
M:dirty_get_registered_users()
end, auth_modules()).
(auth_module(?MYNAME)):dirty_get_registered_users().
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
get_vh_registered_users(Server) ->
(auth_module(Server)):get_vh_registered_users(Server).
get_vh_registered_users(Server) when is_list(Server) ->
lists:flatmap(
fun(M) ->
M:get_vh_registered_users(Server)
end, auth_modules(Server)).
get_password(User, Server) ->
(auth_module(Server)):get_password(User, Server).
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
get_password_s(User, Server) ->
(auth_module(Server)):get_password_s(User, Server).
get_vh_registered_users(Server, Opts) when is_list(Server) ->
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
end, auth_modules(Server)).
is_user_exists(User, Server) ->
(auth_module(Server)):is_user_exists(User, Server).
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
remove_user(User, Server) ->
(auth_module(Server)):remove_user(User, Server).
get_vh_registered_users_number(Server) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
case erlang:function_exported(
M, get_vh_registered_users_number, 1) of
true ->
M:get_vh_registered_users_number(Server);
false ->
length(M:get_vh_registered_users(Server))
end
end, auth_modules(Server))).
%% @spec (Server, Opts) -> Users_Number
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% Users_Number = integer()
get_vh_registered_users_number(Server, Opts) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
case erlang:function_exported(
M, get_vh_registered_users_number, 2) of
true ->
M:get_vh_registered_users_number(Server, Opts);
false ->
length(M:get_vh_registered_users(Server))
end
end, auth_modules(Server))).
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
get_password(User, Server) when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, false) ->
M:get_password(User, Server);
(_M, Password) ->
Password
end, false, auth_modules(Server)).
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
get_password_s(User, Server) when is_list(User), is_list(Server) ->
case get_password(User, Server) of
false ->
"";
Password ->
Password
end.
%% @spec (User, Server) -> {Password, AuthModule} | {false, none}
%% User = string()
%% Server = string()
%% Password = string()
%% AuthModule = authmodule()
%% @doc Get the password of the user and the auth module.
get_password_with_authmodule(User, Server)
when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, {false, _}) ->
{M:get_password(User, Server), M};
(_M, {Password, AuthModule}) ->
{Password, AuthModule}
end, {false, none}, auth_modules(Server)).
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc 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) when is_list(User), is_list(Server) ->
lists:any(
fun(M) ->
case M:is_user_exists(User, Server) of
{error, Error} ->
?ERROR_MSG("The authentication module ~p returned an "
"error~nwhen checking user ~p in server ~p~n"
"Error message: ~p",
[M, User, Server, Error]),
false;
Else ->
Else
end
end, auth_modules(Server)).
%% @spec (Module, User, Server) -> true | false | maybe
%% Module = authmodule()
%% User = string()
%% Server = string()
%% @doc Check if the user exists in all authentications module except
%% the module passed as parameter.
is_user_exists_in_other_modules(Module, User, Server)
when is_list(User), is_list(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.
%% @spec (User, Server) -> ok | error | {error, not_allowed}
%% User = string()
%% Server = string()
%% @doc Remove user.
%% TODO: Fix me: It always return ok even if there was some problem removing the user.
%% dialyzer warning
%% ejabberd_auth.erl:388: The variable _ can never match since previous clauses completely covered the type 'ok'
remove_user(User, Server) when is_list(User), is_list(Server) ->
R = lists:foreach(
fun(M) ->
M:remove_user(User, Server)
end, auth_modules(Server)),
ejabberd_hooks:run(remove_user, list_to_binary(exmpp_stringprep:nameprep(Server)),
[list_to_binary(User), list_to_binary(Server)]),
R.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
%% User = string()
%% Server = string()
%% Password = string()
%% @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)
when is_list(User), is_list(Server), is_list(Password) ->
R = lists:foldl(
fun(_M, ok = Res) ->
Res;
(M, _) ->
M:remove_user(User, Server, Password)
end, error, auth_modules(Server)),
case R of
ok -> ejabberd_hooks:run(remove_user, list_to_binary(exmpp_stringprep:nameprep(Server)),
[list_to_binary(User), list_to_binary(Server)]);
_ -> none
end,
R.
%% @spec (IOList) -> non_negative_float()
%% @doc Calculate informational entropy.
entropy(IOList) ->
case binary_to_list(iolist_to_binary(IOList)) of
"" ->
0.0;
S ->
Set = lists:foldl(
fun(C, [Digit, Printable, LowLetter, HiLetter, Other]) ->
if C >= $a, C =< $z ->
[Digit, Printable, 26, HiLetter, Other];
C >= $0, C =< $9 ->
[9, Printable, LowLetter, HiLetter, Other];
C >= $A, C =< $Z ->
[Digit, Printable, LowLetter, 26, Other];
C >= 16#21, C =< 16#7e ->
[Digit, 33, LowLetter, HiLetter, Other];
true ->
[Digit, Printable, LowLetter, HiLetter, 128]
end
end, [0, 0, 0, 0, 0], S),
length(S) * math:log(lists:sum(Set))/math:log(2)
end.
remove_user(User, Server, Password) ->
(auth_module(Server)):remove_user(User, Server, Password).
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
%% @spec () -> [authmodule()]
%% @doc Return the lists of all the auth modules actually used in the
%% configuration.
auth_module(Server) ->
LServer = jlib:nameprep(Server),
case ejabberd_config:get_local_option({auth_method, LServer}) of
external ->
ejabberd_auth_external;
ldap ->
ejabberd_auth_ldap;
odbc ->
ejabberd_auth_odbc;
_ ->
ejabberd_auth_internal
end.
auth_modules() ->
lists:usort(
lists:flatmap(
fun(Server) ->
auth_modules(Server)
end, ?MYHOSTS)).
%% @spec (Server) -> [authmodule()]
%% Server = string()
%% @doc Return the list of authenticated modules for a given host.
auth_modules(Server) when is_list(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, ejabberd:normalize_host(LServer)}),
Methods = if
Method == undefined -> [];
is_list(Method) -> Method;
is_atom(Method) -> [Method]
end,
[module_name(M) || M <- Methods].
module_name(Method) when is_atom(Method) ->
list_to_atom("ejabberd_auth_" ++ atom_to_list(Method)).

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