25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-10-03 14:45:16 +02:00

merge from 2.1.10 and resolve conflicts

This commit is contained in:
Christophe Romain 2011-12-30 11:33:34 +01:00
commit e0781d9217
42 changed files with 968 additions and 530 deletions

View File

@ -91,7 +91,7 @@ extract_lang_all ()
cd $MSGS_DIR cd $MSGS_DIR
for i in $( ls *.msg ) ; do for i in $( ls *.msg ) ; do
MISSING=`cat $i.translate | grep "\", \"\"}." | wc -l` MISSING=`cat $i.translate | grep "\", \"\"}." | wc -l`
LANGUAGE=`grep "Language:" $i.translate | sed 's/% Language: //g'` LANGUAGE=`grep "X-Language:" $i.translate | sed 's/% Language: //g'`
LASTAUTH=`grep "Author:" $i.translate | head -n 1 | sed 's/% Author: //g'` LASTAUTH=`grep "Author:" $i.translate | head -n 1 | sed 's/% Author: //g'`
echo -e "$i\t$MISSING\t$LANGUAGE\t$LASTAUTH" echo -e "$i\t$MISSING\t$LANGUAGE\t$LASTAUTH"
done done
@ -258,7 +258,7 @@ extract_lang_updateall ()
MISSING=`msgfmt --statistics $PO 2>&1 | awk '{printf "%5s", $4 }'` MISSING=`msgfmt --statistics $PO 2>&1 | awk '{printf "%5s", $4 }'`
echo -n " $MISSING" echo -n " $MISSING"
LANGUAGE=`grep "Language:" $PO | sed 's/\"X-Language: //g' | sed 's/\\\\n\"//g' | awk '{printf "%-12s", $1}'` LANGUAGE=`grep "X-Language:" $PO | sed 's/\"X-Language: //g' | sed 's/\\\\n\"//g' | awk '{printf "%-12s", $1}'`
echo -n " $LANGUAGE" echo -n " $LANGUAGE"
LASTAUTH=`grep "Last-Translator" $PO | sed 's/\"Last-Translator: //g' | sed 's/\\\\n\"//g'` LASTAUTH=`grep "Last-Translator" $PO | sed 's/\"Last-Translator: //g' | sed 's/\\\\n\"//g'`

View File

@ -2,7 +2,7 @@
"http://www.w3.org/TR/REC-html40/loose.dtd"> "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML> <HTML>
<HEAD> <HEAD>
<TITLE>Ejabberd 2.1.9 Developers Guide <TITLE>Ejabberd 2.1.10 Developers Guide
</TITLE> </TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
@ -49,7 +49,7 @@ TD P{margin:0px;}
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex --> <!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex -->
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A> <!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.9 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR> </P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.10 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR> <A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD></TR> <A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD></TR>
</TABLE><DIV CLASS="center"> </TABLE><DIV CLASS="center">

View File

@ -2,7 +2,7 @@
"http://www.w3.org/TR/REC-html40/loose.dtd"> "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML> <HTML>
<HEAD> <HEAD>
<TITLE>Ejabberd 2.1.9 Feature Sheet <TITLE>Ejabberd 2.1.10 Feature Sheet
</TITLE> </TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
@ -50,7 +50,7 @@ SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex --> <!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex -->
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A> <!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.9 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR> </P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.10 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
<A HREF="mailto:s.devrieze@pandora.be"><TT>mailto:s.devrieze@pandora.be</TT></A><BR> <A HREF="mailto:s.devrieze@pandora.be"><TT>mailto:s.devrieze@pandora.be</TT></A><BR>
<A HREF="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD></TR> <A HREF="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD></TR>
</TABLE><DIV CLASS="center"> </TABLE><DIV CLASS="center">

View File

@ -6,7 +6,7 @@
ejabberd 2.1.9 ejabberd 2.1.10
Installation and Operation Guide Installation and Operation Guide
@ -76,7 +76,7 @@ BLOCKQUOTE.figure DIV.center DIV.center HR{display:none;}
<HR SIZE=2><BR> <HR SIZE=2><BR>
<BR> <BR>
<TABLE CELLSPACING=6 CELLPADDING=0><TR><TD ALIGN=right NOWRAP> <FONT SIZE=6><B>ejabberd 2.1.9 </B></FONT></TD></TR> <TABLE CELLSPACING=6 CELLPADDING=0><TR><TD ALIGN=right NOWRAP> <FONT SIZE=6><B>ejabberd 2.1.10 </B></FONT></TD></TR>
<TR><TD ALIGN=right NOWRAP>&nbsp;</TD></TR> <TR><TD ALIGN=right NOWRAP>&nbsp;</TD></TR>
<TR><TD ALIGN=right NOWRAP> <FONT SIZE=6>Installation and Operation Guide</FONT></TD></TR> <TR><TD ALIGN=right NOWRAP> <FONT SIZE=6>Installation and Operation Guide</FONT></TD></TR>
</TABLE><BR> </TABLE><BR>
@ -207,21 +207,20 @@ BLOCKQUOTE.figure DIV.center DIV.center HR{display:none;}
</LI><LI CLASS="li-toc"><A HREF="#htoc92">6.2&#XA0;&#XA0;Clustering Setup</A> </LI><LI CLASS="li-toc"><A HREF="#htoc92">6.2&#XA0;&#XA0;Clustering Setup</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc93">6.3&#XA0;&#XA0;Service Load-Balancing</A> </LI><LI CLASS="li-toc"><A HREF="#htoc93">6.3&#XA0;&#XA0;Service Load-Balancing</A>
<UL CLASS="toc"><LI CLASS="li-toc"> <UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc94">6.3.1&#XA0;&#XA0;Components Load-Balancing</A> <A HREF="#htoc94">6.3.1&#XA0;&#XA0;Domain Load-Balancing Algorithm</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc95">6.3.2&#XA0;&#XA0;Domain Load-Balancing Algorithm</A> </LI><LI CLASS="li-toc"><A HREF="#htoc95">6.3.2&#XA0;&#XA0;Load-Balancing Buckets</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc96">6.3.3&#XA0;&#XA0;Load-Balancing Buckets</A>
</LI></UL> </LI></UL>
</LI></UL> </LI></UL>
</LI><LI CLASS="li-toc"><A HREF="#htoc97">Chapter&#XA0;7&#XA0;&#XA0;Debugging</A> </LI><LI CLASS="li-toc"><A HREF="#htoc96">Chapter&#XA0;7&#XA0;&#XA0;Debugging</A>
<UL CLASS="toc"><LI CLASS="li-toc"> <UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc98">7.1&#XA0;&#XA0;Log Files</A> <A HREF="#htoc97">7.1&#XA0;&#XA0;Log Files</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc99">7.2&#XA0;&#XA0;Debug Console</A> </LI><LI CLASS="li-toc"><A HREF="#htoc98">7.2&#XA0;&#XA0;Debug Console</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc100">7.3&#XA0;&#XA0;Watchdog Alerts</A> </LI><LI CLASS="li-toc"><A HREF="#htoc99">7.3&#XA0;&#XA0;Watchdog Alerts</A>
</LI></UL> </LI></UL>
</LI><LI CLASS="li-toc"><A HREF="#htoc101">Appendix&#XA0;A&#XA0;&#XA0;Internationalization and Localization</A> </LI><LI CLASS="li-toc"><A HREF="#htoc100">Appendix&#XA0;A&#XA0;&#XA0;Internationalization and Localization</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc102">Appendix&#XA0;B&#XA0;&#XA0;Release Notes</A> </LI><LI CLASS="li-toc"><A HREF="#htoc101">Appendix&#XA0;B&#XA0;&#XA0;Release Notes</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc103">Appendix&#XA0;C&#XA0;&#XA0;Acknowledgements</A> </LI><LI CLASS="li-toc"><A HREF="#htoc102">Appendix&#XA0;C&#XA0;&#XA0;Acknowledgements</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc104">Appendix&#XA0;D&#XA0;&#XA0;Copyright Information</A> </LI><LI CLASS="li-toc"><A HREF="#htoc103">Appendix&#XA0;D&#XA0;&#XA0;Copyright Information</A>
</LI></UL><!--TOC chapter Introduction--> </LI></UL><!--TOC chapter Introduction-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc1">Chapter&#XA0;1</A>&#XA0;&#XA0;Introduction</H1><!--SEC END --><P> <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc1">Chapter&#XA0;1</A>&#XA0;&#XA0;Introduction</H1><!--SEC END --><P>
<A NAME="intro"></A></P><P><TT>ejabberd</TT> is a free and open source instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a rock-solid and feature rich XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</P><!--TOC section Key Features--> <A NAME="intro"></A></P><P><TT>ejabberd</TT> is a free and open source instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a rock-solid and feature rich XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</P><!--TOC section Key Features-->
@ -3251,8 +3250,9 @@ represents all the registered users in the virtual host;
which is only recommended for a small server with just a few hundred users. which is only recommended for a small server with just a few hundred users.
The special member directive <TT>@online@</TT> The special member directive <TT>@online@</TT>
represents the online users in the virtual host. represents the online users in the virtual host.
</DD><DT CLASS="dt-description"><B>Displayed groups</B></DT><DD CLASS="dd-description"> A list of groups that will be in the rosters of this </DD><DT CLASS="dt-description"><B>Displayed groups</B></DT><DD CLASS="dd-description">
group&#X2019;s members. A list of groups that will be in the rosters of this group&#X2019;s members.
A group of other vhost can be identified with <TT>groupid@vhost</TT>
</DD></DL><P>Examples: </DD></DL><P>Examples:
</P><UL CLASS="itemize"><LI CLASS="li-itemize"> </P><UL CLASS="itemize"><LI CLASS="li-itemize">
Take the case of a computer club that wants all its members seeing each Take the case of a computer club that wants all its members seeing each
@ -4359,9 +4359,8 @@ enabled only on one machine in the cluster.
</LI></OL><P>You can repeat these steps for other machines supposed to serve this </LI></OL><P>You can repeat these steps for other machines supposed to serve this
domain.</P><P> <A NAME="servicelb"></A> </P><!--TOC section Service Load-Balancing--> domain.</P><P> <A NAME="servicelb"></A> </P><!--TOC section Service Load-Balancing-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc93">6.3</A>&#XA0;&#XA0;<A HREF="#servicelb">Service Load-Balancing</A></H2><!--SEC END --><P> <A NAME="servicelb"></A> <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc93">6.3</A>&#XA0;&#XA0;<A HREF="#servicelb">Service Load-Balancing</A></H2><!--SEC END --><P> <A NAME="servicelb"></A>
</P><P> <A NAME="componentlb"></A> </P><!--TOC subsection Components Load-Balancing--> </P><P> <A NAME="domainlb"></A> </P><!--TOC subsection Domain Load-Balancing Algorithm-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc94">6.3.1</A>&#XA0;&#XA0;<A HREF="#componentlb">Components Load-Balancing</A></H3><!--SEC END --><P> <A NAME="componentlb"></A> </P><P> <A NAME="domainlb"></A> </P><!--TOC subsection Domain Load-Balancing Algorithm--> <H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc94">6.3.1</A>&#XA0;&#XA0;<A HREF="#domainlb">Domain Load-Balancing Algorithm</A></H3><!--SEC END --><P> <A NAME="domainlb"></A>
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc95">6.3.2</A>&#XA0;&#XA0;<A HREF="#domainlb">Domain Load-Balancing Algorithm</A></H3><!--SEC END --><P> <A NAME="domainlb"></A>
</P><P><TT>ejabberd</TT> includes an algorithm to load balance the components that are plugged on an <TT>ejabberd</TT> cluster. It means that you can plug one or several instances of the same component on each <TT>ejabberd</TT> cluster and that the traffic will be automatically distributed.</P><P>The default distribution algorithm try to deliver to a local instance of a component. If several local instances are available, one instance is chosen randomly. If no instance is available locally, one instance is chosen randomly among the remote component instances.</P><P>If you need a different behaviour, you can change the load balancing behaviour with the option <TT>domain_balancing</TT>. The syntax of the option is the following: </P><P><TT>ejabberd</TT> includes an algorithm to load balance the components that are plugged on an <TT>ejabberd</TT> cluster. It means that you can plug one or several instances of the same component on each <TT>ejabberd</TT> cluster and that the traffic will be automatically distributed.</P><P>The default distribution algorithm try to deliver to a local instance of a component. If several local instances are available, one instance is chosen randomly. If no instance is available locally, one instance is chosen randomly among the remote component instances.</P><P>If you need a different behaviour, you can change the load balancing behaviour with the option <TT>domain_balancing</TT>. The syntax of the option is the following:
</P><DL CLASS="description"><DT CLASS="dt-description"><B><TT>{domain_balancing, "component.example.com", BalancingCriteria}.</TT></B></DT></DL><P>Several balancing criteria are available: </P><DL CLASS="description"><DT CLASS="dt-description"><B><TT>{domain_balancing, "component.example.com", BalancingCriteria}.</TT></B></DT></DL><P>Several balancing criteria are available:
</P><UL CLASS="itemize"><LI CLASS="li-itemize"> </P><UL CLASS="itemize"><LI CLASS="li-itemize">
@ -4370,12 +4369,12 @@ domain.</P><P> <A NAME="servicelb"></A> </P><!--TOC section Service Load-Balanci
</LI><LI CLASS="li-itemize"><TT>bare_destination</TT>: the bare JID (without resource) of the packet <TT>to</TT> attribute is used. </LI><LI CLASS="li-itemize"><TT>bare_destination</TT>: the bare JID (without resource) of the packet <TT>to</TT> attribute is used.
</LI><LI CLASS="li-itemize"><TT>bare_source</TT>: the bare JID (without resource) of the packet <TT>from</TT> attribute is used. </LI><LI CLASS="li-itemize"><TT>bare_source</TT>: the bare JID (without resource) of the packet <TT>from</TT> attribute is used.
</LI></UL><P>If the value corresponding to the criteria is the same, the same component instance in the cluster will be used.</P><P> <A NAME="lbbuckets"></A> </P><!--TOC subsection Load-Balancing Buckets--> </LI></UL><P>If the value corresponding to the criteria is the same, the same component instance in the cluster will be used.</P><P> <A NAME="lbbuckets"></A> </P><!--TOC subsection Load-Balancing Buckets-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc96">6.3.3</A>&#XA0;&#XA0;<A HREF="#lbbuckets">Load-Balancing Buckets</A></H3><!--SEC END --><P> <A NAME="lbbuckets"></A> <H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc95">6.3.2</A>&#XA0;&#XA0;<A HREF="#lbbuckets">Load-Balancing Buckets</A></H3><!--SEC END --><P> <A NAME="lbbuckets"></A>
</P><P>When there is a risk of failure for a given component, domain balancing can cause service trouble. If one component is failing the service will not work correctly unless the sessions are rebalanced.</P><P>In this case, it is best to limit the problem to the sessions handled by the failing component. This is what the <TT>domain_balancing_component_number</TT> option does, making the load balancing algorithm not dynamic, but sticky on a fix number of component instances.</P><P>The syntax is: </P><P>When there is a risk of failure for a given component, domain balancing can cause service trouble. If one component is failing the service will not work correctly unless the sessions are rebalanced.</P><P>In this case, it is best to limit the problem to the sessions handled by the failing component. This is what the <TT>domain_balancing_component_number</TT> option does, making the load balancing algorithm not dynamic, but sticky on a fix number of component instances.</P><P>The syntax is:
</P><DL CLASS="description"><DT CLASS="dt-description"><B><TT>{domain_balancing_component_number, "component.example.com", Number}.</TT></B></DT></DL><P> <A NAME="debugging"></A> </P><!--TOC chapter Debugging--> </P><DL CLASS="description"><DT CLASS="dt-description"><B><TT>{domain_balancing_component_number, "component.example.com", Number}.</TT></B></DT></DL><P> <A NAME="debugging"></A> </P><!--TOC chapter Debugging-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc97">Chapter&#XA0;7</A>&#XA0;&#XA0;<A HREF="#debugging">Debugging</A></H1><!--SEC END --><P> <A NAME="debugging"></A> <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc96">Chapter&#XA0;7</A>&#XA0;&#XA0;<A HREF="#debugging">Debugging</A></H1><!--SEC END --><P> <A NAME="debugging"></A>
</P><P> <A NAME="logfiles"></A> </P><!--TOC section Log Files--> </P><P> <A NAME="logfiles"></A> </P><!--TOC section Log Files-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc98">7.1</A>&#XA0;&#XA0;<A HREF="#logfiles">Log Files</A></H2><!--SEC END --><P> <A NAME="logfiles"></A> </P><P>An <TT>ejabberd</TT> node writes two log files: <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc97">7.1</A>&#XA0;&#XA0;<A HREF="#logfiles">Log Files</A></H2><!--SEC END --><P> <A NAME="logfiles"></A> </P><P>An <TT>ejabberd</TT> node writes two log files:
</P><DL CLASS="description"><DT CLASS="dt-description"> </P><DL CLASS="description"><DT CLASS="dt-description">
<B><TT>ejabberd.log</TT></B></DT><DD CLASS="dd-description"> is the ejabberd service log, with the messages reported by <TT>ejabberd</TT> code <B><TT>ejabberd.log</TT></B></DT><DD CLASS="dd-description"> is the ejabberd service log, with the messages reported by <TT>ejabberd</TT> code
</DD><DT CLASS="dt-description"><B><TT>erlang.log</TT></B></DT><DD CLASS="dd-description"> is the Erlang/OTP system log, with the messages reported by Erlang/OTP using SASL (System Architecture Support Libraries) </DD><DT CLASS="dt-description"><B><TT>erlang.log</TT></B></DT><DD CLASS="dd-description"> is the Erlang/OTP system log, with the messages reported by Erlang/OTP using SASL (System Architecture Support Libraries)
@ -4400,12 +4399,12 @@ The ejabberdctl command <TT>reopen-log</TT>
(please refer to section <A HREF="#ectl-commands">4.1.1</A>) (please refer to section <A HREF="#ectl-commands">4.1.1</A>)
reopens the log files, reopens the log files,
and also renames the old ones if you didn&#X2019;t rename them.</P><P> <A NAME="debugconsole"></A> </P><!--TOC section Debug Console--> and also renames the old ones if you didn&#X2019;t rename them.</P><P> <A NAME="debugconsole"></A> </P><!--TOC section Debug Console-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc99">7.2</A>&#XA0;&#XA0;<A HREF="#debugconsole">Debug Console</A></H2><!--SEC END --><P> <A NAME="debugconsole"></A> </P><P>The Debug Console is an Erlang shell attached to an already running <TT>ejabberd</TT> server. <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc98">7.2</A>&#XA0;&#XA0;<A HREF="#debugconsole">Debug Console</A></H2><!--SEC END --><P> <A NAME="debugconsole"></A> </P><P>The Debug Console is an Erlang shell attached to an already running <TT>ejabberd</TT> server.
With this Erlang shell, an experienced administrator can perform complex tasks.</P><P>This shell gives complete control over the <TT>ejabberd</TT> server, With this Erlang shell, an experienced administrator can perform complex tasks.</P><P>This shell gives complete control over the <TT>ejabberd</TT> server,
so it is important to use it with extremely care. so it is important to use it with extremely care.
There are some simple and safe examples in the article There are some simple and safe examples in the article
<A HREF="http://www.ejabberd.im/interconnect-erl-nodes">Interconnecting Erlang Nodes</A></P><P>To exit the shell, close the window or press the keys: control+c control+c.</P><P> <A NAME="watchdog"></A> </P><!--TOC section Watchdog Alerts--> <A HREF="http://www.ejabberd.im/interconnect-erl-nodes">Interconnecting Erlang Nodes</A></P><P>To exit the shell, close the window or press the keys: control+c control+c.</P><P> <A NAME="watchdog"></A> </P><!--TOC section Watchdog Alerts-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc100">7.3</A>&#XA0;&#XA0;<A HREF="#watchdog">Watchdog Alerts</A></H2><!--SEC END --><P> <A NAME="watchdog"></A> <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc99">7.3</A>&#XA0;&#XA0;<A HREF="#watchdog">Watchdog Alerts</A></H2><!--SEC END --><P> <A NAME="watchdog"></A>
</P><P><TT>ejabberd</TT> includes a watchdog mechanism that may be useful to developers </P><P><TT>ejabberd</TT> includes a watchdog mechanism that may be useful to developers
when troubleshooting a problem related to memory usage. when troubleshooting a problem related to memory usage.
If a process in the <TT>ejabberd</TT> server consumes more memory than the configured threshold, If a process in the <TT>ejabberd</TT> server consumes more memory than the configured threshold,
@ -4425,7 +4424,7 @@ or in a conversation with the watchdog alert bot.</P><P>The syntax is:
To remove all watchdog admins, set the option with an empty list: To remove all watchdog admins, set the option with an empty list:
</P><PRE CLASS="verbatim">{watchdog_admins, []}. </P><PRE CLASS="verbatim">{watchdog_admins, []}.
</PRE><P> <A NAME="i18ni10n"></A> </P><!--TOC chapter Internationalization and Localization--> </PRE><P> <A NAME="i18ni10n"></A> </P><!--TOC chapter Internationalization and Localization-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc101">Appendix&#XA0;A</A>&#XA0;&#XA0;<A HREF="#i18ni10n">Internationalization and Localization</A></H1><!--SEC END --><P> <A NAME="i18ni10n"></A> <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc100">Appendix&#XA0;A</A>&#XA0;&#XA0;<A HREF="#i18ni10n">Internationalization and Localization</A></H1><!--SEC END --><P> <A NAME="i18ni10n"></A>
</P><P>The source code of <TT>ejabberd</TT> supports localization. </P><P>The source code of <TT>ejabberd</TT> supports localization.
The translators can edit the The translators can edit the
<A HREF="http://www.gnu.org/software/gettext/">gettext</A> .po files <A HREF="http://www.gnu.org/software/gettext/">gettext</A> .po files
@ -4460,9 +4459,9 @@ HTTP header &#X2018;Accept-Language: ru&#X2019;</TD></TR>
</TABLE></DIV> </TABLE></DIV>
<A NAME="fig:webadmmainru"></A> <A NAME="fig:webadmmainru"></A>
<DIV CLASS="center"><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE><P> <A NAME="releasenotes"></A> </P><!--TOC chapter Release Notes--> <DIV CLASS="center"><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE><P> <A NAME="releasenotes"></A> </P><!--TOC chapter Release Notes-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc102">Appendix&#XA0;B</A>&#XA0;&#XA0;<A HREF="#releasenotes">Release Notes</A></H1><!--SEC END --><P> <A NAME="releasenotes"></A> <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc101">Appendix&#XA0;B</A>&#XA0;&#XA0;<A HREF="#releasenotes">Release Notes</A></H1><!--SEC END --><P> <A NAME="releasenotes"></A>
</P><P>Release notes are available from <A HREF="http://www.process-one.net/en/ejabberd/release_notes/">ejabberd Home Page</A></P><P> <A NAME="acknowledgements"></A> </P><!--TOC chapter Acknowledgements--> </P><P>Release notes are available from <A HREF="http://www.process-one.net/en/ejabberd/release_notes/">ejabberd Home Page</A></P><P> <A NAME="acknowledgements"></A> </P><!--TOC chapter Acknowledgements-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc103">Appendix&#XA0;C</A>&#XA0;&#XA0;<A HREF="#acknowledgements">Acknowledgements</A></H1><!--SEC END --><P> <A NAME="acknowledgements"></A> </P><P>Thanks to all people who contributed to this guide: <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc102">Appendix&#XA0;C</A>&#XA0;&#XA0;<A HREF="#acknowledgements">Acknowledgements</A></H1><!--SEC END --><P> <A NAME="acknowledgements"></A> </P><P>Thanks to all people who contributed to this guide:
</P><UL CLASS="itemize"><LI CLASS="li-itemize"> </P><UL CLASS="itemize"><LI CLASS="li-itemize">
Alexey Shchepin (<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A>) Alexey Shchepin (<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A>)
</LI><LI CLASS="li-itemize">Badlop (<A HREF="xmpp:badlop@jabberes.org"><TT>xmpp:badlop@jabberes.org</TT></A>) </LI><LI CLASS="li-itemize">Badlop (<A HREF="xmpp:badlop@jabberes.org"><TT>xmpp:badlop@jabberes.org</TT></A>)
@ -4475,7 +4474,7 @@ Alexey Shchepin (<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT
</LI><LI CLASS="li-itemize">Sergei Golovan (<A HREF="xmpp:sgolovan@nes.ru"><TT>xmpp:sgolovan@nes.ru</TT></A>) </LI><LI CLASS="li-itemize">Sergei Golovan (<A HREF="xmpp:sgolovan@nes.ru"><TT>xmpp:sgolovan@nes.ru</TT></A>)
</LI><LI CLASS="li-itemize">Vsevolod Pelipas (<A HREF="xmpp:vsevoload@jabber.ru"><TT>xmpp:vsevoload@jabber.ru</TT></A>) </LI><LI CLASS="li-itemize">Vsevolod Pelipas (<A HREF="xmpp:vsevoload@jabber.ru"><TT>xmpp:vsevoload@jabber.ru</TT></A>)
</LI></UL><P> <A NAME="copyright"></A> </P><!--TOC chapter Copyright Information--> </LI></UL><P> <A NAME="copyright"></A> </P><!--TOC chapter Copyright Information-->
<H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc104">Appendix&#XA0;D</A>&#XA0;&#XA0;<A HREF="#copyright">Copyright Information</A></H1><!--SEC END --><P> <A NAME="copyright"></A> </P><P>Ejabberd Installation and Operation Guide.<BR> <H1 CLASS="chapter"><!--SEC ANCHOR --><A NAME="htoc103">Appendix&#XA0;D</A>&#XA0;&#XA0;<A HREF="#copyright">Copyright Information</A></H1><!--SEC END --><P> <A NAME="copyright"></A> </P><P>Ejabberd Installation and Operation Guide.<BR>
Copyright &#XA9; 2003 &#X2014; 2010 ProcessOne</P><P>This document is free software; you can redistribute it and/or Copyright &#XA9; 2003 &#X2014; 2010 ProcessOne</P><P>This document is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2

View File

@ -4127,8 +4127,9 @@ has a unique identification and the following parameters:
which is only recommended for a small server with just a few hundred users. which is only recommended for a small server with just a few hundred users.
The special member directive \term{@online@} The special member directive \term{@online@}
represents the online users in the virtual host. represents the online users in the virtual host.
\item[Displayed groups] A list of groups that will be in the rosters of this \item[Displayed groups]
group's members. A list of groups that will be in the rosters of this group's members.
A group of other vhost can be identified with \term{groupid@vhost}
\end{description} \end{description}
Examples: Examples:
@ -5694,7 +5695,8 @@ domain.
\makesection{servicelb}{Service Load-Balancing} \makesection{servicelb}{Service Load-Balancing}
\ind{component load-balancing} \ind{component load-balancing}
\makesubsection{componentlb}{Components Load-Balancing} % This section never had content, should it?
% \makesubsection{componentlb}{Components Load-Balancing}
\makesubsection{domainlb}{Domain Load-Balancing Algorithm} \makesubsection{domainlb}{Domain Load-Balancing Algorithm}
\ind{options!domain\_balancing} \ind{options!domain\_balancing}

View File

@ -0,0 +1,39 @@
Release Notes
ejabberd 2.1.10
ejabberd 2.1.10 includes a few bugfixes and improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.10
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
The major changes are:
* Erlang/OTP compatibility
- Support Erlang/OTP R15B regexp and drivers (EJAB-1521)
- Fix modules update in R14B04 and higher
- Fix modules update of stripped beams (EJAB-1520)
* XMPP Core
- Fix presence problem in C2S after first unavailable (EJAB-1466)
- Fix bug on S2S shaper when TLS is used
- Prevent overload of incoming S2S connections
* XEPs
- BOSH: Get rid of useless mnesia transaction (EJAB-1502)
- MUC: Don't reveal invitee resource when room informs invitor
- Privacy: Activate "Blocked Contacts" to current c2s connection (EJAB-1519)
- Privacy: Always allow packets from user's server and bare jid (EJAB-1441)
- Pubsub: Add hooks for node creation/deletion (EJAB-1470)
- Shared Rosters: support groupname@vhost in Displayed Groups (EJAB-506)
- Vcard: Fix error when lowercasing some search results (EJAB-1490)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/

View File

@ -1,2 +1,2 @@
% ejabberd version (automatically generated). % ejabberd version (automatically generated).
\newcommand{\version}{2.1.9} \newcommand{\version}{2.1.10}

View File

@ -223,19 +223,19 @@ match_acl(ACL, JID, Host) ->
end. end.
is_regexp_match(String, RegExp) -> is_regexp_match(String, RegExp) ->
case regexp:first_match(String, RegExp) of case ejabberd_regexp:run(String, RegExp) of
nomatch -> nomatch ->
false; false;
{match, _, _} -> match ->
true; true;
{error, ErrDesc} -> {error, ErrDesc} ->
?ERROR_MSG( ?ERROR_MSG(
"Wrong regexp ~p in ACL: ~p", "Wrong regexp ~p in ACL: ~p",
[RegExp, lists:flatten(regexp:format_error(ErrDesc))]), [RegExp, ErrDesc]),
false false
end. end.
is_glob_match(String, Glob) -> is_glob_match(String, Glob) ->
is_regexp_match(String, regexp:sh_to_awk(Glob)). is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).

538
src/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
{application, ejabberd, {application, ejabberd,
[{description, "ejabberd"}, [{description, "ejabberd"},
{vsn, "2.2.9"}, {vsn, "2.2.10"},
{modules, [acl, {modules, [acl,
adhoc, adhoc,
configure, configure,

View File

@ -405,14 +405,15 @@ update_list() ->
[atom_to_list(Beam) || Beam <- UpdatedBeams]. [atom_to_list(Beam) || Beam <- UpdatedBeams].
update("all") -> update("all") ->
[update_module(ModStr) || ModStr <- update_list()]; [update_module(ModStr) || ModStr <- update_list()],
{ok, []};
update(ModStr) -> update(ModStr) ->
update_module(ModStr). update_module(ModStr).
update_module(ModuleNameString) -> update_module(ModuleNameString) ->
ModuleName = list_to_atom(ModuleNameString), ModuleName = list_to_atom(ModuleNameString),
case ejabberd_update:update([ModuleName]) of case ejabberd_update:update([ModuleName]) of
{ok, Res} -> {ok, io_lib:format("Updated: ~p", [Res])}; {ok, _Res} -> {ok, []};
{error, Reason} -> {error, Reason} {error, Reason} -> {error, Reason}
end. end.

View File

@ -2219,10 +2219,10 @@ presence_update(From, Packet, StateData) ->
FromUnavail = (StateData#state.pres_last == undefined) or FromUnavail = (StateData#state.pres_last == undefined) or
StateData#state.pres_invis, StateData#state.pres_invis,
?DEBUG("from unavail = ~p~n", [FromUnavail]), ?DEBUG("from unavail = ~p~n", [FromUnavail]),
NewStateData = StateData#state{pres_last = Packet,
pres_invis = false,
pres_timestamp = Timestamp},
NewState = NewState =
NewStateData = StateData#state{pres_last = Packet,
pres_invis = false,
pres_timestamp = Timestamp},
if if
FromUnavail -> FromUnavail ->
ejabberd_hooks:run(user_available_hook, ejabberd_hooks:run(user_available_hook,

View File

@ -190,7 +190,7 @@ process(["help" | Mode]) ->
print_usage_help(MaxC, ShCode), print_usage_help(MaxC, ShCode),
?STATUS_SUCCESS; ?STATUS_SUCCESS;
[CmdString | _] -> [CmdString | _] ->
{ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"), CmdStringU = ejabberd_regexp:greplace(CmdString, "-", "_"),
print_usage_commands(CmdStringU, MaxC, ShCode), print_usage_commands(CmdStringU, MaxC, ShCode),
?STATUS_SUCCESS ?STATUS_SUCCESS
end; end;
@ -281,7 +281,7 @@ try_call_command(Args, Auth, AccessCommands) ->
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType} %% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType}
call_command([CmdString | Args], Auth, AccessCommands) -> call_command([CmdString | Args], Auth, AccessCommands) ->
{ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"), CmdStringU = ejabberd_regexp:greplace(CmdString, "-", "_"),
Command = list_to_atom(CmdStringU), Command = list_to_atom(CmdStringU),
case ejabberd_commands:get_command_format(Command) of case ejabberd_commands:get_command_format(Command) of
{error, command_unknown} -> {error, command_unknown} ->
@ -678,13 +678,13 @@ filter_commands(All, SubString) ->
end. end.
filter_commands_regexp(All, Glob) -> filter_commands_regexp(All, Glob) ->
RegExp = regexp:sh_to_awk(Glob), RegExp = ejabberd_regexp:sh_to_awk(Glob),
lists:filter( lists:filter(
fun(Command) -> fun(Command) ->
case regexp:first_match(Command, RegExp) of case ejabberd_regexp:run(Command, RegExp) of
{match, _, _} -> match ->
true; true;
_ -> nomatch ->
false false
end end
end, end,

72
src/ejabberd_regexp.erl Normal file
View File

@ -0,0 +1,72 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_regexp.erl
%%% Author : Badlop
%%% Purpose : Frontend to Re and Regexp OTP modules
%%% Created : 8 Dec 2011 by Badlop
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_regexp).
-compile([export_all]).
exec(ReM, ReF, ReA, RgM, RgF, RgA) ->
try apply(ReM, ReF, ReA)
catch
error:undef ->
apply(RgM, RgF, RgA);
A:B ->
{error, {A, B}}
end.
run(String, Regexp) ->
case exec(re, run, [String, Regexp, [{capture, none}]], regexp, first_match, [String, Regexp]) of
{match, _, _} -> match;
{match, _} -> match;
match -> match;
nomatch -> nomatch;
{error, Error} -> {error, Error}
end.
split(String, Regexp) ->
case exec(re, split, [String, Regexp, [{return, list}]], regexp, split, [String, Regexp]) of
{ok, FieldList} -> FieldList;
{error, Error} -> throw(Error);
A -> A
end.
replace(String, Regexp, New) ->
case exec(re, replace, [String, Regexp, New, [{return, list}]], regexp, sub, [String, Regexp, New]) of
{ok, NewString, _RepCount} -> NewString;
{error, Error} -> throw(Error);
A -> A
end.
greplace(String, Regexp, New) ->
case exec(re, replace, [String, Regexp, New, [global, {return, list}]], regexp, sub, [String, Regexp, New]) of
{ok, NewString, _RepCount} -> NewString;
{error, Error} -> throw(Error);
A -> A
end.
sh_to_awk(ShRegExp) ->
case exec(xmerl_regexp, sh_to_awk, [ShRegExp], regexp, sh_to_awk, [ShRegExp]) of
A -> A
end.

View File

@ -41,7 +41,11 @@
dirty_get_connections/0, dirty_get_connections/0,
allow_host/2, allow_host/2,
incoming_s2s_number/0, incoming_s2s_number/0,
outgoing_s2s_number/0 outgoing_s2s_number/0,
clean_temporarily_blocked_table/0,
list_temporarily_blocked_hosts/0,
external_host_overloaded/1,
is_temporarly_blocked/1
]). ]).
%% gen_server callbacks %% gen_server callbacks
@ -57,9 +61,14 @@
-define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER, 1). -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER, 1).
-define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE, 1). -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE, 1).
-define(S2S_OVERLOAD_BLOCK_PERIOD, 60).
%% once a server is temporarly blocked, it stay blocked for 60 seconds
-record(s2s, {fromto, pid, key}). -record(s2s, {fromto, pid, key}).
-record(state, {}). -record(state, {}).
-record(temporarily_blocked, {host, timestamp}).
%%==================================================================== %%====================================================================
%% API %% API
%%==================================================================== %%====================================================================
@ -79,6 +88,31 @@ route(From, To, Packet) ->
ok ok
end. end.
clean_temporarily_blocked_table() ->
mnesia:clear_table(temporarily_blocked).
list_temporarily_blocked_hosts() ->
ets:tab2list(temporarily_blocked).
external_host_overloaded(Host) ->
?INFO_MSG("Disabling connections from ~s for ~p seconds", [Host, ?S2S_OVERLOAD_BLOCK_PERIOD]),
mnesia:transaction( fun() ->
mnesia:write(#temporarily_blocked{host = Host, timestamp = now()})
end).
is_temporarly_blocked(Host) ->
case mnesia:dirty_read(temporarily_blocked, Host) of
[] -> false;
[#temporarily_blocked{timestamp = T}=Entry] ->
case timer:now_diff(now(), T) of
N when N > ?S2S_OVERLOAD_BLOCK_PERIOD * 1000 * 1000 ->
mnesia:dirty_delete_object(Entry),
false;
_ ->
true
end
end.
remove_connection(FromTo, Pid, Key) -> remove_connection(FromTo, Pid, Key) ->
case catch mnesia:dirty_match_object(s2s, #s2s{fromto = FromTo, case catch mnesia:dirty_match_object(s2s, #s2s{fromto = FromTo,
pid = Pid, pid = Pid,
@ -190,6 +224,7 @@ init([]) ->
{attributes, record_info(fields, s2s)}]), {attributes, record_info(fields, s2s)}]),
mnesia:add_table_copy(s2s, node(), ram_copies), mnesia:add_table_copy(s2s, node(), ram_copies),
ejabberd_commands:register_commands(commands()), ejabberd_commands:register_commands(commands()),
mnesia:create_table(temporarily_blocked, [{ram_copies, [node()]}, {attributes, record_info(fields, temporarily_blocked)}]),
{ok, #state{}}. {ok, #state{}}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -511,6 +546,9 @@ update_tables() ->
%% Check if host is in blacklist or white list %% Check if host is in blacklist or white list
allow_host(MyServer, S2SHost) -> allow_host(MyServer, S2SHost) ->
allow_host2(MyServer, S2SHost) andalso (not is_temporarly_blocked(S2SHost)).
allow_host2(MyServer, S2SHost) ->
Hosts = ?MYHOSTS, Hosts = ?MYHOSTS,
case lists:dropwhile( case lists:dropwhile(
fun(ParentDomain) -> fun(ParentDomain) ->

View File

@ -27,7 +27,7 @@
-module(ejabberd_s2s_in). -module(ejabberd_s2s_in).
-author('alexey@process-one.net'). -author('alexey@process-one.net').
-behaviour(gen_fsm). -behaviour(p1_fsm).
%% External exports %% External exports
-export([start/2, -export([start/2,
@ -44,6 +44,7 @@
handle_sync_event/4, handle_sync_event/4,
code_change/4, code_change/4,
handle_info/3, handle_info/3,
print_state/1,
terminate/3]). terminate/3]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -92,10 +93,12 @@
-define(FSMOPTS, []). -define(FSMOPTS, []).
-endif. -endif.
-define(FSMLIMITS, [{max_queue, 2000}]). %% if queue grows more than this, we shutdown this connection.
%% Module start with or without supervisor: %% Module start with or without supervisor:
-ifdef(NO_TRANSIENT_SUPERVISORS). -ifdef(NO_TRANSIENT_SUPERVISORS).
-define(SUPERVISOR_START, gen_fsm:start(ejabberd_s2s_in, [SockData, Opts], -define(SUPERVISOR_START, p1_fsm:start(ejabberd_s2s_in, [SockData, Opts],
?FSMOPTS)). ?FSMOPTS ++ ?FSMLIMITS)).
-else. -else.
-define(SUPERVISOR_START, supervisor:start_child(ejabberd_s2s_in_sup, -define(SUPERVISOR_START, supervisor:start_child(ejabberd_s2s_in_sup,
[SockData, Opts])). [SockData, Opts])).
@ -131,7 +134,7 @@ start(SockData, Opts) ->
?SUPERVISOR_START. ?SUPERVISOR_START.
start_link(SockData, Opts) -> start_link(SockData, Opts) ->
gen_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS). p1_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS ++ ?FSMLIMITS).
socket_type() -> socket_type() ->
xml_stream. xml_stream.
@ -347,8 +350,9 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
error -> error ->
false false
end, end,
AllowRemoteHost = ejabberd_s2s:allow_host("", AuthDomain),
if if
AuthRes -> AuthRes andalso AllowRemoteHost ->
(StateData#state.sockmod):reset_stream( (StateData#state.sockmod):reset_stream(
StateData#state.socket), StateData#state.socket),
send_element(StateData, send_element(StateData,
@ -590,14 +594,7 @@ handle_sync_event(get_state_infos, _From, StateName, StateData) ->
catch catch
_:_ -> {unknown,unknown} _:_ -> {unknown,unknown}
end, end,
Domains = case StateData#state.authenticated of Domains = get_external_hosts(StateData),
true ->
[StateData#state.auth_domain];
false ->
Connections = StateData#state.connections,
[D || {{D, _}, established} <-
dict:to_list(Connections)]
end,
Infos = [ Infos = [
{direction, in}, {direction, in},
{statename, StateName}, {statename, StateName},
@ -656,9 +653,32 @@ handle_info(_, StateName, StateData) ->
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
terminate(Reason, _StateName, StateData) -> terminate(Reason, _StateName, StateData) ->
?DEBUG("terminated: ~p", [Reason]), ?DEBUG("terminated: ~p", [Reason]),
case Reason of
{process_limit, _} ->
[ejabberd_s2s:external_host_overloaded(Host) || Host <- get_external_hosts(StateData)];
_ ->
ok
end,
(StateData#state.sockmod):close(StateData#state.socket), (StateData#state.sockmod):close(StateData#state.socket),
ok. ok.
get_external_hosts(StateData) ->
case StateData#state.authenticated of
true ->
[StateData#state.auth_domain];
false ->
Connections = StateData#state.connections,
[D || {{D, _}, established} <- dict:to_list(Connections)]
end.
%%----------------------------------------------------------------------
%% Func: print_state/1
%% Purpose: Prepare the state to be printed on error log
%% Returns: State to print
%%----------------------------------------------------------------------
print_state(State) ->
State.
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% Internal functions %%% Internal functions
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
@ -811,11 +831,11 @@ match_labels([DL | DLabels], [PL | PLabels]) ->
orelse (C == $-) orelse (C == $*) orelse (C == $-) orelse (C == $*)
end, PL) of end, PL) of
true -> true ->
Regexp = regexp:sh_to_awk(PL), Regexp = ejabberd_regexp:sh_to_awk(PL),
case regexp:match(DL, Regexp) of case ejabberd_regexp:run(DL, Regexp) of
{match, _, _} -> match ->
match_labels(DLabels, PLabels); match_labels(DLabels, PLabels);
_ -> nomatch ->
false false
end; end;
false -> false ->

View File

@ -41,10 +41,10 @@ update() ->
case update_info() of case update_info() of
{ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} -> {ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} ->
Eval = Eval =
release_handler_1:eval_script( eval_script(
LowLevelScript, [], LowLevelScript, [],
[{ejabberd, "", filename:join(Dir, "..")}]), [{ejabberd, "", filename:join(Dir, "..")}]),
?INFO_MSG("eval: ~p~n", [Eval]), ?DEBUG("eval: ~p~n", [Eval]),
Eval; Eval;
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
@ -58,15 +58,25 @@ update(ModulesToUpdate) ->
[A || A <- UpdatedBeamsAll, B <- ModulesToUpdate, A == B], [A || A <- UpdatedBeamsAll, B <- ModulesToUpdate, A == B],
{_, LowLevelScript, _} = build_script(Dir, UpdatedBeamsNow), {_, LowLevelScript, _} = build_script(Dir, UpdatedBeamsNow),
Eval = Eval =
release_handler_1:eval_script( eval_script(
LowLevelScript, [], LowLevelScript, [],
[{ejabberd, "", filename:join(Dir, "..")}]), [{ejabberd, "", filename:join(Dir, "..")}]),
?INFO_MSG("eval: ~p~n", [Eval]), ?DEBUG("eval: ~p~n", [Eval]),
Eval; Eval;
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
end. end.
%% OTP R14B03 and older provided release_handler_1:eval_script/3
%% But OTP R14B04 and newer provide release_handler_1:eval_script/5
eval_script(Script, Apps, LibDirs) ->
case lists:member({eval_script, 5}, release_handler_1:module_info(exports)) of
true ->
release_handler_1:eval_script(Script, Apps, LibDirs, [], []);
false ->
release_handler_1:eval_script(Script, Apps, LibDirs)
end.
%% Get information about the modified modules %% Get information about the modified modules
update_info() -> update_info() ->
Dir = filename:dirname(code:which(ejabberd)), Dir = filename:dirname(code:which(ejabberd)),
@ -118,8 +128,10 @@ get_new_version(Module) ->
get_current_version(Module) -> get_current_version(Module) ->
Attrs = Module:module_info(attributes), Attrs = Module:module_info(attributes),
{value, {vsn, CurVsn}} = lists:keysearch(vsn, 1, Attrs), case lists:keysearch(vsn, 1, Attrs) of
CurVsn. {value, {vsn, CurVsn}} -> CurVsn;
_ -> unknown_version
end.
%% @spec(Dir::string(), UpdatedBeams::[atom()]) -> {Script,LowLevelScript,Check} %% @spec(Dir::string(), UpdatedBeams::[atom()]) -> {Script,LowLevelScript,Check}
build_script(Dir, UpdatedBeams) -> build_script(Dir, UpdatedBeams) ->
@ -134,6 +146,10 @@ build_script(Dir, UpdatedBeams) ->
?DEBUG("script: ~p~n", [Script]), ?DEBUG("script: ~p~n", [Script]),
?DEBUG("low level script: ~p~n", [LowLevelScript]), ?DEBUG("low level script: ~p~n", [LowLevelScript]),
?DEBUG("check: ~p~n", [Check]); ?DEBUG("check: ~p~n", [Check]);
{ok, []} ->
?DEBUG("script: ~p~n", [Script]),
?DEBUG("low level script: ~p~n", [LowLevelScript]),
?DEBUG("check: ~p~n", [Check]);
_ -> _ ->
?ERROR_MSG("script: ~p~n", [Script]), ?ERROR_MSG("script: ~p~n", [Script]),
?ERROR_MSG("low level script: ~p~n", [LowLevelScript]), ?ERROR_MSG("low level script: ~p~n", [LowLevelScript]),

View File

@ -23,6 +23,15 @@
#include <erl_driver.h> #include <erl_driver.h>
#include <zlib.h> #include <zlib.h>
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
#define BUF_SIZE 1024 #define BUF_SIZE 1024
@ -98,10 +107,10 @@ static void ejabberd_zlib_drv_stop(ErlDrvData handle)
} }
static int ejabberd_zlib_drv_control(ErlDrvData handle, static ErlDrvSSizeT ejabberd_zlib_drv_control(ErlDrvData handle,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
ejabberd_zlib_data *d = (ejabberd_zlib_data *)handle; ejabberd_zlib_data *d = (ejabberd_zlib_data *)handle;
int err; int err;
@ -187,7 +196,19 @@ ErlDrvEntry ejabberd_zlib_driver_entry = {
NULL, /* handle */ NULL, /* handle */
ejabberd_zlib_drv_control, /* F_PTR control, port_command callback */ ejabberd_zlib_drv_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(ejabberd_zlib_drv) /* must match name in driver_entry */ DRIVER_INIT(ejabberd_zlib_drv) /* must match name in driver_entry */

View File

@ -6,7 +6,7 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
ASN_FLAGS = -bber_bin +optimize +driver ASN_FLAGS = -bber_bin +optimize
ERLANG_CFLAGS = @ERLANG_CFLAGS@ ERLANG_CFLAGS = @ERLANG_CFLAGS@
ERLANG_LIBS = @ERLANG_LIBS@ ERLANG_LIBS = @ERLANG_LIBS@

View File

@ -6,7 +6,7 @@ EFLAGS = -I .. -pz ..
OUTDIR = .. OUTDIR = ..
BEAMS = ..\eldap.beam ..\eldap_filter.beam ..\eldap_pool.beam ..\eldap_utils.beam ..\eldap_filter_yecc.beam BEAMS = ..\eldap.beam ..\eldap_filter.beam ..\eldap_pool.beam ..\eldap_utils.beam ..\eldap_filter_yecc.beam
ASN_FLAGS = -bber_bin +optimize +driver ASN_FLAGS = -bber_bin +optimize
ALL : $(BEAMS) ALL : $(BEAMS)

View File

@ -439,7 +439,7 @@ init([]) ->
end; end;
init({Hosts, Port, Rootdn, Passwd, Opts}) -> init({Hosts, Port, Rootdn, Passwd, Opts}) ->
catch ssl:start(), catch ssl:start(),
ssl:seed(randoms:get_string()), catch ssl:seed(randoms:get_string()),
Encrypt = case proplists:get_value(encrypt, Opts) of Encrypt = case proplists:get_value(encrypt, Opts) of
tls -> tls; tls -> tls;
_ -> none _ -> none

View File

@ -146,30 +146,36 @@ do_sub(S, [{RegExp, New, Times} | T]) ->
do_sub(Result, T). do_sub(Result, T).
do_sub(S, {RegExp, New}, Iter) -> do_sub(S, {RegExp, New}, Iter) ->
case regexp:sub(S, RegExp, New) of case ejabberd_regexp:run(S, RegExp) of
{ok, NewS, 0} -> match ->
NewS; case ejabberd_regexp:replace(S, RegExp, New) of
{ok, NewS, _} when Iter =< ?MAX_RECURSION -> NewS when Iter =< ?MAX_RECURSION ->
do_sub(NewS, {RegExp, New}, Iter+1); do_sub(NewS, {RegExp, New}, Iter+1);
{ok, _, _} when Iter > ?MAX_RECURSION -> _NewS when Iter > ?MAX_RECURSION ->
erlang:error(max_substitute_recursion); erlang:error(max_substitute_recursion)
_ -> end;
erlang:error(bad_regexp) nomatch ->
S;
_ ->
erlang:error(bad_regexp)
end; end;
do_sub(S, {_, _, N}, _) when N<1 -> do_sub(S, {_, _, N}, _) when N<1 ->
S; S;
do_sub(S, {RegExp, New, Times}, Iter) -> do_sub(S, {RegExp, New, Times}, Iter) ->
case regexp:sub(S, RegExp, New) of case ejabberd_regexp:run(S, RegExp) of
{ok, NewS, 0} -> match ->
NewS; case ejabberd_regexp:replace(S, RegExp, New) of
{ok, NewS, _} when Iter < Times -> NewS when Iter < Times ->
do_sub(NewS, {RegExp, New, Times}, Iter+1); do_sub(NewS, {RegExp, New, Times}, Iter+1);
{ok, NewS, _} -> NewS ->
NewS; NewS
_ -> end;
erlang:error(bad_regexp) nomatch ->
S;
_ ->
erlang:error(bad_regexp)
end. end.
replace_amps(String) -> replace_amps(String) ->

View File

@ -94,17 +94,18 @@ get_user_part(String, Pattern) ->
{'EXIT', _} -> {'EXIT', _} ->
{error, badmatch}; {error, badmatch};
Result -> Result ->
case regexp:sub(Pattern, "%u", Result) of case catch ejabberd_regexp:replace(Pattern, "%u", Result) of
{ok, StringRes, _} -> {'EXIT', _} ->
{error, badmatch};
StringRes ->
case (string:to_lower(StringRes) == case (string:to_lower(StringRes) ==
string:to_lower(String)) of string:to_lower(String)) of
true -> true ->
{ok, Result}; {ok, Result};
false -> false ->
{error, badmatch} {error, badmatch}
end; end
_ -> {error, badmatch} end
end
end. end.
make_filter(Data, UIDs) -> make_filter(Data, UIDs) ->

View File

@ -34,6 +34,16 @@
#define PARSE_COMMAND 0 #define PARSE_COMMAND 0
#define PARSE_FINAL_COMMAND 1 #define PARSE_FINAL_COMMAND 1
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
ei_x_buff event_buf; ei_x_buff event_buf;
ei_x_buff xmlns_buf; ei_x_buff xmlns_buf;
@ -190,10 +200,10 @@ static void expat_erl_stop(ErlDrvData handle)
driver_free((char*)handle); driver_free((char*)handle);
} }
static int expat_erl_control(ErlDrvData drv_data, static ErlDrvSSizeT expat_erl_control(ErlDrvData drv_data,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
expat_data* d = (expat_data*)drv_data; expat_data* d = (expat_data*)drv_data;
int res, errcode; int res, errcode;
@ -280,7 +290,19 @@ ErlDrvEntry expat_driver_entry = {
NULL, /* handle */ NULL, /* handle */
expat_erl_control, /* F_PTR control, port_command callback */ expat_erl_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(expat_erl) /* must match name in driver_entry */ DRIVER_INIT(expat_erl) /* must match name in driver_entry */

View File

@ -186,11 +186,11 @@ get_module_opt(Host, Module, Opt, Default) ->
get_module_opt_host(Host, Module, Default) -> get_module_opt_host(Host, Module, Default) ->
Val = get_module_opt(Host, Module, host, Default), Val = get_module_opt(Host, Module, host, Default),
element(2, regexp:gsub(Val, "@HOST@", Host)). ejabberd_regexp:greplace(Val, "@HOST@", Host).
get_opt_host(Host, Opts, Default) -> get_opt_host(Host, Opts, Default) ->
Val = get_opt(host, Opts, Default), Val = get_opt(host, Opts, Default),
element(2, regexp:gsub(Val, "@HOST@", Host)). ejabberd_regexp:greplace(Val, "@HOST@", Host).
loaded_modules(Host) -> loaded_modules(Host) ->
ets:select(ejabberd_modules, ets:select(ejabberd_modules,

View File

@ -542,7 +542,7 @@ get_local_items({_, Host}, ["all users", [$@ | Diap]], _Server, _Lang) ->
Users -> Users ->
SUsers = lists:sort([{S, U} || {U, S} <- Users]), SUsers = lists:sort([{S, U} || {U, S} <- Users]),
case catch begin case catch begin
{ok, [S1, S2]} = regexp:split(Diap, "-"), [S1, S2] = ejabberd_regexp:split(Diap, "-"),
N1 = list_to_integer(S1), N1 = list_to_integer(S1),
N2 = list_to_integer(S2), N2 = list_to_integer(S2),
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),

View File

@ -33,6 +33,7 @@
%% API: %% API:
-export([start/2, -export([start/2,
preinit/2,
init/1, init/1,
stop/1]). stop/1]).
-export([update_bl_c2s/0]). -export([update_bl_c2s/0]).
@ -49,14 +50,20 @@
-record(bl_c2s, {ip}). -record(bl_c2s, {ip}).
%% Start once for all vhost %% Start once for all vhost
start(Host, Opts) -> start(_Host, _Opts) ->
case whereis(?PROCNAME) of Pid = spawn(?MODULE, preinit, [self(), #state{}]),
undefined -> receive {ok, Pid, PreinitResult} ->
?DEBUG("Starting mod_ip_blacklist ~p ~p~n", [Host, Opts]), PreinitResult
register(?PROCNAME, end.
spawn(?MODULE, init, [#state{}]));
_ -> preinit(Parent, State) ->
ok Pid = self(),
try register(?PROCNAME, Pid) of
true ->
Parent ! {ok, Pid, true},
init(State)
catch error:_ ->
Parent ! {ok, Pid, true}
end. end.
%% TODO: %% TODO:

View File

@ -24,6 +24,16 @@
#include <ei.h> #include <ei.h>
#include <iconv.h> #include <iconv.h>
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
typedef struct { typedef struct {
ErlDrvPort port; ErlDrvPort port;
iconv_t cd; iconv_t cd;
@ -46,10 +56,10 @@ static void iconv_erl_stop(ErlDrvData handle)
driver_free((char*)handle); driver_free((char*)handle);
} }
static int iconv_erl_control(ErlDrvData drv_data, static ErlDrvSSizeT iconv_erl_control(ErlDrvData drv_data,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
int i; int i;
int size; int size;
@ -144,7 +154,19 @@ ErlDrvEntry iconv_driver_entry = {
NULL, /* handle */ NULL, /* handle */
iconv_erl_control, /* F_PTR control, port_command callback */ iconv_erl_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(iconv_erl) /* must match name in driver_entry */ DRIVER_INIT(iconv_erl) /* must match name in driver_entry */

View File

@ -625,7 +625,7 @@ handle_info({send_text, Text}, StateName, StateData) ->
{next_state, StateName, StateData}; {next_state, StateName, StateData};
handle_info({tcp, _Socket, Data}, StateName, StateData) -> handle_info({tcp, _Socket, Data}, StateName, StateData) ->
Buf = StateData#state.inbuf ++ binary_to_list(Data), Buf = StateData#state.inbuf ++ binary_to_list(Data),
{ok, Strings} = regexp:split([C || C <- Buf, C /= $\r], "\n"), Strings = ejabberd_regexp:split([C || C <- Buf, C /= $\r], "\n"),
?DEBUG("strings=~p~n", [Strings]), ?DEBUG("strings=~p~n", [Strings]),
NewBuf = process_lines(StateData#state.encoding, Strings), NewBuf = process_lines(StateData#state.encoding, Strings),
{next_state, StateName, StateData#state{inbuf = NewBuf}}; {next_state, StateName, StateData#state{inbuf = NewBuf}};
@ -797,7 +797,7 @@ process_channel_list_user(StateData, Chan, User) ->
process_channel_topic(StateData, Chan, String) -> process_channel_topic(StateData, Chan, String) ->
{ok, Msg, _} = regexp:sub(String, ".*332[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*332[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( jlib:make_jid(
@ -831,7 +831,7 @@ process_channel_topic_who(StateData, Chan, String) ->
error_nick_in_use(_StateData, String) -> error_nick_in_use(_StateData, String) ->
{ok, Msg, _} = regexp:sub(String, ".*433 +[^ ]* +", ""), Msg = ejabberd_regexp:replace(String, ".*433 +[^ ]* +", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
{xmlelement, "error", [{"code", "409"}, {"type", "cancel"}], {xmlelement, "error", [{"code", "409"}, {"type", "cancel"}],
[{xmlelement, "conflict", [{"xmlns", ?NS_STANZAS}], []}, [{xmlelement, "conflict", [{"xmlns", ?NS_STANZAS}], []},
@ -879,7 +879,7 @@ process_endofwhois(StateData, _String, Nick) ->
[{xmlelement, "body", [], [{xmlcdata, "End of WHOIS"}]}]}). [{xmlelement, "body", [], [{xmlcdata, "End of WHOIS"}]}]}).
process_whois311(StateData, String, Nick, Ident, Irchost) -> process_whois311(StateData, String, Nick, Ident, Irchost) ->
{ok, Fullname, _} = regexp:sub(String, ".*311[^:]*:", ""), Fullname = ejabberd_regexp:replace(String, ".*311[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
@ -891,7 +891,7 @@ process_whois311(StateData, String, Nick, Ident, Irchost) ->
Ident, "@" , Irchost, " : " , Fullname])}]}]}). Ident, "@" , Irchost, " : " , Fullname])}]}]}).
process_whois312(StateData, String, Nick, Ircserver) -> process_whois312(StateData, String, Nick, Ircserver) ->
{ok, Ircserverdesc, _} = regexp:sub(String, ".*312[^:]*:", ""), Ircserverdesc = ejabberd_regexp:replace(String, ".*312[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
@ -902,7 +902,7 @@ process_whois312(StateData, String, Nick, Ircserver) ->
Ircserver, " : ", Ircserverdesc])}]}]}). Ircserver, " : ", Ircserverdesc])}]}]}).
process_whois319(StateData, String, Nick) -> process_whois319(StateData, String, Nick) ->
{ok, Chanlist, _} = regexp:sub(String, ".*319[^:]*:", ""), Chanlist = ejabberd_regexp:replace(String, ".*319[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
@ -916,7 +916,7 @@ process_whois319(StateData, String, Nick) ->
process_chanprivmsg(StateData, Chan, From, String) -> process_chanprivmsg(StateData, Chan, From, String) ->
[FromUser | _] = string:tokens(From, "!"), [FromUser | _] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*PRIVMSG[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*PRIVMSG[^:]*:", ""),
Msg1 = case Msg of Msg1 = case Msg of
[1, $A, $C, $T, $I, $O, $N, $ | Rest] -> [1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest; "/me " ++ Rest;
@ -935,7 +935,7 @@ process_chanprivmsg(StateData, Chan, From, String) ->
process_channotice(StateData, Chan, From, String) -> process_channotice(StateData, Chan, From, String) ->
[FromUser | _] = string:tokens(From, "!"), [FromUser | _] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*NOTICE[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*NOTICE[^:]*:", ""),
Msg1 = case Msg of Msg1 = case Msg of
[1, $A, $C, $T, $I, $O, $N, $ | Rest] -> [1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest; "/me " ++ Rest;
@ -955,7 +955,7 @@ process_channotice(StateData, Chan, From, String) ->
process_privmsg(StateData, _Nick, From, String) -> process_privmsg(StateData, _Nick, From, String) ->
[FromUser | _] = string:tokens(From, "!"), [FromUser | _] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*PRIVMSG[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*PRIVMSG[^:]*:", ""),
Msg1 = case Msg of Msg1 = case Msg of
[1, $A, $C, $T, $I, $O, $N, $ | Rest] -> [1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest; "/me " ++ Rest;
@ -973,7 +973,7 @@ process_privmsg(StateData, _Nick, From, String) ->
process_notice(StateData, _Nick, From, String) -> process_notice(StateData, _Nick, From, String) ->
[FromUser | _] = string:tokens(From, "!"), [FromUser | _] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*NOTICE[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*NOTICE[^:]*:", ""),
Msg1 = case Msg of Msg1 = case Msg of
[1, $A, $C, $T, $I, $O, $N, $ | Rest] -> [1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest; "/me " ++ Rest;
@ -1016,7 +1016,7 @@ process_userinfo(StateData, _Nick, From) ->
process_topic(StateData, Chan, From, String) -> process_topic(StateData, Chan, From, String) ->
[FromUser | _] = string:tokens(From, "!"), [FromUser | _] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*TOPIC[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*TOPIC[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
@ -1030,7 +1030,7 @@ process_topic(StateData, Chan, From, String) ->
process_part(StateData, Chan, From, String) -> process_part(StateData, Chan, From, String) ->
[FromUser | FromIdent] = string:tokens(From, "!"), [FromUser | FromIdent] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*PART[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*PART[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
@ -1059,7 +1059,7 @@ process_part(StateData, Chan, From, String) ->
process_quit(StateData, From, String) -> process_quit(StateData, From, String) ->
[FromUser | FromIdent] = string:tokens(From, "!"), [FromUser | FromIdent] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*QUIT[^:]*:", ""), Msg = ejabberd_regexp:replace(String, ".*QUIT[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
%%NewChans = %%NewChans =
dict:map( dict:map(
@ -1215,7 +1215,7 @@ process_error(StateData, String) ->
end, dict:fetch_keys(StateData#state.channels)). end, dict:fetch_keys(StateData#state.channels)).
error_unknown_num(_StateData, String, Type) -> error_unknown_num(_StateData, String, Type) ->
{ok, Msg, _} = regexp:sub(String, ".*[45][0-9][0-9] +[^ ]* +", ""), Msg = ejabberd_regexp:replace(String, ".*[45][0-9][0-9] +[^ ]* +", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
{xmlelement, "error", [{"code", "500"}, {"type", Type}], {xmlelement, "error", [{"code", "500"}, {"type", Type}],
[{xmlelement, "undefined-condition", [{"xmlns", ?NS_STANZAS}], []}, [{xmlelement, "undefined-condition", [{"xmlns", ?NS_STANZAS}], []},
@ -1313,12 +1313,7 @@ filter_message(Msg) ->
end, filter_mirc_colors(Msg)). end, filter_mirc_colors(Msg)).
filter_mirc_colors(Msg) -> filter_mirc_colors(Msg) ->
case regexp:gsub(Msg, "(\\003[0-9]+)(,[0-9]+)?", "") of ejabberd_regexp:greplace(Msg, "(\\003[0-9]+)(,[0-9]+)?", "").
{ok, Msg2, _} ->
Msg2;
_ ->
Msg
end.
unixtime2string(Unixtime) -> unixtime2string(Unixtime) ->
Secs = Unixtime + calendar:datetime_to_gregorian_seconds( Secs = Unixtime + calendar:datetime_to_gregorian_seconds(

View File

@ -416,11 +416,11 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
io_lib:format("<font class=\"msc\">~s~s~s</font><br/>", io_lib:format("<font class=\"msc\">~s~s~s</font><br/>",
[Nick, ?T(" has set the subject to: "), htmlize(T,NoFollow,FileFormat)]); [Nick, ?T(" has set the subject to: "), htmlize(T,NoFollow,FileFormat)]);
{body, T} -> {body, T} ->
case {regexp:first_match(T, "^/me\s"), Nick} of case {ejabberd_regexp:run(T, "^/me\s"), Nick} of
{_, ""} -> {_, ""} ->
io_lib:format("<font class=\"msm\">~s</font><br/>", io_lib:format("<font class=\"msm\">~s</font><br/>",
[htmlize(T,NoFollow,FileFormat)]); [htmlize(T,NoFollow,FileFormat)]);
{{match, _, _}, _} -> {match, _} ->
io_lib:format("<font class=\"mne\">~s ~s</font><br/>", io_lib:format("<font class=\"mne\">~s ~s</font><br/>",
[Nick, string:substr(htmlize(T,FileFormat), 5)]); [Nick, string:substr(htmlize(T,FileFormat), 5)]);
{nomatch, _} -> {nomatch, _} ->
@ -662,8 +662,7 @@ fw(F, S, O, FileFormat) ->
html -> html ->
S1; S1;
plaintext -> plaintext ->
{ok, Res, _} = regexp:gsub(S1, "<[^>]*>", ""), ejabberd_regexp:greplace(S1, "<[^>]*>", "")
Res
end, end,
io:format(F, S2, []). io:format(F, S2, []).
@ -790,15 +789,15 @@ htmlize(S1, NoFollow, _FileFormat) ->
S2_list). S2_list).
htmlize2(S1, NoFollow) -> htmlize2(S1, NoFollow) ->
S2 = element(2, regexp:gsub(S1, "\\&", "\\&amp;")), S2 = ejabberd_regexp:greplace(S1, "\\&", "\\&amp;"),
S3 = element(2, regexp:gsub(S2, "<", "\\&lt;")), S3 = ejabberd_regexp:greplace(S2, "<", "\\&lt;"),
S4 = element(2, regexp:gsub(S3, ">", "\\&gt;")), S4 = ejabberd_regexp:greplace(S3, ">", "\\&gt;"),
S5 = element(2, regexp:gsub(S4, "((http|https|ftp)://|(mailto|xmpp):)[^] )\'\"}]+", S5 = ejabberd_regexp:greplace(S4, "((http|https|ftp)://|(mailto|xmpp):)[^] )\'\"}]+",
link_regexp(NoFollow))), link_regexp(NoFollow)),
%% Remove 'right-to-left override' unicode character 0x202e %% Remove 'right-to-left override' unicode character 0x202e
S6 = element(2, regexp:gsub(S5, " ", "\\&nbsp;\\&nbsp;")), S6 = ejabberd_regexp:greplace(S5, " ", "\\&nbsp;\\&nbsp;"),
S7 = element(2, regexp:gsub(S6, "\\t", "\\&nbsp;\\&nbsp;\\&nbsp;\\&nbsp;")), S7 = ejabberd_regexp:greplace(S6, "\\t", "\\&nbsp;\\&nbsp;\\&nbsp;\\&nbsp;"),
element(2, regexp:gsub(S7, [226,128,174], "[RLO]")). ejabberd_regexp:greplace(S7, [226,128,174], "[RLO]").
%% Regexp link %% Regexp link
%% Add the nofollow rel attribute when required %% Add the nofollow rel attribute when required

View File

@ -4119,7 +4119,7 @@ check_decline_invitation(Packet) ->
%% Send the decline to the inviter user. %% Send the decline to the inviter user.
%% The original stanza must be slightly modified. %% The original stanza must be slightly modified.
send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) -> send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) ->
FromString = jlib:jid_to_string(FromJID), FromString = jlib:jid_to_string(jlib:jid_remove_resource(FromJID)),
{xmlelement, "decline", DAttrs, DEls} = DEl, {xmlelement, "decline", DAttrs, DEls} = DEl,
DAttrs2 = lists:keydelete("to", 1, DAttrs), DAttrs2 = lists:keydelete("to", 1, DAttrs),
DAttrs3 = [{"from", FromString} | DAttrs2], DAttrs3 = [{"from", FromString} | DAttrs2],

View File

@ -219,6 +219,7 @@ init([ServerHost, Opts]) ->
ejabberd_router:register_route(Host), ejabberd_router:register_route(Host),
update_node_database(Host, ServerHost), update_node_database(Host, ServerHost),
update_state_database(Host, ServerHost), update_state_database(Host, ServerHost),
put(server_host, ServerHost), % not clean, but needed to plug hooks at any location
init_nodes(Host, ServerHost, NodeTree, Plugins), init_nodes(Host, ServerHost, NodeTree, Plugins),
State = #state{host = Host, State = #state{host = Host,
server_host = ServerHost, server_host = ServerHost,
@ -1830,13 +1831,16 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
case transaction(CreateNode, transaction) of case transaction(CreateNode, transaction) of
{result, {NodeId, {Result, broadcast}}} -> {result, {NodeId, {Result, broadcast}}} ->
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions), broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_NodeId, default}} -> {result, {NodeId, default}} ->
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
{result, Reply}; {result, Reply};
{result, {_NodeId, Result}} -> {result, {NodeId, Result}} ->
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
{result, Result}; {result, Result};
Error -> Error ->
%% in case we change transaction to sync_dirty... %% in case we change transaction to sync_dirty...
@ -1879,6 +1883,7 @@ delete_node(Host, Node, Owner) ->
end end
end, end,
Reply = [], Reply = [],
ServerHost = get(server_host), % not clean, but prevent many API changes
case transaction(Host, Node, Action, transaction) of case transaction(Host, Node, Action, transaction) of
{result, {_, {Result, broadcast, Removed}}} -> {result, {_, {Result, broadcast, Removed}}} ->
lists:foreach(fun({RNode, _RSubscriptions}) -> lists:foreach(fun({RNode, _RSubscriptions}) ->
@ -1886,20 +1891,30 @@ delete_node(Host, Node, Owner) ->
NodeId = RNode#pubsub_node.id, NodeId = RNode#pubsub_node.id,
Type = RNode#pubsub_node.type, Type = RNode#pubsub_node.type,
Options = RNode#pubsub_node.options, Options = RNode#pubsub_node.options,
broadcast_removed_node(RH, RN, NodeId, Type, Options) broadcast_removed_node(RH, RN, NodeId, Type, Options),
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId])
end, Removed), end, Removed),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_, {Result, _Removed}}} -> {result, {_, {Result, Removed}}} ->
lists:foreach(fun({RNode, _RSubscriptions}) ->
{RH, RN} = RNode#pubsub_node.nodeid,
NodeId = RNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId])
end, Removed),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_, default}} -> {result, {TNode, default}} ->
NodeId = TNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]),
{result, Reply}; {result, Reply};
{result, {_, Result}} -> {result, {TNode, Result}} ->
NodeId = TNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]),
{result, Result}; {result, Result};
Error -> Error ->
Error Error

View File

@ -217,6 +217,7 @@ init([ServerHost, Opts]) ->
ok ok
end, end,
ejabberd_router:register_route(Host), ejabberd_router:register_route(Host),
put(server_host, ServerHost), % not clean, but needed to plug hooks at any location
init_nodes(Host, ServerHost, NodeTree, Plugins), init_nodes(Host, ServerHost, NodeTree, Plugins),
State = #state{host = Host, State = #state{host = Host,
server_host = ServerHost, server_host = ServerHost,
@ -1596,13 +1597,16 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
case transaction(Host, CreateNode, transaction) of case transaction(Host, CreateNode, transaction) of
{result, {NodeId, {Result, broadcast}}} -> {result, {NodeId, {Result, broadcast}}} ->
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions), broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_NodeId, default}} -> {result, {NodeId, default}} ->
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
{result, Reply}; {result, Reply};
{result, {_NodeId, Result}} -> {result, {NodeId, Result}} ->
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
{result, Result}; {result, Result};
Error -> Error ->
%% in case we change transaction to sync_dirty... %% in case we change transaction to sync_dirty...
@ -1645,6 +1649,7 @@ delete_node(Host, Node, Owner) ->
end end
end, end,
Reply = [], Reply = [],
ServerHost = get(server_host), % not clean, but prevent many API changes
case transaction(Host, Node, Action, transaction) of case transaction(Host, Node, Action, transaction) of
{result, {_, {Result, broadcast, Removed}}} -> {result, {_, {Result, broadcast, Removed}}} ->
lists:foreach(fun({RNode, _RSubscriptions}) -> lists:foreach(fun({RNode, _RSubscriptions}) ->
@ -1652,20 +1657,30 @@ delete_node(Host, Node, Owner) ->
NodeId = RNode#pubsub_node.id, NodeId = RNode#pubsub_node.id,
Type = RNode#pubsub_node.type, Type = RNode#pubsub_node.type,
Options = RNode#pubsub_node.options, Options = RNode#pubsub_node.options,
broadcast_removed_node(RH, RN, NodeId, Type, Options) broadcast_removed_node(RH, RN, NodeId, Type, Options),
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId])
end, Removed), end, Removed),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_, {Result, _Removed}}} -> {result, {_, {Result, Removed}}} ->
lists:foreach(fun({RNode, _RSubscriptions}) ->
{RH, RN} = RNode#pubsub_node.nodeid,
NodeId = RNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId])
end, Removed),
case Result of case Result of
default -> {result, Reply}; default -> {result, Reply};
_ -> {result, Result} _ -> {result, Result}
end; end;
{result, {_, default}} -> {result, {TNode, default}} ->
NodeId = TNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]),
{result, Reply}; {result, Reply};
{result, {_, Result}} -> {result, {TNode, Result}} ->
NodeId = TNode#pubsub_node.id,
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]),
{result, Result}; {result, Result};
Error -> Error ->
Error Error
@ -2146,7 +2161,18 @@ get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners, RSM) ->
send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, last) -> send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, last) ->
Stanza = case get_cached_item(Host, NodeId) of Stanza = case get_cached_item(Host, NodeId) of
undefined -> undefined ->
send_items(Host, Node, NodeId, Type, LJID, 1); % special ODBC optimization, works only with node_hometree_odbc, node_flat_odbc and node_pep_odbc
case node_action(Host, Type, get_last_items, [NodeId, LJID, 1]) of
{result, [LastItem]} ->
{ModifNow, ModifUSR} = LastItem#pubsub_item.modification,
event_stanza_with_delay(
[{xmlelement, "items", nodeAttr(Node),
itemsEls([LastItem])}], ModifNow, ModifUSR);
_ ->
event_stanza(
[{xmlelement, "items", nodeAttr(Node),
itemsEls([])}])
end;
LastItem -> LastItem ->
{ModifNow, ModifUSR} = LastItem#pubsub_item.modification, {ModifNow, ModifUSR} = LastItem#pubsub_item.modification,
event_stanza_with_delay( event_stanza_with_delay(
@ -3266,7 +3292,7 @@ set_configure(Host, Node, From, Els, Lang) ->
end end
end, end,
case transaction(Host, Node, Action, transaction) of case transaction(Host, Node, Action, transaction) of
{result, {TNode, _}} -> {result, {TNode, ok}} ->
NodeId = TNode#pubsub_node.id, NodeId = TNode#pubsub_node.id,
Type = TNode#pubsub_node.type, Type = TNode#pubsub_node.type,
Options = TNode#pubsub_node.options, Options = TNode#pubsub_node.options,

View File

@ -1,5 +1,5 @@
--- mod_pubsub.erl 2011-09-30 13:59:23.000000000 +0200 --- mod_pubsub.erl 2011-12-30 11:27:07.143093497 +0100
+++ mod_pubsub_odbc.erl 2011-09-30 14:04:34.000000000 +0200 +++ mod_pubsub_odbc.erl 2011-12-30 11:26:43.566518734 +0100
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
%%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see
%%% XEP-0060 section 12.18. %%% XEP-0060 section 12.18.
@ -46,10 +46,10 @@
ejabberd_router:register_route(Host), ejabberd_router:register_route(Host),
- update_node_database(Host, ServerHost), - update_node_database(Host, ServerHost),
- update_state_database(Host, ServerHost), - update_state_database(Host, ServerHost),
put(server_host, ServerHost), % not clean, but needed to plug hooks at any location
init_nodes(Host, ServerHost, NodeTree, Plugins), init_nodes(Host, ServerHost, NodeTree, Plugins),
State = #state{host = Host, State = #state{host = Host,
server_host = ServerHost, @@ -283,256 +281,14 @@
@@ -282,256 +280,14 @@
init_nodes(Host, ServerHost, _NodeTree, Plugins) -> init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
%% TODO, this call should be done plugin side %% TODO, this call should be done plugin side
@ -309,7 +309,7 @@
send_loop(State) -> send_loop(State) ->
receive receive
{presence, JID, Pid} -> {presence, JID, Pid} ->
@@ -542,17 +298,15 @@ @@ -543,17 +299,15 @@
%% for each node From is subscribed to %% for each node From is subscribed to
%% and if the node is so configured, send the last published item to From %% and if the node is so configured, send the last published item to From
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
@ -333,7 +333,7 @@
true -> true ->
% resource not concerned about that subscription % resource not concerned about that subscription
ok ok
@@ -671,7 +425,8 @@ @@ -672,7 +426,8 @@
disco_identity(_Host, <<>>, _From) -> disco_identity(_Host, <<>>, _From) ->
[{xmlelement, "identity", [{"category", "pubsub"}, {"type", "pep"}], []}]; [{xmlelement, "identity", [{"category", "pubsub"}, {"type", "pep"}], []}];
disco_identity(Host, Node, From) -> disco_identity(Host, Node, From) ->
@ -343,7 +343,7 @@
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
{result, [{xmlelement, "identity", [{"category", "pubsub"}, {"type", "pep"}], []}, {result, [{xmlelement, "identity", [{"category", "pubsub"}, {"type", "pep"}], []},
@@ -706,7 +461,8 @@ @@ -707,7 +462,8 @@
[?NS_PUBSUB [?NS_PUBSUB
| [?NS_PUBSUB++"#"++Feature || Feature <- features("pep")]]; | [?NS_PUBSUB++"#"++Feature || Feature <- features("pep")]];
disco_features(Host, Node, From) -> disco_features(Host, Node, From) ->
@ -353,7 +353,7 @@
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
{result, [?NS_PUBSUB {result, [?NS_PUBSUB
@@ -731,7 +487,8 @@ @@ -732,7 +488,8 @@
Acc. Acc.
disco_items(Host, <<>>, From) -> disco_items(Host, <<>>, From) ->
@ -363,7 +363,7 @@
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
[{xmlelement, "item", [{xmlelement, "item",
@@ -749,13 +506,14 @@ @@ -750,13 +507,14 @@
_ -> Acc _ -> Acc
end end
end, end,
@ -380,7 +380,7 @@
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of
{result, Items} -> {result, Items} ->
{result, [{xmlelement, "item", {result, [{xmlelement, "item",
@@ -841,10 +599,10 @@ @@ -842,10 +600,10 @@
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]),
lists:foreach(fun lists:foreach(fun
@ -393,7 +393,7 @@
true -> true ->
node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]); node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]);
false -> false ->
@@ -1012,7 +770,8 @@ @@ -1013,7 +771,8 @@
sub_el = SubEl} = IQ -> sub_el = SubEl} = IQ ->
{xmlelement, _, QAttrs, _} = SubEl, {xmlelement, _, QAttrs, _} = SubEl,
Node = xml:get_attr_s("node", QAttrs), Node = xml:get_attr_s("node", QAttrs),
@ -403,7 +403,7 @@
{result, IQRes} -> {result, IQRes} ->
jlib:iq_to_xml( jlib:iq_to_xml(
IQ#iq{type = result, IQ#iq{type = result,
@@ -1125,7 +884,7 @@ @@ -1126,7 +885,7 @@
[] -> [] ->
["leaf"]; %% No sub-nodes: it's a leaf node ["leaf"]; %% No sub-nodes: it's a leaf node
_ -> _ ->
@ -412,7 +412,7 @@
{result, []} -> ["collection"]; {result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"]; {result, _} -> ["leaf", "collection"];
_ -> [] _ -> []
@@ -1141,8 +900,9 @@ @@ -1142,8 +901,9 @@
[]; [];
true -> true ->
[{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} | [{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} |
@ -424,7 +424,7 @@
end, features(Type))] end, features(Type))]
end, end,
%% TODO: add meta-data info (spec section 5.4) %% TODO: add meta-data info (spec section 5.4)
@@ -1171,8 +931,9 @@ @@ -1172,8 +932,9 @@
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []}, {xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_COMMANDS}], []}, {xmlelement, "feature", [{"var", ?NS_COMMANDS}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++ {xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++
@ -436,7 +436,7 @@
end, features(Host, Node))}; end, features(Host, Node))};
<<?NS_COMMANDS>> -> <<?NS_COMMANDS>> ->
command_disco_info(Host, Node, From); command_disco_info(Host, Node, From);
@@ -1182,7 +943,7 @@ @@ -1183,7 +944,7 @@
node_disco_info(Host, Node, From) node_disco_info(Host, Node, From)
end. end.
@ -445,7 +445,7 @@
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
Nodes when is_list(Nodes) -> Nodes when is_list(Nodes) ->
{result, lists:map( {result, lists:map(
@@ -1199,23 +960,24 @@ @@ -1200,23 +961,24 @@
Other -> Other ->
Other Other
end; end;
@ -476,7 +476,7 @@
end, end,
Nodes = lists:map( Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) ->
@@ -1233,7 +995,7 @@ @@ -1234,7 +996,7 @@
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
{xmlelement, "item", [{"jid", Host}, {"name", Name}], []} {xmlelement, "item", [{"jid", Host}, {"name", Name}], []}
end, NodeItems), end, NodeItems),
@ -485,7 +485,7 @@
end, end,
case transaction(Host, Node, Action, sync_dirty) of case transaction(Host, Node, Action, sync_dirty) of
{result, {_, Result}} -> {result, Result}; {result, {_, Result}} -> {result, Result};
@@ -1344,7 +1106,8 @@ @@ -1345,7 +1107,8 @@
(_, Acc) -> (_, Acc) ->
Acc Acc
end, [], xml:remove_cdata(Els)), end, [], xml:remove_cdata(Els)),
@ -495,7 +495,7 @@
{get, "subscriptions"} -> {get, "subscriptions"} ->
get_subscriptions(Host, Node, From, Plugins); get_subscriptions(Host, Node, From, Plugins);
{get, "affiliations"} -> {get, "affiliations"} ->
@@ -1367,7 +1130,9 @@ @@ -1368,7 +1131,9 @@
iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
{xmlelement, _, _, SubEls} = SubEl, {xmlelement, _, _, SubEls} = SubEl,
@ -506,7 +506,7 @@
case Action of case Action of
[{xmlelement, Name, Attrs, Els}] -> [{xmlelement, Name, Attrs, Els}] ->
Node = string_to_node(xml:get_attr_s("node", Attrs)), Node = string_to_node(xml:get_attr_s("node", Attrs)),
@@ -1497,7 +1262,8 @@ @@ -1498,7 +1263,8 @@
_ -> [] _ -> []
end end
end, end,
@ -516,7 +516,7 @@
sync_dirty) of sync_dirty) of
{result, Res} -> Res; {result, Res} -> Res;
Err -> Err Err -> Err
@@ -1536,7 +1302,7 @@ @@ -1537,7 +1303,7 @@
%%% authorization handling %%% authorization handling
@ -525,7 +525,7 @@
Lang = "en", %% TODO fix Lang = "en", %% TODO fix
Stanza = {xmlelement, "message", Stanza = {xmlelement, "message",
[], [],
@@ -1565,7 +1331,7 @@ @@ -1566,7 +1332,7 @@
[{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]}, [{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]},
lists:foreach(fun(Owner) -> lists:foreach(fun(Owner) ->
ejabberd_router:route(service_jid(Host), jlib:make_jid(Owner), Stanza) ejabberd_router:route(service_jid(Host), jlib:make_jid(Owner), Stanza)
@ -534,7 +534,7 @@
find_authorization_response(Packet) -> find_authorization_response(Packet) ->
{xmlelement, _Name, _Attrs, Els} = Packet, {xmlelement, _Name, _Attrs, Els} = Packet,
@@ -1629,8 +1395,8 @@ @@ -1630,8 +1396,8 @@
"true" -> true; "true" -> true;
_ -> false _ -> false
end, end,
@ -545,7 +545,7 @@
{result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]),
if if
not IsApprover -> not IsApprover ->
@@ -1827,7 +1593,7 @@ @@ -1828,7 +1594,7 @@
Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "create", nodeAttr(Node), [{xmlelement, "create", nodeAttr(Node),
[]}]}], []}]}],
@ -553,8 +553,8 @@
+ case transaction(Host, CreateNode, transaction) of + case transaction(Host, CreateNode, transaction) of
{result, {NodeId, {Result, broadcast}}} -> {result, {NodeId, {Result, broadcast}}} ->
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions), broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
case Result of ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
@@ -1928,7 +1694,7 @@ @@ -1943,7 +1709,7 @@
%%<li>The node does not exist.</li> %%<li>The node does not exist.</li>
%%</ul> %%</ul>
subscribe_node(Host, Node, From, JID, Configuration) -> subscribe_node(Host, Node, From, JID, Configuration) ->
@ -563,7 +563,7 @@
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -1936,7 +1702,7 @@ @@ -1951,7 +1717,7 @@
error -> {"", "", ""}; error -> {"", "", ""};
J -> jlib:jid_tolower(J) J -> jlib:jid_tolower(J)
end, end,
@ -572,7 +572,7 @@
Features = features(Type), Features = features(Type),
SubscribeFeature = lists:member("subscribe", Features), SubscribeFeature = lists:member("subscribe", Features),
OptionsFeature = lists:member("subscription-options", Features), OptionsFeature = lists:member("subscription-options", Features),
@@ -1945,6 +1711,7 @@ @@ -1960,6 +1726,7 @@
AccessModel = get_option(Options, access_model), AccessModel = get_option(Options, access_model),
SendLast = get_option(Options, send_last_published_item), SendLast = get_option(Options, send_last_published_item),
AllowedGroups = get_option(Options, roster_groups_allowed, []), AllowedGroups = get_option(Options, roster_groups_allowed, []),
@ -580,7 +580,7 @@
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups),
if if
not SubscribeFeature -> not SubscribeFeature ->
@@ -2283,7 +2050,7 @@ @@ -2298,7 +2065,7 @@
%% <p>The permission are not checked in this function.</p> %% <p>The permission are not checked in this function.</p>
%% @todo We probably need to check that the user doing the query has the right %% @todo We probably need to check that the user doing the query has the right
%% to read the items. %% to read the items.
@ -589,7 +589,7 @@
MaxItems = MaxItems =
if if
SMaxItems == "" -> get_max_items_node(Host); SMaxItems == "" -> get_max_items_node(Host);
@@ -2297,12 +2064,13 @@ @@ -2312,12 +2079,13 @@
{error, Error} -> {error, Error} ->
{error, Error}; {error, Error};
_ -> _ ->
@ -604,7 +604,7 @@
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups),
if if
not RetreiveFeature -> not RetreiveFeature ->
@@ -2315,11 +2083,11 @@ @@ -2330,11 +2098,11 @@
node_call(Type, get_items, node_call(Type, get_items,
[NodeId, From, [NodeId, From,
AccessModel, PresenceSubscription, RosterGroup, AccessModel, PresenceSubscription, RosterGroup,
@ -618,7 +618,7 @@
SendItems = case ItemIDs of SendItems = case ItemIDs of
[] -> [] ->
Items; Items;
@@ -2332,7 +2100,8 @@ @@ -2347,7 +2115,8 @@
%% number of items sent to MaxItems: %% number of items sent to MaxItems:
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
[{xmlelement, "items", nodeAttr(Node), [{xmlelement, "items", nodeAttr(Node),
@ -628,7 +628,7 @@
Error -> Error ->
Error Error
end end
@@ -2354,10 +2123,15 @@ @@ -2369,10 +2138,15 @@
Error -> Error Error -> Error
end. end.
get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) ->
@ -645,14 +645,26 @@
%% @spec (Host, Node, NodeId, Type, LJID, Number) -> any() %% @spec (Host, Node, NodeId, Type, LJID, Number) -> any()
@@ -2370,27 +2144,27 @@ @@ -2385,27 +2159,38 @@
%% @doc <p>Resend the items of a node to the user.</p> %% @doc <p>Resend the items of a node to the user.</p>
%% @todo use cache-last-item feature %% @todo use cache-last-item feature
send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, last) -> send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, last) ->
- case get_cached_item(Host, NodeId) of - case get_cached_item(Host, NodeId) of
+ Stanza = case get_cached_item(Host, NodeId) of + Stanza = case get_cached_item(Host, NodeId) of
undefined -> undefined ->
send_items(Host, Node, NodeId, Type, LJID, 1); - send_items(Host, Node, NodeId, Type, LJID, 1);
+ % special ODBC optimization, works only with node_hometree_odbc, node_flat_odbc and node_pep_odbc
+ case node_action(Host, Type, get_last_items, [NodeId, LJID, 1]) of
+ {result, [LastItem]} ->
+ {ModifNow, ModifUSR} = LastItem#pubsub_item.modification,
+ event_stanza_with_delay(
+ [{xmlelement, "items", nodeAttr(Node),
+ itemsEls([LastItem])}], ModifNow, ModifUSR);
+ _ ->
+ event_stanza(
+ [{xmlelement, "items", nodeAttr(Node),
+ itemsEls([])}])
+ end;
LastItem -> LastItem ->
{ModifNow, ModifUSR} = LastItem#pubsub_item.modification, {ModifNow, ModifUSR} = LastItem#pubsub_item.modification,
- Stanza = event_stanza_with_delay( - Stanza = event_stanza_with_delay(
@ -689,7 +701,7 @@
end end
end; end;
send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, Number) -> send_items(Host, Node, NodeId, Type, {U,S,R} = LJID, Number) ->
@@ -2531,7 +2305,8 @@ @@ -2546,7 +2331,8 @@
error -> error ->
{error, ?ERR_BAD_REQUEST}; {error, ?ERR_BAD_REQUEST};
_ -> _ ->
@ -699,7 +711,7 @@
case lists:member(Owner, Owners) of case lists:member(Owner, Owners) of
true -> true ->
OwnerJID = jlib:make_jid(Owner), OwnerJID = jlib:make_jid(Owner),
@@ -2541,24 +2316,7 @@ @@ -2556,24 +2342,7 @@
end, end,
lists:foreach( lists:foreach(
fun({JID, Affiliation}) -> fun({JID, Affiliation}) ->
@ -725,7 +737,7 @@
end, FilteredEntities), end, FilteredEntities),
{result, []}; {result, []};
_ -> _ ->
@@ -2611,9 +2369,9 @@ @@ -2626,9 +2395,9 @@
end. end.
read_sub(Subscriber, Node, NodeID, SubID, Lang) -> read_sub(Subscriber, Node, NodeID, SubID, Lang) ->
@ -737,7 +749,7 @@
OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)}, OptionsEl = {xmlelement, "options", [{"jid", jlib:jid_to_string(Subscriber)},
{"subid", SubID}|nodeAttr(Node)], {"subid", SubID}|nodeAttr(Node)],
[XdataEl]}, [XdataEl]},
@@ -2645,7 +2403,7 @@ @@ -2660,7 +2429,7 @@
end. end.
set_options_helper(Configuration, JID, NodeID, SubID, Type) -> set_options_helper(Configuration, JID, NodeID, SubID, Type) ->
@ -746,7 +758,7 @@
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -2844,8 +2602,8 @@ @@ -2859,8 +2628,8 @@
{"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]}, {"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]},
ejabberd_router:route(service_jid(Host), jlib:make_jid(JID), Stanza) ejabberd_router:route(service_jid(Host), jlib:make_jid(JID), Stanza)
end, end,
@ -757,7 +769,7 @@
true -> true ->
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
@@ -3208,7 +2966,7 @@ @@ -3223,7 +2992,7 @@
Collection = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]), Collection = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]),
{result, [{Depth, [{N, sub_with_options(N)} || N <- Nodes]} || {Depth, Nodes} <- Collection]} {result, [{Depth, [{N, sub_with_options(N)} || N <- Nodes]} || {Depth, Nodes} <- Collection]}
end, end,
@ -766,7 +778,7 @@
{result, CollSubs} -> subscribed_nodes_by_jid(NotifyType, CollSubs); {result, CollSubs} -> subscribed_nodes_by_jid(NotifyType, CollSubs);
_ -> [] _ -> []
end. end.
@@ -3277,8 +3035,8 @@ @@ -3292,8 +3061,8 @@
[] []
end. end.
sub_with_options(JID, NodeId, SubId) -> sub_with_options(JID, NodeId, SubId) ->
@ -777,7 +789,7 @@
_ -> {JID, SubId, []} _ -> {JID, SubId, []}
end. end.
@@ -3354,6 +3112,30 @@ @@ -3369,6 +3138,30 @@
Result Result
end. end.
@ -808,16 +820,7 @@
%% @spec (Host, Options) -> MaxItems %% @spec (Host, Options) -> MaxItems
%% Host = host() %% Host = host()
%% Options = [Option] %% Options = [Option]
@@ -3484,7 +3266,7 @@ @@ -3765,7 +3558,13 @@
end
end,
case transaction(Host, Node, Action, transaction) of
- {result, {TNode, ok}} ->
+ {result, {TNode, _}} ->
NodeId = TNode#pubsub_node.id,
Type = TNode#pubsub_node.type,
Options = TNode#pubsub_node.options,
@@ -3750,7 +3532,13 @@
tree_action(Host, Function, Args) -> tree_action(Host, Function, Args) ->
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]), ?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
Fun = fun() -> tree_call(Host, Function, Args) end, Fun = fun() -> tree_call(Host, Function, Args) end,
@ -832,7 +835,7 @@
%% @doc <p>node plugin call.</p> %% @doc <p>node plugin call.</p>
node_call(Type, Function, Args) -> node_call(Type, Function, Args) ->
@@ -3770,13 +3558,13 @@ @@ -3785,13 +3584,13 @@
node_action(Host, Type, Function, Args) -> node_action(Host, Type, Function, Args) ->
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]), ?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
@ -848,7 +851,7 @@
case tree_call(Host, get_node, [Host, Node]) of case tree_call(Host, get_node, [Host, Node]) of
N when is_record(N, pubsub_node) -> N when is_record(N, pubsub_node) ->
case Action(N) of case Action(N) of
@@ -3788,13 +3576,19 @@ @@ -3803,13 +3602,19 @@
Error Error
end end
end, Trans). end, Trans).
@ -872,7 +875,7 @@
{result, Result} -> {result, Result}; {result, Result} -> {result, Result};
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{atomic, {result, Result}} -> {result, Result}; {atomic, {result, Result}} -> {result, Result};
@@ -3802,6 +3596,15 @@ @@ -3817,6 +3622,15 @@
{aborted, Reason} -> {aborted, Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR}; {error, ?ERR_INTERNAL_SERVER_ERROR};
@ -888,7 +891,7 @@
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
{error, ?ERR_INTERNAL_SERVER_ERROR}; {error, ?ERR_INTERNAL_SERVER_ERROR};
@@ -3810,6 +3613,17 @@ @@ -3825,6 +3639,17 @@
{error, ?ERR_INTERNAL_SERVER_ERROR} {error, ?ERR_INTERNAL_SERVER_ERROR}
end. end.

View File

@ -463,7 +463,8 @@ get_user_groups(US) ->
[] []
end ++ get_special_users_groups(Host). end ++ get_special_users_groups(Host).
is_group_enabled(Host, Group) -> is_group_enabled(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
case catch mnesia:dirty_read(sr_group, {Group, Host}) of case catch mnesia:dirty_read(sr_group, {Group, Host}) of
[#sr_group{opts = Opts}] -> [#sr_group{opts = Opts}] ->
not lists:member(disabled, Opts); not lists:member(disabled, Opts);
@ -488,7 +489,8 @@ get_group_opt(Host, Group, Opt, Default) ->
get_online_users(Host) -> get_online_users(Host) ->
lists:usort([{U, S} || {U, S, _} <- ejabberd_sm:get_vh_session_list(Host)]). lists:usort([{U, S} || {U, S, _} <- ejabberd_sm:get_vh_session_list(Host)]).
get_group_users(Host, Group) -> get_group_users(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
case get_group_opt(Host, Group, all_users, false) of case get_group_opt(Host, Group, all_users, false) of
true -> true ->
ejabberd_auth:get_vh_registered_users(Host); ejabberd_auth:get_vh_registered_users(Host);
@ -531,7 +533,8 @@ get_group_explicit_users(Host, Group) ->
[] []
end. end.
get_group_name(Host, Group) -> get_group_name(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
get_group_opt(Host, Group, name, Group). get_group_opt(Host, Group, name, Group).
%% Get list of names of groups that have @all@/@online@/etc in the memberlist %% Get list of names of groups that have @all@/@online@/etc in the memberlist
@ -614,8 +617,8 @@ is_user_in_group(US, Group, Host) ->
%% @spec (Host::string(), {User::string(), Server::string()}, Group::string()) -> {atomic, ok} %% @spec (Host::string(), {User::string(), Server::string()}, Group::string()) -> {atomic, ok}
add_user_to_group(Host, US, Group) -> add_user_to_group(Host, US, Group) ->
{LUser, LServer} = US, {LUser, LServer} = US,
case regexp:match(LUser, "^@.+@$") of case ejabberd_regexp:run(LUser, "^@.+@$") of
{match,_,_} -> match ->
GroupOpts = mod_shared_roster:get_group_opts(Host, Group), GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
MoreGroupOpts = MoreGroupOpts =
case LUser of case LUser of
@ -647,8 +650,8 @@ push_displayed_to_user(LUser, LServer, Group, Host, Subscription) ->
remove_user_from_group(Host, US, Group) -> remove_user_from_group(Host, US, Group) ->
GroupHost = {Group, Host}, GroupHost = {Group, Host},
{LUser, LServer} = US, {LUser, LServer} = US,
case regexp:match(LUser, "^@.+@$") of case ejabberd_regexp:run(LUser, "^@.+@$") of
{match,_,_} -> match ->
GroupOpts = mod_shared_roster:get_group_opts(Host, Group), GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
NewGroupOpts = NewGroupOpts =
case LUser of case LUser of
@ -967,7 +970,7 @@ shared_roster_group(Host, Group, Query, Lang) ->
end ++ end ++
[[us_to_list(Member), $\n] || Member <- Members], [[us_to_list(Member), $\n] || Member <- Members],
FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups], FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
DescNL = length(element(2, regexp:split(Description, "\n"))), DescNL = length(ejabberd_regexp:split(Description, "\n")),
FGroup = FGroup =
?XAE("table", [{"class", "withtextareas"}], ?XAE("table", [{"class", "withtextareas"}],
[?XE("tbody", [?XE("tbody",
@ -1114,3 +1117,11 @@ get_opt(Opts, Opt, Default) ->
us_to_list({User, Server}) -> us_to_list({User, Server}) ->
jlib:jid_to_string({User, Server, ""}). jlib:jid_to_string({User, Server, ""}).
split_grouphost(Host, Group) ->
case string:tokens(Group, "@") of
[GroupName, HostName] ->
{HostName, GroupName};
[_] ->
{Host, Group}
end.

View File

@ -219,17 +219,17 @@ set_vcard(User, LServer, VCARD) ->
end, end,
LUser = jlib:nodeprep(User), LUser = jlib:nodeprep(User),
LFN = stringprep:tolower(FN), LFN = string:to_lower(FN),
LFamily = stringprep:tolower(Family), LFamily = string:to_lower(Family),
LGiven = stringprep:tolower(Given), LGiven = string:to_lower(Given),
LMiddle = stringprep:tolower(Middle), LMiddle = string:to_lower(Middle),
LNickname = stringprep:tolower(Nickname), LNickname = string:to_lower(Nickname),
LBDay = stringprep:tolower(BDay), LBDay = string:to_lower(BDay),
LCTRY = stringprep:tolower(CTRY), LCTRY = string:to_lower(CTRY),
LLocality = stringprep:tolower(Locality), LLocality = string:to_lower(Locality),
LEMail = stringprep:tolower(EMail), LEMail = string:to_lower(EMail),
LOrgName = stringprep:tolower(OrgName), LOrgName = string:to_lower(OrgName),
LOrgUnit = stringprep:tolower(OrgUnit), LOrgUnit = string:to_lower(OrgUnit),
US = {LUser, LServer}, US = {LUser, LServer},
@ -541,7 +541,7 @@ filter_fields([], Match, _LServer) ->
Match; Match;
filter_fields([{SVar, [Val]} | Ds], Match, LServer) filter_fields([{SVar, [Val]} | Ds], Match, LServer)
when is_list(Val) and (Val /= "") -> when is_list(Val) and (Val /= "") ->
LVal = stringprep:tolower(Val), LVal = string:to_lower(Val),
NewMatch = case SVar of NewMatch = case SVar of
"user" -> "user" ->
case gen_mod:get_module_opt(LServer, ?MODULE, case gen_mod:get_module_opt(LServer, ?MODULE,
@ -618,17 +618,17 @@ set_vcard_t(R, _) ->
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]), OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
{LUser, _LServer} = US, {LUser, _LServer} = US,
LFN = stringprep:tolower(FN), LFN = string:to_lower(FN),
LFamily = stringprep:tolower(Family), LFamily = string:to_lower(Family),
LGiven = stringprep:tolower(Given), LGiven = string:to_lower(Given),
LMiddle = stringprep:tolower(Middle), LMiddle = string:to_lower(Middle),
LNickname = stringprep:tolower(Nickname), LNickname = string:to_lower(Nickname),
LBDay = stringprep:tolower(BDay), LBDay = string:to_lower(BDay),
LCTRY = stringprep:tolower(CTRY), LCTRY = string:to_lower(CTRY),
LLocality = stringprep:tolower(Locality), LLocality = string:to_lower(Locality),
LEMail = stringprep:tolower(EMail), LEMail = string:to_lower(EMail),
LOrgName = stringprep:tolower(OrgName), LOrgName = string:to_lower(OrgName),
LOrgUnit = stringprep:tolower(OrgUnit), LOrgUnit = string:to_lower(OrgUnit),
if if
(LUser == error) or (LUser == error) or

View File

@ -186,17 +186,17 @@ set_vcard(User, LServer, VCARD) ->
end, end,
LUser = jlib:nodeprep(User), LUser = jlib:nodeprep(User),
LFN = stringprep:tolower(FN), LFN = string:to_lower(FN),
LFamily = stringprep:tolower(Family), LFamily = string:to_lower(Family),
LGiven = stringprep:tolower(Given), LGiven = string:to_lower(Given),
LMiddle = stringprep:tolower(Middle), LMiddle = string:to_lower(Middle),
LNickname = stringprep:tolower(Nickname), LNickname = string:to_lower(Nickname),
LBDay = stringprep:tolower(BDay), LBDay = string:to_lower(BDay),
LCTRY = stringprep:tolower(CTRY), LCTRY = string:to_lower(CTRY),
LLocality = stringprep:tolower(Locality), LLocality = string:to_lower(Locality),
LEMail = stringprep:tolower(EMail), LEMail = string:to_lower(EMail),
LOrgName = stringprep:tolower(OrgName), LOrgName = string:to_lower(OrgName),
LOrgUnit = stringprep:tolower(OrgUnit), LOrgUnit = string:to_lower(OrgUnit),
if if
(LUser == error) or (LUser == error) or
@ -531,7 +531,7 @@ filter_fields([], Match, _LServer) ->
end; end;
filter_fields([{SVar, [Val]} | Ds], Match, LServer) filter_fields([{SVar, [Val]} | Ds], Match, LServer)
when is_list(Val) and (Val /= "") -> when is_list(Val) and (Val /= "") ->
LVal = stringprep:tolower(Val), LVal = string:to_lower(Val),
NewMatch = case SVar of NewMatch = case SVar of
"user" -> make_val(Match, "lusername", LVal); "user" -> make_val(Match, "lusername", LVal);
"fn" -> make_val(Match, "lfn", LVal); "fn" -> make_val(Match, "lfn", LVal);

View File

@ -30,6 +30,16 @@
#define NODEPREP_COMMAND 2 #define NODEPREP_COMMAND 2
#define RESOURCEPREP_COMMAND 3 #define RESOURCEPREP_COMMAND 3
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
typedef struct { typedef struct {
ErlDrvPort port; ErlDrvPort port;
} stringprep_data; } stringprep_data;
@ -194,10 +204,10 @@ static int compose(int ch1, int ch2)
static int stringprep_erl_control(ErlDrvData drv_data, static ErlDrvSSizeT stringprep_erl_control(ErlDrvData drv_data,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
int i, j, pos=1; int i, j, pos=1;
unsigned char c; unsigned char c;
@ -400,7 +410,19 @@ ErlDrvEntry stringprep_driver_entry = {
NULL, /* handle */ NULL, /* handle */
stringprep_erl_control, /* F_PTR control, port_command callback */ stringprep_erl_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(stringprep_erl) /* must match name in driver_entry */ DRIVER_INIT(stringprep_erl) /* must match name in driver_entry */

View File

@ -24,16 +24,26 @@
#include <openssl/md2.h> #include <openssl/md2.h>
#endif #endif
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
static ErlDrvData sha_drv_start(ErlDrvPort port, char *buf) static ErlDrvData sha_drv_start(ErlDrvPort port, char *buf)
{ {
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
return NULL; return NULL;
} }
static int sha_drv_control(ErlDrvData handle, static ErlDrvSSizeT sha_drv_control(ErlDrvData handle,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
ErlDrvBinary *b = NULL; ErlDrvBinary *b = NULL;
@ -89,7 +99,19 @@ ErlDrvEntry sha_driver_entry = {
NULL, /* handle */ NULL, /* handle */
sha_drv_control, /* F_PTR control, port_command callback */ sha_drv_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(sha_drv) /* must match name in driver_entry */ DRIVER_INIT(sha_drv) /* must match name in driver_entry */

View File

@ -44,6 +44,16 @@ typedef unsigned __int32 uint32_t;
#define SSL_OP_NO_TICKET 0 #define SSL_OP_NO_TICKET 0
#endif #endif
/*
* R15B changed several driver callbacks to use ErlDrvSizeT and
* ErlDrvSSizeT typedefs instead of int.
* This provides missing typedefs on older OTP versions.
*/
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
typedef int ErlDrvSizeT;
typedef int ErlDrvSSizeT;
#endif
/* /*
* str_hash is based on the public domain code from * str_hash is based on the public domain code from
* http://www.burtleburtle.net/bob/hash/doobs.html * http://www.burtleburtle.net/bob/hash/doobs.html
@ -305,10 +315,10 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
} }
static int tls_drv_control(ErlDrvData handle, static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
unsigned int command, unsigned int command,
char *buf, int len, char *buf, ErlDrvSizeT len,
char **rbuf, int rlen) char **rbuf, ErlDrvSizeT rlen)
{ {
tls_data *d = (tls_data *)handle; tls_data *d = (tls_data *)handle;
int res; int res;
@ -499,7 +509,19 @@ ErlDrvEntry tls_driver_entry = {
NULL, /* handle */ NULL, /* handle */
tls_drv_control, /* F_PTR control, port_command callback */ tls_drv_control, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */ NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */ NULL, /* F_PTR outputv, reserved */
/* Added in Erlang/OTP R15B: */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
0, /* driver_flags */
NULL, /* handle2 */
NULL, /* process_exit */
NULL /* stop_select */
}; };
DRIVER_INIT(tls_drv) /* must match name in driver_entry */ DRIVER_INIT(tls_drv) /* must match name in driver_entry */

View File

@ -70,7 +70,7 @@
wait_timer, wait_timer,
ctime = 0, ctime = 0,
timer, timer,
jid, jid,
pause=0, pause=0,
unprocessed_req_list = [], % list of request that have been delayed for proper reordering: {Request, PID} unprocessed_req_list = [], % list of request that have been delayed for proper reordering: {Request, PID}
req_list = [], % list of requests (cache) req_list = [], % list of requests (cache)

View File

@ -1239,13 +1239,12 @@ acl_spec_select(ID, Opt) ->
term_to_string(T) -> term_to_string(T) ->
StringParagraph = lists:flatten(io_lib:format("~1000000p", [T])), StringParagraph = lists:flatten(io_lib:format("~1000000p", [T])),
%% Remove from the string all the carriage returns characters %% Remove from the string all the carriage returns characters
{ok, StringLine, _} = regexp:gsub(StringParagraph, "\\n ", ""), ejabberd_regexp:greplace(StringParagraph, "\\n ", "").
StringLine.
%% @spec (T::any(), Cols::integer()) -> {NumLines::integer(), Paragraph::string()} %% @spec (T::any(), Cols::integer()) -> {NumLines::integer(), Paragraph::string()}
term_to_paragraph(T, Cols) -> term_to_paragraph(T, Cols) ->
Paragraph = erl_prettypr:format(erl_syntax:abstract(T), [{paper, Cols}]), Paragraph = erl_prettypr:format(erl_syntax:abstract(T), [{paper, Cols}]),
{ok, FieldList} = regexp:split(Paragraph, "\n"), FieldList = ejabberd_regexp:split(Paragraph, "\n"),
NumLines = length(FieldList), NumLines = length(FieldList),
{NumLines, Paragraph}. {NumLines, Paragraph}.
@ -1558,7 +1557,7 @@ list_users_parse_query(Query, Host) ->
list_users_in_diapason(Host, Diap, Lang, URLFunc) -> list_users_in_diapason(Host, Diap, Lang, URLFunc) ->
Users = ejabberd_auth:get_vh_registered_users(Host), Users = ejabberd_auth:get_vh_registered_users(Host),
SUsers = lists:sort([{S, U} || {U, S} <- Users]), SUsers = lists:sort([{S, U} || {U, S} <- Users]),
{ok, [S1, S2]} = regexp:split(Diap, "-"), [S1, S2] = ejabberd_regexp:split(Diap, "-"),
N1 = list_to_integer(S1), N1 = list_to_integer(S1),
N2 = list_to_integer(S2), N2 = list_to_integer(S2),
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),