1
0
Fork 0
mirror of https://github.com/processone/ejabberd synced 2025-10-05 10:39:29 +02: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

@ -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,13 +37,14 @@
-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 ->
@ -53,16 +54,27 @@ init([Host]) ->
[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