25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Merge from trunk (r1563 to r1613).

PR:		EJABP-1

SVN Revision: 1614
This commit is contained in:
Jean-Sébastien Pédron 2008-10-08 12:02:30 +00:00
parent aaecdc4b8a
commit 67a87af459
34 changed files with 1106 additions and 560 deletions

View File

@ -1,3 +1,7 @@
2008-10-08 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
Merge from trunk (r1563 to r1613).
2008-10-07 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-10-07 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/ejabberd_local.erl: Fix a bug where an error stanza was not * src/ejabberd_local.erl: Fix a bug where an error stanza was not
@ -9,6 +13,10 @@
* src/mod_private.erl, src/mod_private_odbc.erl, src/mod_version.erl: * src/mod_private.erl, src/mod_private_odbc.erl, src/mod_version.erl:
Convert to exmpp. Thanks to Pablo Polvorin! Convert to exmpp. Thanks to Pablo Polvorin!
2008-10-07 Jerome Sautret <jerome.sautret@process-one.net>
* src/mod_roster_odbc.erl: fix MySQL multiple requests issue.
2008-10-06 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-10-06 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/ejabberd_sm.erl (process_iq/3): Fix a bug where we were matching * src/ejabberd_sm.erl (process_iq/3): Fix a bug where we were matching
@ -32,6 +40,29 @@
mixing lists and binaries in a non-working way. Thanks to Pablo mixing lists and binaries in a non-working way. Thanks to Pablo
Polvorin! Polvorin!
2008-10-06 Badlop <badlop@process-one.net>
* doc/guide.html: Regenerated
2008-10-06 Jerome Sautret <jerome.sautret@process-one.net>
* src/ejabberd_rdbms.erl: fix SQL database reconnection
issues (EJAB-764) and add odbc_start_interval configuration
directive (default to 30 seconds).
* src/odbc/ejabberd_odbc.erl: likewise.
* src/odbc/ejabberd_odbc_sup.erl: likewise.
* doc/guide.tex: likewise.
2008-10-03 Jerome Sautret <jerome.sautret@process-one.net>
* src/odbc/odbc_queries.erl: Fix empty query that fail on MySQL.
2008-10-03 Jerome Sautret <jerome.sautret@process-one.net>
* src/mod_vcard_odbc: added vCard support for MS SQL Server 2005.
* src/odbc/odbc_queries.erl: likewise.
* src/odbc/mssql2005.sql: likewise.
2008-10-02 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-10-02 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_roster_odbc.erl: Fix a bug where a JID represented as a * src/mod_roster_odbc.erl: Fix a bug where a JID represented as a
@ -59,6 +90,17 @@
src/mod_roster_odbc.erl: Fix multiple bugs in ODBC mods, thanks to src/mod_roster_odbc.erl: Fix multiple bugs in ODBC mods, thanks to
Pablo Polvorin! Pablo Polvorin!
2008-10-01 Mickael Remond <mremond@process-one.net>
* src/mod_shared_roster.erl: Correct roster push when changing
a shared roster entry name (EJAB-738).
2008-09-30 Badlop <badlop@process-one.net>
* src/*/Makefile.win32: Provide explicit beam filenames because
nmake does not accept wildcards (thanks to Attila
Vangel)(EJAB-543)
2008-09-29 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-09-29 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/jlib.erl (parse_xdata_submit, parse_xdata_fields): Fix a bug * src/jlib.erl (parse_xdata_submit, parse_xdata_fields): Fix a bug
@ -99,6 +141,25 @@
Ejabberd expects new structures. Add table conversion. Add try/catch Ejabberd expects new structures. Add table conversion. Add try/catch
block around exmpp_stringprep:*prep/1 uses. block around exmpp_stringprep:*prep/1 uses.
2008-09-24 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: Allow PEP node type to be mapped with
namespace (EJAB-739). Change get_items to use From (EJAB-751). (Thanks
to Eric Cestari)
* src/mod_pubsub/gen_pubsub_node.erl: Likewise
* src/mod_pubsub/node_dispatch.erl: Likewise
* src/mod_pubsub/node_buddy.erl: Likewise
* src/mod_pubsub/node_zoo.erl: Likewise
* src/mod_pubsub/node.template: Likewise
* src/mod_pubsub/node_private.erl: Likewise
* src/mod_pubsub/node_public.erl: Likewise
* src/mod_pubsub/node_default.erl: Likewise
* src/mod_pubsub/node_pep.erl: Likewise
* src/mod_pubsub/node_club.erl: Likewise
* src/mod_pubsub/node_mb.erl: Added PEP microglobing node (Thanks to
Eric Cestari)
2008-09-23 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-09-23 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_vcard.erl (process_sm_iq): Fix a bug where a badmatch * src/mod_vcard.erl (process_sm_iq): Fix a bug where a badmatch
@ -126,6 +187,11 @@
* src/mod_vcard_ldap.erl, src/mod_vcard_odbc.erl: Convert to exmpp. * src/mod_vcard_ldap.erl, src/mod_vcard_odbc.erl: Convert to exmpp.
2008-09-22 Mickael Remond <mremond@process-one.net>
* src/mod_configure.erl: Fix adhoc commands reply types for
"get-online-users-num" and "get-registered-users-num" (EJAB-756).
2008-09-18 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-09-18 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_roster_odbc.erl: Convert to exmpp. * src/mod_roster_odbc.erl: Convert to exmpp.

View File

@ -514,7 +514,7 @@ indicates you need to also update those tables.</P><P> <A NAME="configure"></A>
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc20">3.1</A>&#XA0;&#XA0;<A HREF="#basicconfig">Basic Configuration</A></H2><!--SEC END --><P> <A NAME="basicconfig"></A> </P><P>The configuration file will be loaded the first time you start <TT>ejabberd</TT>. The <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc20">3.1</A>&#XA0;&#XA0;<A HREF="#basicconfig">Basic Configuration</A></H2><!--SEC END --><P> <A NAME="basicconfig"></A> </P><P>The configuration file will be loaded the first time you start <TT>ejabberd</TT>. The
content from this file will be parsed and stored in the internal <TT>ejabberd</TT> database. Subsequently the content from this file will be parsed and stored in the internal <TT>ejabberd</TT> database. Subsequently the
configuration will be loaded from the database and any commands in the configuration will be loaded from the database and any commands in the
configuration file are appended to the entries in the database. </P><P>Note that <TT>ejabberd</TT> never edits the configuration file. configuration file are appended to the entries in the database.</P><P>Note that <TT>ejabberd</TT> never edits the configuration file.
So, the configuration changes done using the Web Admin So, the configuration changes done using the Web Admin
are stored in the database, but are not reflected in the configuration file. are stored in the database, but are not reflected in the configuration file.
If you want those changes to be use after <TT>ejabberd</TT> restart, you can either If you want those changes to be use after <TT>ejabberd</TT> restart, you can either
@ -635,7 +635,7 @@ Handles c2s connections.<BR>
Handles incoming s2s connections.<BR> Handles incoming s2s connections.<BR>
Options: <TT>inet6</TT>, <TT>ip</TT>, <TT>max_stanza_size</TT> Options: <TT>inet6</TT>, <TT>ip</TT>, <TT>max_stanza_size</TT>
</DD><DT CLASS="dt-description"><B><TT>ejabberd_service</TT></B></DT><DD CLASS="dd-description"> </DD><DT CLASS="dt-description"><B><TT>ejabberd_service</TT></B></DT><DD CLASS="dd-description">
Interacts with <A HREF="http://www.ejabberd.im/tutorials-transports">external components</A> Interacts with an <A HREF="http://www.ejabberd.im/tutorials-transports">external component</A>
(as defined in the Jabber Component Protocol (<A HREF="http://www.xmpp.org/extensions/xep-0114.html">XEP-0114</A>).<BR> (as defined in the Jabber Component Protocol (<A HREF="http://www.xmpp.org/extensions/xep-0114.html">XEP-0114</A>).<BR>
Options: <TT>access</TT>, <TT>hosts</TT>, <TT>inet6</TT>, Options: <TT>access</TT>, <TT>hosts</TT>, <TT>inet6</TT>,
<TT>ip</TT>, <TT>shaper</TT>, <TT>service_check_from</TT> <TT>ip</TT>, <TT>shaper</TT>, <TT>service_check_from</TT>
@ -655,9 +655,10 @@ used to disable control on the from field on packets send by an
external components. The option can be either <TT>true</TT> or external components. The option can be either <TT>true</TT> or
<TT>false</TT>. The default value is <TT>true</TT> which conforms to <A HREF="http://www.xmpp.org/extensions/xep-0114.html">XEP-0114</A>. <TT>false</TT>. The default value is <TT>true</TT> which conforms to <A HREF="http://www.xmpp.org/extensions/xep-0114.html">XEP-0114</A>.
</DD><DT CLASS="dt-description"><B><TT>{hosts, [Hostnames], [HostOptions]}</TT></B></DT><DD CLASS="dd-description"> </DD><DT CLASS="dt-description"><B><TT>{hosts, [Hostnames], [HostOptions]}</TT></B></DT><DD CLASS="dd-description">
This option of <TT>ejabberd_service</TT> allows to define one or more hostnames The external Jabber component that connects to this <TT>ejabberd_service</TT>
of external Jabber components that provide a service. can serve one or more hostnames.
In <TT>HostOptions</TT> it is possible to define the password required to those components In <TT>HostOptions</TT> you can define options for the component;
currently the only allowed option is the password required to the component
when attempt to connect to ejabberd: <TT>{password, Secret}</TT>. when attempt to connect to ejabberd: <TT>{password, Secret}</TT>.
Note that you cannot define in a single <TT>ejabberd_service</TT> components of Note that you cannot define in a single <TT>ejabberd_service</TT> components of
different services: add an <TT>ejabberd_service</TT> for each service, different services: add an <TT>ejabberd_service</TT> for each service,
@ -1261,6 +1262,9 @@ to keep alive the connections to the database.
The default value is &#X2019;undefined&#X2019;, so no keepalive requests are made. The default value is &#X2019;undefined&#X2019;, so no keepalive requests are made.
Specify in seconds: for example 28800 means 8 hours. Specify in seconds: for example 28800 means 8 hours.
</P><PRE CLASS="verbatim">{odbc_keepalive_interval, undefined}. </P><PRE CLASS="verbatim">{odbc_keepalive_interval, undefined}.
</PRE><P>If the connection to the database fails, <TT>ejabberd</TT> waits 30 seconds before retrying.
You can modify this interval with this option:
</P><PRE CLASS="verbatim">{odbc_start_interval, 30}.
</PRE><P> <A NAME="compilemysql"></A> </P><!--TOC subsubsection Driver Compilation--> </PRE><P> <A NAME="compilemysql"></A> </P><!--TOC subsubsection Driver Compilation-->
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#compilemysql">Driver Compilation</A></H4><!--SEC END --><P> <A NAME="compilemysql"></A> <H4 CLASS="subsubsection"><!--SEC ANCHOR --><A HREF="#compilemysql">Driver Compilation</A></H4><!--SEC END --><P> <A NAME="compilemysql"></A>
</P><P>You can skip this step if you installed <TT>ejabberd</TT> using a binary installer or </P><P>You can skip this step if you installed <TT>ejabberd</TT> using a binary installer or
@ -2055,7 +2059,9 @@ change nickname.
status text in presence updates. If disallowed, the <TT>status</TT> status text in presence updates. If disallowed, the <TT>status</TT>
text is stripped before broadcasting the presence update to all text is stripped before broadcasting the presence update to all
the room occupants. the room occupants.
</DD><DT CLASS="dt-description"><B><TT>{anonymous, true}</TT></B></DT><DD CLASS="dd-description"> Occupants are allowed to see the real JIDs of other occupants. </DD><DT CLASS="dt-description"><B><TT>{anonymous, true}</TT></B></DT><DD CLASS="dd-description"> The room is anonymous:
occupants don&#X2019;t see the real JIDs of other occupants.
Note that the room moderators can always see the real JIDs of the occupants.
</DD><DT CLASS="dt-description"><B><TT>{logging, false}</TT></B></DT><DD CLASS="dd-description"> The public messages are logged using <TT>mod_muc_log</TT>. </DD><DT CLASS="dt-description"><B><TT>{logging, false}</TT></B></DT><DD CLASS="dd-description"> The public messages are logged using <TT>mod_muc_log</TT>.
</DD><DT CLASS="dt-description"><B><TT>{max_users, 200}</TT></B></DT><DD CLASS="dd-description"> Maximum number of occupants in the room. </DD><DT CLASS="dt-description"><B><TT>{max_users, 200}</TT></B></DT><DD CLASS="dd-description"> Maximum number of occupants in the room.
</DD><DT CLASS="dt-description"><B><TT>{members_by_default, true}</TT></B></DT><DD CLASS="dd-description"> The occupants that enter the room are participants by default, so they have &#X2019;voice&#X2019;. </DD><DT CLASS="dt-description"><B><TT>{members_by_default, true}</TT></B></DT><DD CLASS="dd-description"> The occupants that enter the room are participants by default, so they have &#X2019;voice&#X2019;.
@ -3184,11 +3190,15 @@ Copy <CODE>~ejabberd/.erlang.cookie</CODE> file from <TT>first</TT> to
<TT>second</TT>.<P>(alt) You can also add &#X2018;<CODE>-cookie content_of_.erlang.cookie</CODE>&#X2019; <TT>second</TT>.<P>(alt) You can also add &#X2018;<CODE>-cookie content_of_.erlang.cookie</CODE>&#X2019;
option to all &#X2018;<TT>erl</TT>&#X2019; commands below.</P></LI><LI CLASS="li-enumerate">On <TT>second</TT> run the following command as the <TT>ejabberd</TT> daemon user, option to all &#X2018;<TT>erl</TT>&#X2019; commands below.</P></LI><LI CLASS="li-enumerate">On <TT>second</TT> run the following command as the <TT>ejabberd</TT> daemon user,
in the working directory of <TT>ejabberd</TT>:<PRE CLASS="verbatim">erl -sname ejabberd \ in the working directory of <TT>ejabberd</TT>:<PRE CLASS="verbatim">erl -sname ejabberd \
-mnesia dir "/var/lib/ejabberd/" \
-mnesia extra_db_nodes "['ejabberd@first']" \ -mnesia extra_db_nodes "['ejabberd@first']" \
-s mnesia -s mnesia
</PRE><P>This will start Mnesia serving the same database as <TT>ejabberd@first</TT>. </PRE><P>This will start Mnesia serving the same database as <TT>ejabberd@first</TT>.
You can check this by running the command &#X2018;<CODE>mnesia:info().</CODE>&#X2019;. You You can check this by running the command &#X2018;<CODE>mnesia:info().</CODE>&#X2019;. You
should see a lot of remote tables and a line like the following:</P><PRE CLASS="verbatim">running db nodes = [ejabberd@first, ejabberd@second] should see a lot of remote tables and a line like the following:</P><P>Note: the Mnesia directory may be different in your system.
To know where does ejabberd expect Mnesia to be installed by default,
call <A HREF="#ejabberdctl">4.1</A> without options and it will show some help,
including the Mnesia database spool dir.</P><PRE CLASS="verbatim">running db nodes = [ejabberd@first, ejabberd@second]
</PRE></LI><LI CLASS="li-enumerate">Now run the following in the same &#X2018;<TT>erl</TT>&#X2019; session:<PRE CLASS="verbatim">mnesia:change_table_copy_type(schema, node(), disc_copies). </PRE></LI><LI CLASS="li-enumerate">Now run the following in the same &#X2018;<TT>erl</TT>&#X2019; session:<PRE CLASS="verbatim">mnesia:change_table_copy_type(schema, node(), disc_copies).
</PRE><P>This will create local disc storage for the database.</P><P>(alt) Change storage type of the <TT>scheme</TT> table to &#X2018;RAM and disc </PRE><P>This will create local disc storage for the database.</P><P>(alt) Change storage type of the <TT>scheme</TT> table to &#X2018;RAM and disc
copy&#X2019; on the second node via the Web Admin.</P></LI><LI CLASS="li-enumerate">Now you can add replicas of various tables to this node with copy&#X2019; on the second node via the Web Admin.</P></LI><LI CLASS="li-enumerate">Now you can add replicas of various tables to this node with

View File

@ -1617,6 +1617,13 @@ Specify in seconds: for example 28800 means 8 hours.
{odbc_keepalive_interval, undefined}. {odbc_keepalive_interval, undefined}.
\end{verbatim} \end{verbatim}
If the connection to the database fails, \ejabberd{} waits 30 seconds before retrying.
You can modify this interval with this option:
\begin{verbatim}
{odbc_start_interval, 30}.
\end{verbatim}
\makesubsubsection{compilemysql}{Driver Compilation} \makesubsubsection{compilemysql}{Driver Compilation}
\ind{MySQL!Driver Compilation} \ind{MySQL!Driver Compilation}

View File

@ -52,14 +52,21 @@ start_hosts() ->
%% Start the ODBC module on the given host %% Start the ODBC module on the given host
start_odbc(Host) -> start_odbc(Host) ->
Supervisor_name = gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
ChildSpec = ChildSpec =
{gen_mod:get_module_proc(Host, ejabberd_odbc_sup), {Supervisor_name,
{ejabberd_odbc_sup, start_link, [Host]}, {ejabberd_odbc_sup, start_link, [Host]},
temporary, transient,
infinity, infinity,
supervisor, supervisor,
[ejabberd_odbc_sup]}, [ejabberd_odbc_sup]},
supervisor:start_child(ejabberd_sup, ChildSpec). case supervisor:start_child(ejabberd_sup, ChildSpec) of
{ok, _PID} ->
ok;
_Error ->
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", [Supervisor_name, _Error]),
start_odbc(Host)
end.
%% Returns true if we have configured odbc_server for the given host %% Returns true if we have configured odbc_server for the given host
needs_odbc(Host) -> needs_odbc(Host) ->

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\ejabberd_zlib.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
SOURCE = ejabberd_zlib_drv.c SOURCE = ejabberd_zlib_drv.c
OBJECT = ejabberd_zlib_drv.o OBJECT = ejabberd_zlib_drv.o

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\eldap.beam ..\eldap_filter.beam ..\eldap_pool.beam ..\eldap_utils.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)

View File

@ -1240,7 +1240,7 @@ get_form(Host, ?NS_ADMINL("get-registered-users-num"), Lang) ->
[#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
[?HFIELD(), [?HFIELD(),
#xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs =
[#xmlattr{name = 'type', value = "jid-single"}, [#xmlattr{name = 'type', value = "text-single"},
#xmlattr{name = 'label', value = ?T(Lang, "Number of registered users")}, #xmlattr{name = 'label', value = ?T(Lang, "Number of registered users")},
#xmlattr{name = 'var', value = "registeredusersnum"}], children = #xmlattr{name = 'var', value = "registeredusersnum"}], children =
[#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(Num)}]}] [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(Num)}]}]
@ -1252,7 +1252,7 @@ get_form(Host, ?NS_ADMINL("get-online-users-num"), Lang) ->
[#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
[?HFIELD(), [?HFIELD(),
#xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs =
[#xmlattr{name = 'type', value = "jid-single"}, [#xmlattr{name = 'type', value = "text-single"},
#xmlattr{name = 'label', value = ?T(Lang, "Number of online users")}, #xmlattr{name = 'label', value = ?T(Lang, "Number of online users")},
#xmlattr{name = 'var', value = "onlineusersnum"}], children = #xmlattr{name = 'var', value = "onlineusersnum"}], children =
[#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(Num)}]}] [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(Num)}]}]

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\iconv.beam ..\mod_irc.beam ..\mod_irc_connection.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
SOURCE = iconv_erl.c SOURCE = iconv_erl.c
OBJECT = iconv_erl.o OBJECT = iconv_erl.o

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\mod_muc.beam ..\mod_muc_log.beam ..\mod_muc_room.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\mod_proxy65.beam ..\mod_proxy65_lib.beam ..\mod_proxy65_service.beam ..\mod_proxy65_sm.beam ..\mod_proxy65_stream.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)
@ -19,7 +18,7 @@ $(OUTDIR)\mod_proxy65_service.beam : mod_proxy65_service.erl
erlc -W $(EFLAGS) -o $(OUTDIR) mod_proxy65_service.erl erlc -W $(EFLAGS) -o $(OUTDIR) mod_proxy65_service.erl
$(OUTDIR)\mod_proxy65_sm.beam : mod_proxy65_sm.erl $(OUTDIR)\mod_proxy65_sm.beam : mod_proxy65_sm.erl
erlc -W $(EFLAGS) -o $(OUTDIR) mod_mod_proxy65_sm.erl erlc -W $(EFLAGS) -o $(OUTDIR) mod_proxy65_sm.erl
$(OUTDIR)\mod_proxy65_stream.beam : mod_proxy65_stream.erl $(OUTDIR)\mod_proxy65_stream.beam : mod_proxy65_stream.erl
erlc -W $(EFLAGS) -o $(OUTDIR) mod_proxy65_stream.erl erlc -W $(EFLAGS) -o $(OUTDIR) mod_proxy65_stream.erl

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\gen_pubsub_node.beam ..\gen_pubsub_nodetree.beam ..\mod_pubsub.beam ..\nodetree_default.beam ..\nodetree_virtual.beam ..\node_buddy.beam ..\node_club.beam ..\node_default.beam ..\node_dispatch.beam ..\node_pep.beam ..\node_private.beam ..\node_public.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)
@ -27,9 +26,23 @@ $(OUTDIR)\nodetree_default.beam : nodetree_default.erl
$(OUTDIR)\nodetree_virtual.beam : nodetree_virtual.erl $(OUTDIR)\nodetree_virtual.beam : nodetree_virtual.erl
erlc -W $(EFLAGS) -o $(OUTDIR) nodetree_virtual.erl erlc -W $(EFLAGS) -o $(OUTDIR) nodetree_virtual.erl
$(OUTDIR)\node_buddy.beam : node_buddy.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_buddy.erl
$(OUTDIR)\node_club.beam : node_club.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_club.erl
$(OUTDIR)\node_default.beam : node_default.erl $(OUTDIR)\node_default.beam : node_default.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_default.erl erlc -W $(EFLAGS) -o $(OUTDIR) node_default.erl
$(OUTDIR)\node_dispatch.beam : node_dispatch.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_dispatch.erl
$(OUTDIR)\node_pep.beam : node_pep.erl $(OUTDIR)\node_pep.beam : node_pep.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_pep.erl erlc -W $(EFLAGS) -o $(OUTDIR) node_pep.erl
$(OUTDIR)\node_private.beam : node_private.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_private.erl
$(OUTDIR)\node_public.beam : node_public.erl
erlc -W $(EFLAGS) -o $(OUTDIR) node_public.erl

View File

@ -63,7 +63,7 @@ behaviour_info(callbacks) ->
{get_state, 3}, {get_state, 3},
{set_state, 1}, {set_state, 1},
{get_items, 7}, {get_items, 7},
{get_items, 2}, {get_items, 3},
{get_item, 8}, {get_item, 8},
{get_item, 3}, {get_item, 3},
{set_item, 1}, {set_item, 1},

View File

@ -77,7 +77,8 @@
delete_item/4, delete_item/4,
get_configure/4, get_configure/4,
set_configure/5, set_configure/5,
get_items/2, get_items/3,
tree_action/3,
node_action/3, node_action/3,
node_action/4 node_action/4
]). ]).
@ -114,6 +115,7 @@
-record(state, {server_host, -record(state, {server_host,
host, host,
access, access,
pep_mapping = [],
nodetree = ?STDTREE, nodetree = ?STDTREE,
plugins = [?STDNODE]}). plugins = [?STDNODE]}).
@ -175,7 +177,7 @@ init([ServerHost, Opts]) ->
{?NS_PUBSUB, ejabberd_sm, iq_sm}, {?NS_PUBSUB, ejabberd_sm, iq_sm},
{?NS_PUBSUB_OWNER, ejabberd_sm, iq_sm}]), {?NS_PUBSUB_OWNER, ejabberd_sm, iq_sm}]),
ejabberd_router:register_route(Host), ejabberd_router:register_route(Host),
{Plugins, NodeTree} = init_plugins(Host, ServerHost, Opts), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
update_database(Host), update_database(Host),
ets:new(gen_mod:get_module_proc(Host, pubsub_state), [set, named_table]), ets:new(gen_mod:get_module_proc(Host, pubsub_state), [set, named_table]),
ets:insert(gen_mod:get_module_proc(Host, pubsub_state), {nodetree, NodeTree}), ets:insert(gen_mod:get_module_proc(Host, pubsub_state), {nodetree, NodeTree}),
@ -183,10 +185,12 @@ init([ServerHost, Opts]) ->
ets:new(gen_mod:get_module_proc(ServerHost, pubsub_state), [set, named_table]), ets:new(gen_mod:get_module_proc(ServerHost, pubsub_state), [set, named_table]),
ets:insert(gen_mod:get_module_proc(ServerHost, pubsub_state), {nodetree, NodeTree}), ets:insert(gen_mod:get_module_proc(ServerHost, pubsub_state), {nodetree, NodeTree}),
ets:insert(gen_mod:get_module_proc(ServerHost, pubsub_state), {plugins, Plugins}), ets:insert(gen_mod:get_module_proc(ServerHost, pubsub_state), {plugins, Plugins}),
ets:insert(gen_mod:get_module_proc(ServerHost, pubsub_state), {pep_mapping, PepMapping}),
init_nodes(Host, ServerHost), init_nodes(Host, ServerHost),
{ok, #state{host = Host, {ok, #state{host = Host,
server_host = ServerHost, server_host = ServerHost,
access = Access, access = Access,
pep_mapping = PepMapping,
nodetree = NodeTree, nodetree = NodeTree,
plugins = Plugins}}. plugins = Plugins}}.
@ -209,12 +213,14 @@ init_plugins(Host, ServerHost, Opts) ->
?DEBUG("** tree plugin is ~p",[TreePlugin]), ?DEBUG("** tree plugin is ~p",[TreePlugin]),
TreePlugin:init(Host, ServerHost, Opts), TreePlugin:init(Host, ServerHost, Opts),
Plugins = lists:usort(gen_mod:get_opt(plugins, Opts, []) ++ [?STDNODE]), Plugins = lists:usort(gen_mod:get_opt(plugins, Opts, []) ++ [?STDNODE]),
PepMapping = lists:usort(gen_mod:get_opt(pep_mapping, Opts, [])),
?DEBUG("** PEP Mapping : ~p~n",[PepMapping]),
lists:foreach(fun(Name) -> lists:foreach(fun(Name) ->
?DEBUG("** init ~s plugin",[Name]), ?DEBUG("** init ~s plugin",[Name]),
Plugin = list_to_atom(?PLUGIN_PREFIX ++ Name), Plugin = list_to_atom(?PLUGIN_PREFIX ++ Name),
Plugin:init(Host, ServerHost, Opts) Plugin:init(Host, ServerHost, Opts)
end, Plugins), end, Plugins),
{Plugins, TreePlugin}. {Plugins, TreePlugin, PepMapping}.
terminate_plugins(Host, ServerHost, Plugins, TreePlugin) -> terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
lists:foreach(fun(Name) -> lists:foreach(fun(Name) ->
@ -371,11 +377,11 @@ disco_sm_items(Acc, _From, To, [], _Lang) ->
{result, NodeItems ++ Items} {result, NodeItems ++ Items}
end; end;
disco_sm_items(Acc, _From, To, Node, _Lang) -> disco_sm_items(Acc, From, To, Node, _Lang) ->
%% TODO, use iq_disco_items(Host, Node, From) %% TODO, use iq_disco_items(Host, Node, From)
Host = To#jid.lserver, Host = To#jid.lserver,
LJID = jlib:jid_tolower(jlib:jid_remove_resource(To)), LJID = jlib:jid_tolower(jlib:jid_remove_resource(To)),
case get_items(Host, Node) of case get_items(Host, Node, From) of
[] -> [] ->
Acc; Acc;
AllItems -> AllItems ->
@ -430,6 +436,8 @@ handle_call(server_host, _From, State) ->
{reply, State#state.server_host, State}; {reply, State#state.server_host, State};
handle_call(plugins, _From, State) -> handle_call(plugins, _From, State) ->
{reply, State#state.plugins, State}; {reply, State#state.plugins, State};
handle_call(pep_mapping, _From, State) ->
{reply, State#state.pep_mapping, State};
handle_call(nodetree, _From, State) -> handle_call(nodetree, _From, State) ->
{reply, State#state.nodetree, State}; {reply, State#state.nodetree, State};
handle_call(stop, _From, State) -> handle_call(stop, _From, State) ->
@ -717,7 +725,7 @@ node_disco_info(Host, Node, From, Identity, Features) ->
[] -> [] ->
["leaf"]; %% No sub-nodes: it's a leaf node ["leaf"]; %% No sub-nodes: it's a leaf node
_ -> _ ->
case node_call(Type, get_items, [Host, Node]) of case node_call(Type, get_items, [Host, Node, From]) of
{result, []} -> ["collection"]; {result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"]; {result, _} -> ["leaf", "collection"];
_ -> [] _ -> []
@ -782,7 +790,7 @@ iq_disco_items(Host, Item, From) ->
%% TODO That is, remove name attribute %% TODO That is, remove name attribute
Action = Action =
fun(#pubsub_node{type = Type}) -> fun(#pubsub_node{type = Type}) ->
NodeItems = case node_call(Type, get_items, [Host, Node]) of NodeItems = case node_call(Type, get_items, [Host, Node, From]) of
{result, I} -> I; {result, I} -> I;
_ -> [] _ -> []
end, end,
@ -1183,10 +1191,7 @@ create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) ->
{error, extended_error(?ERR_NOT_ACCEPTABLE, "nodeid-required")} {error, extended_error(?ERR_NOT_ACCEPTABLE, "nodeid-required")}
end; end;
create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
Type = case Host of Type = select_type(ServerHost, Host, Node, GivenType),
{_User, _Server, _Resource} -> ?PEPNODE;
_ -> GivenType
end,
Parent = lists:sublist(Node, length(Node) - 1), Parent = lists:sublist(Node, length(Node) - 1),
%% TODO, check/set node_type = Type %% TODO, check/set node_type = Type
ParseOptions = case xml:remove_cdata(Configuration) of ParseOptions = case xml:remove_cdata(Configuration) of
@ -1488,12 +1493,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
%% handles auto-create feature %% handles auto-create feature
%% for automatic node creation. we'll take the default node type: %% for automatic node creation. we'll take the default node type:
%% first listed into the plugins configuration option, or pep %% first listed into the plugins configuration option, or pep
Type = case Host of Type = select_type(ServerHost, Host, Node),
{_User, _Server, _Resource} ->
?PEPNODE;
_ ->
hd(plugins(ServerHost))
end,
case lists:member("auto-create", features(Type)) of case lists:member("auto-create", features(Type)) of
true -> true ->
case create_node(Host, ServerHost, Node, Publisher, Type) of case create_node(Host, ServerHost, Node, Publisher, Type) of
@ -1712,8 +1712,8 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) ->
end end
end. end.
get_items(Host, Node) -> get_items(Host, Node, From) ->
case node_action(Host, Node, get_items, [Host, Node]) of case node_action(Host, Node, get_items, [Host, Node, From]) of
{result, Items} -> Items; {result, Items} -> Items;
_ -> [] _ -> []
end. end.
@ -1723,15 +1723,15 @@ get_items(Host, Node) ->
%% Node = pubsubNode() %% Node = pubsubNode()
%% LJID = {U, S, []} %% LJID = {U, S, []}
%% @doc <p>Resend the items of a node to the user.</p> %% @doc <p>Resend the items of a node to the user.</p>
send_all_items(Host, Node, LJID) -> %send_all_items(Host, Node, LJID) ->
send_items(Host, Node, LJID, all). % send_items(Host, Node, LJID, all).
send_last_item(Host, Node, LJID) -> send_last_item(Host, Node, LJID) ->
send_items(Host, Node, LJID, last). send_items(Host, Node, LJID, last).
%% TODO use cache-last-item feature %% TODO use cache-last-item feature
send_items(Host, Node, LJID, Number) -> send_items(Host, Node, LJID, Number) ->
ToSend = case get_items(Host, Node) of ToSend = case get_items(Host, Node, LJID) of
[] -> [] ->
[]; [];
Items -> Items ->
@ -2411,11 +2411,8 @@ get_configure(Host, Node, From, Lang) ->
end, end,
transaction(Host, Node, Action, sync_dirty). transaction(Host, Node, Action, sync_dirty).
get_default(Host, _Node, _From, Lang) -> get_default(Host, Node, _From, Lang) ->
Type = case Host of Type=select_type(Host, Host, Node),
{_, _, _} -> ?PEPNODE;
_ -> hd(plugins(Host))
end,
Options = node_options(Type), Options = node_options(Type),
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_OWNER}], {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_OWNER}],
[{xmlelement, "default", [], [{xmlelement, "default", [],
@ -2663,6 +2660,19 @@ plugins(Host) ->
[{plugins, PL}] -> PL; [{plugins, PL}] -> PL;
_ -> [?STDNODE] _ -> [?STDNODE]
end. end.
select_type(ServerHost, Host, Node, Type)->
?DEBUG("SELECT_TYPE : ~p~n", [Node]),
case Host of
{_User, _Server, _Resource} ->
case ets:lookup(gen_mod:get_module_proc(ServerHost, pubsub_state), pep_mapping) of
[{pep_mapping, PM}] -> ?DEBUG("SELECT_TYPE : ~p~n", [PM]), proplists:get_value(Node, PM,?PEPNODE);
R -> ?DEBUG("SELECT_TYPE why ?: ~p~n", [R]), ?PEPNODE
end;
_ ->
Type
end.
select_type(ServerHost, Host, Node) ->
select_type(ServerHost, Host, Node,hd(plugins(ServerHost))).
features() -> features() ->
[ [
@ -2811,3 +2821,4 @@ uniqid() ->
get_item_name(Host, Node, Id) -> get_item_name(Host, Node, Id) ->
{result, Name} = node_action(Host, Node, get_item_name, [Host, Node, Id]), {result, Name} = node_action(Host, Node, get_item_name, [Host, Node, Id]),
Name. Name.

View File

@ -62,7 +62,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1 set_item/1
@ -168,8 +168,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId)
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -63,7 +63,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -171,8 +171,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -63,7 +63,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -170,8 +170,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -70,7 +70,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -705,9 +705,9 @@ set_state(_) ->
%% relational database), or they can even decide not to persist any items.</p> %% relational database), or they can even decide not to persist any items.</p>
%% <p>If a PubSub plugin wants to delegate the item storage to the default node, %% <p>If a PubSub plugin wants to delegate the item storage to the default node,
%% they can implement this function like this: %% they can implement this function like this:
%% ```get_items(Host, Node) -> %% ```get_items(Host, Node, From) ->
%% node_default:get_items(Host, Node).'''</p> %% node_default:get_items(Host, Node, From).'''</p>
get_items(Host, Node) -> get_items(Host, Node, _From) ->
Items = mnesia:match_object( Items = mnesia:match_object(
#pubsub_item{itemid = {'_', {Host, Node}}, _ = '_'}), #pubsub_item{itemid = {'_', {Host, Node}}, _ = '_'}),
{result, Items}. {result, Items}.
@ -747,7 +747,7 @@ get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubI
%% % Payment is required for a subscription %% % Payment is required for a subscription
%% {error, ?ERR_PAYMENT_REQUIRED}; %% {error, ?ERR_PAYMENT_REQUIRED};
true -> true ->
get_items(Host, Node) get_items(Host, Node, JID)
end. end.
%% @spec (Host, Node, ItemId) -> [Item] | [] %% @spec (Host, Node, ItemId) -> [Item] | []

View File

@ -61,7 +61,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -173,8 +173,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

197
src/mod_pubsub/node_mb.erl Normal file
View File

@ -0,0 +1,197 @@
%%% ====================================================================
%%% ``The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
%%% compliance with the License. You should have received a copy of the
%%% Erlang Public License along with this software. If not, it can be
%%% retrieved via the world wide web at http://www.erlang.org/.
%%%
%%% Software distributed under the License is distributed on an "AS IS"
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%%% the License for the specific language governing rights and limitations
%%% under the License.
%%%
%%% The Initial Developer of the Original Code is ProcessOne.
%%% Portions created by ProcessOne are Copyright 2006-2008, ProcessOne
%%% All Rights Reserved.''
%%% This software is copyright 2006-2008, ProcessOne.
%%%
%%%
%%% @copyright 2006-2008 ProcessOne
%%% @author Eric Cestari <eric@ohmforce.com>
%%% @version {@vsn}, {@date} {@time}
%%% @end
%%% ====================================================================
%%% @doc The module <strong>{@module}</strong> is the pep microblog PubSub plugin.
%%% <p> To be used, mod_pubsub must be configured :
%%% {mod_pubsub, [ % requires mod_caps
%%% {access_createnode, pubsub_createnode},
%%% {plugins, ["default", "pep","mb"]},
%%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]}
%%% ]},
%%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p>
-module(node_mb).
-author('eric@ohmforce.com').
-include("ejabberd.hrl").
-include("pubsub.hrl").
-include("jlib.hrl").
-behaviour(gen_pubsub_node).
%% API definition
-export([init/3, terminate/2,
options/0, features/0,
create_node_permission/6,
create_node/3,
delete_node/2,
purge_node/3,
subscribe_node/8,
unsubscribe_node/5,
publish_item/7,
delete_item/4,
remove_extra_items/4,
get_entity_affiliations/2,
get_node_affiliations/2,
get_affiliation/3,
set_affiliation/4,
get_entity_subscriptions/2,
get_node_subscriptions/2,
get_subscription/3,
set_subscription/4,
get_states/2,
get_state/3,
set_state/1,
get_items/7,
get_items/3,
get_item/8,
get_item/3,
set_item/1,
get_item_name/3
]).
init(Host, ServerHost, Opts) ->
node_pep:init(Host, ServerHost, Opts).
terminate(Host, ServerHost) ->
node_pep:terminate(Host, ServerHost),
ok.
options() ->
[{node_type, pep},
{deliver_payloads, true},
{notify_config, false},
{notify_delete, false},
{notify_retract, false},
{persist_items, true},
{max_items, ?MAXITEMS},
{subscribe, true},
{access_model, presence},
{roster_groups_allowed, []},
{publish_model, publishers},
{max_payload_size, ?MAX_PAYLOAD_SIZE},
{send_last_published_item, on_sub_and_presence},
{deliver_notifications, true},
{presence_based_delivery, true}].
features() ->
["create-nodes", %*
"auto-create", %*
"auto-subscribe", %*
"delete-nodes", %*
"filtered-notifications", %*
"modify-affiliations",
"outcast-affiliation",
"persistent-items",
"publish", %*
"purge-nodes",
"retract-items",
"retrieve-affiliations",
"retrieve-items", %*
"retrieve-subscriptions",
"subscribe" %*
].
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) ->
node_pep:create_node(Host, Node, Owner).
delete_node(Host, Removed) ->
node_pep:delete_node(Host, Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup) ->
node_pep:subscribe_node(
Host, Node, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) ->
node_pep:unsubscribe_node(Host, Node, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) ->
node_pep:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) ->
node_pep:remove_extra_items(Host, Node, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) ->
node_pep:delete_item(Host, Node, JID, ItemId).
purge_node(Host, Node, Owner) ->
node_pep:purge_node(Host, Node, Owner).
get_entity_affiliations(Host, Owner) ->
node_pep:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) ->
node_pep:get_node_affiliations(Host, Node).
get_affiliation(Host, Node, Owner) ->
node_pep:get_affiliation(Host, Node, Owner).
set_affiliation(Host, Node, Owner, Affiliation) ->
node_pep:set_affiliation(Host, Node, Owner, Affiliation).
get_entity_subscriptions(Host,Owner) ->
node_pep:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) ->
node_pep:get_node_subscriptions(Host, Node).
get_subscription(Host,Node,Owner) ->
node_pep:get_subscription(Host,Node,Owner).
set_subscription(Host, Node, Owner, Subscription) ->
node_pep:set_subscription(Host, Node, Owner, Subscription).
get_states(Host, Node) ->
node_pep:get_states(Host, Node).
get_state(Host, Node, JID) ->
node_pep:get_state(Host, Node, JID).
set_state(State) ->
node_pep:set_state(State).
get_items(Host, Node, From) ->
node_pep:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_pep:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) ->
node_pep:get_item(Host, Node, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_pep:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) ->
node_pep:set_item(Item).
get_item_name(Host, Node, Id) ->
node_pep:get_item_name(Host, Node, Id).

View File

@ -59,7 +59,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -123,7 +123,8 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) ->
{User, Server, _} -> true; {User, Server, _} -> true;
_ -> false _ -> false
end; end;
_ -> E ->
?DEBUG("Create not allowed : ~p~n", [E]),
false false
end end
end, end,
@ -215,8 +216,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -63,7 +63,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -173,8 +173,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -63,7 +63,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -170,8 +170,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -54,7 +54,7 @@
get_state/3, get_state/3,
set_state/1, set_state/1,
get_items/7, get_items/7,
get_items/2, get_items/3,
get_item/8, get_item/8,
get_item/3, get_item/3,
set_item/1, set_item/1,
@ -163,8 +163,8 @@ get_state(Host, Node, JID) ->
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node) -> get_items(Host, Node, From) ->
node_default:get_items(Host, Node). node_default:get_items(Host, Node, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).

View File

@ -638,7 +638,7 @@ set_items(User, Server, #xmlel{children = Els}) ->
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
catch odbc_queries:sql_transaction( catch odbc_queries:sql_transaction(
LServer, LServer,
lists:map(fun(El) -> lists:flatmap(fun(El) ->
process_item_set_t(LUser, LServer, El) process_item_set_t(LUser, LServer, El)
end, Els)) end, Els))
catch catch
@ -1060,4 +1060,3 @@ us_to_list({User, Server}) ->
webadmin_user(Acc, _User, _Server, Lang) -> webadmin_user(Acc, _User, _Server, Lang) ->
Acc ++ [?XE("h3", [?ACT("roster/", "Roster")])]. Acc ++ [?XE("h3", [?ACT("roster/", "Roster")])].

View File

@ -161,6 +161,7 @@ get_user_roster(Items, US) ->
process_item(RosterItem, Host) -> process_item(RosterItem, Host) ->
USFrom = {UserFrom, ServerFrom} = RosterItem#roster.us, USFrom = {UserFrom, ServerFrom} = RosterItem#roster.us,
{UserTo, ServerTo, ResourceTo} = RosterItem#roster.jid, {UserTo, ServerTo, ResourceTo} = RosterItem#roster.jid,
NameTo = RosterItem#roster.name,
USTo = {UserTo, ServerTo}, USTo = {UserTo, ServerTo},
DisplayedGroups = get_user_displayed_groups(USFrom), DisplayedGroups = get_user_displayed_groups(USFrom),
CommonGroups = lists:filter(fun(Group) -> CommonGroups = lists:filter(fun(Group) ->
@ -188,24 +189,24 @@ process_item(RosterItem, Host) ->
PersonalGroups -> PersonalGroups ->
%% Store roster items in From and To rosters %% Store roster items in From and To rosters
set_new_rosteritems(UserFrom, ServerFrom, set_new_rosteritems(UserFrom, ServerFrom,
UserTo, ServerTo, ResourceTo, UserTo, ServerTo, ResourceTo, NameTo,
PersonalGroups) PersonalGroups)
end end
end. end.
build_roster_record(User1, Server1, User2, Server2, Groups) -> build_roster_record(User1, Server1, User2, Server2, Name2, Groups) ->
USR2 = {User2, Server2, undefined}, USR2 = {User2, Server2, undefined},
#roster{usj = {User1, Server1, USR2}, #roster{usj = {User1, Server1, USR2},
us = {User1, Server1}, us = {User1, Server1},
jid = USR2, jid = USR2,
name = User2, name = Name2,
subscription = both, subscription = both,
ask = none, ask = none,
groups = Groups groups = Groups
}. }.
set_new_rosteritems(UserFrom, ServerFrom, set_new_rosteritems(UserFrom, ServerFrom,
UserTo, ServerTo, ResourceTo, GroupsFrom) -> UserTo, ServerTo, ResourceTo, NameTo, GroupsFrom) ->
Mod = case lists:member(mod_roster_odbc, Mod = case lists:member(mod_roster_odbc,
gen_mod:loaded_modules(ServerFrom)) of gen_mod:loaded_modules(ServerFrom)) of
true -> mod_roster_odbc; true -> mod_roster_odbc;
@ -213,13 +214,13 @@ set_new_rosteritems(UserFrom, ServerFrom,
end, end,
RIFrom = build_roster_record(UserFrom, ServerFrom, RIFrom = build_roster_record(UserFrom, ServerFrom,
UserTo, ServerTo, GroupsFrom), UserTo, ServerTo, NameTo, GroupsFrom),
set_item(UserFrom, ServerFrom, ResourceTo, RIFrom), set_item(UserFrom, ServerFrom, ResourceTo, RIFrom),
JIDTo = exmpp_jid:make_bare_jid(UserTo, ServerTo), JIDTo = exmpp_jid:make_bare_jid(UserTo, ServerTo),
JIDFrom = exmpp_jid:make_bare_jid(UserFrom, ServerFrom), JIDFrom = exmpp_jid:make_bare_jid(UserFrom, ServerFrom),
RITo = build_roster_record(UserTo, ServerTo, RITo = build_roster_record(UserTo, ServerTo,
UserFrom, ServerFrom, []), UserFrom, ServerFrom, UserFrom,[]),
set_item(UserTo, ServerTo, undefined, RITo), set_item(UserTo, ServerTo, undefined, RITo),
%% From requests %% From requests

View File

@ -131,10 +131,7 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) ->
process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) ->
#jid{lnode = LUser, ldomain = LServer} = To, #jid{lnode = LUser, ldomain = LServer} = To,
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query( case catch odbc_queries:get_vcard(LServer, Username) of
LServer,
["select vcard from vcard "
"where username='", Username, "';"]) of
{selected, ["vcard"], [{SVCARD}]} -> {selected, ["vcard"], [{SVCARD}]} ->
try exmpp_xml:parse_document(SVCARD, try exmpp_xml:parse_document(SVCARD,
[namespace, name_as_atom, autoload_known]) of [namespace, name_as_atom, autoload_known]) of
@ -233,30 +230,13 @@ set_vcard(User, LServer, VCARD) ->
SOrgUnit = ejabberd_odbc:escape(OrgUnit), SOrgUnit = ejabberd_odbc:escape(OrgUnit),
SLOrgUnit = ejabberd_odbc:escape(LOrgUnit), SLOrgUnit = ejabberd_odbc:escape(LOrgUnit),
ejabberd_odbc:sql_transaction( odbc_queries:set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail,
LServer, SFN, SFamily, SGiven, SLBDay, SLCTRY,
[["delete from vcard where username='", LUsername, "';"], SLEMail, SLFN, SLFamily, SLGiven,
["insert into vcard(username, vcard) " SLLocality, SLMiddle, SLNickname,
"values ('", LUsername, "', '", SVCARD, "');"], SLOrgName, SLOrgUnit, SLocality,
["delete from vcard_search where lusername='", LUsername, "';"], SMiddle, SNickname, SOrgName,
["insert into vcard_search(" SOrgUnit, SVCARD, Username)
" username, lusername, fn, lfn, family, lfamily,"
" given, lgiven, middle, lmiddle, nickname, lnickname,"
" bday, lbday, ctry, lctry, locality, llocality,"
" email, lemail, orgname, lorgname, orgunit, lorgunit)"
"values (",
" '", Username, "', '", LUsername, "',"
" '", SFN, "', '", SLFN, "',"
" '", SFamily, "', '", SLFamily, "',"
" '", SGiven, "', '", SLGiven, "',"
" '", SMiddle, "', '", SLMiddle, "',"
" '", SNickname, "', '", SLNickname, "',"
" '", SBDay, "', '", SLBDay, "',"
" '", SCTRY, "', '", SLCTRY, "',"
" '", SLocality, "', '", SLLocality, "',"
" '", SEMail, "', '", SLEMail, "',"
" '", SOrgName, "', '", SLOrgName, "',"
" '", SOrgUnit, "', '", SLOrgUnit, "');"]])
catch catch
_ -> _ ->
{error, badarg} {error, badarg}
@ -643,5 +623,3 @@ remove_user(User, Server) ->
LServer, LServer,
[["delete from vcard where username='", Username, "';"], [["delete from vcard where username='", Username, "';"],
["delete from vcard_search where lusername='", Username, "';"]]). ["delete from vcard_search where lusername='", Username, "';"]]).

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\ejabberd_odbc.beam ..\ejabberd_odbc_sup.beam ..\odbc_queries.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)

View File

@ -30,7 +30,7 @@
-behaviour(gen_server). -behaviour(gen_server).
%% External exports %% External exports
-export([start/1, start_link/1, -export([start/1, start_link/2,
sql_query/2, sql_query/2,
sql_query_t/1, sql_query_t/1,
sql_transaction/2, sql_transaction/2,
@ -63,8 +63,8 @@
start(Host) -> start(Host) ->
gen_server:start(ejabberd_odbc, [Host], []). gen_server:start(ejabberd_odbc, [Host], []).
start_link(Host) -> start_link(Host, StartInterval) ->
gen_server:start_link(ejabberd_odbc, [Host], []). gen_server:start_link(ejabberd_odbc, [Host, StartInterval], []).
sql_query(Host, Query) -> sql_query(Host, Query) ->
gen_server:call(ejabberd_odbc_sup:get_random_pid(Host), gen_server:call(ejabberd_odbc_sup:get_random_pid(Host),
@ -131,10 +131,10 @@ escape_like(C) -> odbc_queries:escape(C).
%% ignore | %% ignore |
%% {stop, Reason} %% {stop, Reason}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
init([Host]) -> init([Host, StartInterval]) ->
case ejabberd_config:get_local_option({odbc_keepalive_interval, Host}) of case ejabberd_config:get_local_option({odbc_keepalive_interval, Host}) of
Interval when is_integer(Interval) -> KeepaliveInterval when is_integer(KeepaliveInterval) ->
timer:apply_interval(Interval*1000, ?MODULE, keep_alive, [self()]); timer:apply_interval(KeepaliveInterval*1000, ?MODULE, keep_alive, [self()]);
undefined -> undefined ->
ok; ok;
_Other -> _Other ->
@ -144,16 +144,16 @@ init([Host]) ->
case SQLServer of case SQLServer of
%% Default pgsql port %% Default pgsql port
{pgsql, Server, DB, Username, Password} -> {pgsql, Server, DB, Username, Password} ->
pgsql_connect(Server, ?PGSQL_PORT, DB, Username, Password); pgsql_connect(Server, ?PGSQL_PORT, DB, Username, Password, StartInterval);
{pgsql, Server, Port, DB, Username, Password} when is_integer(Port) -> {pgsql, Server, Port, DB, Username, Password} when is_integer(Port) ->
pgsql_connect(Server, Port, DB, Username, Password); pgsql_connect(Server, Port, DB, Username, Password, StartInterval);
%% Default mysql port %% Default mysql port
{mysql, Server, DB, Username, Password} -> {mysql, Server, DB, Username, Password} ->
mysql_connect(Server, ?MYSQL_PORT, DB, Username, Password); mysql_connect(Server, ?MYSQL_PORT, DB, Username, Password, StartInterval);
{mysql, Server, Port, DB, Username, Password} when is_integer(Port) -> {mysql, Server, Port, DB, Username, Password} when is_integer(Port) ->
mysql_connect(Server, Port, DB, Username, Password); mysql_connect(Server, Port, DB, Username, Password, StartInterval);
_ when is_list(SQLServer) -> _ when is_list(SQLServer) ->
odbc_connect(SQLServer) odbc_connect(SQLServer, StartInterval)
end. end.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -259,7 +259,7 @@ execute_transaction(State, F, NRestarts) ->
%% part of init/1 %% part of init/1
%% Open an ODBC database connection %% Open an ODBC database connection
odbc_connect(SQLServer) -> odbc_connect(SQLServer, StartInterval) ->
application:start(odbc), application:start(odbc),
case odbc:connect(SQLServer,[{scrollable_cursors, off}]) of case odbc:connect(SQLServer,[{scrollable_cursors, off}]) of
{ok, Ref} -> {ok, Ref} ->
@ -268,8 +268,8 @@ odbc_connect(SQLServer) ->
{error, Reason} -> {error, Reason} ->
?ERROR_MSG("ODBC connection (~s) failed: ~p~n", ?ERROR_MSG("ODBC connection (~s) failed: ~p~n",
[SQLServer, Reason]), [SQLServer, Reason]),
%% If we can't connect we wait for 30 seconds before retrying %% If we can't connect we wait before retrying
timer:sleep(30000), timer:sleep(StartInterval),
{stop, odbc_connection_failed} {stop, odbc_connection_failed}
end. end.
@ -278,15 +278,15 @@ odbc_connect(SQLServer) ->
%% part of init/1 %% part of init/1
%% Open a database connection to PostgreSQL %% Open a database connection to PostgreSQL
pgsql_connect(Server, Port, DB, Username, Password) -> pgsql_connect(Server, Port, DB, Username, Password, StartInterval) ->
case pgsql:connect(Server, DB, Username, Password, Port) of case pgsql:connect(Server, DB, Username, Password, Port) of
{ok, Ref} -> {ok, Ref} ->
erlang:monitor(process, Ref), erlang:monitor(process, Ref),
{ok, #state{db_ref = Ref, db_type = pgsql}}; {ok, #state{db_ref = Ref, db_type = pgsql}};
{error, Reason} -> {error, Reason} ->
?ERROR_MSG("PostgreSQL connection failed: ~p~n", [Reason]), ?ERROR_MSG("PostgreSQL connection failed: ~p~n", [Reason]),
%% If we can't connect we wait for 30 seconds before retrying %% If we can't connect we wait before retrying
timer:sleep(30000), timer:sleep(StartInterval),
{stop, pgsql_connection_failed} {stop, pgsql_connection_failed}
end. end.
@ -317,7 +317,7 @@ pgsql_item_to_odbc(_) ->
%% part of init/1 %% part of init/1
%% Open a database connection to MySQL %% Open a database connection to MySQL
mysql_connect(Server, Port, DB, Username, Password) -> mysql_connect(Server, Port, DB, Username, Password, StartInterval) ->
NoLogFun = fun(_Level,_Format,_Argument) -> ok end, NoLogFun = fun(_Level,_Format,_Argument) -> ok end,
case mysql_conn:start(Server, Port, Username, Password, DB, NoLogFun) of case mysql_conn:start(Server, Port, Username, Password, DB, NoLogFun) of
{ok, Ref} -> {ok, Ref} ->
@ -330,9 +330,10 @@ mysql_connect(Server, Port, DB, Username, Password) ->
"SERIALIZABLE;"], self()), "SERIALIZABLE;"], self()),
{ok, #state{db_ref = Ref, db_type = mysql}}; {ok, #state{db_ref = Ref, db_type = mysql}};
{error, Reason} -> {error, Reason} ->
?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]), ?ERROR_MSG("MySQL connection failed: ~p~nWaiting ~p seconds before retrying...~n",
%% If we can't connect we wait for 30 seconds before retrying [Reason, StartInterval div 1000]),
timer:sleep(30000), %% If we can't connect we wait before retrying
timer:sleep(StartInterval),
{stop, mysql_connection_failed} {stop, mysql_connection_failed}
end. end.

View File

@ -37,32 +37,44 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-define(DEFAULT_POOL_SIZE, 10). -define(DEFAULT_POOL_SIZE, 10).
-define(DEFAULT_ODBC_START_INTERVAL, 30). % 30 seconds
start_link(Host) -> start_link(Host) ->
supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)}, supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)},
?MODULE, [Host]). ?MODULE, [Host]).
init([Host]) -> init([Host]) ->
N = case ejabberd_config:get_local_option({odbc_pool_size, Host}) of PoolSize = case ejabberd_config:get_local_option({odbc_pool_size, Host}) of
I when is_integer(I) -> I when is_integer(I) ->
I; I;
undefined -> undefined ->
?DEFAULT_POOL_SIZE; ?DEFAULT_POOL_SIZE;
Other -> Other ->
?ERROR_MSG("Wrong odbc_pool_size definition '~p' for host ~p, default to ~p~n", ?ERROR_MSG("Wrong odbc_pool_size definition '~p' for host ~p, default to ~p~n",
[Other, Host, ?DEFAULT_POOL_SIZE]), [Other, Host, ?DEFAULT_POOL_SIZE]),
?DEFAULT_POOL_SIZE ?DEFAULT_POOL_SIZE
end, end,
{ok, {{one_for_one, 10, 6}, StartInterval = case ejabberd_config:get_local_option({odbc_start_interval, Host}) of
Interval when is_integer(Interval) ->
Interval;
undefined ->
?DEFAULT_ODBC_START_INTERVAL;
_Other2 ->
?ERROR_MSG("Wrong odbc_start_interval definition '~p' for host ~p"
", defaulting to ~p~n",
[_Other2, Host, ?DEFAULT_ODBC_START_INTERVAL]),
?DEFAULT_ODBC_START_INTERVAL
end,
{ok, {{one_for_one, PoolSize+1, StartInterval},
lists:map( lists:map(
fun(I) -> fun(I) ->
{I, {I,
{ejabberd_odbc, start_link, [Host]}, {ejabberd_odbc, start_link, [Host, StartInterval*1000]},
transient, transient,
brutal_kill, brutal_kill,
worker, worker,
[?MODULE]} [?MODULE]}
end, lists:seq(1, N))}}. end, lists:seq(1, PoolSize))}}.
get_pids(Host) -> get_pids(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE), Proc = gen_mod:get_module_proc(Host, ?MODULE),

View File

@ -104,6 +104,10 @@ if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard]') a
drop table [dbo].[vcard] drop table [dbo].[vcard]
GO GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard_search]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[vcard_search]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[private_storage]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[private_storage]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[private_storage] drop table [dbo].[private_storage]
GO GO
@ -160,25 +164,35 @@ GO
CREATE TABLE [dbo].[vcard] ( CREATE TABLE [dbo].[vcard] (
[username] [varchar] (250) NOT NULL , [username] [varchar] (250) NOT NULL ,
[full_name] [varchar] (250) NULL , [vcard] [text] NOT NULL
[first_name] [varchar] (50) NULL , ) ON [PRIMARY]
[last_name] [varchar] (50) NULL , GO
[nick_name] [varchar] (50) NULL ,
[url] [varchar] (1024) NULL , CREATE TABLE [dbo].[vcard_search] (
[address1] [varchar] (50) NULL , [username] [varchar] (250) NOT NULL ,
[address2] [varchar] (50) NULL , [lusername] [varchar] (250) NOT NULL ,
[locality] [varchar] (50) NULL , [fn] [text] NOT NULL ,
[region] [varchar] (50) NULL , [lfn] [varchar] (250) NOT NULL ,
[pcode] [varchar] (50) NULL , [family] [text] NOT NULL ,
[country] [varchar] (50) NULL , [lfamily] [varchar] (250) NOT NULL ,
[telephone] [varchar] (50) NULL , [given] [text] NOT NULL ,
[email] [varchar] (250) NULL , [lgiven] [varchar] (250) NOT NULL ,
[orgname] [varchar] (50) NULL , [middle] [text] NOT NULL ,
[orgunit] [varchar] (50) NULL , [lmiddle] [varchar] (250) NOT NULL ,
[title] [varchar] (50) NULL , [nickname] [text] NOT NULL ,
[role] [varchar] (50) NULL , [lnickname] [varchar] (250) NOT NULL ,
[b_day] [datetime] NULL , [bday] [text] NOT NULL ,
[descr] [varchar] (500) NULL [lbday] [varchar] (250) NOT NULL ,
[ctry] [text] NOT NULL ,
[lctry] [varchar] (250) NOT NULL ,
[locality] [text] NOT NULL ,
[llocality] [varchar] (250) NOT NULL ,
[email] [text] NOT NULL ,
[lemail] [varchar] (250) NOT NULL ,
[orgname] [text] NOT NULL ,
[lorgname] [varchar] (250) NOT NULL ,
[orgunit] [text] NOT NULL ,
[lorgunit] [varchar] (250) NOT NULL
) ON [PRIMARY] ) ON [PRIMARY]
GO GO
@ -262,6 +276,31 @@ ALTER TABLE [dbo].[vcard] WITH NOCHECK ADD
) WITH FILLFACTOR = 90 ON [PRIMARY] ) WITH FILLFACTOR = 90 ON [PRIMARY]
GO GO
CREATE INDEX [IX_vcard_search_lfn] ON [dbo].[vcard_search]([lfn]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lfamily] ON [dbo].[vcard_search]([lfamily]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lgiven] ON [dbo].[vcard_search]([lgiven]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lmiddle] ON [dbo].[vcard_search]([lmiddle]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lnickname] ON [dbo].[vcard_search]([lnickname]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lbday] ON [dbo].[vcard_search]([lbday]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lctry] ON [dbo].[vcard_search]([lctry]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_llocality] ON [dbo].[vcard_search]([llocality]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lemail] ON [dbo].[vcard_search]([lemail]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lorgname] ON [dbo].[vcard_search]([lorgname]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_vcard_search_lorgunit] ON [dbo].[vcard_search]([lorgunit]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO GO
@ -1050,4 +1089,151 @@ END
GO GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_vcard] **/
/** Set the user's vCard **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_vcard]
@VCard varchar(8000),
@Username varchar(250),
@Lusername varchar(250),
@Fn varchar(8000),
@Lfn varchar(250),
@Family varchar(8000),
@Lfamily varchar(250),
@Given varchar(8000),
@Lgiven varchar(250),
@Middle varchar(8000),
@Lmiddle varchar(250),
@Nickname varchar(8000),
@Lnickname varchar(250),
@Bday varchar(8000),
@Lbday varchar(250),
@Ctry varchar(8000),
@Lctry varchar(250),
@Locality varchar(8000),
@Llocality varchar(250),
@Email varchar(8000),
@Lemail varchar(250),
@Orgname varchar(8000),
@Lorgname varchar(250),
@Orgunit varchar(8000),
@Lorgunit varchar(250)
AS
BEGIN
IF EXISTS (SELECT username FROM vcard with (nolock) WHERE vcard.username = @Username)
BEGIN
UPDATE [vcard]
SET [vcard].username = @LUsername,
[vcard].vcard = @Vcard
WHERE vcard.username = @LUsername;
UPDATE [vcard_search]
SET [vcard_search].username = @Username,
[vcard_search].lusername = @Lusername,
[vcard_search].fn = @Fn,
[vcard_search].lfn = @Lfn,
[vcard_search].family = @Family,
[vcard_search].lfamily = @Lfamily,
[vcard_search].given = @Given,
[vcard_search].lgiven = @Lgiven,
[vcard_search].middle = @Middle,
[vcard_search].lmiddle = @Lmiddle,
[vcard_search].nickname = @Nickname,
[vcard_search].lnickname = @Lnickname,
[vcard_search].bday = @Bday,
[vcard_search].lbday = @Lbday,
[vcard_search].ctry = @Ctry,
[vcard_search].lctry = @Lctry,
[vcard_search].locality = @Locality,
[vcard_search].llocality = @Llocality,
[vcard_search].email = @Email,
[vcard_search].lemail = @Lemail,
[vcard_search].orgname = @Orgname,
[vcard_search].lorgname = @Lorgname,
[vcard_search].orgunit = @Orgunit,
[vcard_search].lorgunit = @Lorgunit
WHERE vcard_search.lusername = @LUsername;
END
ELSE
BEGIN
INSERT INTO [vcard]
( [vcard].username,
[vcard].vcard
)
VALUES
( @lUsername,
@Vcard
);
INSERT INTO [vcard_search]
(
[vcard_search].username ,
[vcard_search].lusername ,
[vcard_search].fn ,
[vcard_search].lfn ,
[vcard_search].family ,
[vcard_search].lfamily ,
[vcard_search].given ,
[vcard_search].lgiven ,
[vcard_search].middle ,
[vcard_search].lmiddle ,
[vcard_search].nickname,
[vcard_search].lnickname,
[vcard_search].bday,
[vcard_search].lbday,
[vcard_search].ctry,
[vcard_search].lctry,
[vcard_search].locality,
[vcard_search].llocality,
[vcard_search].email,
[vcard_search].lemail,
[vcard_search].orgname,
[vcard_search].lorgname,
[vcard_search].orgunit,
[vcard_search].lorgunit
)
VALUES
(
@Username,
@Lusername,
@Fn,
@Lfn,
@Family,
@Lfamily,
@Given,
@Lgiven,
@Middle,
@Lmiddle,
@Nickname,
@Lnickname,
@Bday,
@Lbday,
@Ctry,
@Lctry,
@Locality,
@Llocality,
@Email,
@Lemail,
@Orgname,
@Lorgname,
@Orgunit,
@Lorgunit
)
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_vcard] **/
/** Retrive the user's vCard **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_vcard]
@Username varchar(250)
AS
BEGIN
SELECT vcard.vcard as vcard
FROM vcard WITH (NOLOCK)
WHERE username=@Username;
END
GO

View File

@ -61,6 +61,8 @@
set_private_data_sql/3, set_private_data_sql/3,
get_private_data/3, get_private_data/3,
del_user_private_storage/2, del_user_private_storage/2,
set_vcard/26,
get_vcard/2,
escape/1, escape/1,
count_records_where/3]). count_records_where/3]).
@ -327,11 +329,11 @@ update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
" values (", ItemVals, ");"], " values (", ItemVals, ");"],
["delete from rostergroups " ["delete from rostergroups "
" where username='", Username, "' " " where username='", Username, "' "
" and jid='", SJID, "';"], " and jid='", SJID, "';"]] ++
[["insert into rostergroups(" [["insert into rostergroups("
" username, jid, grp) " " username, jid, grp) "
" values (", ItemGroup, ");"] || " values (", ItemGroup, ");"] ||
ItemGroup <- ItemGroups]]. ItemGroup <- ItemGroups].
roster_subscribe(_LServer, Username, SJID, ItemVals) -> roster_subscribe(_LServer, Username, SJID, ItemVals) ->
ejabberd_odbc:sql_query_t( ejabberd_odbc:sql_query_t(
@ -378,6 +380,42 @@ del_user_private_storage(LServer, Username) ->
LServer, LServer,
["delete from private_storage where username='", Username, "';"]). ["delete from private_storage where username='", Username, "';"]).
set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
SLBDay, SLCTRY, SLEMail, SLFN, SLFamily, SLGiven, SLLocality,
SLMiddle, SLNickname, SLOrgName, SLOrgUnit, SLocality, SMiddle,
SNickname, SOrgName, SOrgUnit, SVCARD, Username) ->
ejabberd_odbc:sql_transaction(
LServer,
[["delete from vcard where username='", LUsername, "';"],
["insert into vcard(username, vcard) "
"values ('", LUsername, "', '", SVCARD, "');"],
["delete from vcard_search where lusername='", LUsername, "';"],
["insert into vcard_search("
" username, lusername, fn, lfn, family, lfamily,"
" given, lgiven, middle, lmiddle, nickname, lnickname,"
" bday, lbday, ctry, lctry, locality, llocality,"
" email, lemail, orgname, lorgname, orgunit, lorgunit)"
"values (",
" '", Username, "', '", LUsername, "',"
" '", SFN, "', '", SLFN, "',"
" '", SFamily, "', '", SLFamily, "',"
" '", SGiven, "', '", SLGiven, "',"
" '", SMiddle, "', '", SLMiddle, "',"
" '", SNickname, "', '", SLNickname, "',"
" '", SBDay, "', '", SLBDay, "',"
" '", SCTRY, "', '", SLCTRY, "',"
" '", SLocality, "', '", SLLocality, "',"
" '", SEMail, "', '", SLEMail, "',"
" '", SOrgName, "', '", SLOrgName, "',"
" '", SOrgUnit, "', '", SLOrgUnit, "');"]]).
get_vcard(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select vcard from vcard "
"where username='", Username, "';"]).
%% Characters to escape %% Characters to escape
escape($\0) -> "\\0"; escape($\0) -> "\\0";
escape($\n) -> "\\n"; escape($\n) -> "\\n";
@ -597,6 +635,25 @@ del_user_private_storage(LServer, Username) ->
LServer, LServer,
["EXECUTE dbo.del_user_storage '", Username, "'"]). ["EXECUTE dbo.del_user_storage '", Username, "'"]).
set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
SLBDay, SLCTRY, SLEMail, SLFN, SLFamily, SLGiven, SLLocality,
SLMiddle, SLNickname, SLOrgName, SLOrgUnit, SLocality, SMiddle,
SNickname, SOrgName, SOrgUnit, SVCARD, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_vcard '", SVCARD, "' , '", Username, "' , '", LUsername, "' , '",
SFN, "' , '", SLFN, "' , '", SFamily, "' , '", SLFamily, "' , '",
SGiven, "' , '", SLGiven, "' , '", SMiddle, "' , '", SLMiddle, "' , '",
SNickname, "' , '", SLNickname, "' , '", SBDay, "' , '", SLBDay, "' , '",
SCTRY, "' , '", SLCTRY, "' , '", SLocality, "' , '", SLLocality, "' , '",
SEMail, "' , '", SLEMail, "' , '", SOrgName, "' , '", SLOrgName, "' , '",
SOrgUnit, "' , '", SLOrgUnit, "'"]).
get_vcard(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_vcard '", Username, "'"]).
%% Characters to escape %% Characters to escape
escape($\0) -> "\\0"; escape($\0) -> "\\0";
escape($\t) -> "\\t"; escape($\t) -> "\\t";

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\stringprep.beam ..\stringprep_sup.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
SOURCE = stringprep_drv.c SOURCE = stringprep_drv.c
AUXIL = uni_data.c uni_norm.c AUXIL = uni_data.c uni_norm.c

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\tls.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
SOURCE = tls_drv.c SOURCE = tls_drv.c
OBJECT = tls_drv.o OBJECT = tls_drv.o

View File

@ -4,8 +4,7 @@ include ..\Makefile.inc
EFLAGS = -I .. -pz .. EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
SOURCES = $(wildcard *.erl) BEAMS = ..\ejabberd_http.beam ..\ejabberd_http_bind.beam ..\ejabberd_http_poll.beam ..\ejabberd_web.beam ..\ejabberd_web_admin.beam ..\mod_http_bind.beam ..\mod_http_fileserver.beam
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
ALL : $(BEAMS) ALL : $(BEAMS)
@ -21,5 +20,14 @@ $(OUTDIR)\ejabberd_web.beam : ejabberd_web.erl
$(OUTDIR)\ejabberd_web_admin.beam : ejabberd_web_admin.erl $(OUTDIR)\ejabberd_web_admin.beam : ejabberd_web_admin.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_web_admin.erl erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_web_admin.erl
$(OUTDIR)\ejabberd_http_bind.beam : ejabberd_http_bind.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_http_bind.erl
$(OUTDIR)\ejabberd_http_poll.beam : ejabberd_http_poll.erl $(OUTDIR)\ejabberd_http_poll.beam : ejabberd_http_poll.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_http_poll.erl erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_http_poll.erl
$(OUTDIR)\mod_http_bind.beam : mod_http_bind.erl
erlc -W $(EFLAGS) -o $(OUTDIR) mod_http_bind.erl
$(OUTDIR)\mod_http_fileserver.beam : mod_http_fileserver.erl
erlc -W $(EFLAGS) -o $(OUTDIR) mod_http_fileserver.erl