* src/mod_last_odbc.erl: Added store_last_info/4 function (thanks

to Sergei Golovan)
* src/mod_last.erl: Likewise

* src/jd2ejd.erl: Support for exporting iq:last information,
better error handling (thanks to Sergei Golovan)

* src/ejabberd_ctl.erl: Added "import-file" and "import-dir"
commands (thanks to Sergei Golovan)

SVN Revision: 358
This commit is contained in:
Alexey Shchepin 2005-05-23 19:47:57 +00:00
parent 6b1e56f786
commit dbb248247b
8 changed files with 118 additions and 51 deletions

View File

@ -1,5 +1,15 @@
2005-05-23 Alexey Shchepin <alexey@sevcom.net> 2005-05-23 Alexey Shchepin <alexey@sevcom.net>
* src/mod_last_odbc.erl: Added store_last_info/4 function (thanks
to Sergei Golovan)
* src/mod_last.erl: Likewise
* src/jd2ejd.erl: Support for exporting iq:last information,
better error handling (thanks to Sergei Golovan)
* src/ejabberd_ctl.erl: Added "import-file" and "import-dir"
commands (thanks to Sergei Golovan)
* doc/guide.tex: Updated (thanks to Sergei Golovan) * doc/guide.tex: Updated (thanks to Sergei Golovan)
* doc/dev.tex: Likewise * doc/dev.tex: Likewise
* doc/disco.png: Likewise * doc/disco.png: Likewise

View File

@ -61,34 +61,38 @@
<A NAME="sec:intro"></A> <A NAME="sec:intro"></A>
<TT>ejabberd</TT> is a Free and Open Source fault-tolerant distributed Jabber <TT>ejabberd</TT> is a Free and Open Source fault-tolerant distributed Jabber
server. It is writen mostly in Erlang.<BR> server. It is written mostly in Erlang.<BR>
<BR> <BR>
The main features of <TT>ejabberd</TT> is: The main features of <TT>ejabberd</TT> are:
<UL><LI> <UL><LI>
Works on most of popular platforms: *nix (tested on Linux and FreeBSD) Works on most of popular platforms: *nix (tested on Linux, FreeBSD and
and Win32 NetBSD) and Win32
<LI>Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of <LI>Distributed: You can run <TT>ejabberd</TT> on a cluster of machines to let all of
them will serve one Jabber domain. them serve one Jabber domain.
<LI>Fault-tolerance: You can setup an <TT>ejabberd</TT> cluster so that all the <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 information required for a properly working service will be stored
permanently on more than one node. This means that if one of the nodes permanently on more than one node. This means that if one of the nodes
crashes, then the others will continue working without disruption. crashes, then the others will continue working without disruption.
You can also add or replace more nodes ``on the fly''. You can also add or replace nodes ``on the fly''.
<LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User <LI>Support for virtual hosting
Chat</A> service <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 IRC transport
<LI>Built-in <LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0060.html">Publish-Subscribe</A> service
<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 Jabber Users Directory service based on users vCards
<LI>Support for <LI>Built-in web-based administration interface
<A HREF="http://www.jabber.org/jeps/jep-0030.html">JEP-0030</A> <LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> service
(Service Discovery). <LI>SSL support
<LI>Support for <LI>Support for LDAP authentication
<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A> <LI>Ability to interface with external components (JIT, MSN-t, Yahoo-t, etc.)
(Statistics Gathering). <LI>Migration from jabberd14 is possible
<LI>Support for <TT>xml:lang</TT> attribute in many XML elements <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> </UL>
<TT>ejabberd</TT> is a Free and Open Source fault-tolerant distributed Jabber
server. It is written mostly in Erlang.<BR>
<BR>
<!--TOC subsection How it works--> <!--TOC subsection How it works-->
<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;How it works</H3><!--SEC END --> <H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;How it works</H3><!--SEC END -->
@ -166,13 +170,13 @@ XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
CDATA = {xmlcdata, string()} CDATA = {xmlcdata, string()}
</PRE>E.&nbsp;g. this stanza: </PRE>E.&nbsp;g. this stanza:
<PRE> <PRE>
&lt;message to='test@conference.e.localhost' type='groupchat'&gt; &lt;message to='test@conference.example.org' type='groupchat'&gt;
&lt;body&gt;test&lt;/body&gt; &lt;body&gt;test&lt;/body&gt;
&lt;/message&gt; &lt;/message&gt;
</PRE>represented as following structure: </PRE>represented as following structure:
<PRE> <PRE>
{xmlelement, "message", {xmlelement, "message",
[{"to", "test@conference.e.localhost"}, [{"to", "test@conference.example.org"},
{"type", "groupchat"}], {"type", "groupchat"}],
[{xmlelement, "body", [{xmlelement, "body",
[], [],

View File

@ -4,7 +4,7 @@
<HEAD><TITLE>Ejabberd Installation and Operation Guide</TITLE> <HEAD><TITLE>Ejabberd Installation and Operation Guide</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO8859-1"> <META http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<META name="GENERATOR" content="hevea 1.07"> <META name="GENERATOR" content="hevea 1.06">
</HEAD> </HEAD>
<BODY > <BODY >
<!--HEVEA command line is: /usr/bin/hevea -charset ISO8859-1 guide.tex --> <!--HEVEA command line is: /usr/bin/hevea -charset ISO8859-1 guide.tex -->
@ -21,7 +21,7 @@
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><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> <A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3>
<H3 ALIGN=center>April 18, 2005</H3><DIV ALIGN=center> <H3 ALIGN=center>May 23, 2005</H3><DIV ALIGN=center>
<IMG SRC="logo.png"> <IMG SRC="logo.png">
@ -141,8 +141,8 @@ Works on most of popular platforms: *nix (tested on Linux, FreeBSD and
<LI>Ability to interface with external components (JIT, MSN-t, Yahoo-t, etc.) <LI>Ability to interface with external components (JIT, MSN-t, Yahoo-t, etc.)
<LI>Migration from jabberd14 is possible <LI>Migration from jabberd14 is possible
<LI>Mostly XMPP-compliant <LI>Mostly XMPP-compliant
<LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0030.html">JEP-0030</A> (Service Discovery). <LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0030.html">Service Discovery</A>.
<LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A> (Statistics Gathering). <LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0039.html">Statistics Gathering</A>.
<LI>Support for <TT>xml:lang</TT> <LI>Support for <TT>xml:lang</TT>
</UL> </UL>
The misfeatures of <TT>ejabberd</TT> are: The misfeatures of <TT>ejabberd</TT> are:
@ -391,7 +391,7 @@ declarations of ACL in config file have following syntax:
</PRE><DT><B><TT>{user_regexp, &lt;regexp&gt;, &lt;server&gt;}</TT></B><DD> Matches user with name </PRE><DT><B><TT>{user_regexp, &lt;regexp&gt;, &lt;server&gt;}</TT></B><DD> Matches user with name
that matches <TT>&lt;regexp&gt;</TT> and from server <TT>&lt;server&gt;</TT>. Example: that matches <TT>&lt;regexp&gt;</TT> and from server <TT>&lt;server&gt;</TT>. Example:
<PRE> <PRE>
{acl, tests, {user, "^test", "localhost"}}. {acl, tests, {user, "^test", "example.org"}}.
</PRE><DT><B><TT>{server_regexp, &lt;regexp&gt;}</TT></B><DD> Matches any JID from server that </PRE><DT><B><TT>{server_regexp, &lt;regexp&gt;}</TT></B><DD> Matches any JID from server that
matches <TT>&lt;regexp&gt;</TT>. Example: matches <TT>&lt;regexp&gt;</TT>. Example:
<PRE> <PRE>
@ -518,7 +518,7 @@ The following additional options are defined for <TT>ejabberd_service</TT>
<BR> <BR>
The following options are defined: The following options are defined:
<DL COMPACT=compact><DT> <DL COMPACT=compact><DT>
<B><TT>http_poll</TT></B><DD> This option enables <A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> <B><TT>http_poll</TT></B><DD> This option enables <A HREF="http://www.jabber.org/jeps/jep-0025.html">JEP-0025</A> (HTTP Polling)
support. It is available then at <CODE>http://server:port/http-poll/</CODE>.<BR> support. It is available then at <CODE>http://server:port/http-poll/</CODE>.<BR>
<BR> <BR>
<DT><B><TT>web_admin</TT></B><DD> This option enables web-based interface for <TT>ejabberd</TT> <DT><B><TT>web_admin</TT></B><DD> This option enables web-based interface for <TT>ejabberd</TT>
@ -629,7 +629,7 @@ Example:
{mod_vcard, []}, {mod_vcard, []},
{mod_offline, []}, {mod_offline, []},
{mod_announce, [{access, announce}]}, {mod_announce, [{access, announce}]},
{mod_echo, [{host, "echo.localhost"}]}, {mod_echo, [{host, "echo.example.org"}]},
{mod_private, []}, {mod_private, []},
{mod_irc, []}, {mod_irc, []},
{mod_muc, []}, {mod_muc, []},
@ -823,9 +823,8 @@ Replicating of table makes lookup in this table faster on this node,
but writing will be slower. And of course if machine with one of but writing will be slower. And of course if machine with one of
replicas is down, other replicas will be used.<BR> replicas is down, other replicas will be used.<BR>
<BR> <BR>
Also section ``5.3 Table Fragmentation'' Also section 5.3 (Table Fragmentation) of
<A HREF="http://www.erlang.se/doc/doc-5.4/lib/mnesia-4.2/doc/html/index.html">here</A> <A HREF="http://www.erlang.se/doc/doc-5.4/lib/mnesia-4.2/doc/html/index.html">Mnesia Reference Manual</A> can be useful.<BR>
can be useful.<BR>
<BR> <BR>
(alt) Same as in previous item, but for other tables.<BR> (alt) Same as in previous item, but for other tables.<BR>
<BR> <BR>
@ -1426,7 +1425,7 @@ All built-in modules support <TT>xml:lang</TT> attribute inside IQ queries.
E.&nbsp;g. on figure&nbsp;<A HREF="#fig:discorus">2</A> showed the reply on the following query: E.&nbsp;g. on figure&nbsp;<A HREF="#fig:discorus">2</A> showed the reply on the following query:
<PRE> <PRE>
&lt;iq id='5' &lt;iq id='5'
to='e.localhost' to='example.org'
type='get' type='get'
xml:lang='ru'&gt; xml:lang='ru'&gt;
&lt;query xmlns='http://jabber.org/protocol/disco#items'/&gt; &lt;query xmlns='http://jabber.org/protocol/disco#items'/&gt;

View File

@ -82,7 +82,7 @@ discipline (see~\ref{sec:modiqdiscoption}).}
\author{Alexey Shchepin \\ \author{Alexey Shchepin \\
\ahrefurl{mailto:alexey@sevcom.net} \\ \ahrefurl{mailto:alexey@sevcom.net} \\
\ahrefurl{xmpp:aleksey@jabber.ru}} \ahrefurl{xmpp:aleksey@jabber.ru}}
\date{April 18, 2005} \date{May 23, 2005}
\begin{document} \begin{document}
\begin{titlepage} \begin{titlepage}

View File

@ -173,6 +173,34 @@ process(Node, ["install-fallback", Path]) ->
?STATUS_BADRPC ?STATUS_BADRPC
end; end;
process(Node, ["import-file", Path]) ->
case rpc:call(Node, jd2ejd, import_file, [Path]) of
ok ->
?STATUS_SUCCESS;
{error, Reason} ->
io:format("Can't import jabberd 1.4 spool file ~p at node ~p: ~p~n",
[filename:absname(Path), Node, Reason]),
?STATUS_ERROR;
{badrpc, Reason} ->
io:format("Can't import jabberd 1.4 spool file ~p at node ~p: ~p~n",
[filename:absname(Path), Node, Reason]),
?STATUS_BADRPC
end;
process(Node, ["import-dir", Path]) ->
case rpc:call(Node, jd2ejd, import_dir, [Path]) of
ok ->
?STATUS_SUCCESS;
{error, Reason} ->
io:format("Can't import jabberd 1.4 spool dir ~p at node ~p: ~p~n",
[filename:absname(Path), Node, Reason]),
?STATUS_ERROR;
{badrpc, Reason} ->
io:format("Can't import jabberd 1.4 spool dir ~p at node ~p: ~p~n",
[filename:absname(Path), Node, Reason]),
?STATUS_BADRPC
end;
process(Node, ["registered-users"]) -> process(Node, ["registered-users"]) ->
case rpc:call(Node, ejabberd_auth, dirty_get_registered_users, []) of case rpc:call(Node, ejabberd_auth, dirty_get_registered_users, []) of
Users when is_list(Users) -> Users when is_list(Users) ->
@ -217,12 +245,14 @@ print_usage() ->
" restart\t\t\trestart ejabberd~n" " restart\t\t\trestart ejabberd~n"
" reopen-log\t\t\treopen log file~n" " reopen-log\t\t\treopen log file~n"
" register user server password\tregister a user~n" " register user server password\tregister a user~n"
" unregister user server\t\tunregister a user~n" " unregister user server\tunregister a user~n"
" backup file\t\t\tstore a database backup in file~n" " backup file\t\t\tstore a database backup to file~n"
" restore file\t\t\trestore a database backup from file~n" " restore file\t\t\trestore a database backup from file~n"
" install-fallback file\t\tinstall a database fallback from file~n" " install-fallback file\t\tinstall a database fallback from file~n"
" dump file\t\t\tdump a database in a text file~n" " dump file\t\t\tdump a database to a text file~n"
" load file\t\t\trestore a database from a text file~n" " load file\t\t\trestore a database from a text file~n"
" import-file file\t\timport user data from jabberd 1.4 spool file~n"
" import-dir dir\t\timport user data from jabberd 1.4 spool directory~n"
" registered-users\t\tlist all registered users~n" " registered-users\t\tlist all registered users~n"
" delete-expired-messages\tdelete expired offline messages from database~n" " delete-expired-messages\tdelete expired offline messages from database~n"
"~n" "~n"

View File

@ -37,19 +37,23 @@ import_file(File) ->
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG( ?ERROR_MSG(
"Error while processing file \"~s\": ~p~n", "Error while processing file \"~s\": ~p~n",
[File, Reason]); [File, Reason]),
{error, Reason};
_ -> _ ->
ok ok
end; end;
{error, Reason} -> {error, Reason} ->
?ERROR_MSG("Can't parse file \"~s\": ~p~n", ?ERROR_MSG("Can't parse file \"~s\": ~p~n",
[File, Reason]) [File, Reason]),
{error, Reason}
end; end;
{error, Reason} -> {error, Reason} ->
?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]) ?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]),
{error, Reason}
end; end;
false -> false ->
?ERROR_MSG("Incorrect user/server name in file \"~s\"~n", [File]) ?ERROR_MSG("Illegal user/server name in file \"~s\"~n", [File]),
{error, "illegal user/server"}
end. end.
@ -65,11 +69,15 @@ import_dir(Dir) ->
false false
end end
end, Files), end, Files),
lists:foreach( lists:foldl(
fun(FN) -> fun(FN, A) ->
import_file(filename:join([Dir, FN])) Res = import_file(filename:join([Dir, FN])),
end, MsgFiles), case {A, Res} of
ok. {ok, ok} -> ok;
{ok, _} -> {error, "see ejabberd log for details"};
_ -> A
end
end, ok, MsgFiles).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% Internal functions %%% Internal functions
@ -99,6 +107,14 @@ xdb_data(User, Server, {xmlelement, _Name, Attrs, _Els} = El) ->
?NS_ROSTER -> ?NS_ROSTER ->
catch mod_roster:set_items(User, Server, El), catch mod_roster:set_items(User, Server, El),
ok; ok;
?NS_LAST ->
TimeStamp = xml:get_attr_s("last", Attrs),
Status = xml:get_tag_cdata(El),
catch mod_last:store_last_info(User,
Server,
list_to_integer(TimeStamp),
Status),
ok;
?NS_VCARD -> ?NS_VCARD ->
catch mod_vcard:process_sm_iq( catch mod_vcard:process_sm_iq(
From, From,

View File

@ -17,6 +17,7 @@
process_local_iq/3, process_local_iq/3,
process_sm_iq/3, process_sm_iq/3,
on_presence_update/4, on_presence_update/4,
store_last_info/4,
remove_user/2]). remove_user/2]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -118,18 +119,21 @@ get_last(IQ, SubEl, LUser, LServer) ->
on_presence_update(User, Server, _Resource, Status) -> on_presence_update(User, Server, _Resource, Status) ->
{MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp = MegaSecs * 1000000 + Secs,
store_last_info(User, Server, TimeStamp, Status).
store_last_info(User, Server, TimeStamp, Status) ->
LUser = jlib:nodeprep(User), LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server), LServer = jlib:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},
{MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp = MegaSecs * 1000000 + Secs,
F = fun() -> F = fun() ->
mnesia:write(#last_activity{us = US, mnesia:write(#last_activity{us = US,
timestamp = TimeStamp, timestamp = TimeStamp,
status = Status}) status = Status})
end, end,
mnesia:transaction(F). mnesia:transaction(F).
remove_user(User, Server) -> remove_user(User, Server) ->
LUser = jlib:nodeprep(User), LUser = jlib:nodeprep(User),

View File

@ -16,7 +16,8 @@
stop/0, stop/0,
process_local_iq/3, process_local_iq/3,
process_sm_iq/3, process_sm_iq/3,
on_presence_update/3, on_presence_update/4,
store_last_info/4,
remove_user/1]). remove_user/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -120,10 +121,13 @@ get_last(IQ, SubEl, LUser) ->
on_presence_update(User, _Resource, Status) -> on_presence_update(User, Server, _Resource, Status) ->
LUser = jlib:nodeprep(User),
{MegaSecs, Secs, _MicroSecs} = now(), {MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp = MegaSecs * 1000000 + Secs, TimeStamp = MegaSecs * 1000000 + Secs,
store_last_info(User, Server, TimeStamp, Status).
store_last_info(User, Server, TimeStamp, Status) ->
LUser = jlib:nodeprep(User),
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)), Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status), State = ejabberd_odbc:escape(Status),