* src/mod_vcard_ldap.erl: Bugfix

* src/mod_vcard.erl: Bugfix

* src/ejabberd_auth_odbc.erl: Bugfix

* doc/dev.tex: Updated

SVN Revision: 406
This commit is contained in:
Alexey Shchepin 2005-08-25 20:48:45 +00:00
parent ee3551db4b
commit a884ba4e8a
6 changed files with 163 additions and 113 deletions

View File

@ -1,3 +1,17 @@
2005-08-25 Alexey Shchepin <alexey@sevcom.net>
* src/mod_vcard_ldap.erl: Bugfix
* src/mod_vcard.erl: Bugfix
2005-08-23 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_auth_odbc.erl: Bugfix
2005-08-21 Alexey Shchepin <alexey@sevcom.net>
* doc/dev.tex: Updated
2005-08-11 Alexey Shchepin <alexey@sevcom.net> 2005-08-11 Alexey Shchepin <alexey@sevcom.net>
* src/cyrsasl_digest.erl: Fixed challenge/response parsing (thanks * src/cyrsasl_digest.erl: Fixed challenge/response parsing (thanks

View File

@ -4,7 +4,7 @@
<HEAD><TITLE>Ejabberd Developers Guide</TITLE> <HEAD><TITLE>Ejabberd Developers 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.06"> <META name="GENERATOR" content="hevea 1.07">
</HEAD> </HEAD>
<BODY > <BODY >
<!--HEVEA command line is: /usr/bin/hevea -charset ISO8859-1 dev.tex --> <!--HEVEA command line is: /usr/bin/hevea -charset ISO8859-1 dev.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>September 10, 2003</H3><DIV ALIGN=center> <H3 ALIGN=center>August 21, 2005</H3><DIV ALIGN=center>
<IMG SRC="logo.png"> <IMG SRC="logo.png">
@ -47,11 +47,12 @@
</UL> </UL>
<LI><A HREF="#htoc7">2&nbsp;&nbsp;XML representation</A> <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="#htoc8">3&nbsp;&nbsp;Module <TT>xml</TT></A>
<LI><A HREF="#htoc9">4&nbsp;&nbsp;<TT>ejabberd</TT> modules</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> <UL><LI>
<A HREF="#htoc10">4.1&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</A> <A HREF="#htoc11">5.1&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</A>
<LI><A HREF="#htoc11">4.2&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></A> <LI><A HREF="#htoc12">5.2&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></A>
<LI><A HREF="#htoc12">4.3&nbsp;&nbsp;Services</A> <LI><A HREF="#htoc13">5.3&nbsp;&nbsp;Services</A>
</UL> </UL>
</UL> </UL>
@ -90,9 +91,6 @@ Works on most of popular platforms: *nix (tested on Linux, FreeBSD and
<LI>Support for <A HREF="http://www.jabber.org/jeps/jep-0039.html">Statistics Gathering</A>. <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>
<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 -->
@ -158,7 +156,7 @@ does not exist, then it is opened and registered.<BR>
<H2><A NAME="htoc7">2</A>&nbsp;&nbsp;XML representation</H2><!--SEC END --> <H2><A NAME="htoc7">2</A>&nbsp;&nbsp;XML representation</H2><!--SEC END -->
<A NAME="sec:xmlrepr"></A> <A NAME="sec:xmlrepr"></A>
Each XML stanza represented as following tuple: Each XML stanza is represented as the following tuple:
<PRE> <PRE>
XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]} XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string() Name = string()
@ -173,7 +171,7 @@ XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
&lt;message to='test@conference.example.org' 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>is represented as the following structure:
<PRE> <PRE>
{xmlelement, "message", {xmlelement, "message",
[{"to", "test@conference.example.org"}, [{"to", "test@conference.example.org"},
@ -233,21 +231,34 @@ Res = string() | XMLElement
get_tag_attr/2, get_tag_attr_s/2 get_tag_attr/2, get_tag_attr_s/2
get_subtag/2 get_subtag/2
</PRE></DL> </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--> <!--TOC section <TT>ejabberd</TT> modules-->
<H2><A NAME="htoc9">4</A>&nbsp;&nbsp;<TT>ejabberd</TT> modules</H2><!--SEC END --> <H2><A NAME="htoc10">5</A>&nbsp;&nbsp;<TT>ejabberd</TT> modules</H2><!--SEC END -->
<A NAME="sec:emods"></A> <A NAME="sec:emods"></A>
<!--TOC subsection <CODE>gen_mod</CODE> behaviour--> <!--TOC subsection <CODE>gen_mod</CODE> behaviour-->
<H3><A NAME="htoc10">4.1</A>&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</H3><!--SEC END --> <H3><A NAME="htoc11">5.1</A>&nbsp;&nbsp;<CODE>gen_mod</CODE> behaviour</H3><!--SEC END -->
<A NAME="sec:genmod"></A> <A NAME="sec:genmod"></A>
TBD<BR> TBD<BR>
<BR> <BR>
<!--TOC subsection Module <CODE>gen_iq_handler</CODE>--> <!--TOC subsection Module <CODE>gen_iq_handler</CODE>-->
<H3><A NAME="htoc11">4.2</A>&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></H3><!--SEC END --> <H3><A NAME="htoc12">5.2</A>&nbsp;&nbsp;Module <CODE>gen_iq_handler</CODE></H3><!--SEC END -->
<A NAME="sec:geniqhandl"></A> <A NAME="sec:geniqhandl"></A>
The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets
@ -255,23 +266,25 @@ of particular XML namespaces that addressed to server or to users bare JIDs.<BR>
<BR> <BR>
In this module the following functions are defined: In this module the following functions are defined:
<DL COMPACT=compact><DT> <DL COMPACT=compact><DT>
<CODE><B>add_iq_handler(Component, NS, Module, Function, Type)</B></CODE><DD> <CODE><B>add_iq_handler(Component, Host, NS, Module, Function, Type)</B></CODE><DD>
<PRE> <PRE>
Component = Module = Function = atom() Component = Module = Function = atom()
NS = string() Host = NS = string()
Type = no_queue | one_queue | parallel Type = no_queue | one_queue | parallel
</PRE>Registers function <CODE>Module:Function</CODE> as handler for IQ packets that </PRE>Registers function <CODE>Module:Function</CODE> as handler for IQ packets on
contain child of namespace <CODE>NS</CODE> in <CODE>Component</CODE>. Queueing virtual host <CODE>Host</CODE> that contain child of namespace <CODE>NS</CODE> in
discipline is <CODE>Type</CODE>. There are at least two components defined: <CODE>Component</CODE>. Queueing discipline is <CODE>Type</CODE>. There are at least
two components defined:
<DL COMPACT=compact><DT> <DL COMPACT=compact><DT>
<CODE><B>ejabberd_local</B></CODE><DD> Handles packets that addressed to server JID; <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. <DT><CODE><B>ejabberd_sm</B></CODE><DD> Handles packets that addressed to users bare JIDs.
</DL> </DL>
<DT><CODE><B>remove_iq_handler(Component, NS)</B></CODE><DD> <DT><CODE><B>remove_iq_handler(Component, Host, NS)</B></CODE><DD>
<PRE> <PRE>
Component = atom() Component = atom()
NS = string() Host = NS = string()
</PRE>Removes IQ handler for namespace <CODE>NS</CODE> from <CODE>Component</CODE>. </PRE>Removes IQ handler on virtual host <CODE>Host</CODE> for namespace <CODE>NS</CODE> from
<CODE>Component</CODE>.
</DL> </DL>
Handler function must have the following type: Handler function must have the following type:
<DL COMPACT=compact><DT> <DL COMPACT=compact><DT>
@ -284,8 +297,8 @@ From = To = jid()
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/1, -export([start/2,
stop/0, stop/1,
process_local_iq/3]). process_local_iq/3]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -293,13 +306,13 @@ From = To = jid()
-define(NS_CPUTIME, "ejabberd:cputime"). -define(NS_CPUTIME, "ejabberd:cputime").
start(Opts) -&gt; start(Host, Opts) -&gt;
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_CPUTIME, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc). ?MODULE, process_local_iq, IQDisc).
stop() -&gt; stop(Host) -&gt;
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_CPUTIME). gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt; process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
case Type of case Type of
@ -317,7 +330,7 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
</PRE> </PRE>
<!--TOC subsection Services--> <!--TOC subsection Services-->
<H3><A NAME="htoc12">4.3</A>&nbsp;&nbsp;Services</H3><!--SEC END --> <H3><A NAME="htoc13">5.3</A>&nbsp;&nbsp;Services</H3><!--SEC END -->
<A NAME="sec:services"></A> <A NAME="sec:services"></A>
TBD<BR> TBD<BR>
@ -328,14 +341,15 @@ TODO: use <CODE>proc_lib</CODE>
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/1, init/1, stop/0]). -export([start/2, init/1, stop/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
start(Opts) -&gt; start(Host, Opts) -&gt;
Host = gen_mod:get_opt(host, Opts, "echo." ++ ?MYNAME), MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(ejabberd_mod_echo, spawn(?MODULE, init, [Host])). register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) -&gt; init(Host) -&gt;
ejabberd_router:register_local_route(Host), ejabberd_router:register_local_route(Host),
@ -347,15 +361,16 @@ loop(Host) -&gt;
ejabberd_router:route(To, From, Packet), ejabberd_router:route(To, From, Packet),
loop(Host); loop(Host);
stop -&gt; stop -&gt;
ejabberd_router:unregister_local_route(Host), ejabberd_router:unregister_route(Host),
ok; ok;
_ -&gt; _ -&gt;
loop(Host) loop(Host)
end. end.
stop() -&gt; stop(Host) -&gt;
ejabberd_mod_echo ! stop, Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ok. Proc ! stop,
{wait, Proc}.
</PRE> </PRE>
<!--HTMLFOOT--> <!--HTMLFOOT-->
<!--ENDHTML--> <!--ENDHTML-->

View File

@ -41,7 +41,7 @@
\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{September 10, 2003} \date{August 21, 2005}
\begin{document} \begin{document}
\begin{titlepage} \begin{titlepage}
@ -89,8 +89,6 @@ The main features of \ejabberd{} are:
\item Support for \tjepref{0039}{Statistics Gathering}. \item Support for \tjepref{0039}{Statistics Gathering}.
\item Support for \ns{xml:lang} \item Support for \ns{xml:lang}
\end{itemize} \end{itemize}
\ejabberd{} is a Free and Open Source fault-tolerant distributed \Jabber{}
server. It is written mostly in Erlang.
@ -158,7 +156,7 @@ does not exist, then it is opened and registered.
\section{XML representation} \section{XML representation}
\label{sec:xmlrepr} \label{sec:xmlrepr}
Each XML stanza represented as following tuple: Each XML stanza is represented as the following tuple:
\begin{verbatim} \begin{verbatim}
XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]} XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string() Name = string()
@ -175,7 +173,7 @@ E.\,g. this stanza:
<body>test</body> <body>test</body>
</message> </message>
\end{verbatim} \end{verbatim}
represented as following structure: is represented as the following structure:
\begin{verbatim} \begin{verbatim}
{xmlelement, "message", {xmlelement, "message",
[{"to", "test@conference.example.org"}, [{"to", "test@conference.example.org"},
@ -245,6 +243,18 @@ Res = string() | XMLElement
\end{description} \end{description}
\section{Module \texttt{xml\_stream}}
\label{sec:xmlstreammod}
\begin{description}
\item[\verb!parse_element(Str) -> XMLElement | {error, Err}!]
\begin{verbatim}
Str = string()
Err = term()
\end{verbatim}
Parses \texttt{Str} using XML parser, returns either parsed element or error
tuple.
\end{description}
\section{\ejabberd{} modules} \section{\ejabberd{} modules}
@ -264,25 +274,27 @@ of particular XML namespaces that addressed to server or to users bare JIDs.
In this module the following functions are defined: In this module the following functions are defined:
\begin{description} \begin{description}
\item[\verb|add_iq_handler(Component, NS, Module, Function, Type)|] \item[\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|]
\begin{verbatim} \begin{verbatim}
Component = Module = Function = atom() Component = Module = Function = atom()
NS = string() Host = NS = string()
Type = no_queue | one_queue | parallel Type = no_queue | one_queue | parallel
\end{verbatim} \end{verbatim}
Registers function \verb|Module:Function| as handler for IQ packets that Registers function \verb|Module:Function| as handler for IQ packets on
contain child of namespace \verb|NS| in \verb|Component|. Queueing virtual host \verb|Host| that contain child of namespace \verb|NS| in
discipline is \verb|Type|. There are at least two components defined: \verb|Component|. Queueing discipline is \verb|Type|. There are at least
two components defined:
\begin{description} \begin{description}
\item[\verb|ejabberd_local|] Handles packets that addressed to server JID; \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_sm|] Handles packets that addressed to users bare JIDs.
\end{description} \end{description}
\item[\verb|remove_iq_handler(Component, NS)|] \item[\verb|remove_iq_handler(Component, Host, NS)|]
\begin{verbatim} \begin{verbatim}
Component = atom() Component = atom()
NS = string() Host = NS = string()
\end{verbatim} \end{verbatim}
Removes IQ handler for namespace \verb|NS| from \verb|Component|. Removes IQ handler on virtual host \verb|Host| for namespace \verb|NS| from
\verb|Component|.
\end{description} \end{description}
Handler function must have the following type: Handler function must have the following type:
@ -300,8 +312,8 @@ From = To = jid()
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/1, -export([start/2,
stop/0, stop/1,
process_local_iq/3]). process_local_iq/3]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -309,13 +321,13 @@ From = To = jid()
-define(NS_CPUTIME, "ejabberd:cputime"). -define(NS_CPUTIME, "ejabberd:cputime").
start(Opts) -> start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_CPUTIME, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc). ?MODULE, process_local_iq, IQDisc).
stop() -> stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_CPUTIME). gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of case Type of
@ -345,14 +357,15 @@ TODO: use \verb|proc_lib|
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/1, init/1, stop/0]). -export([start/2, init/1, stop/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
start(Opts) -> start(Host, Opts) ->
Host = gen_mod:get_opt(host, Opts, "echo." ++ ?MYNAME), MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(ejabberd_mod_echo, spawn(?MODULE, init, [Host])). register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) -> init(Host) ->
ejabberd_router:register_local_route(Host), ejabberd_router:register_local_route(Host),
@ -364,15 +377,16 @@ loop(Host) ->
ejabberd_router:route(To, From, Packet), ejabberd_router:route(To, From, Packet),
loop(Host); loop(Host);
stop -> stop ->
ejabberd_router:unregister_local_route(Host), ejabberd_router:unregister_route(Host),
ok; ok;
_ -> _ ->
loop(Host) loop(Host)
end. end.
stop() -> stop(Host) ->
ejabberd_mod_echo ! stop, Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ok. Proc ! stop,
{wait, Proc}.
\end{verbatim} \end{verbatim}

View File

@ -122,11 +122,12 @@ dirty_get_registered_users() ->
get_vh_registered_users(?MYNAME). get_vh_registered_users(?MYNAME).
get_vh_registered_users(Server) -> get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
case catch ejabberd_odbc:sql_query( case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server), LServer,
"select username from users") of "select username from users") of
{selected, ["username"], Res} -> {selected, ["username"], Res} ->
[U || {U} <- Res]; [{U, LServer} || {U} <- Res];
_ -> _ ->
[] []
end. end.

View File

@ -12,7 +12,7 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, init/2, stop/1, -export([start/2, init/3, stop/1,
process_local_iq/3, process_local_iq/3,
process_sm_iq/3, process_sm_iq/3,
reindex_vcards/0, reindex_vcards/0,
@ -70,36 +70,36 @@ start(Host, Opts) ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
catch mod_disco:register_sm_feature(Host, ?NS_VCARD), catch mod_disco:register_sm_feature(Host, ?NS_VCARD),
Hosts = gen_mod:get_hosts(Opts, "vjud."), MyHost = gen_mod:get_opt(host, Opts, "vjud." ++ Host),
Search = gen_mod:get_opt(search, Opts, true), Search = gen_mod:get_opt(search, Opts, true),
register(gen_mod:get_module_proc(Host, ?PROCNAME), register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [Hosts, Search])). spawn(?MODULE, init, [MyHost, Host, Search])).
init(Hosts, Search) -> init(Host, ServerHost, Search) ->
case Search of case Search of
false -> false ->
loop(Hosts); loop(Host, ServerHost);
_ -> _ ->
ejabberd_router:register_routes(Hosts), ejabberd_router:register_route(Host),
loop(Hosts) loop(Host, ServerHost)
end. end.
loop(Hosts) -> loop(Host, ServerHost) ->
receive receive
{route, From, To, Packet} -> {route, From, To, Packet} ->
case catch do_route(From, To, Packet) of case catch do_route(ServerHost, From, To, Packet) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p", [Reason]);
_ -> _ ->
ok ok
end, end,
loop(Hosts); loop(Host, ServerHost);
stop -> stop ->
catch ejabberd_router:unregister_routes(Hosts), ejabberd_router:unregister_route(Host),
ok; ok;
_ -> _ ->
loop(Hosts) loop(Host, ServerHost)
end. end.
stop(Host) -> stop(Host) ->
@ -272,7 +272,7 @@ set_vcard(User, LServer, VCARD) ->
do_route(From, To, Packet) -> do_route(ServerHost, From, To, Packet) ->
#jid{user = User, resource = Resource} = To, #jid{user = User, resource = Resource} = To,
if if
(User /= "") or (Resource /= "") -> (User /= "") or (Resource /= "") ->
@ -310,7 +310,7 @@ do_route(From, To, Packet) ->
[{xmlelement, "x", [{xmlelement, "x",
[{"xmlns", ?NS_XDATA}, [{"xmlns", ?NS_XDATA},
{"type", "result"}], {"type", "result"}],
search_result(Lang, To, XData) search_result(Lang, To, ServerHost, XData)
}]}]}, }]}]},
ejabberd_router:route( ejabberd_router:route(
To, From, jlib:iq_to_xml(ResIQ)) To, From, jlib:iq_to_xml(ResIQ))
@ -420,7 +420,7 @@ find_xdata_el1([_ | Els]) ->
{xmlelement, "field", [{"label", translate:translate(Lang, Label)}, {xmlelement, "field", [{"label", translate:translate(Lang, Label)},
{"var", Var}], []}). {"var", Var}], []}).
search_result(Lang, JID, Data) -> search_result(Lang, JID, ServerHost, Data) ->
[{xmlelement, "title", [], [{xmlelement, "title", [],
[{xmlcdata, translate:translate(Lang, "Results of search in ") ++ [{xmlcdata, translate:translate(Lang, "Results of search in ") ++
jlib:jid_to_string(JID)}]}, jlib:jid_to_string(JID)}]},
@ -437,7 +437,7 @@ search_result(Lang, JID, Data) ->
?LFIELD("email", "email"), ?LFIELD("email", "email"),
?LFIELD("Organization Name", "orgname"), ?LFIELD("Organization Name", "orgname"),
?LFIELD("Organization Unit", "orgunit") ?LFIELD("Organization Unit", "orgunit")
]}] ++ lists:map(fun record_to_item/1, search(JID#jid.lserver, Data)). ]}] ++ lists:map(fun record_to_item/1, search(ServerHost, Data)).
-define(FIELD(Var, Val), -define(FIELD(Var, Val),
{xmlelement, "field", [{"var", Var}], {xmlelement, "field", [{"var", Var}],

View File

@ -12,7 +12,7 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([start/2, init/2, stop/1, -export([start/2, init/3, stop/1,
process_local_iq/3, process_local_iq/3,
process_sm_iq/3, process_sm_iq/3,
remove_user/1]). remove_user/1]).
@ -21,6 +21,7 @@
-include("eldap/eldap.hrl"). -include("eldap/eldap.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
-define(PROCNAME, ejabberd_mod_vcard_ldap).
start(Host, Opts) -> start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
@ -28,45 +29,47 @@ start(Host, Opts) ->
?MODULE, process_local_iq, IQDisc), ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
?MODULE, process_sm_iq, IQDisc), ?MODULE, process_sm_iq, IQDisc),
LDAPServers = ejabberd_config:get_local_option(ldap_servers), LDAPServers = ejabberd_config:get_local_option({ldap_servers, Host}),
RootDN = ejabberd_config:get_local_option(ldap_rootdn), RootDN = ejabberd_config:get_local_option({ldap_rootdn, Host}),
Password = ejabberd_config:get_local_option(ldap_password), Password = ejabberd_config:get_local_option({ldap_password, Host}),
eldap:start_link("mod_vcard_ldap", LDAPServers, 389, RootDN, Password), eldap:start_link("mod_vcard_ldap", LDAPServers, 389, RootDN, Password),
Host = gen_mod:get_opt(host, Opts, "vjud." ++ ?MYNAME), MyHost = gen_mod:get_opt(host, Opts, "vjud." ++ Host),
Search = gen_mod:get_opt(search, Opts, true), Search = gen_mod:get_opt(search, Opts, true),
register(ejabberd_mod_vcard_ldap, spawn(?MODULE, init, [Host, Search])). register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost, Host, Search])).
init(Host, Search) -> init(Host, ServerHost, Search) ->
case Search of case Search of
false -> false ->
loop(Host); loop(Host, ServerHost);
_ -> _ ->
ejabberd_router:register_route(Host), ejabberd_router:register_route(Host),
loop(Host) loop(Host, ServerHost)
end. end.
loop(Host) -> loop(Host, ServerHost) ->
receive receive
{route, From, To, Packet} -> {route, From, To, Packet} ->
case catch do_route(From, To, Packet) of case catch do_route(ServerHost, From, To, Packet) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p", [Reason]);
_ -> _ ->
ok ok
end, end,
loop(Host); loop(Host, ServerHost);
stop -> stop ->
catch ejabberd_router:unregister_route(Host), ejabberd_router:unregister_route(Host),
ok; ok;
_ -> _ ->
loop(Host) loop(Host, ServerHost)
end. end.
stop(Host) -> stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD),
ejabberd_mod_vcard_ldap ! stop, Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ok. Proc ! stop,
{wait, Proc}.
process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of case Type of
@ -92,10 +95,10 @@ process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ)
]}]} ]}]}
end. end.
find_ldap_user(User) -> find_ldap_user(Host, User) ->
Attr = ejabberd_config:get_local_option(ldap_uidattr), Attr = ejabberd_config:get_local_option({ldap_uidattr, Host}),
Filter = eldap:equalityMatch(Attr, User), Filter = eldap:equalityMatch(Attr, User),
Base = ejabberd_config:get_local_option(ldap_base), Base = ejabberd_config:get_local_option({ldap_base, Host}),
case eldap:search("mod_vcard_ldap", [{base, Base}, case eldap:search("mod_vcard_ldap", [{base, Base},
{filter, Filter}, {filter, Filter},
{attributes, []}]) of {attributes, []}]) of
@ -192,12 +195,13 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
set -> set ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get -> get ->
#jid{luser = LUser} = To, #jid{luser = LUser, lserver = LServer} = To,
case find_ldap_user(LUser) of case find_ldap_user(LServer, LUser) of
#eldap_entry{attributes = Attributes} -> #eldap_entry{attributes = Attributes} ->
Vcard = ldap_attributes_to_vcard(Attributes,From,To), Vcard = ldap_attributes_to_vcard(Attributes,From,To),
IQ#iq{type = result, sub_el = Vcard}; IQ#iq{type = result, sub_el = Vcard};
_ -> IQ#iq{type = result, sub_el = []} _ ->
IQ#iq{type = result, sub_el = []}
end end
end. end.
@ -234,7 +238,7 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
do_route(From, To, Packet) -> do_route(ServerHost, From, To, Packet) ->
#jid{user = User, resource = Resource} = To, #jid{user = User, resource = Resource} = To,
if if
(User /= "") or (Resource /= "") -> (User /= "") or (Resource /= "") ->
@ -272,7 +276,7 @@ do_route(From, To, Packet) ->
[{xmlelement, "x", [{xmlelement, "x",
[{"xmlns", ?NS_XDATA}, [{"xmlns", ?NS_XDATA},
{"type", "result"}], {"type", "result"}],
search_result(Lang, To, XData) search_result(Lang, To, ServerHost, XData)
}]}]}, }]}]},
ejabberd_router:route( ejabberd_router:route(
To, From, jlib:iq_to_xml(ResIQ)) To, From, jlib:iq_to_xml(ResIQ))
@ -382,7 +386,7 @@ find_xdata_el1([_ | Els]) ->
{xmlelement, "field", [{"label", translate:translate(Lang, Label)}, {xmlelement, "field", [{"label", translate:translate(Lang, Label)},
{"var", Var}], []}). {"var", Var}], []}).
search_result(Lang, JID, Data) -> search_result(Lang, JID, ServerHost, Data) ->
[{xmlelement, "title", [], [{xmlelement, "title", [],
[{xmlcdata, translate:translate(Lang, "Results of search in ") ++ [{xmlcdata, translate:translate(Lang, "Results of search in ") ++
jlib:jid_to_string(JID)}]}, jlib:jid_to_string(JID)}]},
@ -401,7 +405,7 @@ search_result(Lang, JID, Data) ->
?LFIELD("Organization Unit", "orgunit") ?LFIELD("Organization Unit", "orgunit")
]}] ++ lists:map(fun(E) -> ]}] ++ lists:map(fun(E) ->
record_to_item(E#eldap_entry.attributes) record_to_item(E#eldap_entry.attributes)
end, search(JID#jid.lserver, Data)). end, search(ServerHost, Data)).
-define(FIELD(Var, Val), -define(FIELD(Var, Val),
{xmlelement, "field", [{"var", Var}], {xmlelement, "field", [{"var", Var}],
@ -491,8 +495,8 @@ record_to_item(Attributes) ->
search(LServer, Data) -> search(LServer, Data) ->
Filter = make_filter(Data), Filter = make_filter(Data),
Base = ejabberd_config:get_local_option(ldap_base), Base = ejabberd_config:get_local_option({ldap_base, LServer}),
UIDAttr = ejabberd_config:get_local_option(ldap_uidattr), UIDAttr = ejabberd_config:get_local_option({ldap_uidattr, LServer}),
case eldap:search("mod_vcard_ldap",[{base, Base}, case eldap:search("mod_vcard_ldap",[{base, Base},
{filter, Filter}, {filter, Filter},
{attributes, []}]) of {attributes, []}]) of
@ -500,15 +504,17 @@ search(LServer, Data) ->
[X || X <- E, [X || X <- E,
ejabberd_auth:is_user_exists( ejabberd_auth:is_user_exists(
ldap_get_value(X, UIDAttr), LServer)]; ldap_get_value(X, UIDAttr), LServer)];
_ -> Err ->
?ERROR_MSG("~p", ["Bad search"]) ?ERROR_MSG("Bad search: ~p", [[LServer, {base, Base},
{filter, Filter},
{attributes, []}]])
end. end.
make_filter(Data) -> make_filter(Data) ->
Filter = [X || X <- lists:map(fun(R) -> Filter = [X || X <- lists:map(fun(R) ->
make_assertion(R) make_assertion(R)
end,Data), end, Data),
X /= none ], X /= none ],
case Filter of case Filter of
[F] -> [F] ->