* 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>
* 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/dev.tex: Likewise
* doc/disco.png: Likewise

View File

@ -61,34 +61,38 @@
<A NAME="sec:intro"></A>
<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>
The main features of <TT>ejabberd</TT> is:
The main features of <TT>ejabberd</TT> are:
<UL><LI>
Works on most of popular platforms: *nix (tested on Linux and FreeBSD)
and Win32
<LI>Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of
them will serve one Jabber domain.
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 more nodes ``on the fly''.
<LI>Built-in <A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User
Chat</A> service
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 <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>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-0039.html">JEP-0039</A>
(Statistics Gathering).
<LI>Support for <TT>xml:lang</TT> attribute in many XML elements
<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>
<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-->
<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()}
</PRE>E.&nbsp;g. this stanza:
<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;/message&gt;
</PRE>represented as following structure:
<PRE>
{xmlelement, "message",
[{"to", "test@conference.e.localhost"},
[{"to", "test@conference.example.org"},
{"type", "groupchat"}],
[{xmlelement, "body",
[],

View File

@ -4,7 +4,7 @@
<HEAD><TITLE>Ejabberd Installation and Operation Guide</TITLE>
<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>
<BODY >
<!--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="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">
@ -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>Migration from jabberd14 is possible
<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-0039.html">JEP-0039</A> (Statistics Gathering).
<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>
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
that matches <TT>&lt;regexp&gt;</TT> and from server <TT>&lt;server&gt;</TT>. Example:
<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
matches <TT>&lt;regexp&gt;</TT>. Example:
<PRE>
@ -518,7 +518,7 @@ The following additional options are defined for <TT>ejabberd_service</TT>
<BR>
The following options are defined:
<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>
<BR>
<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_offline, []},
{mod_announce, [{access, announce}]},
{mod_echo, [{host, "echo.localhost"}]},
{mod_echo, [{host, "echo.example.org"}]},
{mod_private, []},
{mod_irc, []},
{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
replicas is down, other replicas will be used.<BR>
<BR>
Also section ``5.3 Table Fragmentation''
<A HREF="http://www.erlang.se/doc/doc-5.4/lib/mnesia-4.2/doc/html/index.html">here</A>
can be useful.<BR>
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">Mnesia Reference Manual</A> can be useful.<BR>
<BR>
(alt) Same as in previous item, but for other tables.<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:
<PRE>
&lt;iq id='5'
to='e.localhost'
to='example.org'
type='get'
xml:lang='ru'&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 \\
\ahrefurl{mailto:alexey@sevcom.net} \\
\ahrefurl{xmpp:aleksey@jabber.ru}}
\date{April 18, 2005}
\date{May 23, 2005}
\begin{document}
\begin{titlepage}

View File

@ -173,6 +173,34 @@ process(Node, ["install-fallback", Path]) ->
?STATUS_BADRPC
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"]) ->
case rpc:call(Node, ejabberd_auth, dirty_get_registered_users, []) of
Users when is_list(Users) ->
@ -217,12 +245,14 @@ print_usage() ->
" restart\t\t\trestart ejabberd~n"
" reopen-log\t\t\treopen log file~n"
" register user server password\tregister a user~n"
" unregister user server\t\tunregister a user~n"
" backup file\t\t\tstore a database backup in file~n"
" unregister user server\tunregister a user~n"
" backup file\t\t\tstore a database backup to file~n"
" restore file\t\t\trestore a database backup 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"
" 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"
" delete-expired-messages\tdelete expired offline messages from database~n"
"~n"

View File

@ -37,19 +37,23 @@ import_file(File) ->
{'EXIT', Reason} ->
?ERROR_MSG(
"Error while processing file \"~s\": ~p~n",
[File, Reason]);
[File, Reason]),
{error, Reason};
_ ->
ok
end;
{error, Reason} ->
?ERROR_MSG("Can't parse file \"~s\": ~p~n",
[File, Reason])
[File, Reason]),
{error, Reason}
end;
{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;
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.
@ -65,11 +69,15 @@ import_dir(Dir) ->
false
end
end, Files),
lists:foreach(
fun(FN) ->
import_file(filename:join([Dir, FN]))
end, MsgFiles),
ok.
lists:foldl(
fun(FN, A) ->
Res = import_file(filename:join([Dir, FN])),
case {A, Res} of
{ok, ok} -> ok;
{ok, _} -> {error, "see ejabberd log for details"};
_ -> A
end
end, ok, MsgFiles).
%%%----------------------------------------------------------------------
%%% Internal functions
@ -99,6 +107,14 @@ xdb_data(User, Server, {xmlelement, _Name, Attrs, _Els} = El) ->
?NS_ROSTER ->
catch mod_roster:set_items(User, Server, El),
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 ->
catch mod_vcard:process_sm_iq(
From,

View File

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

View File

@ -16,7 +16,8 @@
stop/0,
process_local_iq/3,
process_sm_iq/3,
on_presence_update/3,
on_presence_update/4,
store_last_info/4,
remove_user/1]).
-include("ejabberd.hrl").
@ -120,10 +121,13 @@ get_last(IQ, SubEl, LUser) ->
on_presence_update(User, _Resource, Status) ->
LUser = jlib:nodeprep(User),
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),
Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status),